Mercurial > lcfOS
comparison python/ppci/target/arm/instructions.py @ 345:b4882ff0ed06
Added more arm isa tests
author | Windel Bouwman |
---|---|
date | Sun, 02 Mar 2014 17:12:08 +0100 |
parents | 86b02c98a717 |
children | 3bb7dcfe5529 |
comparison
equal
deleted
inserted
replaced
344:1378c4b027a0 | 345:b4882ff0ed06 |
---|---|
1 | 1 |
2 | 2 |
3 from ..basetarget import Instruction | 3 from ..basetarget import Instruction |
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 # 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) | |
20 | |
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)) | |
8 | 41 |
9 # Instructions: | 42 # Instructions: |
10 | 43 |
11 class ArmInstruction(Instruction): | 44 class ArmInstruction(Instruction): |
12 def __init__(self): | 45 def __init__(self): |
20 self.reg = reg | 53 self.reg = reg |
21 self.imm = imm | 54 self.imm = imm |
22 | 55 |
23 def encode(self): | 56 def encode(self): |
24 self.token[0:12] = self.imm | 57 self.token[0:12] = self.imm |
25 self.token[12:16] = self.reg.num | 58 self.token.Rd = self.reg.num |
26 self.token[16:20] = 0 | 59 self.token[16:20] = 0 |
27 self.token[20] = 0 | 60 self.token[20] = 0 |
28 self.token[21:28] = 0b0011101 | 61 self.token[21:28] = 0b0011101 |
29 self.token.cond = 0xE # Always! | 62 self.token.cond = 0xE # Always! |
30 return self.token.encode() | 63 return self.token.encode() |
31 | 64 |
32 def relocations(self): | 65 def relocations(self): |
33 return [] | 66 return [] |
34 | 67 |
35 def __repr__(self): | 68 def __repr__(self): |
36 return 'DCD 0x{0:X}'.format(self.expr) | 69 return 'Mov {}, {}'.format(self.reg, self.imm) |
37 | 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 | |
125 | |
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 |