/src/capstonev5/arch/ARM/ARMAddressingModes.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- 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 | | // This file contains the ARM addressing mode implementation stuff. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | /* Capstone Disassembly Engine */ |
15 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ |
16 | | |
17 | | #ifndef CS_LLVM_TARGET_ARM_ARMADDRESSINGMODES_H |
18 | | #define CS_LLVM_TARGET_ARM_ARMADDRESSINGMODES_H |
19 | | |
20 | | #include "capstone/platform.h" |
21 | | #include "../../MathExtras.h" |
22 | | |
23 | | /// ARM_AM - ARM Addressing Mode Stuff |
24 | | typedef enum ARM_AM_ShiftOpc { |
25 | | ARM_AM_no_shift = 0, |
26 | | ARM_AM_asr, |
27 | | ARM_AM_lsl, |
28 | | ARM_AM_lsr, |
29 | | ARM_AM_ror, |
30 | | ARM_AM_rrx |
31 | | } ARM_AM_ShiftOpc; |
32 | | |
33 | | typedef enum ARM_AM_AddrOpc { |
34 | | ARM_AM_sub = 0, |
35 | | ARM_AM_add |
36 | | } ARM_AM_AddrOpc; |
37 | | |
38 | | static inline const char *ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op) |
39 | 62.0k | { |
40 | 62.0k | return Op == ARM_AM_sub ? "-" : ""; |
41 | 62.0k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAddrOpcStr ARMInstPrinter.c:ARM_AM_getAddrOpcStr Line | Count | Source | 39 | 62.0k | { | 40 | 62.0k | return Op == ARM_AM_sub ? "-" : ""; | 41 | 62.0k | } |
|
42 | | |
43 | | static inline const char *ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op) |
44 | 27.8k | { |
45 | 27.8k | switch (Op) { |
46 | 0 | default: return ""; //llvm_unreachable("Unknown shift opc!"); |
47 | 6.14k | case ARM_AM_asr: return "asr"; |
48 | 9.14k | case ARM_AM_lsl: return "lsl"; |
49 | 6.46k | case ARM_AM_lsr: return "lsr"; |
50 | 5.18k | case ARM_AM_ror: return "ror"; |
51 | 921 | case ARM_AM_rrx: return "rrx"; |
52 | 27.8k | } |
53 | 27.8k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getShiftOpcStr ARMInstPrinter.c:ARM_AM_getShiftOpcStr Line | Count | Source | 44 | 27.8k | { | 45 | 27.8k | switch (Op) { | 46 | 0 | default: return ""; //llvm_unreachable("Unknown shift opc!"); | 47 | 6.14k | case ARM_AM_asr: return "asr"; | 48 | 9.14k | case ARM_AM_lsl: return "lsl"; | 49 | 6.46k | case ARM_AM_lsr: return "lsr"; | 50 | 5.18k | case ARM_AM_ror: return "ror"; | 51 | 921 | case ARM_AM_rrx: return "rrx"; | 52 | 27.8k | } | 53 | 27.8k | } |
|
54 | | |
55 | | static inline unsigned ARM_AM_getShiftOpcEncoding(ARM_AM_ShiftOpc Op) |
56 | 0 | { |
57 | 0 | switch (Op) { |
58 | 0 | default: return (unsigned int)-1; //llvm_unreachable("Unknown shift opc!"); |
59 | 0 | case ARM_AM_asr: return 2; |
60 | 0 | case ARM_AM_lsl: return 0; |
61 | 0 | case ARM_AM_lsr: return 1; |
62 | 0 | case ARM_AM_ror: return 3; |
63 | 0 | } |
64 | 0 | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getShiftOpcEncoding Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getShiftOpcEncoding |
65 | | |
66 | | typedef enum ARM_AM_AMSubMode { |
67 | | ARM_AM_bad_am_submode = 0, |
68 | | ARM_AM_ia, |
69 | | ARM_AM_ib, |
70 | | ARM_AM_da, |
71 | | ARM_AM_db |
72 | | } ARM_AM_AMSubMode; |
73 | | |
74 | | static inline const char *ARM_AM_getAMSubModeStr(ARM_AM_AMSubMode Mode) |
75 | 0 | { |
76 | 0 | switch (Mode) { |
77 | 0 | default: return ""; |
78 | 0 | case ARM_AM_ia: return "ia"; |
79 | 0 | case ARM_AM_ib: return "ib"; |
80 | 0 | case ARM_AM_da: return "da"; |
81 | 0 | case ARM_AM_db: return "db"; |
82 | 0 | } |
83 | 0 | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAMSubModeStr Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAMSubModeStr |
84 | | |
85 | | /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. |
86 | | /// |
87 | | static inline unsigned rotr32(unsigned Val, unsigned Amt) |
88 | 17.4k | { |
89 | | //assert(Amt < 32 && "Invalid rotate amount"); |
90 | 17.4k | return (Val >> Amt) | (Val << ((32-Amt)&31)); |
91 | 17.4k | } Unexecuted instantiation: ARMDisassembler.c:rotr32 Line | Count | Source | 88 | 17.4k | { | 89 | | //assert(Amt < 32 && "Invalid rotate amount"); | 90 | 17.4k | return (Val >> Amt) | (Val << ((32-Amt)&31)); | 91 | 17.4k | } |
|
92 | | |
93 | | /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. |
94 | | /// |
95 | | static inline unsigned rotl32(unsigned Val, unsigned Amt) |
96 | 4.79k | { |
97 | | //assert(Amt < 32 && "Invalid rotate amount"); |
98 | 4.79k | return (Val << Amt) | (Val >> ((32-Amt)&31)); |
99 | 4.79k | } Unexecuted instantiation: ARMDisassembler.c:rotl32 Line | Count | Source | 96 | 4.79k | { | 97 | | //assert(Amt < 32 && "Invalid rotate amount"); | 98 | 4.79k | return (Val << Amt) | (Val >> ((32-Amt)&31)); | 99 | 4.79k | } |
|
100 | | |
101 | | //===--------------------------------------------------------------------===// |
102 | | // Addressing Mode #1: shift_operand with registers |
103 | | //===--------------------------------------------------------------------===// |
104 | | // |
105 | | // This 'addressing mode' is used for arithmetic instructions. It can |
106 | | // represent things like: |
107 | | // reg |
108 | | // reg [asr|lsl|lsr|ror|rrx] reg |
109 | | // reg [asr|lsl|lsr|ror|rrx] imm |
110 | | // |
111 | | // This is stored three operands [rega, regb, opc]. The first is the base |
112 | | // reg, the second is the shift amount (or reg0 if not present or imm). The |
113 | | // third operand encodes the shift opcode and the imm if a reg isn't present. |
114 | | // |
115 | | static inline unsigned getSORegOpc(ARM_AM_ShiftOpc ShOp, unsigned Imm) |
116 | 0 | { |
117 | 0 | return ShOp | (Imm << 3); |
118 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getSORegOpc Unexecuted instantiation: ARMInstPrinter.c:getSORegOpc |
119 | | |
120 | | static inline unsigned getSORegOffset(unsigned Op) |
121 | 13.5k | { |
122 | 13.5k | return Op >> 3; |
123 | 13.5k | } Unexecuted instantiation: ARMDisassembler.c:getSORegOffset ARMInstPrinter.c:getSORegOffset Line | Count | Source | 121 | 13.5k | { | 122 | 13.5k | return Op >> 3; | 123 | 13.5k | } |
|
124 | | |
125 | | static inline ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op) |
126 | 36.1k | { |
127 | 36.1k | return (ARM_AM_ShiftOpc)(Op & 7); |
128 | 36.1k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegShOp ARMInstPrinter.c:ARM_AM_getSORegShOp Line | Count | Source | 126 | 36.1k | { | 127 | 36.1k | return (ARM_AM_ShiftOpc)(Op & 7); | 128 | 36.1k | } |
|
129 | | |
130 | | /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return |
131 | | /// the 8-bit imm value. |
132 | | static inline unsigned getSOImmValImm(unsigned Imm) |
133 | 0 | { |
134 | 0 | return Imm & 0xFF; |
135 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getSOImmValImm Unexecuted instantiation: ARMInstPrinter.c:getSOImmValImm |
136 | | |
137 | | /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return |
138 | | /// the rotate amount. |
139 | | static inline unsigned getSOImmValRot(unsigned Imm) |
140 | 0 | { |
141 | 0 | return (Imm >> 8) * 2; |
142 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getSOImmValRot Unexecuted instantiation: ARMInstPrinter.c:getSOImmValRot |
143 | | |
144 | | /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, |
145 | | /// computing the rotate amount to use. If this immediate value cannot be |
146 | | /// handled with a single shifter-op, determine a good rotate amount that will |
147 | | /// take a maximal chunk of bits out of the immediate. |
148 | | static inline unsigned getSOImmValRotate(unsigned Imm) |
149 | 4.79k | { |
150 | 4.79k | unsigned TZ, RotAmt; |
151 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate |
152 | | // of zero. |
153 | 4.79k | if ((Imm & ~255U) == 0) return 0; |
154 | | |
155 | | // Use CTZ to compute the rotate amount. |
156 | 4.79k | TZ = CountTrailingZeros_32(Imm); |
157 | | |
158 | | // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, |
159 | | // not 9. |
160 | 4.79k | RotAmt = TZ & ~1; |
161 | | |
162 | | // If we can handle this spread, return it. |
163 | 4.79k | if ((rotr32(Imm, RotAmt) & ~255U) == 0) |
164 | 3.28k | return (32-RotAmt)&31; // HW rotates right, not left. |
165 | | |
166 | | // For values like 0xF000000F, we should ignore the low 6 bits, then |
167 | | // retry the hunt. |
168 | 1.51k | if (Imm & 63U) { |
169 | 1.51k | unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); |
170 | 1.51k | unsigned RotAmt2 = TZ2 & ~1; |
171 | 1.51k | if ((rotr32(Imm, RotAmt2) & ~255U) == 0) |
172 | 1.51k | return (32-RotAmt2)&31; // HW rotates right, not left. |
173 | 1.51k | } |
174 | | |
175 | | // Otherwise, we have no way to cover this span of bits with a single |
176 | | // shifter_op immediate. Return a chunk of bits that will be useful to |
177 | | // handle. |
178 | 0 | return (32-RotAmt)&31; // HW rotates right, not left. |
179 | 1.51k | } Unexecuted instantiation: ARMDisassembler.c:getSOImmValRotate ARMInstPrinter.c:getSOImmValRotate Line | Count | Source | 149 | 4.79k | { | 150 | 4.79k | unsigned TZ, RotAmt; | 151 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 152 | | // of zero. | 153 | 4.79k | if ((Imm & ~255U) == 0) return 0; | 154 | | | 155 | | // Use CTZ to compute the rotate amount. | 156 | 4.79k | TZ = CountTrailingZeros_32(Imm); | 157 | | | 158 | | // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, | 159 | | // not 9. | 160 | 4.79k | RotAmt = TZ & ~1; | 161 | | | 162 | | // If we can handle this spread, return it. | 163 | 4.79k | if ((rotr32(Imm, RotAmt) & ~255U) == 0) | 164 | 3.28k | return (32-RotAmt)&31; // HW rotates right, not left. | 165 | | | 166 | | // For values like 0xF000000F, we should ignore the low 6 bits, then | 167 | | // retry the hunt. | 168 | 1.51k | if (Imm & 63U) { | 169 | 1.51k | unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); | 170 | 1.51k | unsigned RotAmt2 = TZ2 & ~1; | 171 | 1.51k | if ((rotr32(Imm, RotAmt2) & ~255U) == 0) | 172 | 1.51k | return (32-RotAmt2)&31; // HW rotates right, not left. | 173 | 1.51k | } | 174 | | | 175 | | // Otherwise, we have no way to cover this span of bits with a single | 176 | | // shifter_op immediate. Return a chunk of bits that will be useful to | 177 | | // handle. | 178 | 0 | return (32-RotAmt)&31; // HW rotates right, not left. | 179 | 1.51k | } |
|
180 | | |
181 | | /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit |
182 | | /// into an shifter_operand immediate operand, return the 12-bit encoding for |
183 | | /// it. If not, return -1. |
184 | | static inline int getSOImmVal(unsigned Arg) |
185 | 6.34k | { |
186 | 6.34k | unsigned RotAmt; |
187 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate |
188 | | // of zero. |
189 | 6.34k | if ((Arg & ~255U) == 0) return Arg; |
190 | | |
191 | 4.79k | RotAmt = getSOImmValRotate(Arg); |
192 | | |
193 | | // If this cannot be handled with a single shifter_op, bail out. |
194 | 4.79k | if (rotr32(~255U, RotAmt) & Arg) |
195 | 0 | return -1; |
196 | | |
197 | | // Encode this correctly. |
198 | 4.79k | return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); |
199 | 4.79k | } Unexecuted instantiation: ARMDisassembler.c:getSOImmVal ARMInstPrinter.c:getSOImmVal Line | Count | Source | 185 | 6.34k | { | 186 | 6.34k | unsigned RotAmt; | 187 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 188 | | // of zero. | 189 | 6.34k | if ((Arg & ~255U) == 0) return Arg; | 190 | | | 191 | 4.79k | RotAmt = getSOImmValRotate(Arg); | 192 | | | 193 | | // If this cannot be handled with a single shifter_op, bail out. | 194 | 4.79k | if (rotr32(~255U, RotAmt) & Arg) | 195 | 0 | return -1; | 196 | | | 197 | | // Encode this correctly. | 198 | 4.79k | return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); | 199 | 4.79k | } |
|
200 | | |
201 | | /// isSOImmTwoPartVal - Return true if the specified value can be obtained by |
202 | | /// or'ing together two SOImmVal's. |
203 | | static inline bool isSOImmTwoPartVal(unsigned V) |
204 | 0 | { |
205 | 0 | // If this can be handled with a single shifter_op, bail out. |
206 | 0 | V = rotr32(~255U, getSOImmValRotate(V)) & V; |
207 | 0 | if (V == 0) |
208 | 0 | return false; |
209 | 0 |
|
210 | 0 | // If this can be handled with two shifter_op's, accept. |
211 | 0 | V = rotr32(~255U, getSOImmValRotate(V)) & V; |
212 | 0 | return V == 0; |
213 | 0 | } Unexecuted instantiation: ARMDisassembler.c:isSOImmTwoPartVal Unexecuted instantiation: ARMInstPrinter.c:isSOImmTwoPartVal |
214 | | |
215 | | /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, |
216 | | /// return the first chunk of it. |
217 | | static inline unsigned getSOImmTwoPartFirst(unsigned V) |
218 | 0 | { |
219 | 0 | return rotr32(255U, getSOImmValRotate(V)) & V; |
220 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getSOImmTwoPartFirst Unexecuted instantiation: ARMInstPrinter.c:getSOImmTwoPartFirst |
221 | | |
222 | | /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, |
223 | | /// return the second chunk of it. |
224 | | static inline unsigned getSOImmTwoPartSecond(unsigned V) |
225 | 0 | { |
226 | 0 | // Mask out the first hunk. |
227 | 0 | V = rotr32(~255U, getSOImmValRotate(V)) & V; |
228 | 0 |
|
229 | 0 | // Take what's left. |
230 | 0 | //assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); |
231 | 0 | return V; |
232 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getSOImmTwoPartSecond Unexecuted instantiation: ARMInstPrinter.c:getSOImmTwoPartSecond |
233 | | |
234 | | /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed |
235 | | /// by a left shift. Returns the shift amount to use. |
236 | | static inline unsigned getThumbImmValShift(unsigned Imm) |
237 | 0 | { |
238 | 0 | // 8-bit (or less) immediates are trivially immediate operand with a shift |
239 | 0 | // of zero. |
240 | 0 | if ((Imm & ~255U) == 0) return 0; |
241 | 0 |
|
242 | 0 | // Use CTZ to compute the shift amount. |
243 | 0 | return CountTrailingZeros_32(Imm); |
244 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getThumbImmValShift Unexecuted instantiation: ARMInstPrinter.c:getThumbImmValShift |
245 | | |
246 | | /// isThumbImmShiftedVal - Return true if the specified value can be obtained |
247 | | /// by left shifting a 8-bit immediate. |
248 | | static inline bool isThumbImmShiftedVal(unsigned V) |
249 | 0 | { |
250 | 0 | // If this can be handled with |
251 | 0 | V = (~255U << getThumbImmValShift(V)) & V; |
252 | 0 | return V == 0; |
253 | 0 | } Unexecuted instantiation: ARMDisassembler.c:isThumbImmShiftedVal Unexecuted instantiation: ARMInstPrinter.c:isThumbImmShiftedVal |
254 | | |
255 | | /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed |
256 | | /// by a left shift. Returns the shift amount to use. |
257 | | static inline unsigned getThumbImm16ValShift(unsigned Imm) |
258 | 0 | { |
259 | 0 | // 16-bit (or less) immediates are trivially immediate operand with a shift |
260 | 0 | // of zero. |
261 | 0 | if ((Imm & ~65535U) == 0) return 0; |
262 | 0 |
|
263 | 0 | // Use CTZ to compute the shift amount. |
264 | 0 | return CountTrailingZeros_32(Imm); |
265 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getThumbImm16ValShift Unexecuted instantiation: ARMInstPrinter.c:getThumbImm16ValShift |
266 | | |
267 | | /// isThumbImm16ShiftedVal - Return true if the specified value can be |
268 | | /// obtained by left shifting a 16-bit immediate. |
269 | | static inline bool isThumbImm16ShiftedVal(unsigned V) |
270 | 0 | { |
271 | 0 | // If this can be handled with |
272 | 0 | V = (~65535U << getThumbImm16ValShift(V)) & V; |
273 | 0 | return V == 0; |
274 | 0 | } Unexecuted instantiation: ARMDisassembler.c:isThumbImm16ShiftedVal Unexecuted instantiation: ARMInstPrinter.c:isThumbImm16ShiftedVal |
275 | | |
276 | | /// getThumbImmNonShiftedVal - If V is a value that satisfies |
277 | | /// isThumbImmShiftedVal, return the non-shiftd value. |
278 | | static inline unsigned getThumbImmNonShiftedVal(unsigned V) |
279 | 0 | { |
280 | 0 | return V >> getThumbImmValShift(V); |
281 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getThumbImmNonShiftedVal Unexecuted instantiation: ARMInstPrinter.c:getThumbImmNonShiftedVal |
282 | | |
283 | | |
284 | | /// getT2SOImmValSplat - Return the 12-bit encoded representation |
285 | | /// if the specified value can be obtained by splatting the low 8 bits |
286 | | /// into every other byte or every byte of a 32-bit value. i.e., |
287 | | /// 00000000 00000000 00000000 abcdefgh control = 0 |
288 | | /// 00000000 abcdefgh 00000000 abcdefgh control = 1 |
289 | | /// abcdefgh 00000000 abcdefgh 00000000 control = 2 |
290 | | /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 |
291 | | /// Return -1 if none of the above apply. |
292 | | /// See ARM Reference Manual A6.3.2. |
293 | | static inline int getT2SOImmValSplatVal(unsigned V) |
294 | 0 | { |
295 | 0 | unsigned u, Vs, Imm; |
296 | 0 | // control = 0 |
297 | 0 | if ((V & 0xffffff00) == 0) |
298 | 0 | return V; |
299 | 0 |
|
300 | 0 | // If the value is zeroes in the first byte, just shift those off |
301 | 0 | Vs = ((V & 0xff) == 0) ? V >> 8 : V; |
302 | 0 | // Any passing value only has 8 bits of payload, splatted across the word |
303 | 0 | Imm = Vs & 0xff; |
304 | 0 | // Likewise, any passing values have the payload splatted into the 3rd byte |
305 | 0 | u = Imm | (Imm << 16); |
306 | 0 |
|
307 | 0 | // control = 1 or 2 |
308 | 0 | if (Vs == u) |
309 | 0 | return (((Vs == V) ? 1 : 2) << 8) | Imm; |
310 | 0 |
|
311 | 0 | // control = 3 |
312 | 0 | if (Vs == (u | (u << 8))) |
313 | 0 | return (3 << 8) | Imm; |
314 | 0 |
|
315 | 0 | return -1; |
316 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmValSplatVal Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmValSplatVal |
317 | | |
318 | | /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the |
319 | | /// specified value is a rotated 8-bit value. Return -1 if no rotation |
320 | | /// encoding is possible. |
321 | | /// See ARM Reference Manual A6.3.2. |
322 | | static inline int getT2SOImmValRotateVal(unsigned V) |
323 | 0 | { |
324 | 0 | unsigned RotAmt = CountLeadingZeros_32(V); |
325 | 0 | if (RotAmt >= 24) |
326 | 0 | return -1; |
327 | 0 |
|
328 | 0 | // If 'Arg' can be handled with a single shifter_op return the value. |
329 | 0 | if ((rotr32(0xff000000U, RotAmt) & V) == V) |
330 | 0 | return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); |
331 | 0 |
|
332 | 0 | return -1; |
333 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmValRotateVal Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmValRotateVal |
334 | | |
335 | | /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit |
336 | | /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit |
337 | | /// encoding for it. If not, return -1. |
338 | | /// See ARM Reference Manual A6.3.2. |
339 | | static inline int getT2SOImmVal(unsigned Arg) |
340 | 0 | { |
341 | 0 | int Rot; |
342 | 0 | // If 'Arg' is an 8-bit splat, then get the encoded value. |
343 | 0 | int Splat = getT2SOImmValSplatVal(Arg); |
344 | 0 | if (Splat != -1) |
345 | 0 | return Splat; |
346 | 0 |
|
347 | 0 | // If 'Arg' can be handled with a single shifter_op return the value. |
348 | 0 | Rot = getT2SOImmValRotateVal(Arg); |
349 | 0 | if (Rot != -1) |
350 | 0 | return Rot; |
351 | 0 |
|
352 | 0 | return -1; |
353 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmVal Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmVal |
354 | | |
355 | | static inline unsigned getT2SOImmValRotate(unsigned V) |
356 | 0 | { |
357 | 0 | unsigned RotAmt; |
358 | 0 |
|
359 | 0 | if ((V & ~255U) == 0) |
360 | 0 | return 0; |
361 | 0 |
|
362 | 0 | // Use CTZ to compute the rotate amount. |
363 | 0 | RotAmt = CountTrailingZeros_32(V); |
364 | 0 | return (32 - RotAmt) & 31; |
365 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmValRotate Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmValRotate |
366 | | |
367 | | static inline bool isT2SOImmTwoPartVal (unsigned Imm) |
368 | 0 | { |
369 | 0 | unsigned V = Imm; |
370 | 0 | // Passing values can be any combination of splat values and shifter |
371 | 0 | // values. If this can be handled with a single shifter or splat, bail |
372 | 0 | // out. Those should be handled directly, not with a two-part val. |
373 | 0 | if (getT2SOImmValSplatVal(V) != -1) |
374 | 0 | return false; |
375 | 0 | V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; |
376 | 0 | if (V == 0) |
377 | 0 | return false; |
378 | 0 |
|
379 | 0 | // If this can be handled as an immediate, accept. |
380 | 0 | if (getT2SOImmVal(V) != -1) return true; |
381 | 0 |
|
382 | 0 | // Likewise, try masking out a splat value first. |
383 | 0 | V = Imm; |
384 | 0 | if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) |
385 | 0 | V &= ~0xff00ff00U; |
386 | 0 | else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) |
387 | 0 | V &= ~0x00ff00ffU; |
388 | 0 | // If what's left can be handled as an immediate, accept. |
389 | 0 | if (getT2SOImmVal(V) != -1) return true; |
390 | 0 |
|
391 | 0 | // Otherwise, do not accept. |
392 | 0 | return false; |
393 | 0 | } Unexecuted instantiation: ARMDisassembler.c:isT2SOImmTwoPartVal Unexecuted instantiation: ARMInstPrinter.c:isT2SOImmTwoPartVal |
394 | | |
395 | | static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) |
396 | 0 | { |
397 | 0 | //assert (isT2SOImmTwoPartVal(Imm) && |
398 | 0 | // "Immedate cannot be encoded as two part immediate!"); |
399 | 0 | // Try a shifter operand as one part |
400 | 0 | unsigned V = rotr32 (~(unsigned int)255, getT2SOImmValRotate(Imm)) & Imm; |
401 | 0 | // If the rest is encodable as an immediate, then return it. |
402 | 0 | if (getT2SOImmVal(V) != -1) return V; |
403 | 0 |
|
404 | 0 | // Try masking out a splat value first. |
405 | 0 | if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) |
406 | 0 | return Imm & 0xff00ff00U; |
407 | 0 |
|
408 | 0 | // The other splat is all that's left as an option. |
409 | 0 | //assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); |
410 | 0 | return Imm & 0x00ff00ffU; |
411 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmTwoPartFirst Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmTwoPartFirst |
412 | | |
413 | | static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) |
414 | 0 | { |
415 | 0 | // Mask out the first hunk |
416 | 0 | Imm ^= getT2SOImmTwoPartFirst(Imm); |
417 | 0 | // Return what's left |
418 | 0 | //assert (getT2SOImmVal(Imm) != -1 && |
419 | 0 | // "Unable to encode second part of T2 two part SO immediate"); |
420 | 0 | return Imm; |
421 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getT2SOImmTwoPartSecond Unexecuted instantiation: ARMInstPrinter.c:getT2SOImmTwoPartSecond |
422 | | |
423 | | |
424 | | //===--------------------------------------------------------------------===// |
425 | | // Addressing Mode #2 |
426 | | //===--------------------------------------------------------------------===// |
427 | | // |
428 | | // This is used for most simple load/store instructions. |
429 | | // |
430 | | // addrmode2 := reg +/- reg shop imm |
431 | | // addrmode2 := reg +/- imm12 |
432 | | // |
433 | | // The first operand is always a Reg. The second operand is a reg if in |
434 | | // reg/reg form, otherwise it's reg#0. The third field encodes the operation |
435 | | // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The |
436 | | // fourth operand 16-17 encodes the index mode. |
437 | | // |
438 | | // If this addressing mode is a frame index (before prolog/epilog insertion |
439 | | // and code rewriting), this operand will have the form: FI#, reg0, <offs> |
440 | | // with no shift amount for the frame offset. |
441 | | // |
442 | | static inline unsigned ARM_AM_getAM2Opc(ARM_AM_AddrOpc Opc, unsigned Imm12, ARM_AM_ShiftOpc SO, |
443 | | unsigned IdxMode) |
444 | 27.3k | { |
445 | | //assert(Imm12 < (1 << 12) && "Imm too large!"); |
446 | 27.3k | bool isSub = Opc == ARM_AM_sub; |
447 | 27.3k | return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; |
448 | 27.3k | } ARMDisassembler.c:ARM_AM_getAM2Opc Line | Count | Source | 444 | 27.3k | { | 445 | | //assert(Imm12 < (1 << 12) && "Imm too large!"); | 446 | 27.3k | bool isSub = Opc == ARM_AM_sub; | 447 | 27.3k | return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; | 448 | 27.3k | } |
Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM2Opc |
449 | | |
450 | | static inline unsigned getAM2Offset(unsigned AM2Opc) |
451 | 13.8k | { |
452 | 13.8k | return AM2Opc & ((1 << 12)-1); |
453 | 13.8k | } Unexecuted instantiation: ARMDisassembler.c:getAM2Offset ARMInstPrinter.c:getAM2Offset Line | Count | Source | 451 | 13.8k | { | 452 | 13.8k | return AM2Opc & ((1 << 12)-1); | 453 | 13.8k | } |
|
454 | | |
455 | | static inline ARM_AM_AddrOpc getAM2Op(unsigned AM2Opc) |
456 | 13.7k | { |
457 | 13.7k | return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add; |
458 | 13.7k | } Unexecuted instantiation: ARMDisassembler.c:getAM2Op ARMInstPrinter.c:getAM2Op Line | Count | Source | 456 | 13.7k | { | 457 | 13.7k | return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add; | 458 | 13.7k | } |
|
459 | | |
460 | | static inline ARM_AM_ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) |
461 | 8.28k | { |
462 | 8.28k | return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7); |
463 | 8.28k | } Unexecuted instantiation: ARMDisassembler.c:getAM2ShiftOpc ARMInstPrinter.c:getAM2ShiftOpc Line | Count | Source | 461 | 8.28k | { | 462 | 8.28k | return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7); | 463 | 8.28k | } |
|
464 | | |
465 | | static inline unsigned getAM2IdxMode(unsigned AM2Opc) |
466 | 0 | { |
467 | 0 | return (AM2Opc >> 16); |
468 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getAM2IdxMode Unexecuted instantiation: ARMInstPrinter.c:getAM2IdxMode |
469 | | |
470 | | //===--------------------------------------------------------------------===// |
471 | | // Addressing Mode #3 |
472 | | //===--------------------------------------------------------------------===// |
473 | | // |
474 | | // This is used for sign-extending loads, and load/store-pair instructions. |
475 | | // |
476 | | // addrmode3 := reg +/- reg |
477 | | // addrmode3 := reg +/- imm8 |
478 | | // |
479 | | // The first operand is always a Reg. The second operand is a reg if in |
480 | | // reg/reg form, otherwise it's reg#0. The third field encodes the operation |
481 | | // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the |
482 | | // index mode. |
483 | | |
484 | | /// getAM3Opc - This function encodes the addrmode3 opc field. |
485 | | static inline unsigned getAM3Opc(ARM_AM_AddrOpc Opc, unsigned char Offset, |
486 | | unsigned IdxMode) |
487 | 0 | { |
488 | 0 | bool isSub = Opc == ARM_AM_sub; |
489 | 0 | return ((int)isSub << 8) | Offset | (IdxMode << 9); |
490 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getAM3Opc Unexecuted instantiation: ARMInstPrinter.c:getAM3Opc |
491 | | |
492 | | static inline unsigned char getAM3Offset(unsigned AM3Opc) |
493 | 3.28k | { |
494 | 3.28k | return AM3Opc & 0xFF; |
495 | 3.28k | } Unexecuted instantiation: ARMDisassembler.c:getAM3Offset ARMInstPrinter.c:getAM3Offset Line | Count | Source | 493 | 3.28k | { | 494 | 3.28k | return AM3Opc & 0xFF; | 495 | 3.28k | } |
|
496 | | |
497 | | static inline ARM_AM_AddrOpc getAM3Op(unsigned AM3Opc) |
498 | 7.19k | { |
499 | 7.19k | return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
500 | 7.19k | } Unexecuted instantiation: ARMDisassembler.c:getAM3Op ARMInstPrinter.c:getAM3Op Line | Count | Source | 498 | 7.19k | { | 499 | 7.19k | return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 500 | 7.19k | } |
|
501 | | |
502 | | static inline unsigned getAM3IdxMode(unsigned AM3Opc) |
503 | 0 | { |
504 | 0 | return (AM3Opc >> 9); |
505 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getAM3IdxMode Unexecuted instantiation: ARMInstPrinter.c:getAM3IdxMode |
506 | | |
507 | | //===--------------------------------------------------------------------===// |
508 | | // Addressing Mode #4 |
509 | | //===--------------------------------------------------------------------===// |
510 | | // |
511 | | // This is used for load / store multiple instructions. |
512 | | // |
513 | | // addrmode4 := reg, <mode> |
514 | | // |
515 | | // The four modes are: |
516 | | // IA - Increment after |
517 | | // IB - Increment before |
518 | | // DA - Decrement after |
519 | | // DB - Decrement before |
520 | | // For VFP instructions, only the IA and DB modes are valid. |
521 | | |
522 | | static inline ARM_AM_AMSubMode getAM4SubMode(unsigned Mode) |
523 | 0 | { |
524 | 0 | return (ARM_AM_AMSubMode)(Mode & 0x7); |
525 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getAM4SubMode Unexecuted instantiation: ARMInstPrinter.c:getAM4SubMode |
526 | | |
527 | | static inline unsigned getAM4ModeImm(ARM_AM_AMSubMode SubMode) |
528 | 0 | { |
529 | 0 | return (int)SubMode; |
530 | 0 | } Unexecuted instantiation: ARMDisassembler.c:getAM4ModeImm Unexecuted instantiation: ARMInstPrinter.c:getAM4ModeImm |
531 | | |
532 | | //===--------------------------------------------------------------------===// |
533 | | // Addressing Mode #5 |
534 | | //===--------------------------------------------------------------------===// |
535 | | // |
536 | | // This is used for coprocessor instructions, such as FP load/stores. |
537 | | // |
538 | | // addrmode5 := reg +/- imm8*4 |
539 | | // |
540 | | // The first operand is always a Reg. The second operand encodes the |
541 | | // operation in bit 8 and the immediate in bits 0-7. |
542 | | |
543 | | /// getAM5Opc - This function encodes the addrmode5 opc field. |
544 | | static inline unsigned ARM_AM_getAM5Opc(ARM_AM_AddrOpc Opc, unsigned char Offset) |
545 | 23.9k | { |
546 | 23.9k | bool isSub = Opc == ARM_AM_sub; |
547 | 23.9k | return ((int)isSub << 8) | Offset; |
548 | 23.9k | } ARMDisassembler.c:ARM_AM_getAM5Opc Line | Count | Source | 545 | 23.9k | { | 546 | 23.9k | bool isSub = Opc == ARM_AM_sub; | 547 | 23.9k | return ((int)isSub << 8) | Offset; | 548 | 23.9k | } |
Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM5Opc |
549 | | static inline unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc) |
550 | 23.9k | { |
551 | 23.9k | return AM5Opc & 0xFF; |
552 | 23.9k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Offset ARMInstPrinter.c:ARM_AM_getAM5Offset Line | Count | Source | 550 | 23.9k | { | 551 | 23.9k | return AM5Opc & 0xFF; | 552 | 23.9k | } |
|
553 | | static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc) |
554 | 23.9k | { |
555 | 23.9k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
556 | 23.9k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Op ARMInstPrinter.c:ARM_AM_getAM5Op Line | Count | Source | 554 | 23.9k | { | 555 | 23.9k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 556 | 23.9k | } |
|
557 | | |
558 | | //===--------------------------------------------------------------------===// |
559 | | // Addressing Mode #5 FP16 |
560 | | //===--------------------------------------------------------------------===// |
561 | | // |
562 | | // This is used for coprocessor instructions, such as 16-bit FP load/stores. |
563 | | // |
564 | | // addrmode5fp16 := reg +/- imm8*2 |
565 | | // |
566 | | // The first operand is always a Reg. The second operand encodes the |
567 | | // operation (add or subtract) in bit 8 and the immediate in bits 0-7. |
568 | | |
569 | | /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field. |
570 | | static inline unsigned getAM5FP16Opc(ARM_AM_AddrOpc Opc, unsigned char Offset) |
571 | 268 | { |
572 | 268 | bool isSub = Opc == ARM_AM_sub; |
573 | 268 | return ((int)isSub << 8) | Offset; |
574 | 268 | } ARMDisassembler.c:getAM5FP16Opc Line | Count | Source | 571 | 268 | { | 572 | 268 | bool isSub = Opc == ARM_AM_sub; | 573 | 268 | return ((int)isSub << 8) | Offset; | 574 | 268 | } |
Unexecuted instantiation: ARMInstPrinter.c:getAM5FP16Opc |
575 | | |
576 | | static inline unsigned char getAM5FP16Offset(unsigned AM5Opc) |
577 | 223 | { |
578 | 223 | return AM5Opc & 0xFF; |
579 | 223 | } Unexecuted instantiation: ARMDisassembler.c:getAM5FP16Offset ARMInstPrinter.c:getAM5FP16Offset Line | Count | Source | 577 | 223 | { | 578 | 223 | return AM5Opc & 0xFF; | 579 | 223 | } |
|
580 | | |
581 | | static inline ARM_AM_AddrOpc getAM5FP16Op(unsigned AM5Opc) |
582 | 223 | { |
583 | 223 | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
584 | 223 | } Unexecuted instantiation: ARMDisassembler.c:getAM5FP16Op ARMInstPrinter.c:getAM5FP16Op Line | Count | Source | 582 | 223 | { | 583 | 223 | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 584 | 223 | } |
|
585 | | |
586 | | //===--------------------------------------------------------------------===// |
587 | | // Addressing Mode #6 |
588 | | //===--------------------------------------------------------------------===// |
589 | | // |
590 | | // This is used for NEON load / store instructions. |
591 | | // |
592 | | // addrmode6 := reg with optional alignment |
593 | | // |
594 | | // This is stored in two operands [regaddr, align]. The first is the |
595 | | // address register. The second operand is the value of the alignment |
596 | | // specifier in bytes or zero if no explicit alignment. |
597 | | // Valid alignments depend on the specific instruction. |
598 | | |
599 | | //===--------------------------------------------------------------------===// |
600 | | // NEON Modified Immediates |
601 | | //===--------------------------------------------------------------------===// |
602 | | // |
603 | | // Several NEON instructions (e.g., VMOV) take a "modified immediate" |
604 | | // vector operand, where a small immediate encoded in the instruction |
605 | | // specifies a full NEON vector value. These modified immediates are |
606 | | // represented here as encoded integers. The low 8 bits hold the immediate |
607 | | // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold |
608 | | // the "Cmode" field of the instruction. The interfaces below treat the |
609 | | // Op and Cmode values as a single 5-bit value. |
610 | | |
611 | | static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) |
612 | 0 | { |
613 | 0 | return (OpCmode << 8) | Val; |
614 | 0 | } Unexecuted instantiation: ARMDisassembler.c:createNEONModImm Unexecuted instantiation: ARMInstPrinter.c:createNEONModImm |
615 | | static inline unsigned getNEONModImmOpCmode(unsigned ModImm) |
616 | 2.82k | { |
617 | 2.82k | return (ModImm >> 8) & 0x1f; |
618 | 2.82k | } Unexecuted instantiation: ARMDisassembler.c:getNEONModImmOpCmode ARMInstPrinter.c:getNEONModImmOpCmode Line | Count | Source | 616 | 2.82k | { | 617 | 2.82k | return (ModImm >> 8) & 0x1f; | 618 | 2.82k | } |
|
619 | | static inline unsigned getNEONModImmVal(unsigned ModImm) |
620 | 2.82k | { |
621 | 2.82k | return ModImm & 0xff; |
622 | 2.82k | } Unexecuted instantiation: ARMDisassembler.c:getNEONModImmVal ARMInstPrinter.c:getNEONModImmVal Line | Count | Source | 620 | 2.82k | { | 621 | 2.82k | return ModImm & 0xff; | 622 | 2.82k | } |
|
623 | | |
624 | | /// decodeNEONModImm - Decode a NEON modified immediate value into the |
625 | | /// element value and the element size in bits. (If the element size is |
626 | | /// smaller than the vector, it is splatted into all the elements.) |
627 | | static inline uint64_t ARM_AM_decodeNEONModImm(unsigned ModImm, unsigned *EltBits) |
628 | 2.82k | { |
629 | 2.82k | unsigned OpCmode = getNEONModImmOpCmode(ModImm); |
630 | 2.82k | unsigned Imm8 = getNEONModImmVal(ModImm); |
631 | 2.82k | uint64_t Val = 0; |
632 | 2.82k | unsigned ByteNum; |
633 | | |
634 | 2.82k | if (OpCmode == 0xe) { |
635 | | // 8-bit vector elements |
636 | 102 | Val = Imm8; |
637 | 102 | *EltBits = 8; |
638 | 2.72k | } else if ((OpCmode & 0xc) == 0x8) { |
639 | | // 16-bit vector elements |
640 | 338 | ByteNum = (OpCmode & 0x6) >> 1; |
641 | 338 | Val = (uint64_t)Imm8 << (8 * ByteNum); |
642 | 338 | *EltBits = 16; |
643 | 2.38k | } else if ((OpCmode & 0x8) == 0) { |
644 | | // 32-bit vector elements, zero with one byte set |
645 | 787 | ByteNum = (OpCmode & 0x6) >> 1; |
646 | 787 | Val = (uint64_t)Imm8 << (8 * ByteNum); |
647 | 787 | *EltBits = 32; |
648 | 1.59k | } else if ((OpCmode & 0xe) == 0xc) { |
649 | | // 32-bit vector elements, one byte with low bits set |
650 | 926 | ByteNum = 1 + (OpCmode & 0x1); |
651 | 926 | Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); |
652 | 926 | *EltBits = 32; |
653 | 926 | } else if (OpCmode == 0x1e) { |
654 | | // 64-bit vector elements |
655 | 6.04k | for (ByteNum = 0; ByteNum < 8; ++ByteNum) { |
656 | 5.37k | if ((ModImm >> ByteNum) & 1) |
657 | 3.80k | Val |= (uint64_t)0xff << (8 * ByteNum); |
658 | 5.37k | } |
659 | 672 | *EltBits = 64; |
660 | 672 | } else { |
661 | | //llvm_unreachable("Unsupported NEON immediate"); |
662 | 0 | } |
663 | 2.82k | return Val; |
664 | 2.82k | } Unexecuted instantiation: ARMDisassembler.c:ARM_AM_decodeNEONModImm ARMInstPrinter.c:ARM_AM_decodeNEONModImm Line | Count | Source | 628 | 2.82k | { | 629 | 2.82k | unsigned OpCmode = getNEONModImmOpCmode(ModImm); | 630 | 2.82k | unsigned Imm8 = getNEONModImmVal(ModImm); | 631 | 2.82k | uint64_t Val = 0; | 632 | 2.82k | unsigned ByteNum; | 633 | | | 634 | 2.82k | if (OpCmode == 0xe) { | 635 | | // 8-bit vector elements | 636 | 102 | Val = Imm8; | 637 | 102 | *EltBits = 8; | 638 | 2.72k | } else if ((OpCmode & 0xc) == 0x8) { | 639 | | // 16-bit vector elements | 640 | 338 | ByteNum = (OpCmode & 0x6) >> 1; | 641 | 338 | Val = (uint64_t)Imm8 << (8 * ByteNum); | 642 | 338 | *EltBits = 16; | 643 | 2.38k | } else if ((OpCmode & 0x8) == 0) { | 644 | | // 32-bit vector elements, zero with one byte set | 645 | 787 | ByteNum = (OpCmode & 0x6) >> 1; | 646 | 787 | Val = (uint64_t)Imm8 << (8 * ByteNum); | 647 | 787 | *EltBits = 32; | 648 | 1.59k | } else if ((OpCmode & 0xe) == 0xc) { | 649 | | // 32-bit vector elements, one byte with low bits set | 650 | 926 | ByteNum = 1 + (OpCmode & 0x1); | 651 | 926 | Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); | 652 | 926 | *EltBits = 32; | 653 | 926 | } else if (OpCmode == 0x1e) { | 654 | | // 64-bit vector elements | 655 | 6.04k | for (ByteNum = 0; ByteNum < 8; ++ByteNum) { | 656 | 5.37k | if ((ModImm >> ByteNum) & 1) | 657 | 3.80k | Val |= (uint64_t)0xff << (8 * ByteNum); | 658 | 5.37k | } | 659 | 672 | *EltBits = 64; | 660 | 672 | } else { | 661 | | //llvm_unreachable("Unsupported NEON immediate"); | 662 | 0 | } | 663 | 2.82k | return Val; | 664 | 2.82k | } |
|
665 | | |
666 | | ARM_AM_AMSubMode getLoadStoreMultipleSubMode(int Opcode); |
667 | | |
668 | | //===--------------------------------------------------------------------===// |
669 | | // Floating-point Immediates |
670 | | // |
671 | | static inline float getFPImmFloat(unsigned Imm) |
672 | 1.36k | { |
673 | | // We expect an 8-bit binary encoding of a floating-point number here. |
674 | 1.36k | union { |
675 | 1.36k | uint32_t I; |
676 | 1.36k | float F; |
677 | 1.36k | } FPUnion; |
678 | | |
679 | 1.36k | uint8_t Sign = (Imm >> 7) & 0x1; |
680 | 1.36k | uint8_t Exp = (Imm >> 4) & 0x7; |
681 | 1.36k | uint8_t Mantissa = Imm & 0xf; |
682 | | |
683 | | // 8-bit FP iEEEE Float Encoding |
684 | | // abcd efgh aBbbbbbc defgh000 00000000 00000000 |
685 | | // |
686 | | // where B = NOT(b); |
687 | | |
688 | 1.36k | FPUnion.I = 0; |
689 | 1.36k | FPUnion.I |= ((uint32_t) Sign) << 31; |
690 | 1.36k | FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; |
691 | 1.36k | FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; |
692 | 1.36k | FPUnion.I |= (Exp & 0x3) << 23; |
693 | 1.36k | FPUnion.I |= Mantissa << 19; |
694 | 1.36k | return FPUnion.F; |
695 | 1.36k | } Unexecuted instantiation: ARMDisassembler.c:getFPImmFloat ARMInstPrinter.c:getFPImmFloat Line | Count | Source | 672 | 1.36k | { | 673 | | // We expect an 8-bit binary encoding of a floating-point number here. | 674 | 1.36k | union { | 675 | 1.36k | uint32_t I; | 676 | 1.36k | float F; | 677 | 1.36k | } FPUnion; | 678 | | | 679 | 1.36k | uint8_t Sign = (Imm >> 7) & 0x1; | 680 | 1.36k | uint8_t Exp = (Imm >> 4) & 0x7; | 681 | 1.36k | uint8_t Mantissa = Imm & 0xf; | 682 | | | 683 | | // 8-bit FP iEEEE Float Encoding | 684 | | // abcd efgh aBbbbbbc defgh000 00000000 00000000 | 685 | | // | 686 | | // where B = NOT(b); | 687 | | | 688 | 1.36k | FPUnion.I = 0; | 689 | 1.36k | FPUnion.I |= ((uint32_t) Sign) << 31; | 690 | 1.36k | FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; | 691 | 1.36k | FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; | 692 | 1.36k | FPUnion.I |= (Exp & 0x3) << 23; | 693 | 1.36k | FPUnion.I |= Mantissa << 19; | 694 | 1.36k | return FPUnion.F; | 695 | 1.36k | } |
|
696 | | |
697 | | #endif |
698 | | |