Mercurial > lcfOS
comparison 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 |
comparison
equal
deleted
inserted
replaced
289:bd2593de3ff8 | 290:7b38782ed496 |
---|---|
1 from asmnodes import ASymbol, AInstruction, ANumber | |
2 from ppci import CompilerError | |
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 | |
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) | |
24 | |
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 | |
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 | |
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): | |
60 assert type(name) is str | |
61 self.name = name | |
62 | |
63 @classmethod | |
64 def Create(cls, vop): | |
65 if type(vop) is ASymbol: | |
66 return cls(vop.name) | |
67 | |
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 | |
75 class Nop(Instruction): | |
76 """ Instruction that does nothing and has zero size """ | |
77 def encode(self): | |
78 return bytes() | |
79 | |
80 | |
81 | |
82 class PseudoInstruction(Instruction): | |
83 pass | |
84 | |
85 | |
86 class Label(PseudoInstruction): | |
87 def __init__(self, name): | |
88 self.name = name | |
89 self.address = 0 | |
90 | |
91 def __repr__(self): | |
92 return '{}:'.format(self.name) | |
93 | |
94 def encode(self): | |
95 return bytes() | |
96 | |
97 @classmethod | |
98 def Create(cls, vop): | |
99 if type(vop) is ASymbol: | |
100 name = vop.name | |
101 return cls(name) | |
102 | |
103 | |
104 class Comment(PseudoInstruction): | |
105 def __init__(self, txt): | |
106 self.txt = txt | |
107 | |
108 def encode(self): | |
109 return bytes() | |
110 | |
111 def __repr__(self): | |
112 return '; {}'.format(self.txt) | |
113 | |
114 | |
115 class Alignment(PseudoInstruction): | |
116 def __init__(self, a): | |
117 self.align = a | |
118 | |
119 def __repr__(self): | |
120 return 'ALIGN({})'.format(self.align) | |
121 | |
122 def encode(self): | |
123 pad = [] | |
124 address = self.address | |
125 while (address % self.align) != 0: | |
126 address += 1 | |
127 pad.append(0) | |
128 return bytes(pad) | |
129 | |
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() | |
139 | |
140 class Register(Operand): | |
141 def __init__(self, name): | |
142 self.name = name | |
143 | |
144 | |
145 class Target: | |
146 def __init__(self, name, desc=''): | |
147 self.name = name | |
148 self.desc = desc | |
149 self.registers = [] | |
150 self.instructions = [] | |
151 | |
152 def instruction(self, cls): | |
153 """ Decorator function that registers an instruction to this target """ | |
154 self.addInstruction(cls) | |
155 return cls | |
156 | |
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 | |
165 def addInstruction(self, ins_class): | |
166 self.instructions.append(ins_class) | |
167 | |
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] | |
177 raise CompilerError('Cannot map {0}'.format(operand)) | |
178 | |
179 def mapInstruction(self, vi): | |
180 assert type(vi) is AInstruction | |
181 """ Map ast tree to real instruction for this target """ | |
182 | |
183 # map to real operands: | |
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) | |
187 | |
188 # look for a suitable instruction | |
189 for ic in self.instructions: | |
190 if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands): | |
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: | |
195 if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)): | |
196 return ic(*rops) | |
197 raise CompilerError('No suitable instruction found for "{0}"'.format(vi)) | |
198 |