blob: e6f7516e8a29592c16ca0f5fcf3a0f5727d773e8 [file] [log] [blame]
Johnny Chen4baf2e32011-01-24 18:24:53 +00001//===-- lldb_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
Johnny Chen108d5aa2011-01-26 01:00:55 +000013#include "InstructionUtils.h"
14
Johnny Chenc3b5bc32011-01-24 19:50:30 +000015// Common utilities for the ARM/Thumb Instruction Set Architecture.
Johnny Chen4baf2e32011-01-24 18:24:53 +000016
17namespace lldb_private {
18
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000019static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
20{
Johnny Chen108d5aa2011-01-26 01:00:55 +000021 return Bits32(val, msbit, lsbit);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000022}
23
24static inline uint32_t bit(const uint32_t val, const uint32_t msbit)
25{
26 return bits(val, msbit, msbit);
27}
28
Johnny Chen60c0d622011-01-25 23:49:39 +000029static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000030{
Johnny Chen60c0d622011-01-25 23:49:39 +000031 uint32_t m = shift % N;
32 return (val >> m) | (val << (N - m));
33}
34
Johnny Chen07f2f5a2011-02-14 19:08:41 +000035// (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)
36static inline uint32_t ARMExpandImm_C(uint32_t val, uint32_t carry_in, uint32_t &carry_out)
37{
38 uint32_t imm32; // the expanded result
39 uint32_t imm = bits(val, 7, 0); // immediate value
40 uint32_t amt = 2 * bits(val, 11, 8); // rotate amount
41 if (amt == 0)
42 {
43 imm32 = imm;
44 carry_out = carry_in;
45 }
46 else
47 {
48 imm32 = ror(imm, 32, amt);
49 carry_out = Bit32(imm32, 31);
50 }
51 return imm32;
52}
53
Johnny Chen60c0d622011-01-25 23:49:39 +000054static inline uint32_t ARMExpandImm(uint32_t val)
55{
Johnny Chen07f2f5a2011-02-14 19:08:41 +000056 // 'carry_in' argument to following function call does not affect the imm32 result.
57 uint32_t carry_in = 0;
58 uint32_t carry_out;
59 return ARMExpandImm_C(val, carry_in, carry_out);
60}
61
62// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
63static inline uint32_t ThumbExpandImm_C(uint32_t val, uint32_t carry_in, uint32_t &carry_out)
64{
Johnny Chen3e9a41c2011-02-14 19:09:36 +000065 uint32_t imm32; // the expaned result
Johnny Chen07f2f5a2011-02-14 19:08:41 +000066 const uint32_t i = bit(val, 26);
67 const uint32_t imm3 = bits(val, 14, 12);
68 const uint32_t abcdefgh = bits(val, 7, 0);
69 const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;
70
71 if (bits(imm12, 11, 10) == 0)
72 {
73 switch (bits(imm12, 8, 9)) {
74 case 0:
75 imm32 = abcdefgh;
76 break;
77
78 case 1:
79 imm32 = abcdefgh << 16 | abcdefgh;
80 break;
81
82 case 2:
83 imm32 = abcdefgh << 24 | abcdefgh << 8;
84 break;
85
86 case 3:
87 imm32 = abcdefgh << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh;
88 break;
89 }
90 carry_out = carry_in;
91 }
92 else
93 {
94 const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0);
95 imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7));
96 carry_out = Bit32(imm32, 31);
97 }
98 return imm32;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000099}
100
Johnny Chen60c0d622011-01-25 23:49:39 +0000101static inline uint32_t ThumbExpandImm(uint32_t val)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000102{
Johnny Chen07f2f5a2011-02-14 19:08:41 +0000103 // 'carry_in' argument to following function call does not affect the imm32 result.
104 uint32_t carry_in = 0;
105 uint32_t carry_out;
106 return ThumbExpandImm_C(val, carry_in, carry_out);
Johnny Chen60c0d622011-01-25 23:49:39 +0000107}
108
109// imm32 = ZeroExtend(i:imm3:imm8, 32)
110static inline uint32_t ThumbImm12(uint32_t val)
111{
112 const uint32_t i = bit(val, 26);
113 const uint32_t imm3 = bits(val, 14, 12);
114 const uint32_t imm8 = bits(val, 7, 0);
115 const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;
116 return imm12;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +0000117}
118
Johnny Chene4455022011-01-26 00:08:59 +0000119// imm32 = ZeroExtend(imm7:'00', 32)
120static inline uint32_t ThumbImmScaled(uint32_t val)
121{
122 const uint32_t imm7 = bits(val, 6, 0);
123 return imm7 * 4;
124}
125
Johnny Chen4baf2e32011-01-24 18:24:53 +0000126// This function performs the check for the register numbers 13 and 15 that are
127// not permitted for many Thumb register specifiers.
128static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
129
Johnny Chen4baf2e32011-01-24 18:24:53 +0000130} // namespace lldb_private
131
132#endif // lldb_ARMUtils_h_