342
|
1
|
|
2
|
|
3 from ..basetarget import Instruction
|
|
4
|
|
5 from .token import ArmToken
|
345
|
6 from .registers import R0, SP, ArmRegister
|
|
7
|
|
8 # Helpers:
|
|
9
|
|
10 def rotate_right(v, n):
|
|
11 """ bit-wise Rotate right n times """
|
|
12 mask = (2**n) - 1
|
|
13 mask_bits = v & mask
|
|
14 return (v >> n) | (mask_bits << (32 - n))
|
|
15
|
|
16 def rotate_left(v, n):
|
|
17 assert n >= 0
|
|
18 assert n < 32
|
|
19 return rotate_right(v, 32 - n)
|
342
|
20
|
345
|
21 masks = [rotate_right(0xFF, i * 2) for i in range(16)]
|
|
22 #0x000000FF,
|
|
23 #0xC000007F,
|
|
24 #0xF000000F,
|
|
25 #0xFC000003,
|
|
26 #0xFF000000, # 4
|
|
27
|
|
28 assert masks[4] == 0xFF000000, hex(masks[4])
|
|
29
|
|
30 def encode_imm32(v):
|
|
31 """ Bundle 32 bit value into 4 bits rotation and 8 bits value
|
|
32 """
|
|
33 for i in range(0, 16):
|
|
34 v2 = rotate_left(v, i*2)
|
|
35 if (v2 & 0xFFFFFF00) == 0:
|
|
36 rotation = i
|
|
37 val = v2 & 0xFF
|
|
38 x = (rotation << 8) | val
|
|
39 return x
|
|
40 raise Exception("Invalid value {}".format(v))
|
342
|
41
|
|
42 # Instructions:
|
|
43
|
|
44 class ArmInstruction(Instruction):
|
|
45 def __init__(self):
|
|
46 self.token = ArmToken()
|
|
47
|
|
48
|
|
49 class Mov(ArmInstruction):
|
|
50 """ Mov Rd, imm16 """
|
|
51 def __init__(self, reg, imm):
|
|
52 super().__init__()
|
|
53 self.reg = reg
|
|
54 self.imm = imm
|
|
55
|
|
56 def encode(self):
|
|
57 self.token[0:12] = self.imm
|
345
|
58 self.token.Rd = self.reg.num
|
342
|
59 self.token[16:20] = 0
|
|
60 self.token[20] = 0
|
|
61 self.token[21:28] = 0b0011101
|
|
62 self.token.cond = 0xE # Always!
|
|
63 return self.token.encode()
|
|
64
|
|
65 def relocations(self):
|
|
66 return []
|
|
67
|
|
68 def __repr__(self):
|
345
|
69 return 'Mov {}, {}'.format(self.reg, self.imm)
|
|
70
|
|
71
|
|
72 def Add(*args):
|
|
73 if len(args) == 3 and isinstance(args[0], ArmRegister) and \
|
|
74 isinstance(args[1], ArmRegister):
|
|
75 if isinstance(args[2], ArmRegister):
|
|
76 return Add1(args[0], args[1], args[2])
|
|
77 elif isinstance(args[2], int):
|
|
78 return Add2(args[0], args[1], args[2])
|
|
79 raise Exception()
|
|
80
|
|
81 def Sub(*args):
|
|
82 if len(args) == 3 and isinstance(args[0], ArmRegister) and \
|
|
83 isinstance(args[1], ArmRegister):
|
|
84 if isinstance(args[2], ArmRegister):
|
|
85 return Sub1(args[0], args[1], args[2])
|
|
86 elif isinstance(args[2], int):
|
|
87 return Sub2(args[0], args[1], args[2])
|
|
88 raise Exception()
|
|
89
|
|
90 class OpRegRegReg(ArmInstruction):
|
|
91 """ add rd, rn, rm """
|
|
92 def __init__(self, rd, rn, rm, shift=0):
|
|
93 super().__init__()
|
|
94 self.rd = rd
|
|
95 self.rn = rn
|
|
96 self.rm = rm
|
|
97
|
|
98 def encode(self):
|
|
99 self.token[0:4] = self.rm.num
|
|
100 self.token[4] = 0
|
|
101 self.token[5:7] = 0
|
|
102 self.token[7:12] = 0 # Shift
|
|
103 self.token.Rd = self.rd.num
|
|
104 self.token.Rn = self.rn.num
|
|
105 self.token.S = 0 # Set flags
|
|
106 self.token[21:28] = self.opcode
|
|
107 self.token.cond = 0xE # Always!
|
|
108 return self.token.encode()
|
|
109
|
|
110 def __repr__(self):
|
|
111 return 'add {}, {}, {}'.format(self.rd, self.rn, self.rm)
|
|
112
|
|
113
|
|
114 class Add1(OpRegRegReg):
|
|
115 opcode = 0b0000100
|
|
116
|
|
117
|
|
118 class Sub1(OpRegRegReg):
|
|
119 opcode = 0b0000010
|
|
120
|
|
121
|
|
122 class Orr1(OpRegRegReg):
|
|
123 opcode = 0b0001100
|
|
124
|
342
|
125
|
345
|
126 class OpRegRegImm(ArmInstruction):
|
|
127 """ add rd, rn, imm12 """
|
|
128 def __init__(self, rd, rn, imm):
|
|
129 super().__init__()
|
|
130 self.rd = rd
|
|
131 self.rn = rn
|
|
132 self.imm2 = encode_imm32(imm)
|
|
133 self.imm = imm
|
|
134
|
|
135 def encode(self):
|
|
136 self.token[0:12] = self.imm2
|
|
137 self.token.Rd = self.rd.num
|
|
138 self.token.Rn = self.rn.num
|
|
139 self.token.S = 0 # Set flags
|
|
140 self.token[21:28] = self.opcode
|
|
141 self.token.cond = 0xE # Always!
|
|
142 return self.token.encode()
|
|
143
|
|
144 def __repr__(self):
|
|
145 return 'add {}, {}, {}'.format(self.rd, self.rn, self.imm)
|
|
146
|
|
147
|
|
148 class Add2(OpRegRegImm):
|
|
149 opcode = 0b0010100
|
|
150
|
|
151
|
|
152 class Sub2(OpRegRegImm):
|
|
153 opcode = 0b0010010
|
|
154
|
|
155
|
|
156
|
|
157 # Branches:
|
|
158
|
|
159 class BranchBaseRoot(ArmInstruction):
|
|
160 def __init__(self, target):
|
|
161 super().__init__()
|
|
162 self.target = target
|
|
163
|
|
164 def encode(self):
|
|
165 self.token.cond = self.cond
|
|
166 self.token[24:28] = self.opcode
|
|
167 return self.token.encode()
|
|
168
|
|
169 def relocations(self):
|
|
170 return [(self.target, 'b_imm24')]
|
|
171
|
|
172
|
|
173 class BranchBase(BranchBaseRoot):
|
|
174 opcode = 0b1010
|
|
175
|
|
176 class BranchLinkBase(BranchBaseRoot):
|
|
177 opcode = 0b1011
|
|
178
|
|
179 class Bl(BranchLinkBase):
|
|
180 cond = 0xE
|
|
181
|
|
182 class B(BranchBase):
|
|
183 cond = 0xE
|
|
184
|
|
185 class Beq(BranchBase):
|
|
186 cond = 0x0
|
|
187
|
|
188 class Bgt(BranchBase):
|
|
189 cond = 0xC
|
|
190
|
|
191 class Ble(BranchBase):
|
|
192 cond = 0xD
|
|
193
|
|
194
|