Mercurial > lcfOS
comparison python/cortexm3.py @ 218:494828a7adf1
added some sort of cache to assembler
author | Windel Bouwman |
---|---|
date | Fri, 05 Jul 2013 15:30:22 +0200 |
parents | python/arm_cm3.py@57c032c5e753 |
children | 1fa3e0050b49 |
comparison
equal
deleted
inserted
replaced
217:8b2e5f3cd579 | 218:494828a7adf1 |
---|---|
1 import struct, types | |
2 from target import Register, Instruction, Target, Imm8, Label, Imm3 | |
3 from asmnodes import ASymbol, ANumber, AUnop, ABinop | |
4 from ppci import CompilerError | |
5 import ir | |
6 | |
7 # TODO: encode this in DSL (domain specific language) | |
8 | |
9 def u16(h): | |
10 return struct.pack('<H', h) | |
11 | |
12 def u32(x): | |
13 return struct.pack('<I', x) | |
14 | |
15 armtarget = Target('arm') | |
16 | |
17 class ArmReg(Register): | |
18 def __init__(self, num, name): | |
19 super().__init__(name) | |
20 self.num = num | |
21 def __repr__(self): | |
22 return self.name | |
23 | |
24 class RegOp: | |
25 def __init__(self, num): | |
26 assert num < 16 | |
27 self.num = num | |
28 | |
29 @classmethod | |
30 def Create(cls, vop): | |
31 if type(vop) is ASymbol: | |
32 name = vop.name | |
33 regs = {} | |
34 for r in armtarget.registers: | |
35 regs[r.name] = r | |
36 if name in regs: | |
37 r = regs[name] | |
38 return cls(r.num) | |
39 | |
40 def getRegNum(n): | |
41 for r in armtarget.registers: | |
42 if r.num == n: | |
43 return r | |
44 | |
45 def getRegisterRange(n1, n2): | |
46 regs = [] | |
47 if n1.num < n2.num: | |
48 for n in range(n1.num, n2.num + 1): | |
49 r = getRegNum(n) | |
50 assert r | |
51 regs.append(r) | |
52 return regs | |
53 | |
54 class MemoryOp: | |
55 def __init__(self, basereg, offset): | |
56 assert type(basereg) is ArmReg | |
57 self.basereg = basereg | |
58 self.offset = offset | |
59 | |
60 @classmethod | |
61 def Create(cls, vop): | |
62 if type(vop) is AUnop and vop.operation == '[]': | |
63 vop = vop.arg # descent | |
64 if type(vop) is ABinop: | |
65 if vop.op == '+' and type(vop.arg1) is ASymbol and type(vop.arg2) is ANumber: | |
66 offset = vop.arg2.number | |
67 basereg = RegOp.Create(vop.arg1) | |
68 if not basereg: | |
69 return | |
70 else: | |
71 return | |
72 elif type(vop) is ASymbol: | |
73 offset = 0 | |
74 basereg = RegOp.Create(vop) | |
75 if not basereg: | |
76 return | |
77 else: | |
78 return | |
79 return cls(getRegNum(basereg.num), offset) | |
80 pass | |
81 | |
82 class RegisterSet: | |
83 def __init__(self, regs): | |
84 assert type(regs) is set | |
85 self.regs = regs | |
86 def __repr__(self): | |
87 return ','.join([str(r) for r in self.regs]) | |
88 @classmethod | |
89 def Create(cls, vop): | |
90 assert type(vop) is AUnop and vop.operation == '{}' | |
91 assert type(vop.arg) is list | |
92 regs = set() | |
93 for arg in vop.arg: | |
94 if type(arg) is ASymbol: | |
95 reg = RegOp.Create(arg) | |
96 if not reg: | |
97 return | |
98 regs.add(reg) | |
99 elif type(arg) is ABinop and arg.op == '-': | |
100 reg1 = RegOp.Create(arg.arg1) | |
101 reg2 = RegOp.Create(arg.arg2) | |
102 if not reg1: | |
103 return | |
104 if not reg2: | |
105 return | |
106 for r in getRegisterRange(reg1, reg2): | |
107 regs.add(r) | |
108 else: | |
109 raise Exception('Cannot be') | |
110 return cls(regs) | |
111 | |
112 def registerNumbers(self): | |
113 return [r.num for r in self.regs] | |
114 | |
115 # 8 bit registers: | |
116 r0 = ArmReg(0, 'r0') | |
117 armtarget.registers.append(r0) | |
118 r1 = ArmReg(1, 'r1') | |
119 armtarget.registers.append(r1) | |
120 r2 = ArmReg(2, 'r2') | |
121 armtarget.registers.append(r2) | |
122 r3 = ArmReg(3, 'r3') | |
123 armtarget.registers.append(r3) | |
124 r4 = ArmReg(4, 'r4') | |
125 armtarget.registers.append(r4) | |
126 r5 = ArmReg(5, 'r5') | |
127 armtarget.registers.append(r5) | |
128 r6 = ArmReg(6, 'r6') | |
129 armtarget.registers.append(r6) | |
130 r7 = ArmReg(7, 'r7') | |
131 armtarget.registers.append(r7) | |
132 r10 = ArmReg(10, 'r10') | |
133 armtarget.registers.append(r10) | |
134 r11 = ArmReg(11, 'r11') | |
135 armtarget.registers.append(r11) | |
136 # Other registers: | |
137 # TODO | |
138 sp = ArmReg(13, 'sp') | |
139 armtarget.registers.append(sp) | |
140 lr = ArmReg(14, 'lr') | |
141 armtarget.registers.append(lr) | |
142 pc = ArmReg(15, 'pc') | |
143 armtarget.registers.append(pc) | |
144 | |
145 class ArmInstruction(Instruction): | |
146 pass | |
147 | |
148 class ldr_ins(ArmInstruction): | |
149 mnemonic = 'ldr' | |
150 opcode = 1337 | |
151 irpattern = 'todo' | |
152 | |
153 class dcd_ins(ArmInstruction): | |
154 mnemonic = 'dcd' | |
155 def __init__(self, expr): | |
156 self.expr = expr | |
157 def encode(self): | |
158 return u32(self.expr) | |
159 | |
160 @armtarget.instruction | |
161 class storeimm5_ins(ArmInstruction): | |
162 """ str Rt, [Rn, imm5], store value into memory """ | |
163 mnemonic = 'str' | |
164 operands = (RegOp, MemoryOp) | |
165 def __init__(self, rt, memop): | |
166 assert memop.offset % 4 == 0 | |
167 self.imm5 = memop.offset >> 2 | |
168 self.rn = memop.basereg.num | |
169 self.rt = rt.num | |
170 | |
171 def encode(self): | |
172 Rn = self.rn | |
173 Rt = self.rt | |
174 imm5 = self.imm5 | |
175 h = (0xC << 11) | (imm5 << 6) | (Rn << 3) | Rt | |
176 return u16(h) | |
177 | |
178 @armtarget.instruction | |
179 class loadimm5_ins(ArmInstruction): | |
180 """ str Rt, [Rn, imm5], store value into memory """ | |
181 mnemonic = 'ldr' | |
182 operands = (RegOp, MemoryOp) | |
183 def __init__(self, rt, memop): | |
184 assert memop.offset % 4 == 0 | |
185 self.imm5 = memop.offset >> 2 | |
186 self.rn = memop.basereg.num | |
187 self.rt = rt.num | |
188 | |
189 def encode(self): | |
190 Rn = self.rn | |
191 Rt = self.rt | |
192 imm5 = self.imm5 | |
193 h = (0xD << 11) | (imm5 << 6) | (Rn << 3) | Rt | |
194 return u16(h) | |
195 | |
196 @armtarget.instruction | |
197 class mov_ins(ArmInstruction): | |
198 """ mov Rd, imm8, move immediate value into register """ | |
199 mnemonic = 'mov' | |
200 opcode = 4 # 00100 Rd(3) imm8 | |
201 operands = (RegOp, Imm8) | |
202 irpattern = ir.ImmLoad | |
203 def __init__(self, rd, imm): | |
204 self.imm = imm.imm | |
205 self.r = rd.num | |
206 | |
207 @classmethod | |
208 def FromIr(cls, ir_ins): | |
209 pass | |
210 | |
211 def encode(self): | |
212 rd = self.r | |
213 opcode = self.opcode | |
214 imm8 = self.imm | |
215 h = (opcode << 11) | (rd << 8) | imm8 | |
216 return u16(h) | |
217 | |
218 @armtarget.instruction | |
219 class movregreg_ins(ArmInstruction): | |
220 """ mov Rd, Rm """ | |
221 mnemonic = 'mov' | |
222 opcode = 8 # 01000 Rd(3) imm8 | |
223 operands = (RegOp, RegOp) | |
224 def __init__(self, rd, rm): | |
225 self.rd = rd | |
226 self.rm = rm | |
227 def encode(self): | |
228 rd = self.rd.num | |
229 D = (rd & 0x8) >> 3 | |
230 assert D < 2 | |
231 rd = rd & 0x7 | |
232 rm = self.rm.num | |
233 assert rm < 16 | |
234 opcode = self.opcode | |
235 h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd | |
236 return u16(h) | |
237 | |
238 @armtarget.instruction | |
239 class addregregimm3_ins(ArmInstruction): | |
240 """ add Rd, Rn, imm3 """ | |
241 mnemonic = 'add' | |
242 opcode = 3 # 00011 | |
243 operands = (RegOp, RegOp, Imm3) | |
244 irpattern = 3 | |
245 def __init__(self, rd, rn, imm3): | |
246 self.rd = rd | |
247 self.rn = rn | |
248 self.imm3 = imm3 | |
249 def encode(self): | |
250 rd = self.rd.num | |
251 rn = self.rn.num | |
252 imm3 = self.imm3.imm | |
253 opcode = self.opcode | |
254 h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd | |
255 return u16(h) | |
256 | |
257 @armtarget.instruction | |
258 class cmpregimm8_ins(ArmInstruction): | |
259 """ cmp Rn, imm8 """ | |
260 mnemonic = 'cmp' | |
261 opcode = 5 # 00101 | |
262 operands = (RegOp, Imm8) | |
263 def __init__(self, rn, imm): | |
264 self.rn = rn | |
265 self.imm = imm | |
266 def encode(self): | |
267 rn = self.rn.num | |
268 imm = self.imm.imm | |
269 opcode = self.opcode | |
270 h = (opcode << 11) | (rn << 8) | imm | |
271 return u16(h) | |
272 | |
273 @armtarget.instruction | |
274 class cmp_ins(ArmInstruction): | |
275 """ cmp Rn, Rm """ | |
276 mnemonic = 'cmp' | |
277 operands = (RegOp, RegOp) | |
278 def __init__(self, rn, rm): | |
279 self.rn = rn | |
280 self.rm = rm | |
281 def encode(self): | |
282 rn = self.rn.num | |
283 rm = self.rm.num | |
284 assert rn < 8 | |
285 assert rm < 8 | |
286 opcode = 0x42 | |
287 h = (opcode << 8) | (1 << 7) | (rm << 3) | (rn & 0x7) | |
288 return u16(h) | |
289 | |
290 @armtarget.instruction | |
291 class jmp_ins(ArmInstruction): | |
292 operands = (Label,) | |
293 mnemonic = 'jmp' | |
294 def __init__(self, target_label): | |
295 self.target = target_label | |
296 def fixUp(self): | |
297 pass | |
298 def encode(self): | |
299 h = 1337 # TODO | |
300 return u16(h) | |
301 | |
302 @armtarget.instruction | |
303 class push_ins(ArmInstruction): | |
304 operands = (RegisterSet,) | |
305 mnemonic = 'push' | |
306 def __init__(self, regs): | |
307 assert (type(regs),) == self.operands, (type(regs),) | |
308 self.regs = regs | |
309 def __repr__(self): | |
310 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
311 def encode(self): | |
312 reg_list = 0 | |
313 M = 0 | |
314 for n in self.regs.registerNumbers(): | |
315 if n < 8: | |
316 reg_list |= (1 << n) | |
317 elif n == 14: | |
318 M = 1 | |
319 else: | |
320 raise NotImplementedError('not implemented for this register') | |
321 h = (0x5a << 9) | (M << 8) | reg_list | |
322 return u16(h) | |
323 | |
324 @armtarget.instruction | |
325 class pop_ins(ArmInstruction): | |
326 operands = (RegisterSet,) | |
327 mnemonic = 'pop' | |
328 def __init__(self, regs): | |
329 self.regs = regs | |
330 def __repr__(self): | |
331 return '{0} {{{1}}}'.format(self.mnemonic, self.regs) | |
332 def encode(self): | |
333 reg_list = 0 | |
334 P = 0 | |
335 for n in self.regs.registerNumbers(): | |
336 if n < 8: | |
337 reg_list |= (1 << n) | |
338 elif n == 15: | |
339 P = 1 | |
340 else: | |
341 raise NotImplementedError('not implemented for this register') | |
342 h = (0x5E << 9) | (P << 8) | reg_list | |
343 return u16(h) | |
344 return u16(0) | |
345 | |
346 @armtarget.instruction | |
347 class yield_ins(ArmInstruction): | |
348 operands = () | |
349 mnemonic = 'yield' | |
350 def encode(self): | |
351 return u16(0xbf10) | |
352 | |
353 armtarget.check() | |
354 |