205
|
1 import struct, types
|
206
|
2 from target import Register, Instruction, Target, Imm8, Label, Imm3
|
|
3 from asmnodes import ASymbol, ANumber, AUnop, ABinop
|
202
|
4 from ppci import CompilerError
|
205
|
5 import ir
|
202
|
6
|
218
|
7 # TODO: encode this in DSL (domain specific language)
|
|
8
|
202
|
9 def u16(h):
|
|
10 return struct.pack('<H', h)
|
|
11
|
205
|
12 def u32(x):
|
|
13 return struct.pack('<I', x)
|
|
14
|
202
|
15 armtarget = Target('arm')
|
|
16
|
|
17 class ArmReg(Register):
|
|
18 def __init__(self, num, name):
|
|
19 super().__init__(name)
|
|
20 self.num = num
|
206
|
21 def __repr__(self):
|
|
22 return self.name
|
202
|
23
|
203
|
24 class RegOp:
|
|
25 def __init__(self, num):
|
206
|
26 assert num < 16
|
203
|
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
|
206
|
40 def getRegNum(n):
|
|
41 for r in armtarget.registers:
|
|
42 if r.num == n:
|
|
43 return r
|
203
|
44
|
206
|
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
|
203
|
53
|
212
|
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
|
205
|
82 class RegisterSet:
|
|
83 def __init__(self, regs):
|
206
|
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]
|
205
|
114
|
202
|
115 # 8 bit registers:
|
205
|
116 r0 = ArmReg(0, 'r0')
|
|
117 armtarget.registers.append(r0)
|
206
|
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)
|
202
|
124 r4 = ArmReg(4, 'r4')
|
|
125 armtarget.registers.append(r4)
|
203
|
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)
|
218
|
132 r10 = ArmReg(10, 'r10')
|
|
133 armtarget.registers.append(r10)
|
|
134 r11 = ArmReg(11, 'r11')
|
|
135 armtarget.registers.append(r11)
|
206
|
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)
|
202
|
144
|
|
145 class ArmInstruction(Instruction):
|
|
146 pass
|
|
147
|
|
148 class ldr_ins(ArmInstruction):
|
|
149 mnemonic = 'ldr'
|
|
150 opcode = 1337
|
205
|
151 irpattern = 'todo'
|
202
|
152
|
205
|
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)
|
202
|
159
|
|
160 @armtarget.instruction
|
212
|
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
|
202
|
197 class mov_ins(ArmInstruction):
|
|
198 """ mov Rd, imm8, move immediate value into register """
|
|
199 mnemonic = 'mov'
|
203
|
200 opcode = 4 # 00100 Rd(3) imm8
|
|
201 operands = (RegOp, Imm8)
|
205
|
202 irpattern = ir.ImmLoad
|
203
|
203 def __init__(self, rd, imm):
|
|
204 self.imm = imm.imm
|
|
205 self.r = rd.num
|
205
|
206
|
|
207 @classmethod
|
|
208 def FromIr(cls, ir_ins):
|
|
209 pass
|
|
210
|
202
|
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
|
203
|
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)
|
205
|
244 irpattern = 3
|
203
|
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)
|
202
|
272
|
|
273 @armtarget.instruction
|
218
|
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
|
205
|
291 class jmp_ins(ArmInstruction):
|
206
|
292 operands = (Label,)
|
205
|
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):
|
206
|
304 operands = (RegisterSet,)
|
205
|
305 mnemonic = 'push'
|
|
306 def __init__(self, regs):
|
206
|
307 assert (type(regs),) == self.operands, (type(regs),)
|
205
|
308 self.regs = regs
|
206
|
309 def __repr__(self):
|
|
310 return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
|
205
|
311 def encode(self):
|
206
|
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)
|
205
|
323
|
|
324 @armtarget.instruction
|
|
325 class pop_ins(ArmInstruction):
|
206
|
326 operands = (RegisterSet,)
|
205
|
327 mnemonic = 'pop'
|
|
328 def __init__(self, regs):
|
|
329 self.regs = regs
|
207
|
330 def __repr__(self):
|
|
331 return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
|
205
|
332 def encode(self):
|
206
|
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)
|
205
|
344 return u16(0)
|
|
345
|
|
346 @armtarget.instruction
|
202
|
347 class yield_ins(ArmInstruction):
|
|
348 operands = ()
|
|
349 mnemonic = 'yield'
|
|
350 def encode(self):
|
|
351 return u16(0xbf10)
|
|
352
|
206
|
353 armtarget.check()
|
|
354
|