line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# $Id$ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package CPU::Z80::Assembler::Opcode; |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
CPU::Z80::Assembler::Opcode - Represents one assembly expression to be computed at link time |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
14
|
|
|
|
|
|
|
|
15
|
31
|
|
|
31
|
|
38282
|
use strict; |
|
31
|
|
|
|
|
78
|
|
|
31
|
|
|
|
|
936
|
|
16
|
31
|
|
|
31
|
|
160
|
use warnings; |
|
31
|
|
|
|
|
80
|
|
|
31
|
|
|
|
|
1330
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our $VERSION = '2.23'; |
19
|
|
|
|
|
|
|
|
20
|
31
|
|
|
31
|
|
179
|
use Asm::Preproc::Line; |
|
31
|
|
|
|
|
60
|
|
|
31
|
|
|
|
|
197
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
23
|
22724
|
|
|
22724
|
1
|
568936
|
my($class, %args) = @_; |
24
|
|
|
|
|
|
|
bless [ |
25
|
|
|
|
|
|
|
$args{address}, # address where loaded |
26
|
|
|
|
|
|
|
$args{line} || Asm::Preproc::Line->new(), |
27
|
|
|
|
|
|
|
# line where tokens found |
28
|
22724
|
|
66
|
|
|
132133
|
$args{child} || [], # list of children of this node |
|
|
|
100
|
|
|
|
|
29
|
|
|
|
|
|
|
# each child is a byte value or an expression |
30
|
|
|
|
|
|
|
# to compute the byte(s) |
31
|
|
|
|
|
|
|
], $class; |
32
|
|
|
|
|
|
|
} |
33
|
80898
|
100
|
|
80898
|
1
|
185953
|
sub address { defined($_[1]) ? $_[0][0] = $_[1] : $_[0][0] } |
34
|
2812
|
100
|
|
2812
|
1
|
12020
|
sub line { defined($_[1]) ? $_[0][1] = $_[1] : $_[0][1] } |
35
|
91693
|
50
|
|
91693
|
1
|
278304
|
sub child { defined($_[1]) ? $_[0][2] = $_[1] : $_[0][2] } |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 SYNOPSIS |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
use CPU::Z80::Assembler::Opcode; |
42
|
|
|
|
|
|
|
$opcode = CPU::Z80::Assembler::Opcode->new( |
43
|
|
|
|
|
|
|
address => 0, |
44
|
|
|
|
|
|
|
line => $line, |
45
|
|
|
|
|
|
|
child => [byte, byte, ["type", $expr]]); |
46
|
|
|
|
|
|
|
$value = $opcode->evaluate; |
47
|
|
|
|
|
|
|
$bytes = $opcode->bytes($address, \%symbol_table); |
48
|
|
|
|
|
|
|
$size = $opcode->size; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head1 DESCRIPTION |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
This module defines the class that represents one assembly instruction to be |
53
|
|
|
|
|
|
|
added to the object code. The instruction can contain references to |
54
|
|
|
|
|
|
|
L expressions that are computed at link time. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head1 EXPORTS |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
Nothing. |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 FUNCTIONS |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 new |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Creates a new object. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head2 address |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Address where this opcode is loaded, computed at link time. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 child |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
The number of children is the number of bytes stored in the object code for |
73
|
|
|
|
|
|
|
this instruction. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
Each child is either a scalar containing the byte value to be added to the object code, |
76
|
|
|
|
|
|
|
or a L expression to be evaluated at link time. In case |
77
|
|
|
|
|
|
|
of a word expression, then a special undef value is used as a placeholder to keep |
78
|
|
|
|
|
|
|
the C list the correct size. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 line |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Get/set the line - text, file name and line number where the token was read. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=cut |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head2 evaluate |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Called when opcode is referred to by a label, returns the opcode address. |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=cut |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
95
|
|
|
|
|
|
|
|
96
|
8661
|
|
|
8661
|
1
|
15424
|
sub evaluate { my($self) = @_; |
97
|
8661
|
|
|
|
|
17076
|
return $self->address; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 bytes |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
$bytes = $opcode->bytes($address, \%symbol_table); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Computes all the expressions in C and returns the bytes string |
107
|
|
|
|
|
|
|
with the result object code. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=cut |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub bytes { |
114
|
21132
|
|
|
21132
|
1
|
37036
|
my($self, $address, $symbol_table) = @_; |
115
|
|
|
|
|
|
|
|
116
|
21132
|
|
|
|
|
31200
|
my $bytes = ""; |
117
|
21132
|
|
|
|
|
29037
|
for my $expr (@{$self->child}) { |
|
21132
|
|
|
|
|
33203
|
|
118
|
65613
|
100
|
|
|
|
134811
|
if (! defined($expr)) { |
|
|
100
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# skip undefined values - used as placeholder for the second byte of a word |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
elsif (ref($expr)) { |
122
|
11269
|
|
|
|
|
26527
|
$bytes .= $expr->bytes($address, $symbol_table); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
else { |
125
|
51617
|
|
|
|
|
104457
|
$bytes .= pack("C", $expr & 0xFF); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} |
128
|
21132
|
|
|
|
|
53537
|
return $bytes; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 size |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$size = $opcode->size; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Return the number of bytes that this opcode will generate. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=cut |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
142
|
|
|
|
|
|
|
|
143
|
66561
|
|
|
66561
|
1
|
106295
|
sub size { my($self) = @_; |
144
|
66561
|
|
|
|
|
87799
|
return scalar(@{$self->child}); |
|
66561
|
|
|
|
|
104408
|
|
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head1 BUGS and FEEDBACK |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
See L. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head1 SEE ALSO |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
L |
156
|
|
|
|
|
|
|
L |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 AUTHORS, COPYRIGHT and LICENCE |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
See L. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=cut |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
1; |
167
|
|
|
|
|
|
|
|