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