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