Mercurial > lcfOS
annotate python/target/basetarget.py @ 290:7b38782ed496
File moves
author | Windel Bouwman |
---|---|
date | Sun, 24 Nov 2013 11:24:15 +0100 |
parents | python/target.py@02385f62f250 |
children | 534b94b40aa8 |
rev | line source |
---|---|
235 | 1 from asmnodes import ASymbol, AInstruction, ANumber |
200 | 2 from ppci import CompilerError |
199 | 3 |
4 """ | |
5 Base classes for defining a target | |
6 """ | |
7 | |
8 # Machine code interface: | |
9 class Operand: | |
10 """ Single machine operand """ | |
11 pass | |
12 | |
206 | 13 # standard immediates: |
14 | |
15 class Imm8: | |
16 def __init__(self, imm): | |
17 assert imm < 256 | |
18 self.imm = imm | |
19 | |
20 @classmethod | |
21 def Create(cls, vop): | |
22 if type(vop) is ANumber and vop.number < 256: | |
23 return cls(vop.number) | |
234 | 24 |
275 | 25 class Imm7: |
26 def __init__(self, imm): | |
27 assert imm < 128 | |
28 self.imm = imm | |
29 | |
30 @classmethod | |
31 def Create(cls, vop): | |
32 if type(vop) is ANumber and vop.number < 128: | |
33 return cls(vop.number) | |
34 | |
206 | 35 class Imm3: |
36 def __init__(self, imm): | |
37 assert imm < 8 | |
38 assert type(imm) is int | |
39 self.imm = imm | |
40 | |
41 @classmethod | |
42 def Create(cls, vop): | |
43 if type(vop) is ANumber and vop.number < 8: | |
44 return cls(vop.number) | |
45 | |
235 | 46 class Imm32: |
47 def __init__(self, imm): | |
48 assert imm < 2**32 | |
49 assert type(imm) is int | |
50 self.imm = imm | |
51 | |
52 @classmethod | |
53 def Create(cls, vop): | |
54 if type(vop) is ANumber and vop.number < 2**32: | |
55 return cls(vop.number) | |
56 | |
57 | |
58 class LabelRef: | |
59 def __init__(self, name): | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
60 assert type(name) is str |
235 | 61 self.name = name |
62 | |
63 @classmethod | |
64 def Create(cls, vop): | |
65 if type(vop) is ASymbol: | |
66 return cls(vop.name) | |
67 | |
234 | 68 class Instruction: |
69 def encode(self): | |
70 raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self))) | |
71 def resolve(self, f): | |
72 pass | |
73 | |
74 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
75 class Nop(Instruction): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
76 """ Instruction that does nothing and has zero size """ |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
77 def encode(self): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
78 return bytes() |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
79 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
80 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
81 |
234 | 82 class PseudoInstruction(Instruction): |
83 pass | |
84 | |
85 | |
86 class Label(PseudoInstruction): | |
206 | 87 def __init__(self, name): |
88 self.name = name | |
234 | 89 self.address = 0 |
206 | 90 |
235 | 91 def __repr__(self): |
92 return '{}:'.format(self.name) | |
93 | |
94 def encode(self): | |
95 return bytes() | |
96 | |
206 | 97 @classmethod |
98 def Create(cls, vop): | |
99 if type(vop) is ASymbol: | |
100 name = vop.name | |
101 return cls(name) | |
102 | |
235 | 103 |
234 | 104 class Comment(PseudoInstruction): |
105 def __init__(self, txt): | |
106 self.txt = txt | |
249 | 107 |
235 | 108 def encode(self): |
109 return bytes() | |
249 | 110 |
234 | 111 def __repr__(self): |
112 return '; {}'.format(self.txt) | |
113 | |
235 | 114 |
234 | 115 class Alignment(PseudoInstruction): |
116 def __init__(self, a): | |
117 self.align = a | |
235 | 118 |
119 def __repr__(self): | |
120 return 'ALIGN({})'.format(self.align) | |
121 | |
234 | 122 def encode(self): |
123 pad = [] | |
124 address = self.address | |
235 | 125 while (address % self.align) != 0: |
234 | 126 address += 1 |
127 pad.append(0) | |
128 return bytes(pad) | |
129 | |
249 | 130 class DebugInfo(PseudoInstruction): |
131 def __init__(self, i): | |
132 self.info = i | |
133 | |
134 def __repr__(self): | |
135 return 'DebugInfo: {}'.format(self.info) | |
136 | |
137 def encode(self): | |
138 return bytes() | |
234 | 139 |
199 | 140 class Register(Operand): |
141 def __init__(self, name): | |
142 self.name = name | |
143 | |
144 | |
145 class Target: | |
201 | 146 def __init__(self, name, desc=''): |
147 self.name = name | |
148 self.desc = desc | |
200 | 149 self.registers = [] |
199 | 150 self.instructions = [] |
200 | 151 |
201 | 152 def instruction(self, cls): |
153 """ Decorator function that registers an instruction to this target """ | |
202 | 154 self.addInstruction(cls) |
201 | 155 return cls |
156 | |
206 | 157 def check(self): |
158 """ Check target """ | |
159 for i in self.instructions: | |
160 assert hasattr(i, 'mnemonic') | |
161 assert hasattr(i, 'operands'), str(i) | |
162 assert type(i.mnemonic) is str | |
163 assert type(i.operands) is tuple, str(i) | |
164 | |
202 | 165 def addInstruction(self, ins_class): |
166 self.instructions.append(ins_class) | |
167 | |
200 | 168 def mapOperand(self, operand): |
169 """ Try to map an operand to a target type """ | |
170 if type(operand) is ASymbol: | |
171 # Try to map to register: | |
172 regs = {} | |
173 for r in self.registers: | |
174 regs[r.name] = r | |
175 if operand.name in regs: | |
176 return regs[operand.name] | |
201 | 177 raise CompilerError('Cannot map {0}'.format(operand)) |
199 | 178 |
200 | 179 def mapInstruction(self, vi): |
203 | 180 assert type(vi) is AInstruction |
200 | 181 """ Map ast tree to real instruction for this target """ |
199 | 182 |
200 | 183 # map to real operands: |
236 | 184 if vi.mnemonic.upper() == 'ALIGN' and len(vi.operands) == 1: |
185 if type(vi.operands[0]) == ANumber: | |
186 return Alignment(vi.operands[0].number) | |
200 | 187 |
188 # look for a suitable instruction | |
189 for ic in self.instructions: | |
219 | 190 if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands): |
203 | 191 # Try to map operands to the correct operand types: |
192 rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)] | |
193 | |
194 # Check if we succeeded: | |
277 | 195 if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)): |
203 | 196 return ic(*rops) |
201 | 197 raise CompilerError('No suitable instruction found for "{0}"'.format(vi)) |
200 | 198 |