blob: b6ba3fea6928417e5f5785f79ccd50d230ba1e07 [file] [log] [blame]
Greg Clayton7349bd92011-05-09 20:18:18 +00001//===-- ARMUtils.h ----------------------------------------------*- C++ -*-===//
Johnny Chen91027002011-01-24 18:24:53 +00002//
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
Johnny Chen22deaa52011-02-16 01:27:54 +000013#include "ARMDefines.h"
Johnny Chen74889b22011-01-26 01:00:55 +000014#include "InstructionUtils.h"
Johnny Chen7a03c852011-02-15 17:52:22 +000015#include "llvm/Support/MathExtras.h" // for SignExtend64 template function
Johnny Chen74889b22011-01-26 01:00:55 +000016
Johnny Chen44a40842011-01-24 19:50:30 +000017// Common utilities for the ARM/Thumb Instruction Set Architecture.
Johnny Chen91027002011-01-24 18:24:53 +000018
19namespace lldb_private {
20
Johnny Chen0f605742011-02-17 17:31:08 +000021static inline uint32_t Align(uint32_t val, uint32_t alignment)
22{
23 return alignment * (val / alignment);
24}
25
Johnny Chen7a03c852011-02-15 17:52:22 +000026static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t)
27{
Greg Clayton23f59502012-07-17 03:23:13 +000028 switch (type)
29 {
Johnny Chen7a03c852011-02-15 17:52:22 +000030 default:
Greg Clayton850cc892011-06-02 22:23:35 +000031 //assert(0 && "Invalid shift type");
Johnny Chen7a03c852011-02-15 17:52:22 +000032 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 }
Greg Clayton23f59502012-07-17 03:23:13 +000053 shift_t = SRType_Invalid;
54 return UINT32_MAX;
55
Johnny Chen7a03c852011-02-15 17:52:22 +000056}
57
Johnny Chen5f88bcc2011-02-22 21:17:52 +000058// A8.6.35 CMP (register) -- Encoding T3
59// Convenience function.
60static 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.
67static 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
Johnny Chena4afff92011-02-15 20:10:55 +000072static 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
Johnny Chen7a03c852011-02-15 17:52:22 +000078static inline ARM_ShifterType DecodeRegShift(const uint32_t type)
79{
80 switch (type) {
81 default:
Greg Clayton850cc892011-06-02 22:23:35 +000082 //assert(0 && "Invalid shift type");
83 return SRType_Invalid;
Johnny Chen7a03c852011-02-15 17:52:22 +000084 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
Johnny Chen6ef27352011-06-02 22:50:51 +000095static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +000096{
Johnny Chen6ef27352011-06-02 22:50:51 +000097 if (amount == 0) {
98 *success = false;
99 return 0;
100 }
101 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000102 carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000103 return value << amount;
104}
105
Johnny Chen6ef27352011-06-02 22:50:51 +0000106static inline uint32_t LSL(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000107{
Johnny Chen6ef27352011-06-02 22:50:51 +0000108 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000109 if (amount == 0)
110 return value;
111 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000112 uint32_t result = LSL_C(value, amount, dont_care, success);
113 if (*success)
114 return result;
115 else
116 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000117}
118
Johnny Chen6ef27352011-06-02 22:50:51 +0000119static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000120{
Johnny Chen6ef27352011-06-02 22:50:51 +0000121 if (amount == 0) {
122 *success = false;
123 return 0;
124 }
125 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000126 carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000127 return value >> amount;
128}
129
Johnny Chen6ef27352011-06-02 22:50:51 +0000130static inline uint32_t LSR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000131{
Johnny Chen6ef27352011-06-02 22:50:51 +0000132 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000133 if (amount == 0)
134 return value;
135 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000136 uint32_t result = LSR_C(value, amount, dont_care, success);
137 if (*success)
138 return result;
139 else
140 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000141}
142
Johnny Chen6ef27352011-06-02 22:50:51 +0000143static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000144{
Johnny Chen6ef27352011-06-02 22:50:51 +0000145 if (amount == 0 || amount > 32) {
146 *success = false;
147 return 0;
148 }
149 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000150 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 }
Johnny Chen7a03c852011-02-15 17:52:22 +0000162}
163
Johnny Chen6ef27352011-06-02 22:50:51 +0000164static inline uint32_t ASR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000165{
Johnny Chen6ef27352011-06-02 22:50:51 +0000166 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000167 if (amount == 0)
168 return value;
169 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000170 uint32_t result = ASR_C(value, amount, dont_care, success);
171 if (*success)
172 return result;
173 else
174 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000175}
176
Johnny Chen6ef27352011-06-02 22:50:51 +0000177static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000178{
Johnny Chen6ef27352011-06-02 22:50:51 +0000179 if (amount == 0) {
180 *success = false;
181 return 0;
182 }
183 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000184 uint32_t amt = amount % 32;
185 uint32_t result = Rotr32(value, amt);
Johnny Chen7a03c852011-02-15 17:52:22 +0000186 carry_out = Bit32(value, 31);
187 return result;
188}
189
Johnny Chen6ef27352011-06-02 22:50:51 +0000190static inline uint32_t ROR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000191{
Johnny Chen6ef27352011-06-02 22:50:51 +0000192 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000193 if (amount == 0)
194 return value;
195 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000196 uint32_t result = ROR_C(value, amount, dont_care, success);
197 if (*success)
198 return result;
199 else
200 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000201}
202
Johnny Chen6ef27352011-06-02 22:50:51 +0000203static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000204{
Johnny Chen6ef27352011-06-02 22:50:51 +0000205 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000206 carry_out = Bit32(value, 0);
207 return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1);
208}
209
Johnny Chen6ef27352011-06-02 22:50:51 +0000210static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000211{
Johnny Chen6ef27352011-06-02 22:50:51 +0000212 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000213 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000214 uint32_t result = RRX_C(value, carry_in, dont_care, success);
215 if (*success)
216 return result;
217 else
218 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000219}
220
221static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
Johnny Chen6ef27352011-06-02 22:50:51 +0000222 const uint32_t carry_in, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000223{
Johnny Chen6ef27352011-06-02 22:50:51 +0000224 if (type == SRType_RRX && amount != 1) {
225 *success = false;
226 return 0;
227 }
228 *success = true;
229
230 if (amount == 0) {
Johnny Chen7a03c852011-02-15 17:52:22 +0000231 carry_out = carry_in;
232 return value;
233 }
234 uint32_t result;
235 switch (type) {
236 case SRType_LSL:
Johnny Chen6ef27352011-06-02 22:50:51 +0000237 result = LSL_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000238 break;
239 case SRType_LSR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000240 result = LSR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000241 break;
242 case SRType_ASR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000243 result = ASR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000244 break;
245 case SRType_ROR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000246 result = ROR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000247 break;
248 case SRType_RRX:
Johnny Chen6ef27352011-06-02 22:50:51 +0000249 result = RRX_C(value, carry_in, carry_out, success);
250 break;
251 default:
252 *success = false;
Johnny Chen7a03c852011-02-15 17:52:22 +0000253 break;
254 }
Johnny Chen6ef27352011-06-02 22:50:51 +0000255 if (*success)
256 return result;
257 else
258 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000259}
260
261static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
Johnny Chen6ef27352011-06-02 22:50:51 +0000262 const uint32_t carry_in, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000263{
264 // Don't care about carry out in this case.
265 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000266 uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success);
267 if (*success)
268 return result;
269 else
270 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000271}
272
Johnny Chenccc99632011-01-25 22:45:28 +0000273static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
274{
Johnny Chen74889b22011-01-26 01:00:55 +0000275 return Bits32(val, msbit, lsbit);
Johnny Chenccc99632011-01-25 22:45:28 +0000276}
277
278static inline uint32_t bit(const uint32_t val, const uint32_t msbit)
279{
280 return bits(val, msbit, msbit);
281}
282
Johnny Chend5cd6452011-01-25 23:49:39 +0000283static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift)
Johnny Chenccc99632011-01-25 22:45:28 +0000284{
Johnny Chend5cd6452011-01-25 23:49:39 +0000285 uint32_t m = shift % N;
286 return (val >> m) | (val << (N - m));
287}
288
Johnny Chene2b86a32011-02-14 19:08:41 +0000289// (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000290static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
Johnny Chene2b86a32011-02-14 19:08:41 +0000291{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000292 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
Johnny Chene2b86a32011-02-14 19:08:41 +0000295 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
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000308static inline uint32_t ARMExpandImm(uint32_t opcode)
Johnny Chend5cd6452011-01-25 23:49:39 +0000309{
Johnny Chene2b86a32011-02-14 19:08:41 +0000310 // 'carry_in' argument to following function call does not affect the imm32 result.
311 uint32_t carry_in = 0;
312 uint32_t carry_out;
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000313 return ARMExpandImm_C(opcode, carry_in, carry_out);
Johnny Chene2b86a32011-02-14 19:08:41 +0000314}
315
316// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000317static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
Johnny Chene2b86a32011-02-14 19:08:41 +0000318{
Bruce Mitcheneraaa0ba32014-07-08 18:05:41 +0000319 uint32_t imm32; // the expanded result
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000320 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);
Johnny Chene2b86a32011-02-14 19:08:41 +0000323 const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;
324
325 if (bits(imm12, 11, 10) == 0)
326 {
Caroline Tice466327d2011-03-24 21:11:26 +0000327 switch (bits(imm12, 9, 8)) {
Greg Clayton23f59502012-07-17 03:23:13 +0000328 default: // Keep static analyzer happy with a default case
Johnny Chene2b86a32011-02-14 19:08:41 +0000329 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;
Johnny Chenccc99632011-01-25 22:45:28 +0000354}
355
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000356static inline uint32_t ThumbExpandImm(uint32_t opcode)
Johnny Chenccc99632011-01-25 22:45:28 +0000357{
Johnny Chene2b86a32011-02-14 19:08:41 +0000358 // 'carry_in' argument to following function call does not affect the imm32 result.
359 uint32_t carry_in = 0;
360 uint32_t carry_out;
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000361 return ThumbExpandImm_C(opcode, carry_in, carry_out);
Johnny Chend5cd6452011-01-25 23:49:39 +0000362}
363
364// imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000365static inline uint32_t ThumbImm12(uint32_t opcode)
Johnny Chend5cd6452011-01-25 23:49:39 +0000366{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000367 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);
Johnny Chend5cd6452011-01-25 23:49:39 +0000370 const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;
371 return imm12;
Johnny Chenccc99632011-01-25 22:45:28 +0000372}
373
Johnny Chen3fde51b2011-01-26 00:08:59 +0000374// imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chend88d96c2011-02-23 21:24:25 +0000375static inline uint32_t ThumbImm7Scaled(uint32_t opcode)
Johnny Chen3fde51b2011-01-26 00:08:59 +0000376{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000377 const uint32_t imm7 = bits(opcode, 6, 0);
Johnny Chen3fde51b2011-01-26 00:08:59 +0000378 return imm7 * 4;
379}
380
Johnny Chend88d96c2011-02-23 21:24:25 +0000381// imm32 = ZeroExtend(imm8:'00', 32)
382static inline uint32_t ThumbImm8Scaled(uint32_t opcode)
383{
384 const uint32_t imm8 = bits(opcode, 7, 0);
385 return imm8 * 4;
386}
387
Johnny Chen91027002011-01-24 18:24:53 +0000388// This function performs the check for the register numbers 13 and 15 that are
389// not permitted for many Thumb register specifiers.
390static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
391
Johnny Chen91027002011-01-24 18:24:53 +0000392} // namespace lldb_private
393
394#endif // lldb_ARMUtils_h_