blob: fce066d91ffc1ed8415175d7e9d600b6e2b457a0 [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{
28 switch (type) {
29 default:
Greg Clayton850cc892011-06-02 22:23:35 +000030 //assert(0 && "Invalid shift type");
31 return UINT32_MAX;
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 }
53}
54
Johnny Chen5f88bcc2011-02-22 21:17:52 +000055// A8.6.35 CMP (register) -- Encoding T3
56// Convenience function.
57static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode, ARM_ShifterType &shift_t)
58{
59 return DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
60}
61
62// A8.6.35 CMP (register) -- Encoding A1
63// Convenience function.
64static inline uint32_t DecodeImmShiftARM(const uint32_t opcode, ARM_ShifterType &shift_t)
65{
66 return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
67}
68
Johnny Chena4afff92011-02-15 20:10:55 +000069static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t, const uint32_t imm5)
70{
71 ARM_ShifterType dont_care;
72 return DecodeImmShift(shift_t, imm5, dont_care);
73}
74
Johnny Chen7a03c852011-02-15 17:52:22 +000075static inline ARM_ShifterType DecodeRegShift(const uint32_t type)
76{
77 switch (type) {
78 default:
Greg Clayton850cc892011-06-02 22:23:35 +000079 //assert(0 && "Invalid shift type");
80 return SRType_Invalid;
Johnny Chen7a03c852011-02-15 17:52:22 +000081 case 0:
82 return SRType_LSL;
83 case 1:
84 return SRType_LSR;
85 case 2:
86 return SRType_ASR;
87 case 3:
88 return SRType_ROR;
89 }
90}
91
Johnny Chen6ef27352011-06-02 22:50:51 +000092static 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 +000093{
Johnny Chen6ef27352011-06-02 22:50:51 +000094 if (amount == 0) {
95 *success = false;
96 return 0;
97 }
98 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +000099 carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000100 return value << amount;
101}
102
Johnny Chen6ef27352011-06-02 22:50:51 +0000103static inline uint32_t LSL(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000104{
Johnny Chen6ef27352011-06-02 22:50:51 +0000105 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000106 if (amount == 0)
107 return value;
108 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000109 uint32_t result = LSL_C(value, amount, dont_care, success);
110 if (*success)
111 return result;
112 else
113 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000114}
115
Johnny Chen6ef27352011-06-02 22:50:51 +0000116static 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 +0000117{
Johnny Chen6ef27352011-06-02 22:50:51 +0000118 if (amount == 0) {
119 *success = false;
120 return 0;
121 }
122 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000123 carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000124 return value >> amount;
125}
126
Johnny Chen6ef27352011-06-02 22:50:51 +0000127static inline uint32_t LSR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000128{
Johnny Chen6ef27352011-06-02 22:50:51 +0000129 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000130 if (amount == 0)
131 return value;
132 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000133 uint32_t result = LSR_C(value, amount, dont_care, success);
134 if (*success)
135 return result;
136 else
137 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000138}
139
Johnny Chen6ef27352011-06-02 22:50:51 +0000140static 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 +0000141{
Johnny Chen6ef27352011-06-02 22:50:51 +0000142 if (amount == 0 || amount > 32) {
143 *success = false;
144 return 0;
145 }
146 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000147 bool negative = BitIsSet(value, 31);
148 if (amount <= 32)
149 {
150 carry_out = Bit32(value, amount - 1);
151 int64_t extended = llvm::SignExtend64<32>(value);
152 return UnsignedBits(extended, amount + 31, amount);
153 }
154 else
155 {
156 carry_out = (negative ? 1 : 0);
157 return (negative ? 0xffffffff : 0);
158 }
Johnny Chen7a03c852011-02-15 17:52:22 +0000159}
160
Johnny Chen6ef27352011-06-02 22:50:51 +0000161static inline uint32_t ASR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000162{
Johnny Chen6ef27352011-06-02 22:50:51 +0000163 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000164 if (amount == 0)
165 return value;
166 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000167 uint32_t result = ASR_C(value, amount, dont_care, success);
168 if (*success)
169 return result;
170 else
171 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000172}
173
Johnny Chen6ef27352011-06-02 22:50:51 +0000174static 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 +0000175{
Johnny Chen6ef27352011-06-02 22:50:51 +0000176 if (amount == 0) {
177 *success = false;
178 return 0;
179 }
180 *success = true;
Johnny Chenf35024b2011-02-15 22:21:33 +0000181 uint32_t amt = amount % 32;
182 uint32_t result = Rotr32(value, amt);
Johnny Chen7a03c852011-02-15 17:52:22 +0000183 carry_out = Bit32(value, 31);
184 return result;
185}
186
Johnny Chen6ef27352011-06-02 22:50:51 +0000187static inline uint32_t ROR(const uint32_t value, const uint32_t amount, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000188{
Johnny Chen6ef27352011-06-02 22:50:51 +0000189 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000190 if (amount == 0)
191 return value;
192 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000193 uint32_t result = ROR_C(value, amount, dont_care, success);
194 if (*success)
195 return result;
196 else
197 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000198}
199
Johnny Chen6ef27352011-06-02 22:50:51 +0000200static 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 +0000201{
Johnny Chen6ef27352011-06-02 22:50:51 +0000202 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000203 carry_out = Bit32(value, 0);
204 return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1);
205}
206
Johnny Chen6ef27352011-06-02 22:50:51 +0000207static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000208{
Johnny Chen6ef27352011-06-02 22:50:51 +0000209 *success = true;
Johnny Chen7a03c852011-02-15 17:52:22 +0000210 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000211 uint32_t result = RRX_C(value, carry_in, dont_care, success);
212 if (*success)
213 return result;
214 else
215 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000216}
217
218static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
Johnny Chen6ef27352011-06-02 22:50:51 +0000219 const uint32_t carry_in, uint32_t &carry_out, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000220{
Johnny Chen6ef27352011-06-02 22:50:51 +0000221 if (type == SRType_RRX && amount != 1) {
222 *success = false;
223 return 0;
224 }
225 *success = true;
226
227 if (amount == 0) {
Johnny Chen7a03c852011-02-15 17:52:22 +0000228 carry_out = carry_in;
229 return value;
230 }
231 uint32_t result;
232 switch (type) {
233 case SRType_LSL:
Johnny Chen6ef27352011-06-02 22:50:51 +0000234 result = LSL_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000235 break;
236 case SRType_LSR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000237 result = LSR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000238 break;
239 case SRType_ASR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000240 result = ASR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000241 break;
242 case SRType_ROR:
Johnny Chen6ef27352011-06-02 22:50:51 +0000243 result = ROR_C(value, amount, carry_out, success);
Johnny Chen7a03c852011-02-15 17:52:22 +0000244 break;
245 case SRType_RRX:
Johnny Chen6ef27352011-06-02 22:50:51 +0000246 result = RRX_C(value, carry_in, carry_out, success);
247 break;
248 default:
249 *success = false;
Johnny Chen7a03c852011-02-15 17:52:22 +0000250 break;
251 }
Johnny Chen6ef27352011-06-02 22:50:51 +0000252 if (*success)
253 return result;
254 else
255 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000256}
257
258static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
Johnny Chen6ef27352011-06-02 22:50:51 +0000259 const uint32_t carry_in, bool *success)
Johnny Chen7a03c852011-02-15 17:52:22 +0000260{
261 // Don't care about carry out in this case.
262 uint32_t dont_care;
Johnny Chen6ef27352011-06-02 22:50:51 +0000263 uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success);
264 if (*success)
265 return result;
266 else
267 return 0;
Johnny Chen7a03c852011-02-15 17:52:22 +0000268}
269
Johnny Chenccc99632011-01-25 22:45:28 +0000270static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
271{
Johnny Chen74889b22011-01-26 01:00:55 +0000272 return Bits32(val, msbit, lsbit);
Johnny Chenccc99632011-01-25 22:45:28 +0000273}
274
275static inline uint32_t bit(const uint32_t val, const uint32_t msbit)
276{
277 return bits(val, msbit, msbit);
278}
279
Johnny Chend5cd6452011-01-25 23:49:39 +0000280static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift)
Johnny Chenccc99632011-01-25 22:45:28 +0000281{
Johnny Chend5cd6452011-01-25 23:49:39 +0000282 uint32_t m = shift % N;
283 return (val >> m) | (val << (N - m));
284}
285
Johnny Chene2b86a32011-02-14 19:08:41 +0000286// (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000287static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
Johnny Chene2b86a32011-02-14 19:08:41 +0000288{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000289 uint32_t imm32; // the expanded result
290 uint32_t imm = bits(opcode, 7, 0); // immediate value
291 uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount
Johnny Chene2b86a32011-02-14 19:08:41 +0000292 if (amt == 0)
293 {
294 imm32 = imm;
295 carry_out = carry_in;
296 }
297 else
298 {
299 imm32 = ror(imm, 32, amt);
300 carry_out = Bit32(imm32, 31);
301 }
302 return imm32;
303}
304
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000305static inline uint32_t ARMExpandImm(uint32_t opcode)
Johnny Chend5cd6452011-01-25 23:49:39 +0000306{
Johnny Chene2b86a32011-02-14 19:08:41 +0000307 // 'carry_in' argument to following function call does not affect the imm32 result.
308 uint32_t carry_in = 0;
309 uint32_t carry_out;
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000310 return ARMExpandImm_C(opcode, carry_in, carry_out);
Johnny Chene2b86a32011-02-14 19:08:41 +0000311}
312
313// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000314static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
Johnny Chene2b86a32011-02-14 19:08:41 +0000315{
Johnny Chenac407592011-02-14 19:09:36 +0000316 uint32_t imm32; // the expaned result
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000317 const uint32_t i = bit(opcode, 26);
318 const uint32_t imm3 = bits(opcode, 14, 12);
319 const uint32_t abcdefgh = bits(opcode, 7, 0);
Johnny Chene2b86a32011-02-14 19:08:41 +0000320 const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;
321
322 if (bits(imm12, 11, 10) == 0)
323 {
Caroline Tice466327d2011-03-24 21:11:26 +0000324 switch (bits(imm12, 9, 8)) {
Johnny Chene2b86a32011-02-14 19:08:41 +0000325 case 0:
326 imm32 = abcdefgh;
327 break;
328
329 case 1:
330 imm32 = abcdefgh << 16 | abcdefgh;
331 break;
332
333 case 2:
334 imm32 = abcdefgh << 24 | abcdefgh << 8;
335 break;
336
337 case 3:
338 imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh;
339 break;
340 }
341 carry_out = carry_in;
342 }
343 else
344 {
345 const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0);
346 imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7));
347 carry_out = Bit32(imm32, 31);
348 }
349 return imm32;
Johnny Chenccc99632011-01-25 22:45:28 +0000350}
351
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000352static inline uint32_t ThumbExpandImm(uint32_t opcode)
Johnny Chenccc99632011-01-25 22:45:28 +0000353{
Johnny Chene2b86a32011-02-14 19:08:41 +0000354 // 'carry_in' argument to following function call does not affect the imm32 result.
355 uint32_t carry_in = 0;
356 uint32_t carry_out;
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000357 return ThumbExpandImm_C(opcode, carry_in, carry_out);
Johnny Chend5cd6452011-01-25 23:49:39 +0000358}
359
360// imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000361static inline uint32_t ThumbImm12(uint32_t opcode)
Johnny Chend5cd6452011-01-25 23:49:39 +0000362{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000363 const uint32_t i = bit(opcode, 26);
364 const uint32_t imm3 = bits(opcode, 14, 12);
365 const uint32_t imm8 = bits(opcode, 7, 0);
Johnny Chend5cd6452011-01-25 23:49:39 +0000366 const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;
367 return imm12;
Johnny Chenccc99632011-01-25 22:45:28 +0000368}
369
Johnny Chen3fde51b2011-01-26 00:08:59 +0000370// imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chend88d96c2011-02-23 21:24:25 +0000371static inline uint32_t ThumbImm7Scaled(uint32_t opcode)
Johnny Chen3fde51b2011-01-26 00:08:59 +0000372{
Johnny Chen5f88bcc2011-02-22 21:17:52 +0000373 const uint32_t imm7 = bits(opcode, 6, 0);
Johnny Chen3fde51b2011-01-26 00:08:59 +0000374 return imm7 * 4;
375}
376
Johnny Chend88d96c2011-02-23 21:24:25 +0000377// imm32 = ZeroExtend(imm8:'00', 32)
378static inline uint32_t ThumbImm8Scaled(uint32_t opcode)
379{
380 const uint32_t imm8 = bits(opcode, 7, 0);
381 return imm8 * 4;
382}
383
Johnny Chen91027002011-01-24 18:24:53 +0000384// This function performs the check for the register numbers 13 and 15 that are
385// not permitted for many Thumb register specifiers.
386static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
387
Johnny Chen91027002011-01-24 18:24:53 +0000388} // namespace lldb_private
389
390#endif // lldb_ARMUtils_h_