1 //===-- ARMUtils.h ----------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef lldb_ARMUtils_h_
11 #define lldb_ARMUtils_h_
12
13 #include "ARMDefines.h"
14 #include "InstructionUtils.h"
15 #include "llvm/Support/MathExtras.h" // for SignExtend64 template function
16
17 // Common utilities for the ARM/Thumb Instruction Set Architecture.
18
19 namespace lldb_private {
20
Align(uint32_t val,uint32_t alignment)21 static inline uint32_t Align(uint32_t val, uint32_t alignment)
22 {
23 return alignment * (val / alignment);
24 }
25
DecodeImmShift(const uint32_t type,const uint32_t imm5,ARM_ShifterType & shift_t)26 static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t)
27 {
28 switch (type)
29 {
30 default:
31 //assert(0 && "Invalid shift type");
32 case 0:
33 shift_t = SRType_LSL;
34 return imm5;
35 case 1:
36 shift_t = SRType_LSR;
37 return (imm5 == 0 ? 32 : imm5);
38 case 2:
39 shift_t = SRType_ASR;
40 return (imm5 == 0 ? 32 : imm5);
41 case 3:
42 if (imm5 == 0)
43 {
44 shift_t = SRType_RRX;
45 return 1;
46 }
47 else
48 {
49 shift_t = SRType_ROR;
50 return imm5;
51 }
52 }
53 shift_t = SRType_Invalid;
54 return UINT32_MAX;
55
56 }
57
58 // A8.6.35 CMP (register) -- Encoding T3
59 // Convenience function.
DecodeImmShiftThumb(const uint32_t opcode,ARM_ShifterType & shift_t)60 static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode, ARM_ShifterType &shift_t)
61 {
62 return DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
63 }
64
65 // A8.6.35 CMP (register) -- Encoding A1
66 // Convenience function.
DecodeImmShiftARM(const uint32_t opcode,ARM_ShifterType & shift_t)67 static inline uint32_t DecodeImmShiftARM(const uint32_t opcode, ARM_ShifterType &shift_t)
68 {
69 return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
70 }
71
DecodeImmShift(const ARM_ShifterType shift_t,const uint32_t imm5)72 static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t, const uint32_t imm5)
73 {
74 ARM_ShifterType dont_care;
75 return DecodeImmShift(shift_t, imm5, dont_care);
76 }
77
DecodeRegShift(const uint32_t type)78 static inline ARM_ShifterType DecodeRegShift(const uint32_t type)
79 {
80 switch (type) {
81 default:
82 //assert(0 && "Invalid shift type");
83 return SRType_Invalid;
84 case 0:
85 return SRType_LSL;
86 case 1:
87 return SRType_LSR;
88 case 2:
89 return SRType_ASR;
90 case 3:
91 return SRType_ROR;
92 }
93 }
94
LSL_C(const uint32_t value,const uint32_t amount,uint32_t & carry_out,bool * success)95 static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
96 {
97 if (amount == 0) {
98 *success = false;
99 return 0;
100 }
101 *success = true;
102 carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0;
103 return value << amount;
104 }
105
LSL(const uint32_t value,const uint32_t amount,bool * success)106 static inline uint32_t LSL(const uint32_t value, const uint32_t amount, bool *success)
107 {
108 *success = true;
109 if (amount == 0)
110 return value;
111 uint32_t dont_care;
112 uint32_t result = LSL_C(value, amount, dont_care, success);
113 if (*success)
114 return result;
115 else
116 return 0;
117 }
118
LSR_C(const uint32_t value,const uint32_t amount,uint32_t & carry_out,bool * success)119 static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
120 {
121 if (amount == 0) {
122 *success = false;
123 return 0;
124 }
125 *success = true;
126 carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0;
127 return value >> amount;
128 }
129
LSR(const uint32_t value,const uint32_t amount,bool * success)130 static inline uint32_t LSR(const uint32_t value, const uint32_t amount, bool *success)
131 {
132 *success = true;
133 if (amount == 0)
134 return value;
135 uint32_t dont_care;
136 uint32_t result = LSR_C(value, amount, dont_care, success);
137 if (*success)
138 return result;
139 else
140 return 0;
141 }
142
ASR_C(const uint32_t value,const uint32_t amount,uint32_t & carry_out,bool * success)143 static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
144 {
145 if (amount == 0 || amount > 32) {
146 *success = false;
147 return 0;
148 }
149 *success = true;
150 bool negative = BitIsSet(value, 31);
151 if (amount <= 32)
152 {
153 carry_out = Bit32(value, amount - 1);
154 int64_t extended = llvm::SignExtend64<32>(value);
155 return UnsignedBits(extended, amount + 31, amount);
156 }
157 else
158 {
159 carry_out = (negative ? 1 : 0);
160 return (negative ? 0xffffffff : 0);
161 }
162 }
163
ASR(const uint32_t value,const uint32_t amount,bool * success)164 static inline uint32_t ASR(const uint32_t value, const uint32_t amount, bool *success)
165 {
166 *success = true;
167 if (amount == 0)
168 return value;
169 uint32_t dont_care;
170 uint32_t result = ASR_C(value, amount, dont_care, success);
171 if (*success)
172 return result;
173 else
174 return 0;
175 }
176
ROR_C(const uint32_t value,const uint32_t amount,uint32_t & carry_out,bool * success)177 static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
178 {
179 if (amount == 0) {
180 *success = false;
181 return 0;
182 }
183 *success = true;
184 uint32_t amt = amount % 32;
185 uint32_t result = Rotr32(value, amt);
186 carry_out = Bit32(value, 31);
187 return result;
188 }
189
ROR(const uint32_t value,const uint32_t amount,bool * success)190 static inline uint32_t ROR(const uint32_t value, const uint32_t amount, bool *success)
191 {
192 *success = true;
193 if (amount == 0)
194 return value;
195 uint32_t dont_care;
196 uint32_t result = ROR_C(value, amount, dont_care, success);
197 if (*success)
198 return result;
199 else
200 return 0;
201 }
202
RRX_C(const uint32_t value,const uint32_t carry_in,uint32_t & carry_out,bool * success)203 static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in, uint32_t &carry_out, bool *success)
204 {
205 *success = true;
206 carry_out = Bit32(value, 0);
207 return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1);
208 }
209
RRX(const uint32_t value,const uint32_t carry_in,bool * success)210 static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, bool *success)
211 {
212 *success = true;
213 uint32_t dont_care;
214 uint32_t result = RRX_C(value, carry_in, dont_care, success);
215 if (*success)
216 return result;
217 else
218 return 0;
219 }
220
Shift_C(const uint32_t value,ARM_ShifterType type,const uint32_t amount,const uint32_t carry_in,uint32_t & carry_out,bool * success)221 static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
222 const uint32_t carry_in, uint32_t &carry_out, bool *success)
223 {
224 if (type == SRType_RRX && amount != 1) {
225 *success = false;
226 return 0;
227 }
228 *success = true;
229
230 if (amount == 0) {
231 carry_out = carry_in;
232 return value;
233 }
234 uint32_t result;
235 switch (type) {
236 case SRType_LSL:
237 result = LSL_C(value, amount, carry_out, success);
238 break;
239 case SRType_LSR:
240 result = LSR_C(value, amount, carry_out, success);
241 break;
242 case SRType_ASR:
243 result = ASR_C(value, amount, carry_out, success);
244 break;
245 case SRType_ROR:
246 result = ROR_C(value, amount, carry_out, success);
247 break;
248 case SRType_RRX:
249 result = RRX_C(value, carry_in, carry_out, success);
250 break;
251 default:
252 *success = false;
253 break;
254 }
255 if (*success)
256 return result;
257 else
258 return 0;
259 }
260
Shift(const uint32_t value,ARM_ShifterType type,const uint32_t amount,const uint32_t carry_in,bool * success)261 static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
262 const uint32_t carry_in, bool *success)
263 {
264 // Don't care about carry out in this case.
265 uint32_t dont_care;
266 uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success);
267 if (*success)
268 return result;
269 else
270 return 0;
271 }
272
bits(const uint32_t val,const uint32_t msbit,const uint32_t lsbit)273 static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
274 {
275 return Bits32(val, msbit, lsbit);
276 }
277
bit(const uint32_t val,const uint32_t msbit)278 static inline uint32_t bit(const uint32_t val, const uint32_t msbit)
279 {
280 return bits(val, msbit, msbit);
281 }
282
ror(uint32_t val,uint32_t N,uint32_t shift)283 static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift)
284 {
285 uint32_t m = shift % N;
286 return (val >> m) | (val << (N - m));
287 }
288
289 // (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)
ARMExpandImm_C(uint32_t opcode,uint32_t carry_in,uint32_t & carry_out)290 static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
291 {
292 uint32_t imm32; // the expanded result
293 uint32_t imm = bits(opcode, 7, 0); // immediate value
294 uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount
295 if (amt == 0)
296 {
297 imm32 = imm;
298 carry_out = carry_in;
299 }
300 else
301 {
302 imm32 = ror(imm, 32, amt);
303 carry_out = Bit32(imm32, 31);
304 }
305 return imm32;
306 }
307
ARMExpandImm(uint32_t opcode)308 static inline uint32_t ARMExpandImm(uint32_t opcode)
309 {
310 // 'carry_in' argument to following function call does not affect the imm32 result.
311 uint32_t carry_in = 0;
312 uint32_t carry_out;
313 return ARMExpandImm_C(opcode, carry_in, carry_out);
314 }
315
316 // (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
ThumbExpandImm_C(uint32_t opcode,uint32_t carry_in,uint32_t & carry_out)317 static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
318 {
319 uint32_t imm32; // the expaned result
320 const uint32_t i = bit(opcode, 26);
321 const uint32_t imm3 = bits(opcode, 14, 12);
322 const uint32_t abcdefgh = bits(opcode, 7, 0);
323 const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;
324
325 if (bits(imm12, 11, 10) == 0)
326 {
327 switch (bits(imm12, 9, 8)) {
328 default: // Keep static analyzer happy with a default case
329 case 0:
330 imm32 = abcdefgh;
331 break;
332
333 case 1:
334 imm32 = abcdefgh << 16 | abcdefgh;
335 break;
336
337 case 2:
338 imm32 = abcdefgh << 24 | abcdefgh << 8;
339 break;
340
341 case 3:
342 imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh;
343 break;
344 }
345 carry_out = carry_in;
346 }
347 else
348 {
349 const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0);
350 imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7));
351 carry_out = Bit32(imm32, 31);
352 }
353 return imm32;
354 }
355
ThumbExpandImm(uint32_t opcode)356 static inline uint32_t ThumbExpandImm(uint32_t opcode)
357 {
358 // 'carry_in' argument to following function call does not affect the imm32 result.
359 uint32_t carry_in = 0;
360 uint32_t carry_out;
361 return ThumbExpandImm_C(opcode, carry_in, carry_out);
362 }
363
364 // imm32 = ZeroExtend(i:imm3:imm8, 32)
ThumbImm12(uint32_t opcode)365 static inline uint32_t ThumbImm12(uint32_t opcode)
366 {
367 const uint32_t i = bit(opcode, 26);
368 const uint32_t imm3 = bits(opcode, 14, 12);
369 const uint32_t imm8 = bits(opcode, 7, 0);
370 const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;
371 return imm12;
372 }
373
374 // imm32 = ZeroExtend(imm7:'00', 32)
ThumbImm7Scaled(uint32_t opcode)375 static inline uint32_t ThumbImm7Scaled(uint32_t opcode)
376 {
377 const uint32_t imm7 = bits(opcode, 6, 0);
378 return imm7 * 4;
379 }
380
381 // imm32 = ZeroExtend(imm8:'00', 32)
ThumbImm8Scaled(uint32_t opcode)382 static inline uint32_t ThumbImm8Scaled(uint32_t opcode)
383 {
384 const uint32_t imm8 = bits(opcode, 7, 0);
385 return imm8 * 4;
386 }
387
388 // This function performs the check for the register numbers 13 and 15 that are
389 // not permitted for many Thumb register specifiers.
BadReg(uint32_t n)390 static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
391
392 } // namespace lldb_private
393
394 #endif // lldb_ARMUtils_h_
395