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