/src/capstonenext/arch/ARM/ARMAddressingModes.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine, http://www.capstone-engine.org */ |
2 | | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */ |
3 | | /* Rot127 <unisono@quyllur.org> 2022-2023 */ |
4 | | /* Automatically translated source file from LLVM. */ |
5 | | |
6 | | /* LLVM-commit: <commit> */ |
7 | | /* LLVM-tag: <tag> */ |
8 | | |
9 | | /* Only small edits allowed. */ |
10 | | /* For multiple similar edits, please create a Patch for the translator. */ |
11 | | |
12 | | /* Capstone's C++ file translator: */ |
13 | | /* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */ |
14 | | |
15 | | //===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===// |
16 | | // |
17 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
18 | | // See https://llvm.org/LICENSE.txt for license information. |
19 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
20 | | // |
21 | | //===----------------------------------------------------------------------===// |
22 | | // |
23 | | // This file contains the ARM addressing mode implementation stuff. |
24 | | // |
25 | | //===----------------------------------------------------------------------===// |
26 | | |
27 | | #ifndef CS_ARM_ADDRESSINGMODES_H |
28 | | #define CS_ARM_ADDRESSINGMODES_H |
29 | | |
30 | | #include "../../cs_priv.h" |
31 | | #include <capstone/platform.h> |
32 | | |
33 | | #include <assert.h> |
34 | | #include "../../MathExtras.h" |
35 | | |
36 | | #define CONCAT(a, b) CONCAT_(a, b) |
37 | | #define CONCAT_(a, b) a##_##b |
38 | | |
39 | | /// ARM_AM - ARM Addressing Mode Stuff |
40 | | // CS namespace begin: ARM_AM |
41 | | |
42 | | typedef enum ShiftOpc { |
43 | | ARM_AM_no_shift = 0, |
44 | | ARM_AM_asr, |
45 | | ARM_AM_lsl, |
46 | | ARM_AM_lsr, |
47 | | ARM_AM_ror, |
48 | | ARM_AM_rrx, |
49 | | ARM_AM_uxtw |
50 | | } ARM_AM_ShiftOpc; |
51 | | |
52 | | typedef enum AddrOpc { ARM_AM_sub = 0, ARM_AM_add } ARM_AM_AddrOpc; |
53 | | |
54 | | static inline const char *ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op) |
55 | 62.0k | { |
56 | 62.0k | return Op == ARM_AM_sub ? "-" : ""; |
57 | 62.0k | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAddrOpcStr Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAddrOpcStr Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAddrOpcStr ARMInstPrinter.c:ARM_AM_getAddrOpcStr Line | Count | Source | 55 | 62.0k | { | 56 | 62.0k | return Op == ARM_AM_sub ? "-" : ""; | 57 | 62.0k | } |
|
58 | | |
59 | | static inline const char *ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op) |
60 | 22.4k | { |
61 | 22.4k | switch (Op) { |
62 | 0 | default: |
63 | 0 | CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", NULL); |
64 | 4.95k | case ARM_AM_asr: |
65 | 4.95k | return "asr"; |
66 | 6.36k | case ARM_AM_lsl: |
67 | 6.36k | return "lsl"; |
68 | 5.28k | case ARM_AM_lsr: |
69 | 5.28k | return "lsr"; |
70 | 4.48k | case ARM_AM_ror: |
71 | 4.48k | return "ror"; |
72 | 1.07k | case ARM_AM_rrx: |
73 | 1.07k | return "rrx"; |
74 | 297 | case ARM_AM_uxtw: |
75 | 297 | return "uxtw"; |
76 | 22.4k | } |
77 | 22.4k | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getShiftOpcStr Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getShiftOpcStr Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getShiftOpcStr ARMInstPrinter.c:ARM_AM_getShiftOpcStr Line | Count | Source | 60 | 22.4k | { | 61 | 22.4k | switch (Op) { | 62 | 0 | default: | 63 | 0 | CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", NULL); | 64 | 4.95k | case ARM_AM_asr: | 65 | 4.95k | return "asr"; | 66 | 6.36k | case ARM_AM_lsl: | 67 | 6.36k | return "lsl"; | 68 | 5.28k | case ARM_AM_lsr: | 69 | 5.28k | return "lsr"; | 70 | 4.48k | case ARM_AM_ror: | 71 | 4.48k | return "ror"; | 72 | 1.07k | case ARM_AM_rrx: | 73 | 1.07k | return "rrx"; | 74 | 297 | case ARM_AM_uxtw: | 75 | 297 | return "uxtw"; | 76 | 22.4k | } | 77 | 22.4k | } |
|
78 | | |
79 | | static inline unsigned ARM_AM_getShiftOpcEncoding(ARM_AM_ShiftOpc Op) |
80 | 0 | { |
81 | 0 | switch (Op) { |
82 | 0 | default: |
83 | 0 | CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", 0); |
84 | 0 | case ARM_AM_asr: |
85 | 0 | return 2; |
86 | 0 | case ARM_AM_lsl: |
87 | 0 | return 0; |
88 | 0 | case ARM_AM_lsr: |
89 | 0 | return 1; |
90 | 0 | case ARM_AM_ror: |
91 | 0 | return 3; |
92 | 0 | } |
93 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getShiftOpcEncoding Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getShiftOpcEncoding Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getShiftOpcEncoding Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getShiftOpcEncoding |
94 | | |
95 | | typedef enum AMSubMode { |
96 | | ARM_AM_bad_am_submode = 0, |
97 | | ARM_AM_ia, |
98 | | ARM_AM_ib, |
99 | | ARM_AM_da, |
100 | | ARM_AM_db |
101 | | } ARM_AM_SubMode; |
102 | | |
103 | | static inline const char *ARM_AM_getAMSubModeStr(ARM_AM_SubMode Mode) |
104 | 0 | { |
105 | 0 | switch (Mode) { |
106 | 0 | default: |
107 | 0 | CS_ASSERT_RET_VAL(0 && "Unknown addressing sub-mode!", NULL); |
108 | 0 | case ARM_AM_ia: |
109 | 0 | return "ia"; |
110 | 0 | case ARM_AM_ib: |
111 | 0 | return "ib"; |
112 | 0 | case ARM_AM_da: |
113 | 0 | return "da"; |
114 | 0 | case ARM_AM_db: |
115 | 0 | return "db"; |
116 | 0 | } |
117 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAMSubModeStr Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAMSubModeStr Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAMSubModeStr Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAMSubModeStr |
118 | | |
119 | | //===--------------------------------------------------------------------===// |
120 | | // Addressing Mode #1: shift_operand with registers |
121 | | //===--------------------------------------------------------------------===// |
122 | | // |
123 | | // This 'addressing mode' is used for arithmetic instructions. It can |
124 | | // represent things like: |
125 | | // reg |
126 | | // reg [asr|lsl|lsr|ror|rrx] reg |
127 | | // reg [asr|lsl|lsr|ror|rrx] imm |
128 | | // |
129 | | // This is stored three operands [rega, regb, opc]. The first is the base |
130 | | // reg, the second is the shift amount (or reg0 if not present or imm). The |
131 | | // third operand encodes the shift opcode and the imm if a reg isn't present. |
132 | | static inline unsigned ARM_AM_rotr32(unsigned Val, unsigned Amt) |
133 | 44.7k | { |
134 | 44.7k | CS_ASSERT(Amt <= 32); |
135 | 44.7k | if (Amt == 32) { |
136 | 0 | return Val; |
137 | 0 | } |
138 | 44.7k | return (Val >> Amt) | |
139 | 44.7k | (Val << ((32 - Amt) & |
140 | 44.7k | 31)); // NOLINT(clang-analyzer-core.BitwiseShift) |
141 | 44.7k | } ARMMapping.c:ARM_AM_rotr32 Line | Count | Source | 133 | 25.0k | { | 134 | 25.0k | CS_ASSERT(Amt <= 32); | 135 | 25.0k | if (Amt == 32) { | 136 | 0 | return Val; | 137 | 0 | } | 138 | 25.0k | return (Val >> Amt) | | 139 | 25.0k | (Val << ((32 - Amt) & | 140 | 25.0k | 31)); // NOLINT(clang-analyzer-core.BitwiseShift) | 141 | 25.0k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_rotr32 Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_rotr32 ARMInstPrinter.c:ARM_AM_rotr32 Line | Count | Source | 133 | 19.7k | { | 134 | 19.7k | CS_ASSERT(Amt <= 32); | 135 | 19.7k | if (Amt == 32) { | 136 | 0 | return Val; | 137 | 0 | } | 138 | 19.7k | return (Val >> Amt) | | 139 | 19.7k | (Val << ((32 - Amt) & | 140 | 19.7k | 31)); // NOLINT(clang-analyzer-core.BitwiseShift) | 141 | 19.7k | } |
|
142 | | |
143 | | static inline unsigned ARM_AM_rotl32(unsigned Val, unsigned Amt) |
144 | 10.6k | { |
145 | 10.6k | return (Val << Amt) | (Val >> ((32 - Amt) & 31)); |
146 | 10.6k | } ARMMapping.c:ARM_AM_rotl32 Line | Count | Source | 144 | 5.33k | { | 145 | 5.33k | return (Val << Amt) | (Val >> ((32 - Amt) & 31)); | 146 | 5.33k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_rotl32 Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_rotl32 ARMInstPrinter.c:ARM_AM_rotl32 Line | Count | Source | 144 | 5.33k | { | 145 | 5.33k | return (Val << Amt) | (Val >> ((32 - Amt) & 31)); | 146 | 5.33k | } |
|
147 | | |
148 | | static inline unsigned ARM_AM_getSORegOpc(ARM_AM_ShiftOpc ShOp, unsigned Imm) |
149 | 0 | { |
150 | 0 | return ShOp | (Imm << 3); |
151 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getSORegOpc Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegOpc Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSORegOpc Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getSORegOpc |
152 | | |
153 | | static inline unsigned ARM_AM_getSORegOffset(unsigned Op) |
154 | 22.6k | { |
155 | 22.6k | return Op >> 3; |
156 | 22.6k | } ARMMapping.c:ARM_AM_getSORegOffset Line | Count | Source | 154 | 11.2k | { | 155 | 11.2k | return Op >> 3; | 156 | 11.2k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegOffset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSORegOffset ARMInstPrinter.c:ARM_AM_getSORegOffset Line | Count | Source | 154 | 11.3k | { | 155 | 11.3k | return Op >> 3; | 156 | 11.3k | } |
|
157 | | |
158 | | static inline ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op) |
159 | 55.7k | { |
160 | 55.7k | return (ARM_AM_ShiftOpc)(Op & 7); |
161 | 55.7k | } ARMMapping.c:ARM_AM_getSORegShOp Line | Count | Source | 159 | 19.5k | { | 160 | 19.5k | return (ARM_AM_ShiftOpc)(Op & 7); | 161 | 19.5k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegShOp Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSORegShOp ARMInstPrinter.c:ARM_AM_getSORegShOp Line | Count | Source | 159 | 36.1k | { | 160 | 36.1k | return (ARM_AM_ShiftOpc)(Op & 7); | 161 | 36.1k | } |
|
162 | | |
163 | | /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return |
164 | | /// the 8-bit imm value. |
165 | | static inline unsigned ARM_AM_getSOImmValImm(unsigned Imm) |
166 | 0 | { |
167 | 0 | return Imm & 0xFF; |
168 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getSOImmValImm Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmValImm Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmValImm Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getSOImmValImm |
169 | | |
170 | | /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return |
171 | | /// the rotate amount. |
172 | | static inline unsigned ARM_AM_getSOImmValRot(unsigned Imm) |
173 | 0 | { |
174 | 0 | return (Imm >> 8) * 2; |
175 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getSOImmValRot Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmValRot Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmValRot Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getSOImmValRot |
176 | | |
177 | | /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, |
178 | | /// computing the rotate amount to use. If this immediate value cannot be |
179 | | /// handled with a single shifter-op, determine a good rotate amount that will |
180 | | /// take a maximal chunk of bits out of the immediate. |
181 | | static inline unsigned ARM_AM_getSOImmValRotate(unsigned Imm) |
182 | 10.6k | { |
183 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate |
184 | | // of zero. |
185 | 10.6k | if ((Imm & ~255U) == 0) |
186 | 0 | return 0; |
187 | | |
188 | | // Use CTZ to compute the rotate amount. |
189 | 10.6k | unsigned TZ = CountTrailingZeros_32(Imm); |
190 | | |
191 | | // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, |
192 | | // not 9. |
193 | 10.6k | unsigned RotAmt = TZ & ~1; |
194 | | |
195 | | // If we can handle this spread, return it. |
196 | 10.6k | if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0) |
197 | 4.97k | return (32 - RotAmt) & 31; // HW rotates right, not left. |
198 | | |
199 | | // For values like 0xF000000F, we should ignore the low 6 bits, then |
200 | | // retry the hunt. |
201 | 5.69k | if (Imm & 63U) { |
202 | 5.69k | unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); |
203 | 5.69k | unsigned RotAmt2 = TZ2 & ~1; |
204 | 5.69k | if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0) |
205 | 5.69k | return (32 - RotAmt2) & |
206 | 5.69k | 31; // HW rotates right, not left. |
207 | 5.69k | } |
208 | | |
209 | | // Otherwise, we have no way to cover this span of bits with a single |
210 | | // shifter_op immediate. Return a chunk of bits that will be useful to |
211 | | // handle. |
212 | 0 | return (32 - RotAmt) & 31; // HW rotates right, not left. |
213 | 5.69k | } ARMMapping.c:ARM_AM_getSOImmValRotate Line | Count | Source | 182 | 5.33k | { | 183 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 184 | | // of zero. | 185 | 5.33k | if ((Imm & ~255U) == 0) | 186 | 0 | return 0; | 187 | | | 188 | | // Use CTZ to compute the rotate amount. | 189 | 5.33k | unsigned TZ = CountTrailingZeros_32(Imm); | 190 | | | 191 | | // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, | 192 | | // not 9. | 193 | 5.33k | unsigned RotAmt = TZ & ~1; | 194 | | | 195 | | // If we can handle this spread, return it. | 196 | 5.33k | if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0) | 197 | 2.48k | return (32 - RotAmt) & 31; // HW rotates right, not left. | 198 | | | 199 | | // For values like 0xF000000F, we should ignore the low 6 bits, then | 200 | | // retry the hunt. | 201 | 2.84k | if (Imm & 63U) { | 202 | 2.84k | unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); | 203 | 2.84k | unsigned RotAmt2 = TZ2 & ~1; | 204 | 2.84k | if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0) | 205 | 2.84k | return (32 - RotAmt2) & | 206 | 2.84k | 31; // HW rotates right, not left. | 207 | 2.84k | } | 208 | | | 209 | | // Otherwise, we have no way to cover this span of bits with a single | 210 | | // shifter_op immediate. Return a chunk of bits that will be useful to | 211 | | // handle. | 212 | 0 | return (32 - RotAmt) & 31; // HW rotates right, not left. | 213 | 2.84k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmValRotate Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmValRotate ARMInstPrinter.c:ARM_AM_getSOImmValRotate Line | Count | Source | 182 | 5.33k | { | 183 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 184 | | // of zero. | 185 | 5.33k | if ((Imm & ~255U) == 0) | 186 | 0 | return 0; | 187 | | | 188 | | // Use CTZ to compute the rotate amount. | 189 | 5.33k | unsigned TZ = CountTrailingZeros_32(Imm); | 190 | | | 191 | | // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, | 192 | | // not 9. | 193 | 5.33k | unsigned RotAmt = TZ & ~1; | 194 | | | 195 | | // If we can handle this spread, return it. | 196 | 5.33k | if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0) | 197 | 2.48k | return (32 - RotAmt) & 31; // HW rotates right, not left. | 198 | | | 199 | | // For values like 0xF000000F, we should ignore the low 6 bits, then | 200 | | // retry the hunt. | 201 | 2.84k | if (Imm & 63U) { | 202 | 2.84k | unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); | 203 | 2.84k | unsigned RotAmt2 = TZ2 & ~1; | 204 | 2.84k | if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0) | 205 | 2.84k | return (32 - RotAmt2) & | 206 | 2.84k | 31; // HW rotates right, not left. | 207 | 2.84k | } | 208 | | | 209 | | // Otherwise, we have no way to cover this span of bits with a single | 210 | | // shifter_op immediate. Return a chunk of bits that will be useful to | 211 | | // handle. | 212 | 0 | return (32 - RotAmt) & 31; // HW rotates right, not left. | 213 | 2.84k | } |
|
214 | | |
215 | | /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit |
216 | | /// into an shifter_operand immediate operand, return the 12-bit encoding for |
217 | | /// it. If not, return -1. |
218 | | static inline int ARM_AM_getSOImmVal(unsigned Arg) |
219 | 12.4k | { |
220 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate |
221 | | // of zero. |
222 | 12.4k | if ((Arg & ~255U) == 0) |
223 | 1.74k | return Arg; |
224 | | |
225 | 10.6k | unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg); |
226 | | |
227 | | // If this cannot be handled with a single shifter_op, bail out. |
228 | 10.6k | if (ARM_AM_rotr32(~255U, RotAmt) & Arg) |
229 | 0 | return -1; |
230 | | |
231 | | // Encode this correctly. |
232 | 10.6k | return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8); |
233 | 10.6k | } ARMMapping.c:ARM_AM_getSOImmVal Line | Count | Source | 219 | 6.20k | { | 220 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 221 | | // of zero. | 222 | 6.20k | if ((Arg & ~255U) == 0) | 223 | 871 | return Arg; | 224 | | | 225 | 5.33k | unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg); | 226 | | | 227 | | // If this cannot be handled with a single shifter_op, bail out. | 228 | 5.33k | if (ARM_AM_rotr32(~255U, RotAmt) & Arg) | 229 | 0 | return -1; | 230 | | | 231 | | // Encode this correctly. | 232 | 5.33k | return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8); | 233 | 5.33k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmVal ARMInstPrinter.c:ARM_AM_getSOImmVal Line | Count | Source | 219 | 6.20k | { | 220 | | // 8-bit (or less) immediates are trivially shifter_operands with a rotate | 221 | | // of zero. | 222 | 6.20k | if ((Arg & ~255U) == 0) | 223 | 871 | return Arg; | 224 | | | 225 | 5.33k | unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg); | 226 | | | 227 | | // If this cannot be handled with a single shifter_op, bail out. | 228 | 5.33k | if (ARM_AM_rotr32(~255U, RotAmt) & Arg) | 229 | 0 | return -1; | 230 | | | 231 | | // Encode this correctly. | 232 | 5.33k | return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8); | 233 | 5.33k | } |
|
234 | | |
235 | | /// isSOImmTwoPartVal - Return true if the specified value can be obtained by |
236 | | /// or'ing together two SOImmVal's. |
237 | | static inline bool ARM_AM_isSOImmTwoPartVal(unsigned V) |
238 | 0 | { |
239 | 0 | // If this can be handled with a single shifter_op, bail out. |
240 | 0 | V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V; |
241 | 0 | if (V == 0) |
242 | 0 | return false; |
243 | 0 |
|
244 | 0 | // If this can be handled with two shifter_op's, accept. |
245 | 0 | V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V; |
246 | 0 | return V == 0; |
247 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isSOImmTwoPartVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isSOImmTwoPartVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isSOImmTwoPartVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isSOImmTwoPartVal |
248 | | |
249 | | /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, |
250 | | /// return the first chunk of it. |
251 | | static inline unsigned ARM_AM_getSOImmTwoPartFirst(unsigned V) |
252 | 0 | { |
253 | 0 | return ARM_AM_rotr32(255U, ARM_AM_getSOImmValRotate(V)) & V; |
254 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getSOImmTwoPartFirst Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmTwoPartFirst Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmTwoPartFirst Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getSOImmTwoPartFirst |
255 | | |
256 | | /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, |
257 | | /// return the second chunk of it. |
258 | | static inline unsigned ARM_AM_getSOImmTwoPartSecond(unsigned V) |
259 | 0 | { |
260 | 0 | // Mask out the first hunk. |
261 | 0 | V = ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(V)) & V; |
262 | 0 |
|
263 | 0 | // Take what's left. |
264 | 0 |
|
265 | 0 | return V; |
266 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getSOImmTwoPartSecond Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmTwoPartSecond Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmTwoPartSecond Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getSOImmTwoPartSecond |
267 | | |
268 | | /// isSOImmTwoPartValNeg - Return true if the specified value can be obtained |
269 | | /// by two SOImmVal, that -V = First + Second. |
270 | | /// "R+V" can be optimized to (sub (sub R, First), Second). |
271 | | /// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second). |
272 | | static inline bool ARM_AM_isSOImmTwoPartValNeg(unsigned V) |
273 | 0 | { |
274 | 0 | unsigned First; |
275 | 0 | if (!ARM_AM_isSOImmTwoPartVal(-V)) |
276 | 0 | return false; |
277 | 0 | // Return false if ~(-First) is not a SoImmval. |
278 | 0 | First = ARM_AM_getSOImmTwoPartFirst(-V); |
279 | 0 | First = ~(-First); |
280 | 0 | return !(ARM_AM_rotr32(~255U, ARM_AM_getSOImmValRotate(First)) & First); |
281 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isSOImmTwoPartValNeg Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isSOImmTwoPartValNeg Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isSOImmTwoPartValNeg Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isSOImmTwoPartValNeg |
282 | | |
283 | | /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed |
284 | | /// by a left shift. Returns the shift amount to use. |
285 | | static inline unsigned ARM_AM_getThumbImmValShift(unsigned Imm) |
286 | 0 | { |
287 | 0 | // 8-bit (or less) immediates are trivially immediate operand with a shift |
288 | 0 | // of zero. |
289 | 0 | if ((Imm & ~255U) == 0) |
290 | 0 | return 0; |
291 | 0 |
|
292 | 0 | // Use CTZ to compute the shift amount. |
293 | 0 | return CountTrailingZeros_32(Imm); |
294 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getThumbImmValShift Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getThumbImmValShift Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getThumbImmValShift Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getThumbImmValShift |
295 | | |
296 | | /// isThumbImmShiftedVal - Return true if the specified value can be obtained |
297 | | /// by left shifting a 8-bit immediate. |
298 | | static inline bool ARM_AM_isThumbImmShiftedVal(unsigned V) |
299 | 0 | { |
300 | 0 | // If this can be handled with |
301 | 0 | V = (~255U << ARM_AM_getThumbImmValShift(V)) & V; |
302 | 0 | return V == 0; |
303 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isThumbImmShiftedVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isThumbImmShiftedVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isThumbImmShiftedVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isThumbImmShiftedVal |
304 | | |
305 | | /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed |
306 | | /// by a left shift. Returns the shift amount to use. |
307 | | static inline unsigned ARM_AM_getThumbImm16ValShift(unsigned Imm) |
308 | 0 | { |
309 | 0 | // 16-bit (or less) immediates are trivially immediate operand with a shift |
310 | 0 | // of zero. |
311 | 0 | if ((Imm & ~65535U) == 0) |
312 | 0 | return 0; |
313 | 0 |
|
314 | 0 | // Use CTZ to compute the shift amount. |
315 | 0 | return CountTrailingZeros_32(Imm); |
316 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getThumbImm16ValShift Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getThumbImm16ValShift Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getThumbImm16ValShift Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getThumbImm16ValShift |
317 | | |
318 | | /// isThumbImm16ShiftedVal - Return true if the specified value can be |
319 | | /// obtained by left shifting a 16-bit immediate. |
320 | | static inline bool ARM_AM_isThumbImm16ShiftedVal(unsigned V) |
321 | 0 | { |
322 | 0 | // If this can be handled with |
323 | 0 | V = (~65535U << ARM_AM_getThumbImm16ValShift(V)) & V; |
324 | 0 | return V == 0; |
325 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isThumbImm16ShiftedVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isThumbImm16ShiftedVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isThumbImm16ShiftedVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isThumbImm16ShiftedVal |
326 | | |
327 | | /// getThumbImmNonShiftedVal - If V is a value that satisfies |
328 | | /// isThumbImmShiftedVal, return the non-shiftd value. |
329 | | static inline unsigned ARM_AM_getThumbImmNonShiftedVal(unsigned V) |
330 | 0 | { |
331 | 0 | return V >> ARM_AM_getThumbImmValShift(V); |
332 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getThumbImmNonShiftedVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getThumbImmNonShiftedVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getThumbImmNonShiftedVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getThumbImmNonShiftedVal |
333 | | |
334 | | /// getT2SOImmValSplat - Return the 12-bit encoded representation |
335 | | /// if the specified value can be obtained by splatting the low 8 bits |
336 | | /// into every other byte or every byte of a 32-bit value. i.e., |
337 | | /// 00000000 00000000 00000000 abcdefgh control = 0 |
338 | | /// 00000000 abcdefgh 00000000 abcdefgh control = 1 |
339 | | /// abcdefgh 00000000 abcdefgh 00000000 control = 2 |
340 | | /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 |
341 | | /// Return -1 if none of the above apply. |
342 | | /// See ARM Reference Manual A6.3.2. |
343 | | static inline int ARM_AM_getT2SOImmValSplatVal(unsigned V) |
344 | 0 | { |
345 | 0 | unsigned u, Vs, Imm; |
346 | 0 | // control = 0 |
347 | 0 | if ((V & 0xffffff00) == 0) |
348 | 0 | return V; |
349 | 0 |
|
350 | 0 | // If the value is zeroes in the first byte, just shift those off |
351 | 0 | Vs = ((V & 0xff) == 0) ? V >> 8 : V; |
352 | 0 | // Any passing value only has 8 bits of payload, splatted across the word |
353 | 0 | Imm = Vs & 0xff; |
354 | 0 | // Likewise, any passing values have the payload splatted into the 3rd byte |
355 | 0 | u = Imm | (Imm << 16); |
356 | 0 |
|
357 | 0 | // control = 1 or 2 |
358 | 0 | if (Vs == u) |
359 | 0 | return (((Vs == V) ? 1 : 2) << 8) | Imm; |
360 | 0 |
|
361 | 0 | // control = 3 |
362 | 0 | if (Vs == (u | (u << 8))) |
363 | 0 | return (3 << 8) | Imm; |
364 | 0 |
|
365 | 0 | return -1; |
366 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmValSplatVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmValSplatVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmValSplatVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmValSplatVal |
367 | | |
368 | | /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the |
369 | | /// specified value is a rotated 8-bit value. Return -1 if no rotation |
370 | | /// encoding is possible. |
371 | | /// See ARM Reference Manual A6.3.2. |
372 | | static inline int ARM_AM_getT2SOImmValRotateVal(unsigned V) |
373 | 0 | { |
374 | 0 | unsigned RotAmt = CountLeadingZeros_32(V); |
375 | 0 | if (RotAmt >= 24) |
376 | 0 | return -1; |
377 | 0 |
|
378 | 0 | // If 'Arg' can be handled with a single shifter_op return the value. |
379 | 0 | if ((ARM_AM_rotr32(0xff000000U, RotAmt) & V) == V) |
380 | 0 | return (ARM_AM_rotr32(V, 24 - RotAmt) & 0x7f) | |
381 | 0 | ((RotAmt + 8) << 7); |
382 | 0 |
|
383 | 0 | return -1; |
384 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmValRotateVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmValRotateVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmValRotateVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmValRotateVal |
385 | | |
386 | | /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit |
387 | | /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit |
388 | | /// encoding for it. If not, return -1. |
389 | | /// See ARM Reference Manual A6.3.2. |
390 | | static inline int ARM_AM_getT2SOImmVal(unsigned Arg) |
391 | 0 | { |
392 | 0 | // If 'Arg' is an 8-bit splat, then get the encoded value. |
393 | 0 | int Splat = ARM_AM_getT2SOImmValSplatVal(Arg); |
394 | 0 | if (Splat != -1) |
395 | 0 | return Splat; |
396 | 0 |
|
397 | 0 | // If 'Arg' can be handled with a single shifter_op return the value. |
398 | 0 | int Rot = ARM_AM_getT2SOImmValRotateVal(Arg); |
399 | 0 | if (Rot != -1) |
400 | 0 | return Rot; |
401 | 0 |
|
402 | 0 | return -1; |
403 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmVal |
404 | | |
405 | | static inline unsigned ARM_AM_getT2SOImmValRotate(unsigned V) |
406 | 0 | { |
407 | 0 | if ((V & ~255U) == 0) |
408 | 0 | return 0; |
409 | 0 | // Use CTZ to compute the rotate amount. |
410 | 0 | unsigned RotAmt = CountTrailingZeros_32(V); |
411 | 0 | return (32 - RotAmt) & 31; |
412 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmValRotate Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmValRotate Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmValRotate Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmValRotate |
413 | | |
414 | | static inline bool ARM_AM_isT2SOImmTwoPartVal(unsigned Imm) |
415 | 0 | { |
416 | 0 | unsigned V = Imm; |
417 | 0 | // Passing values can be any combination of splat values and shifter |
418 | 0 | // values. If this can be handled with a single shifter or splat, bail |
419 | 0 | // out. Those should be handled directly, not with a two-part val. |
420 | 0 | if (ARM_AM_getT2SOImmValSplatVal(V) != -1) |
421 | 0 | return false; |
422 | 0 | V = ARM_AM_rotr32(~255U, ARM_AM_getT2SOImmValRotate(V)) & V; |
423 | 0 | if (V == 0) |
424 | 0 | return false; |
425 | 0 |
|
426 | 0 | // If this can be handled as an immediate, accept. |
427 | 0 | if (ARM_AM_getT2SOImmVal(V) != -1) |
428 | 0 | return true; |
429 | 0 |
|
430 | 0 | // Likewise, try masking out a splat value first. |
431 | 0 | V = Imm; |
432 | 0 | if (ARM_AM_getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) |
433 | 0 | V &= ~0xff00ff00U; |
434 | 0 | else if (ARM_AM_getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) |
435 | 0 | V &= ~0x00ff00ffU; |
436 | 0 | // If what's left can be handled as an immediate, accept. |
437 | 0 | if (ARM_AM_getT2SOImmVal(V) != -1) |
438 | 0 | return true; |
439 | 0 |
|
440 | 0 | // Otherwise, do not accept. |
441 | 0 | return false; |
442 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isT2SOImmTwoPartVal Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isT2SOImmTwoPartVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isT2SOImmTwoPartVal Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isT2SOImmTwoPartVal |
443 | | |
444 | | static inline unsigned ARM_AM_getT2SOImmTwoPartFirst(unsigned Imm) |
445 | 0 | { |
446 | 0 | CS_ASSERT(ARM_AM_isT2SOImmTwoPartVal(Imm) && |
447 | 0 | "Immedate cannot be encoded as two part immediate!"); |
448 | 0 | // Try a shifter operand as one part |
449 | 0 | unsigned V = ARM_AM_rotr32(~255, ARM_AM_getT2SOImmValRotate(Imm)) & Imm; |
450 | 0 | // If the rest is encodable as an immediate, then return it. |
451 | 0 | if (ARM_AM_getT2SOImmVal(V) != -1) |
452 | 0 | return V; |
453 | 0 |
|
454 | 0 | // Try masking out a splat value first. |
455 | 0 | if (ARM_AM_getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) |
456 | 0 | return Imm & 0xff00ff00U; |
457 | 0 |
|
458 | 0 | // The other splat is all that's left as an option. |
459 | 0 | CS_ASSERT(ARM_AM_getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); |
460 | 0 | return Imm & 0x00ff00ffU; |
461 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmTwoPartFirst Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmTwoPartFirst Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmTwoPartFirst Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmTwoPartFirst |
462 | | |
463 | | static inline unsigned ARM_AM_getT2SOImmTwoPartSecond(unsigned Imm) |
464 | 0 | { |
465 | 0 | // Mask out the first hunk |
466 | 0 | Imm ^= ARM_AM_getT2SOImmTwoPartFirst(Imm); |
467 | 0 | // Return what's left |
468 | 0 | CS_ASSERT(ARM_AM_getT2SOImmVal(Imm) != -1 && |
469 | 0 | "Unable to encode second part of T2 two part SO immediate"); |
470 | 0 | return Imm; |
471 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getT2SOImmTwoPartSecond Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getT2SOImmTwoPartSecond Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getT2SOImmTwoPartSecond Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getT2SOImmTwoPartSecond |
472 | | |
473 | | //===--------------------------------------------------------------------===// |
474 | | // Addressing Mode #2 |
475 | | //===--------------------------------------------------------------------===// |
476 | | // |
477 | | // This is used for most simple load/store instructions. |
478 | | // |
479 | | // addrmode2 := reg +/- reg shop imm |
480 | | // addrmode2 := reg +/- imm12 |
481 | | // |
482 | | // The first operand is always a Reg. The second operand is a reg if in |
483 | | // reg/reg form, otherwise it's reg#0. The third field encodes the operation |
484 | | // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The |
485 | | // fourth operand 16-17 encodes the index mode. |
486 | | // |
487 | | // If this addressing mode is a frame index (before prolog/epilog insertion |
488 | | // and code rewriting), this operand will have the form: FI#, reg0, <offs> |
489 | | // with no shift amount for the frame offset. |
490 | | // |
491 | | static inline unsigned ARM_AM_getAM2Opc(ARM_AM_AddrOpc Opc, unsigned Imm12, |
492 | | ARM_AM_ShiftOpc SO, unsigned IdxMode) |
493 | 27.3k | { |
494 | 27.3k | CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!"); |
495 | 27.3k | bool isSub = Opc == ARM_AM_sub; |
496 | 27.3k | return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16); |
497 | 27.3k | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM2Opc ARMDisassembler.c:ARM_AM_getAM2Opc Line | Count | Source | 493 | 27.3k | { | 494 | 27.3k | CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!"); | 495 | 27.3k | bool isSub = Opc == ARM_AM_sub; | 496 | 27.3k | return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16); | 497 | 27.3k | } |
Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2Opc Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM2Opc |
498 | | |
499 | | static inline unsigned ARM_AM_getAM2Offset(unsigned AM2Opc) |
500 | 27.7k | { |
501 | 27.7k | return AM2Opc & ((1 << 12) - 1); |
502 | 27.7k | } ARMMapping.c:ARM_AM_getAM2Offset Line | Count | Source | 500 | 15.8k | { | 501 | 15.8k | return AM2Opc & ((1 << 12) - 1); | 502 | 15.8k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2Offset ARMInstPrinter.c:ARM_AM_getAM2Offset Line | Count | Source | 500 | 11.9k | { | 501 | 11.9k | return AM2Opc & ((1 << 12) - 1); | 502 | 11.9k | } |
|
503 | | |
504 | | static inline ARM_AM_AddrOpc ARM_AM_getAM2Op(unsigned AM2Opc) |
505 | 23.3k | { |
506 | 23.3k | return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add; |
507 | 23.3k | } ARMMapping.c:ARM_AM_getAM2Op Line | Count | Source | 505 | 11.6k | { | 506 | 11.6k | return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add; | 507 | 11.6k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2Op ARMInstPrinter.c:ARM_AM_getAM2Op Line | Count | Source | 505 | 11.6k | { | 506 | 11.6k | return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add; | 507 | 11.6k | } |
|
508 | | |
509 | | static inline ARM_AM_ShiftOpc ARM_AM_getAM2ShiftOpc(unsigned AM2Opc) |
510 | 14.0k | { |
511 | 14.0k | return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7); |
512 | 14.0k | } ARMMapping.c:ARM_AM_getAM2ShiftOpc Line | Count | Source | 510 | 7.04k | { | 511 | 7.04k | return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7); | 512 | 7.04k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2ShiftOpc Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2ShiftOpc ARMInstPrinter.c:ARM_AM_getAM2ShiftOpc Line | Count | Source | 510 | 7.04k | { | 511 | 7.04k | return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7); | 512 | 7.04k | } |
|
513 | | |
514 | | static inline unsigned ARM_AM_getAM2IdxMode(unsigned AM2Opc) |
515 | 0 | { |
516 | 0 | return (AM2Opc >> 16); |
517 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM2IdxMode Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2IdxMode Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2IdxMode Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM2IdxMode |
518 | | |
519 | | //===--------------------------------------------------------------------===// |
520 | | // Addressing Mode #3 |
521 | | //===--------------------------------------------------------------------===// |
522 | | // |
523 | | // This is used for sign-extending loads, and load/store-pair instructions. |
524 | | // |
525 | | // addrmode3 := reg +/- reg |
526 | | // addrmode3 := reg +/- imm8 |
527 | | // |
528 | | // The first operand is always a Reg. The second operand is a reg if in |
529 | | // reg/reg form, otherwise it's reg#0. The third field encodes the operation |
530 | | // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the |
531 | | // index mode. |
532 | | /// getAM3Opc - This function encodes the addrmode3 opc field. |
533 | | static inline unsigned ARM_AM_getAM3Opc(ARM_AM_AddrOpc Opc, |
534 | | unsigned char Offset, unsigned IdxMode) |
535 | 0 | { |
536 | 0 | bool isSub = Opc == ARM_AM_sub; |
537 | 0 | return ((int)isSub << 8) | Offset | (IdxMode << 9); |
538 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM3Opc Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3Opc Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3Opc Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM3Opc |
539 | | |
540 | | static inline unsigned char ARM_AM_getAM3Offset(unsigned AM3Opc) |
541 | 4.96k | { |
542 | 4.96k | return AM3Opc & 0xFF; |
543 | 4.96k | } ARMMapping.c:ARM_AM_getAM3Offset Line | Count | Source | 541 | 2.48k | { | 542 | 2.48k | return AM3Opc & 0xFF; | 543 | 2.48k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3Offset ARMInstPrinter.c:ARM_AM_getAM3Offset Line | Count | Source | 541 | 2.48k | { | 542 | 2.48k | return AM3Opc & 0xFF; | 543 | 2.48k | } |
|
544 | | |
545 | | static inline ARM_AM_AddrOpc ARM_AM_getAM3Op(unsigned AM3Opc) |
546 | 10.9k | { |
547 | 10.9k | return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
548 | 10.9k | } ARMMapping.c:ARM_AM_getAM3Op Line | Count | Source | 546 | 5.47k | { | 547 | 5.47k | return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 548 | 5.47k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3Op ARMInstPrinter.c:ARM_AM_getAM3Op Line | Count | Source | 546 | 5.47k | { | 547 | 5.47k | return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 548 | 5.47k | } |
|
549 | | |
550 | | static inline unsigned ARM_AM_getAM3IdxMode(unsigned AM3Opc) |
551 | 0 | { |
552 | 0 | return (AM3Opc >> 9); |
553 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM3IdxMode Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3IdxMode Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3IdxMode Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM3IdxMode |
554 | | |
555 | | //===--------------------------------------------------------------------===// |
556 | | // Addressing Mode #4 |
557 | | //===--------------------------------------------------------------------===// |
558 | | // |
559 | | // This is used for load / store multiple instructions. |
560 | | // |
561 | | // addrmode4 := reg, <mode> |
562 | | // |
563 | | // The four modes are: |
564 | | // IA - Increment after |
565 | | // IB - Increment before |
566 | | // DA - Decrement after |
567 | | // DB - Decrement before |
568 | | // For VFP instructions, only the IA and DB modes are valid. |
569 | | static inline ARM_AM_SubMode ARM_AM_getAM4SubMode(unsigned Mode) |
570 | 0 | { |
571 | 0 | return (ARM_AM_SubMode)(Mode & 0x7); |
572 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM4SubMode Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM4SubMode Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM4SubMode Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM4SubMode |
573 | | |
574 | | static inline unsigned ARM_AM_getAM4ModeImm(ARM_AM_SubMode SubMode) |
575 | 0 | { |
576 | 0 | return (int)SubMode; |
577 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM4ModeImm Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM4ModeImm Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM4ModeImm Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM4ModeImm |
578 | | |
579 | | //===--------------------------------------------------------------------===// |
580 | | // Addressing Mode #5 |
581 | | //===--------------------------------------------------------------------===// |
582 | | // |
583 | | // This is used for coprocessor instructions, such as FP load/stores. |
584 | | // |
585 | | // addrmode5 := reg +/- imm8*4 |
586 | | // |
587 | | // The first operand is always a Reg. The second operand encodes the |
588 | | // operation (add or subtract) in bit 8 and the immediate in bits 0-7. |
589 | | /// getAM5Opc - This function encodes the addrmode5 opc field. |
590 | | static inline unsigned ARM_AM_getAM5Opc(ARM_AM_AddrOpc Opc, |
591 | | unsigned char Offset) |
592 | 23.9k | { |
593 | 23.9k | bool isSub = Opc == ARM_AM_sub; |
594 | 23.9k | return ((int)isSub << 8) | Offset; |
595 | 23.9k | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5Opc ARMDisassembler.c:ARM_AM_getAM5Opc Line | Count | Source | 592 | 23.9k | { | 593 | 23.9k | bool isSub = Opc == ARM_AM_sub; | 594 | 23.9k | return ((int)isSub << 8) | Offset; | 595 | 23.9k | } |
Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5Opc Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM5Opc |
596 | | |
597 | | static inline unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc) |
598 | 36.6k | { |
599 | 36.6k | return AM5Opc & 0xFF; |
600 | 36.6k | } ARMMapping.c:ARM_AM_getAM5Offset Line | Count | Source | 598 | 12.6k | { | 599 | 12.6k | return AM5Opc & 0xFF; | 600 | 12.6k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5Offset ARMInstPrinter.c:ARM_AM_getAM5Offset Line | Count | Source | 598 | 23.9k | { | 599 | 23.9k | return AM5Opc & 0xFF; | 600 | 23.9k | } |
|
601 | | |
602 | | static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc) |
603 | 36.6k | { |
604 | 36.6k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
605 | 36.6k | } ARMMapping.c:ARM_AM_getAM5Op Line | Count | Source | 603 | 12.6k | { | 604 | 12.6k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 605 | 12.6k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5Op ARMInstPrinter.c:ARM_AM_getAM5Op Line | Count | Source | 603 | 23.9k | { | 604 | 23.9k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 605 | 23.9k | } |
|
606 | | |
607 | | //===--------------------------------------------------------------------===// |
608 | | // Addressing Mode #5 FP16 |
609 | | //===--------------------------------------------------------------------===// |
610 | | // |
611 | | // This is used for coprocessor instructions, such as 16-bit FP load/stores. |
612 | | // |
613 | | // addrmode5fp16 := reg +/- imm8*2 |
614 | | // |
615 | | // The first operand is always a Reg. The second operand encodes the |
616 | | // operation (add or subtract) in bit 8 and the immediate in bits 0-7. |
617 | | /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field. |
618 | | static inline unsigned ARM_AM_getAM5FP16Opc(ARM_AM_AddrOpc Opc, |
619 | | unsigned char Offset) |
620 | 733 | { |
621 | 733 | bool isSub = Opc == ARM_AM_sub; |
622 | 733 | return ((int)isSub << 8) | Offset; |
623 | 733 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5FP16Opc ARMDisassembler.c:ARM_AM_getAM5FP16Opc Line | Count | Source | 620 | 733 | { | 621 | 733 | bool isSub = Opc == ARM_AM_sub; | 622 | 733 | return ((int)isSub << 8) | Offset; | 623 | 733 | } |
Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5FP16Opc Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_getAM5FP16Opc |
624 | | |
625 | | static inline unsigned char ARM_AM_getAM5FP16Offset(unsigned AM5Opc) |
626 | 682 | { |
627 | 682 | return AM5Opc & 0xFF; |
628 | 682 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5FP16Offset Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5FP16Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5FP16Offset ARMInstPrinter.c:ARM_AM_getAM5FP16Offset Line | Count | Source | 626 | 682 | { | 627 | 682 | return AM5Opc & 0xFF; | 628 | 682 | } |
|
629 | | |
630 | | static inline ARM_AM_AddrOpc ARM_AM_getAM5FP16Op(unsigned AM5Opc) |
631 | 1.18k | { |
632 | 1.18k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; |
633 | 1.18k | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5FP16Op Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5FP16Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5FP16Op ARMInstPrinter.c:ARM_AM_getAM5FP16Op Line | Count | Source | 631 | 1.18k | { | 632 | 1.18k | return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add; | 633 | 1.18k | } |
|
634 | | |
635 | | //===--------------------------------------------------------------------===// |
636 | | // Addressing Mode #6 |
637 | | //===--------------------------------------------------------------------===// |
638 | | // |
639 | | // This is used for NEON load / store instructions. |
640 | | // |
641 | | // addrmode6 := reg with optional alignment |
642 | | // |
643 | | // This is stored in two operands [regaddr, align]. The first is the |
644 | | // address register. The second operand is the value of the alignment |
645 | | // specifier in bytes or zero if no explicit alignment. |
646 | | // Valid alignments depend on the specific instruction. |
647 | | //===--------------------------------------------------------------------===// |
648 | | // NEON/MVE Modified Immediates |
649 | | //===--------------------------------------------------------------------===// |
650 | | // |
651 | | // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate" |
652 | | // vector operand, where a small immediate encoded in the instruction |
653 | | // specifies a full NEON vector value. These modified immediates are |
654 | | // represented here as encoded integers. The low 8 bits hold the immediate |
655 | | // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold |
656 | | // the "Cmode" field of the instruction. The interfaces below treat the |
657 | | // Op and Cmode values as a single 5-bit value. |
658 | | static inline unsigned ARM_AM_createVMOVModImm(unsigned OpCmode, unsigned Val) |
659 | 0 | { |
660 | 0 | return (OpCmode << 8) | Val; |
661 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_createVMOVModImm Unexecuted instantiation: ARMDisassembler.c:ARM_AM_createVMOVModImm Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_createVMOVModImm Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_createVMOVModImm |
662 | | |
663 | | static inline unsigned ARM_AM_getVMOVModImmOpCmode(unsigned ModImm) |
664 | 3.04k | { |
665 | 3.04k | return (ModImm >> 8) & 0x1f; |
666 | 3.04k | } ARMMapping.c:ARM_AM_getVMOVModImmOpCmode Line | Count | Source | 664 | 1.52k | { | 665 | 1.52k | return (ModImm >> 8) & 0x1f; | 666 | 1.52k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getVMOVModImmOpCmode Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getVMOVModImmOpCmode ARMInstPrinter.c:ARM_AM_getVMOVModImmOpCmode Line | Count | Source | 664 | 1.52k | { | 665 | 1.52k | return (ModImm >> 8) & 0x1f; | 666 | 1.52k | } |
|
667 | | |
668 | | static inline unsigned ARM_AM_getVMOVModImmVal(unsigned ModImm) |
669 | 3.04k | { |
670 | 3.04k | return ModImm & 0xff; |
671 | 3.04k | } ARMMapping.c:ARM_AM_getVMOVModImmVal Line | Count | Source | 669 | 1.52k | { | 670 | 1.52k | return ModImm & 0xff; | 671 | 1.52k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getVMOVModImmVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getVMOVModImmVal ARMInstPrinter.c:ARM_AM_getVMOVModImmVal Line | Count | Source | 669 | 1.52k | { | 670 | 1.52k | return ModImm & 0xff; | 671 | 1.52k | } |
|
672 | | |
673 | | /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the |
674 | | /// element value and the element size in bits. (If the element size is |
675 | | /// smaller than the vector, it is splatted into all the elements.) |
676 | | static inline uint64_t ARM_AM_decodeVMOVModImm(unsigned ModImm, |
677 | | unsigned *EltBits) |
678 | 3.04k | { |
679 | 3.04k | unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm); |
680 | 3.04k | unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm); |
681 | 3.04k | uint64_t Val = 0; |
682 | | |
683 | 3.04k | if (OpCmode == 0xe) { |
684 | | // 8-bit vector elements |
685 | 92 | Val = Imm8; |
686 | 92 | *EltBits = 8; |
687 | 2.95k | } else if ((OpCmode & 0xc) == 0x8) { |
688 | | // 16-bit vector elements |
689 | 252 | unsigned ByteNum = (OpCmode & 0x6) >> 1; |
690 | 252 | Val = Imm8 << (8 * ByteNum); |
691 | 252 | *EltBits = 16; |
692 | 2.69k | } else if ((OpCmode & 0x8) == 0) { |
693 | | // 32-bit vector elements, zero with one byte set |
694 | 1.28k | unsigned ByteNum = (OpCmode & 0x6) >> 1; |
695 | 1.28k | Val = Imm8 << (8 * ByteNum); |
696 | 1.28k | *EltBits = 32; |
697 | 1.41k | } else if ((OpCmode & 0xe) == 0xc) { |
698 | | // 32-bit vector elements, one byte with low bits set |
699 | 1.30k | unsigned ByteNum = 1 + (OpCmode & 0x1); |
700 | 1.30k | Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); |
701 | 1.30k | *EltBits = 32; |
702 | 1.30k | } else if (OpCmode == 0x1e) { |
703 | | // 64-bit vector elements |
704 | 972 | for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { |
705 | 864 | if ((ModImm >> ByteNum) & 1) |
706 | 454 | Val |= (uint64_t)0xff << (8 * ByteNum); |
707 | 864 | } |
708 | 108 | *EltBits = 64; |
709 | 108 | } else { |
710 | 0 | CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0); |
711 | 0 | } |
712 | 3.04k | return Val; |
713 | 3.04k | } ARMMapping.c:ARM_AM_decodeVMOVModImm Line | Count | Source | 678 | 1.52k | { | 679 | 1.52k | unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm); | 680 | 1.52k | unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm); | 681 | 1.52k | uint64_t Val = 0; | 682 | | | 683 | 1.52k | if (OpCmode == 0xe) { | 684 | | // 8-bit vector elements | 685 | 46 | Val = Imm8; | 686 | 46 | *EltBits = 8; | 687 | 1.47k | } else if ((OpCmode & 0xc) == 0x8) { | 688 | | // 16-bit vector elements | 689 | 126 | unsigned ByteNum = (OpCmode & 0x6) >> 1; | 690 | 126 | Val = Imm8 << (8 * ByteNum); | 691 | 126 | *EltBits = 16; | 692 | 1.34k | } else if ((OpCmode & 0x8) == 0) { | 693 | | // 32-bit vector elements, zero with one byte set | 694 | 642 | unsigned ByteNum = (OpCmode & 0x6) >> 1; | 695 | 642 | Val = Imm8 << (8 * ByteNum); | 696 | 642 | *EltBits = 32; | 697 | 707 | } else if ((OpCmode & 0xe) == 0xc) { | 698 | | // 32-bit vector elements, one byte with low bits set | 699 | 653 | unsigned ByteNum = 1 + (OpCmode & 0x1); | 700 | 653 | Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); | 701 | 653 | *EltBits = 32; | 702 | 653 | } else if (OpCmode == 0x1e) { | 703 | | // 64-bit vector elements | 704 | 486 | for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { | 705 | 432 | if ((ModImm >> ByteNum) & 1) | 706 | 227 | Val |= (uint64_t)0xff << (8 * ByteNum); | 707 | 432 | } | 708 | 54 | *EltBits = 64; | 709 | 54 | } else { | 710 | 0 | CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0); | 711 | 0 | } | 712 | 1.52k | return Val; | 713 | 1.52k | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_decodeVMOVModImm Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_decodeVMOVModImm ARMInstPrinter.c:ARM_AM_decodeVMOVModImm Line | Count | Source | 678 | 1.52k | { | 679 | 1.52k | unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm); | 680 | 1.52k | unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm); | 681 | 1.52k | uint64_t Val = 0; | 682 | | | 683 | 1.52k | if (OpCmode == 0xe) { | 684 | | // 8-bit vector elements | 685 | 46 | Val = Imm8; | 686 | 46 | *EltBits = 8; | 687 | 1.47k | } else if ((OpCmode & 0xc) == 0x8) { | 688 | | // 16-bit vector elements | 689 | 126 | unsigned ByteNum = (OpCmode & 0x6) >> 1; | 690 | 126 | Val = Imm8 << (8 * ByteNum); | 691 | 126 | *EltBits = 16; | 692 | 1.34k | } else if ((OpCmode & 0x8) == 0) { | 693 | | // 32-bit vector elements, zero with one byte set | 694 | 642 | unsigned ByteNum = (OpCmode & 0x6) >> 1; | 695 | 642 | Val = Imm8 << (8 * ByteNum); | 696 | 642 | *EltBits = 32; | 697 | 707 | } else if ((OpCmode & 0xe) == 0xc) { | 698 | | // 32-bit vector elements, one byte with low bits set | 699 | 653 | unsigned ByteNum = 1 + (OpCmode & 0x1); | 700 | 653 | Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); | 701 | 653 | *EltBits = 32; | 702 | 653 | } else if (OpCmode == 0x1e) { | 703 | | // 64-bit vector elements | 704 | 486 | for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { | 705 | 432 | if ((ModImm >> ByteNum) & 1) | 706 | 227 | Val |= (uint64_t)0xff << (8 * ByteNum); | 707 | 432 | } | 708 | 54 | *EltBits = 64; | 709 | 54 | } else { | 710 | 0 | CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0); | 711 | 0 | } | 712 | 1.52k | return Val; | 713 | 1.52k | } |
|
714 | | |
715 | | // Generic validation for single-byte immediate (0X00, 00X0, etc). |
716 | | static inline bool ARM_AM_isNEONBytesplat(unsigned Value, unsigned Size) |
717 | 0 | { |
718 | 0 | CS_ASSERT(Size >= 1 && Size <= 4 && "Invalid size"); |
719 | 0 | unsigned count = 0; |
720 | 0 | for (unsigned i = 0; i < Size; ++i) { |
721 | 0 | if (Value & 0xff) |
722 | 0 | count++; |
723 | 0 | Value >>= 8; |
724 | 0 | } |
725 | 0 | return count == 1; |
726 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isNEONBytesplat Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isNEONBytesplat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isNEONBytesplat Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isNEONBytesplat |
727 | | |
728 | | /// Checks if Value is a correct immediate for instructions like VBIC/VORR. |
729 | | static inline bool ARM_AM_isNEONi16splat(unsigned Value) |
730 | 0 | { |
731 | 0 | if (Value > 0xffff) |
732 | 0 | return false; |
733 | 0 | // i16 value with set bits only in one byte X0 or 0X. |
734 | 0 | return Value == 0 || ARM_AM_isNEONBytesplat(Value, 2); |
735 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isNEONi16splat Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isNEONi16splat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isNEONi16splat Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isNEONi16splat |
736 | | |
737 | | // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR |
738 | | static inline unsigned ARM_AM_encodeNEONi16splat(unsigned Value) |
739 | 0 | { |
740 | 0 | CS_ASSERT(ARM_AM_isNEONi16splat(Value) && "Invalid NEON splat value"); |
741 | 0 | if (Value >= 0x100) |
742 | 0 | Value = (Value >> 8) | 0xa00; |
743 | 0 | else |
744 | 0 | Value |= 0x800; |
745 | 0 | return Value; |
746 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_encodeNEONi16splat Unexecuted instantiation: ARMDisassembler.c:ARM_AM_encodeNEONi16splat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_encodeNEONi16splat Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_encodeNEONi16splat |
747 | | |
748 | | /// Checks if Value is a correct immediate for instructions like VBIC/VORR. |
749 | | static inline bool ARM_AM_isNEONi32splat(unsigned Value) |
750 | 0 | { |
751 | 0 | // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. |
752 | 0 | return Value == 0 || ARM_AM_isNEONBytesplat(Value, 4); |
753 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_isNEONi32splat Unexecuted instantiation: ARMDisassembler.c:ARM_AM_isNEONi32splat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_isNEONi32splat Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_isNEONi32splat |
754 | | |
755 | | /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR. |
756 | | static inline unsigned ARM_AM_encodeNEONi32splat(unsigned Value) |
757 | 0 | { |
758 | 0 | CS_ASSERT(ARM_AM_isNEONi32splat(Value) && "Invalid NEON splat value"); |
759 | 0 | if (Value >= 0x100 && Value <= 0xff00) |
760 | 0 | Value = (Value >> 8) | 0x200; |
761 | 0 | else if (Value > 0xffff && Value <= 0xff0000) |
762 | 0 | Value = (Value >> 16) | 0x400; |
763 | 0 | else if (Value > 0xffffff) |
764 | 0 | Value = (Value >> 24) | 0x600; |
765 | 0 | return Value; |
766 | 0 | } Unexecuted instantiation: ARMMapping.c:ARM_AM_encodeNEONi32splat Unexecuted instantiation: ARMDisassembler.c:ARM_AM_encodeNEONi32splat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_encodeNEONi32splat Unexecuted instantiation: ARMInstPrinter.c:ARM_AM_encodeNEONi32splat |
767 | | |
768 | | //===--------------------------------------------------------------------===// |
769 | | // Floating-point Immediates |
770 | | // |
771 | | static inline float ARM_AM_getFPImmFloat(unsigned Imm) |
772 | 544 | { |
773 | | // We expect an 8-bit binary encoding of a floating-point number here. |
774 | | |
775 | 544 | uint32_t Sign = (Imm >> 7) & 0x1; |
776 | 544 | uint32_t Exp = (Imm >> 4) & 0x7; |
777 | 544 | uint32_t Mantissa = Imm & 0xf; |
778 | | |
779 | | // 8-bit FP IEEE Float Encoding |
780 | | // abcd efgh aBbbbbbc defgh000 00000000 00000000 |
781 | | // |
782 | | // where B = NOT(b); |
783 | 544 | uint32_t I = 0; |
784 | 544 | I |= Sign << 31; |
785 | 544 | I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; |
786 | 544 | I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; |
787 | 544 | I |= (Exp & 0x3) << 23; |
788 | 544 | I |= Mantissa << 19; |
789 | 544 | return BitsToFloat(I); |
790 | 544 | } ARMMapping.c:ARM_AM_getFPImmFloat Line | Count | Source | 772 | 272 | { | 773 | | // We expect an 8-bit binary encoding of a floating-point number here. | 774 | | | 775 | 272 | uint32_t Sign = (Imm >> 7) & 0x1; | 776 | 272 | uint32_t Exp = (Imm >> 4) & 0x7; | 777 | 272 | uint32_t Mantissa = Imm & 0xf; | 778 | | | 779 | | // 8-bit FP IEEE Float Encoding | 780 | | // abcd efgh aBbbbbbc defgh000 00000000 00000000 | 781 | | // | 782 | | // where B = NOT(b); | 783 | 272 | uint32_t I = 0; | 784 | 272 | I |= Sign << 31; | 785 | 272 | I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; | 786 | 272 | I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; | 787 | 272 | I |= (Exp & 0x3) << 23; | 788 | 272 | I |= Mantissa << 19; | 789 | 272 | return BitsToFloat(I); | 790 | 272 | } |
Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getFPImmFloat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getFPImmFloat ARMInstPrinter.c:ARM_AM_getFPImmFloat Line | Count | Source | 772 | 272 | { | 773 | | // We expect an 8-bit binary encoding of a floating-point number here. | 774 | | | 775 | 272 | uint32_t Sign = (Imm >> 7) & 0x1; | 776 | 272 | uint32_t Exp = (Imm >> 4) & 0x7; | 777 | 272 | uint32_t Mantissa = Imm & 0xf; | 778 | | | 779 | | // 8-bit FP IEEE Float Encoding | 780 | | // abcd efgh aBbbbbbc defgh000 00000000 00000000 | 781 | | // | 782 | | // where B = NOT(b); | 783 | 272 | uint32_t I = 0; | 784 | 272 | I |= Sign << 31; | 785 | 272 | I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; | 786 | 272 | I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; | 787 | 272 | I |= (Exp & 0x3) << 23; | 788 | 272 | I |= Mantissa << 19; | 789 | 272 | return BitsToFloat(I); | 790 | 272 | } |
|
791 | | |
792 | | #endif // CS_ARM_ADDRESSINGMODES_H |