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
|
205
|
52 class RegisterSet:
|
|
53 def __init__(self, regs):
|
206
|
54 assert type(regs) is set
|
|
55 self.regs = regs
|
|
56 def __repr__(self):
|
|
57 return ','.join([str(r) for r in self.regs])
|
|
58 @classmethod
|
|
59 def Create(cls, vop):
|
|
60 assert type(vop) is AUnop and vop.operation == '{}'
|
|
61 assert type(vop.arg) is list
|
|
62 regs = set()
|
|
63 for arg in vop.arg:
|
|
64 if type(arg) is ASymbol:
|
|
65 reg = RegOp.Create(arg)
|
|
66 if not reg:
|
|
67 return
|
|
68 regs.add(reg)
|
|
69 elif type(arg) is ABinop and arg.op == '-':
|
|
70 reg1 = RegOp.Create(arg.arg1)
|
|
71 reg2 = RegOp.Create(arg.arg2)
|
|
72 if not reg1:
|
|
73 return
|
|
74 if not reg2:
|
|
75 return
|
|
76 for r in getRegisterRange(reg1, reg2):
|
|
77 regs.add(r)
|
|
78 else:
|
|
79 raise Exception('Cannot be')
|
|
80 return cls(regs)
|
|
81
|
|
82 def registerNumbers(self):
|
|
83 return [r.num for r in self.regs]
|
205
|
84
|
202
|
85 # 8 bit registers:
|
205
|
86 r0 = ArmReg(0, 'r0')
|
|
87 armtarget.registers.append(r0)
|
206
|
88 r1 = ArmReg(1, 'r1')
|
|
89 armtarget.registers.append(r1)
|
|
90 r2 = ArmReg(2, 'r2')
|
|
91 armtarget.registers.append(r2)
|
|
92 r3 = ArmReg(3, 'r3')
|
|
93 armtarget.registers.append(r3)
|
202
|
94 r4 = ArmReg(4, 'r4')
|
|
95 armtarget.registers.append(r4)
|
203
|
96 r5 = ArmReg(5, 'r5')
|
|
97 armtarget.registers.append(r5)
|
|
98 r6 = ArmReg(6, 'r6')
|
|
99 armtarget.registers.append(r6)
|
|
100 r7 = ArmReg(7, 'r7')
|
|
101 armtarget.registers.append(r7)
|
206
|
102 # Other registers:
|
|
103 # TODO
|
|
104 sp = ArmReg(13, 'sp')
|
|
105 armtarget.registers.append(sp)
|
|
106 lr = ArmReg(14, 'lr')
|
|
107 armtarget.registers.append(lr)
|
|
108 pc = ArmReg(15, 'pc')
|
|
109 armtarget.registers.append(pc)
|
202
|
110
|
|
111 class ArmInstruction(Instruction):
|
|
112 pass
|
|
113
|
|
114 class ldr_ins(ArmInstruction):
|
|
115 mnemonic = 'ldr'
|
|
116 opcode = 1337
|
205
|
117 irpattern = 'todo'
|
202
|
118
|
205
|
119 class dcd_ins(ArmInstruction):
|
|
120 mnemonic = 'dcd'
|
|
121 def __init__(self, expr):
|
|
122 self.expr = expr
|
|
123 def encode(self):
|
|
124 return u32(self.expr)
|
202
|
125
|
|
126 @armtarget.instruction
|
|
127 class mov_ins(ArmInstruction):
|
|
128 """ mov Rd, imm8, move immediate value into register """
|
|
129 mnemonic = 'mov'
|
203
|
130 opcode = 4 # 00100 Rd(3) imm8
|
|
131 operands = (RegOp, Imm8)
|
205
|
132 irpattern = ir.ImmLoad
|
203
|
133 def __init__(self, rd, imm):
|
|
134 self.imm = imm.imm
|
|
135 self.r = rd.num
|
205
|
136
|
|
137 @classmethod
|
|
138 def FromIr(cls, ir_ins):
|
|
139 pass
|
|
140
|
202
|
141 def encode(self):
|
|
142 rd = self.r
|
|
143 opcode = self.opcode
|
|
144 imm8 = self.imm
|
|
145 h = (opcode << 11) | (rd << 8) | imm8
|
|
146 return u16(h)
|
|
147
|
203
|
148 @armtarget.instruction
|
|
149 class movregreg_ins(ArmInstruction):
|
|
150 """ mov Rd, Rm """
|
|
151 mnemonic = 'mov'
|
|
152 opcode = 8 # 01000 Rd(3) imm8
|
|
153 operands = (RegOp, RegOp)
|
|
154 def __init__(self, rd, rm):
|
|
155 self.rd = rd
|
|
156 self.rm = rm
|
|
157 def encode(self):
|
|
158 rd = self.rd.num
|
|
159 D = (rd & 0x8) >> 3
|
|
160 assert D < 2
|
|
161 rd = rd & 0x7
|
|
162 rm = self.rm.num
|
|
163 assert rm < 16
|
|
164 opcode = self.opcode
|
|
165 h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd
|
|
166 return u16(h)
|
|
167
|
|
168 @armtarget.instruction
|
|
169 class addregregimm3_ins(ArmInstruction):
|
|
170 """ add Rd, Rn, imm3 """
|
|
171 mnemonic = 'add'
|
|
172 opcode = 3 # 00011
|
|
173 operands = (RegOp, RegOp, Imm3)
|
205
|
174 irpattern = 3
|
203
|
175 def __init__(self, rd, rn, imm3):
|
|
176 self.rd = rd
|
|
177 self.rn = rn
|
|
178 self.imm3 = imm3
|
|
179 def encode(self):
|
|
180 rd = self.rd.num
|
|
181 rn = self.rn.num
|
|
182 imm3 = self.imm3.imm
|
|
183 opcode = self.opcode
|
|
184 h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd
|
|
185 return u16(h)
|
|
186
|
|
187 @armtarget.instruction
|
|
188 class cmpregimm8_ins(ArmInstruction):
|
|
189 """ cmp Rn, imm8 """
|
|
190 mnemonic = 'cmp'
|
|
191 opcode = 5 # 00101
|
|
192 operands = (RegOp, Imm8)
|
|
193 def __init__(self, rn, imm):
|
|
194 self.rn = rn
|
|
195 self.imm = imm
|
|
196 def encode(self):
|
|
197 rn = self.rn.num
|
|
198 imm = self.imm.imm
|
|
199 opcode = self.opcode
|
|
200 h = (opcode << 11) | (rn << 8) | imm
|
|
201 return u16(h)
|
202
|
202
|
|
203 @armtarget.instruction
|
205
|
204 class jmp_ins(ArmInstruction):
|
206
|
205 operands = (Label,)
|
205
|
206 mnemonic = 'jmp'
|
|
207 def __init__(self, target_label):
|
|
208 self.target = target_label
|
|
209 def fixUp(self):
|
|
210 pass
|
|
211 def encode(self):
|
|
212 h = 1337 # TODO
|
|
213 return u16(h)
|
|
214
|
|
215 @armtarget.instruction
|
|
216 class push_ins(ArmInstruction):
|
206
|
217 operands = (RegisterSet,)
|
205
|
218 mnemonic = 'push'
|
|
219 def __init__(self, regs):
|
206
|
220 print(self.operands)
|
|
221 assert (type(regs),) == self.operands, (type(regs),)
|
205
|
222 self.regs = regs
|
206
|
223 def __repr__(self):
|
|
224 return '{0} {{{1}}}'.format(self.mnemonic, self.regs)
|
205
|
225 def encode(self):
|
206
|
226 reg_list = 0
|
|
227 M = 0
|
|
228 for n in self.regs.registerNumbers():
|
|
229 if n < 8:
|
|
230 reg_list |= (1 << n)
|
|
231 elif n == 14:
|
|
232 M = 1
|
|
233 else:
|
|
234 raise NotImplementedError('not implemented for this register')
|
|
235 h = (0x5a << 9) | (M << 8) | reg_list
|
|
236 return u16(h)
|
205
|
237
|
|
238 @armtarget.instruction
|
|
239 class pop_ins(ArmInstruction):
|
206
|
240 operands = (RegisterSet,)
|
205
|
241 mnemonic = 'pop'
|
|
242 def __init__(self, regs):
|
|
243 self.regs = regs
|
|
244 def encode(self):
|
206
|
245 reg_list = 0
|
|
246 P = 0
|
|
247 for n in self.regs.registerNumbers():
|
|
248 if n < 8:
|
|
249 reg_list |= (1 << n)
|
|
250 elif n == 15:
|
|
251 P = 1
|
|
252 else:
|
|
253 raise NotImplementedError('not implemented for this register')
|
|
254 h = (0x5E << 9) | (P << 8) | reg_list
|
|
255 return u16(h)
|
205
|
256 return u16(0)
|
|
257
|
|
258 @armtarget.instruction
|
202
|
259 class yield_ins(ArmInstruction):
|
|
260 operands = ()
|
|
261 mnemonic = 'yield'
|
|
262 def encode(self):
|
|
263 return u16(0xbf10)
|
|
264
|
206
|
265 armtarget.check()
|
|
266
|