comparison python/ppci/target/arm/instructions.py @ 347:742588fb8cd6 devel

Merge into devel branch
author Windel Bouwman
date Fri, 07 Mar 2014 17:10:21 +0100
parents 3bb7dcfe5529
children 2b02bd286fe9
comparison
equal deleted inserted replaced
343:11c5a8a70c02 347:742588fb8cd6
1
2 1
3 from ..basetarget import Instruction 2 from ..basetarget import Instruction
3 from ...bitfun import rotate_left
4 4
5 from .token import ArmToken 5 from .token import ArmToken
6 from .registers import R0, SP 6 from .registers import R0, SP, ArmRegister
7 7
8
9 def encode_imm32(v):
10 """ Bundle 32 bit value into 4 bits rotation and 8 bits value
11 """
12 for i in range(0, 16):
13 v2 = rotate_left(v, i*2)
14 if (v2 & 0xFFFFFF00) == 0:
15 rotation = i
16 val = v2 & 0xFF
17 x = (rotation << 8) | val
18 return x
19 raise Exception("Invalid value {}".format(v))
8 20
9 # Instructions: 21 # Instructions:
10 22
11 class ArmInstruction(Instruction): 23 class ArmInstruction(Instruction):
12 def __init__(self): 24 def __init__(self):
13 self.token = ArmToken() 25 self.token = ArmToken()
14 26
15 27
16 class Mov(ArmInstruction): 28 class Dcd(ArmInstruction):
29 def __init__(self, v):
30 super().__init__()
31 self.v = v
32
33 def encode(self):
34 self.token[0:32] = self.v
35 return self.token.encode()
36
37
38 def Mov(*args):
39 if len(args) == 2:
40 if isinstance(args[1], int):
41 return Mov1(*args)
42 elif isinstance(args[1], ArmRegister):
43 return Mov2(*args)
44 raise Exception()
45
46
47 class Mov1(ArmInstruction):
17 """ Mov Rd, imm16 """ 48 """ Mov Rd, imm16 """
18 def __init__(self, reg, imm): 49 def __init__(self, reg, imm):
19 super().__init__() 50 super().__init__()
51 assert type(imm) is int
20 self.reg = reg 52 self.reg = reg
21 self.imm = imm 53 self.imm = imm
22 54
23 def encode(self): 55 def encode(self):
24 self.token[0:12] = self.imm 56 self.token[0:12] = encode_imm32(self.imm)
25 self.token[12:16] = self.reg.num 57 self.token.Rd = self.reg.num
26 self.token[16:20] = 0 58 self.token[16:20] = 0
27 self.token[20] = 0 59 self.token[20] = 0 # Set flags
28 self.token[21:28] = 0b0011101 60 self.token[21:28] = 0b0011101
29 self.token.cond = 0xE # Always! 61 self.token.cond = AL
30 return self.token.encode() 62 return self.token.encode()
31 63
32 def relocations(self): 64 def relocations(self):
33 return [] 65 return []
34 66
35 def __repr__(self): 67 def __repr__(self):
36 return 'DCD 0x{0:X}'.format(self.expr) 68 return 'Mov {}, {}'.format(self.reg, self.imm)
37 69
70
71 class Mov2(ArmInstruction):
72 def __init__(self, rd, rm):
73 super().__init__()
74 self.rd = rd
75 self.rm = rm
76
77 def encode(self):
78 self.token[0:4] = self.rm.num
79 self.token[4:12] = 0
80 self.token[12:16] = self.rd.num
81 self.token[16:20] = 0
82 self.token.S = 0
83 self.token[21:28] = 0xD
84 self.token.cond = AL
85 return self.token.encode()
86
87
88 def Add(*args):
89 if len(args) == 3 and isinstance(args[0], ArmRegister) and \
90 isinstance(args[1], ArmRegister):
91 if isinstance(args[2], ArmRegister):
92 return Add1(args[0], args[1], args[2])
93 elif isinstance(args[2], int):
94 return Add2(args[0], args[1], args[2])
95 raise Exception()
96
97 def Sub(*args):
98 if len(args) == 3 and isinstance(args[0], ArmRegister) and \
99 isinstance(args[1], ArmRegister):
100 if isinstance(args[2], ArmRegister):
101 return Sub1(args[0], args[1], args[2])
102 elif isinstance(args[2], int):
103 return Sub2(args[0], args[1], args[2])
104 raise Exception()
105
106 def Mul(*args):
107 return Mul1(args[0], args[1], args[2])
108
109
110 class Mul(ArmInstruction):
111 def __init__(self, rd, rn, rm):
112 super().__init__()
113 self.rd = rd
114 self.rn = rn
115 self.rm = rm
116
117 def encode(self):
118 self.token[0:4] = self.rn.num
119 self.token[4:8] = 0b1001
120 self.token[8:12] = self.rm.num
121 self.token[16:20] = self.rd.num
122 self.token.S = 0
123 self.token.cond = AL
124 return self.token.encode()
125
126
127 class OpRegRegReg(ArmInstruction):
128 """ add rd, rn, rm """
129 def __init__(self, rd, rn, rm, shift=0):
130 super().__init__()
131 self.rd = rd
132 self.rn = rn
133 self.rm = rm
134
135 def encode(self):
136 self.token[0:4] = self.rm.num
137 self.token[4] = 0
138 self.token[5:7] = 0
139 self.token[7:12] = 0 # Shift
140 self.token.Rd = self.rd.num
141 self.token.Rn = self.rn.num
142 self.token.S = 0 # Set flags
143 self.token[21:28] = self.opcode
144 self.token.cond = 0xE # Always!
145 return self.token.encode()
146
147 def __repr__(self):
148 return 'add {}, {}, {}'.format(self.rd, self.rn, self.rm)
149
150
151 class Add1(OpRegRegReg):
152 opcode = 0b0000100
153
154
155 class Sub1(OpRegRegReg):
156 opcode = 0b0000010
157
158
159 class Orr1(OpRegRegReg):
160 opcode = 0b0001100
161
162
163 class OpRegRegImm(ArmInstruction):
164 """ add rd, rn, imm12 """
165 def __init__(self, rd, rn, imm):
166 super().__init__()
167 self.rd = rd
168 self.rn = rn
169 self.imm2 = encode_imm32(imm)
170 self.imm = imm
171
172 def encode(self):
173 self.token[0:12] = self.imm2
174 self.token.Rd = self.rd.num
175 self.token.Rn = self.rn.num
176 self.token.S = 0 # Set flags
177 self.token[21:28] = self.opcode
178 self.token.cond = 0xE # Always!
179 return self.token.encode()
180
181 def __repr__(self):
182 return 'add {}, {}, {}'.format(self.rd, self.rn, self.imm)
183
184
185 class Add2(OpRegRegImm):
186 opcode = 0b0010100
187
188
189 class Sub2(OpRegRegImm):
190 opcode = 0b0010010
191
192
193
194 # Branches:
195
196 class BranchBaseRoot(ArmInstruction):
197 def __init__(self, target):
198 super().__init__()
199 self.target = target
200
201 def encode(self):
202 self.token.cond = self.cond
203 self.token[24:28] = self.opcode
204 return self.token.encode()
205
206 def relocations(self):
207 return [(self.target, 'b_imm24')]
208
209
210 EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL = range(15)
211
212 class BranchBase(BranchBaseRoot):
213 opcode = 0b1010
214
215 class BranchLinkBase(BranchBaseRoot):
216 opcode = 0b1011
217
218 class Bl(BranchLinkBase):
219 cond = AL
220
221 class B(BranchBase):
222 cond = AL
223
224 class Beq(BranchBase):
225 cond = EQ
226
227 class Bgt(BranchBase):
228 cond = GT
229
230 class Ble(BranchBase):
231 cond = LE
232
233 class Blt(BranchBase):
234 cond = LT
235
236
237 # Memory:
238
239 def reg_list_to_mask(reg_list):
240 mask = 0
241 for reg in reg_list:
242 mask |= (1 << reg.num)
243 return mask
244
245
246 class Push(ArmInstruction):
247 def __init__(self, register_set):
248 super().__init__()
249 self.reg_list = register_set
250
251 def encode(self):
252 self.token.cond = AL
253 self.token[16:28] = 0b100100101101
254 reg_list = 0
255 self.token[0:16] = reg_list_to_mask(self.reg_list)
256 return self.token.encode()
257
258 class Pop(ArmInstruction):
259 def __init__(self, register_set):
260 super().__init__()
261 self.reg_list = register_set
262
263 def encode(self):
264 self.token.cond = AL
265 self.token[16:28] = 0b100010111101
266 self.token[0:16] = reg_list_to_mask(self.reg_list)
267 return self.token.encode()
268
269
270 def Ldr(*args):
271 if len(args) == 3 and isinstance(args[1], ArmRegister):
272 return Ldr1(*args)
273 elif len(args) == 2 and isinstance(args[1], ArmRegister):
274 return Ldr1(args[0], args[1], 0)
275 raise Exception()
276
277 def Str(*args):
278 if len(args) == 3 and isinstance(args[1], ArmRegister):
279 return Str1(*args)
280 elif len(args) == 2 and isinstance(args[1], ArmRegister):
281 return Str1(args[0], args[1], 0)
282 raise Exception()
283
284
285 class LdrStrBase(ArmInstruction):
286 def __init__(self, rt, rn, offset):
287 super().__init__()
288 self.rt = rt
289 self.rn = rn
290 self.offset = offset
291
292 def encode(self):
293 self.token.cond = AL
294 self.token.Rn = self.rn.num
295 self.token[25:28] = self.opcode
296 self.token[20] = self.bit20
297 self.token[12:16] = self.rt.num
298 self.token[24] = 1 # Index
299 if self.offset >= 0:
300 self.token[23] = 1 # U == 1 'add'
301 self.token[0:12] = self.offset
302 else:
303 self.token[23] = 0
304 self.token[0:12] = -self.offset
305 return self.token.encode()
306
307
308 class Str1(LdrStrBase):
309 opcode = 0b010
310 bit20 = 0
311
312
313 class Ldr1(LdrStrBase):
314 opcode = 0b010
315 bit20 = 1
316
317
318 class Ldr3(ArmInstruction):
319 """ Load PC relative constant value """
320 def __init__(self, rt, label):
321 self.rt = rt
322 self.label = label
323