/src/capstonenext/arch/ARM/ARMAddressingModes.h
Line  | Count  | Source  | 
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  | 84.0k  | { | 
56  | 84.0k  |   return Op == ARM_AM_sub ? "-" : "";  | 
57  | 84.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  | 84.0k  | { |  56  | 84.0k  |   return Op == ARM_AM_sub ? "-" : "";  |  57  | 84.0k  | }  |  
  | 
58  |  |  | 
59  |  | static inline const char *ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op)  | 
60  | 31.4k  | { | 
61  | 31.4k  |   switch (Op) { | 
62  | 0  |   default:  | 
63  | 0  |     CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", NULL);  | 
64  | 8.26k  |   case ARM_AM_asr:  | 
65  | 8.26k  |     return "asr";  | 
66  | 7.40k  |   case ARM_AM_lsl:  | 
67  | 7.40k  |     return "lsl";  | 
68  | 6.45k  |   case ARM_AM_lsr:  | 
69  | 6.45k  |     return "lsr";  | 
70  | 7.26k  |   case ARM_AM_ror:  | 
71  | 7.26k  |     return "ror";  | 
72  | 1.15k  |   case ARM_AM_rrx:  | 
73  | 1.15k  |     return "rrx";  | 
74  | 902  |   case ARM_AM_uxtw:  | 
75  | 902  |     return "uxtw";  | 
76  | 31.4k  |   }  | 
77  | 31.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  | 31.4k  | { |  61  | 31.4k  |   switch (Op) { |  62  | 0  |   default:  |  63  | 0  |     CS_ASSERT_RET_VAL(0 && "Unknown shift opc!", NULL);  |  64  | 8.26k  |   case ARM_AM_asr:  |  65  | 8.26k  |     return "asr";  |  66  | 7.40k  |   case ARM_AM_lsl:  |  67  | 7.40k  |     return "lsl";  |  68  | 6.45k  |   case ARM_AM_lsr:  |  69  | 6.45k  |     return "lsr";  |  70  | 7.26k  |   case ARM_AM_ror:  |  71  | 7.26k  |     return "ror";  |  72  | 1.15k  |   case ARM_AM_rrx:  |  73  | 1.15k  |     return "rrx";  |  74  | 902  |   case ARM_AM_uxtw:  |  75  | 902  |     return "uxtw";  |  76  | 31.4k  |   }  |  77  | 31.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.9k  | { | 
134  | 44.9k  |   CS_ASSERT(Amt <= 32);  | 
135  | 44.9k  |   if (Amt == 32) { | 
136  | 0  |     return Val;  | 
137  | 0  |   }  | 
138  |  |   // NOLINTBEGIN(clang-analyzer-core.BitwiseShift)  | 
139  | 44.9k  |   return (Val >> Amt) | (Val << ((32 - Amt) & 31));  | 
140  |  |   // NOLINTEND(clang-analyzer-core.BitwiseShift)  | 
141  | 44.9k  | } 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  |  |   // NOLINTBEGIN(clang-analyzer-core.BitwiseShift)  |  139  | 25.0k  |   return (Val >> Amt) | (Val << ((32 - Amt) & 31));  |  140  |  |   // NOLINTEND(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.8k  | { |  134  | 19.8k  |   CS_ASSERT(Amt <= 32);  |  135  | 19.8k  |   if (Amt == 32) { |  136  | 0  |     return Val;  |  137  | 0  |   }  |  138  |  |   // NOLINTBEGIN(clang-analyzer-core.BitwiseShift)  |  139  | 19.8k  |   return (Val >> Amt) | (Val << ((32 - Amt) & 31));  |  140  |  |   // NOLINTEND(clang-analyzer-core.BitwiseShift)  |  141  | 19.8k  | }  |  
  | 
142  |  |  | 
143  |  | static inline unsigned ARM_AM_rotl32(unsigned Val, unsigned Amt)  | 
144  | 11.0k  | { | 
145  | 11.0k  |   return (Val << Amt) | (Val >> ((32 - Amt) & 31));  | 
146  | 11.0k  | } ARMMapping.c:ARM_AM_rotl32 Line  | Count  | Source  |  144  | 5.51k  | { |  145  | 5.51k  |   return (Val << Amt) | (Val >> ((32 - Amt) & 31));  |  146  | 5.51k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_rotl32 Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_rotl32 ARMInstPrinter.c:ARM_AM_rotl32 Line  | Count  | Source  |  144  | 5.51k  | { |  145  | 5.51k  |   return (Val << Amt) | (Val >> ((32 - Amt) & 31));  |  146  | 5.51k  | }  |  
  | 
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  | 29.1k  | { | 
155  | 29.1k  |   return Op >> 3;  | 
156  | 29.1k  | } ARMMapping.c:ARM_AM_getSORegOffset Line  | Count  | Source  |  154  | 14.0k  | { |  155  | 14.0k  |   return Op >> 3;  |  156  | 14.0k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegOffset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSORegOffset ARMInstPrinter.c:ARM_AM_getSORegOffset Line  | Count  | Source  |  154  | 15.0k  | { |  155  | 15.0k  |   return Op >> 3;  |  156  | 15.0k  | }  |  
  | 
157  |  |  | 
158  |  | static inline ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op)  | 
159  | 71.9k  | { | 
160  | 71.9k  |   return (ARM_AM_ShiftOpc)(Op & 7);  | 
161  | 71.9k  | } ARMMapping.c:ARM_AM_getSORegShOp Line  | Count  | Source  |  159  | 26.3k  | { |  160  | 26.3k  |   return (ARM_AM_ShiftOpc)(Op & 7);  |  161  | 26.3k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSORegShOp Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSORegShOp ARMInstPrinter.c:ARM_AM_getSORegShOp Line  | Count  | Source  |  159  | 45.5k  | { |  160  | 45.5k  |   return (ARM_AM_ShiftOpc)(Op & 7);  |  161  | 45.5k  | }  |  
  | 
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  | 11.0k  | { | 
183  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  | 
184  |  |   // of zero.  | 
185  | 11.0k  |   if ((Imm & ~255U) == 0)  | 
186  | 0  |     return 0;  | 
187  |  |  | 
188  |  |   // Use CTZ to compute the rotate amount.  | 
189  | 11.0k  |   unsigned TZ = CountTrailingZeros_32(Imm);  | 
190  |  |  | 
191  |  |   // Rotate amount must be even.  Something like 0x200 must be rotated 8 bits,  | 
192  |  |   // not 9.  | 
193  | 11.0k  |   unsigned RotAmt = TZ & ~1;  | 
194  |  |  | 
195  |  |   // If we can handle this spread, return it.  | 
196  | 11.0k  |   if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0)  | 
197  | 7.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  | 3.54k  |   if (Imm & 63U) { | 
202  | 3.54k  |     unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);  | 
203  | 3.54k  |     unsigned RotAmt2 = TZ2 & ~1;  | 
204  | 3.54k  |     if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0)  | 
205  | 3.54k  |       return (32 - RotAmt2) &  | 
206  | 3.54k  |              31; // HW rotates right, not left.  | 
207  | 3.54k  |   }  | 
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  | 3.54k  | } ARMMapping.c:ARM_AM_getSOImmValRotate Line  | Count  | Source  |  182  | 5.51k  | { |  183  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  |  184  |  |   // of zero.  |  185  | 5.51k  |   if ((Imm & ~255U) == 0)  |  186  | 0  |     return 0;  |  187  |  |  |  188  |  |   // Use CTZ to compute the rotate amount.  |  189  | 5.51k  |   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.51k  |   unsigned RotAmt = TZ & ~1;  |  194  |  |  |  195  |  |   // If we can handle this spread, return it.  |  196  | 5.51k  |   if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0)  |  197  | 3.74k  |     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  | 1.77k  |   if (Imm & 63U) { |  202  | 1.77k  |     unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);  |  203  | 1.77k  |     unsigned RotAmt2 = TZ2 & ~1;  |  204  | 1.77k  |     if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0)  |  205  | 1.77k  |       return (32 - RotAmt2) &  |  206  | 1.77k  |              31; // HW rotates right, not left.  |  207  | 1.77k  |   }  |  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  | 1.77k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmValRotate Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmValRotate ARMInstPrinter.c:ARM_AM_getSOImmValRotate Line  | Count  | Source  |  182  | 5.51k  | { |  183  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  |  184  |  |   // of zero.  |  185  | 5.51k  |   if ((Imm & ~255U) == 0)  |  186  | 0  |     return 0;  |  187  |  |  |  188  |  |   // Use CTZ to compute the rotate amount.  |  189  | 5.51k  |   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.51k  |   unsigned RotAmt = TZ & ~1;  |  194  |  |  |  195  |  |   // If we can handle this spread, return it.  |  196  | 5.51k  |   if ((ARM_AM_rotr32(Imm, RotAmt) & ~255U) == 0)  |  197  | 3.74k  |     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  | 1.77k  |   if (Imm & 63U) { |  202  | 1.77k  |     unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U);  |  203  | 1.77k  |     unsigned RotAmt2 = TZ2 & ~1;  |  204  | 1.77k  |     if ((ARM_AM_rotr32(Imm, RotAmt2) & ~255U) == 0)  |  205  | 1.77k  |       return (32 - RotAmt2) &  |  206  | 1.77k  |              31; // HW rotates right, not left.  |  207  | 1.77k  |   }  |  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  | 1.77k  | }  |  
  | 
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  | 14.1k  | { | 
220  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  | 
221  |  |   // of zero.  | 
222  | 14.1k  |   if ((Arg & ~255U) == 0)  | 
223  | 3.12k  |     return Arg;  | 
224  |  |  | 
225  | 11.0k  |   unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg);  | 
226  |  |  | 
227  |  |   // If this cannot be handled with a single shifter_op, bail out.  | 
228  | 11.0k  |   if (ARM_AM_rotr32(~255U, RotAmt) & Arg)  | 
229  | 0  |     return -1;  | 
230  |  |  | 
231  |  |   // Encode this correctly.  | 
232  | 11.0k  |   return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8);  | 
233  | 11.0k  | } ARMMapping.c:ARM_AM_getSOImmVal Line  | Count  | Source  |  219  | 7.07k  | { |  220  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  |  221  |  |   // of zero.  |  222  | 7.07k  |   if ((Arg & ~255U) == 0)  |  223  | 1.56k  |     return Arg;  |  224  |  |  |  225  | 5.51k  |   unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg);  |  226  |  |  |  227  |  |   // If this cannot be handled with a single shifter_op, bail out.  |  228  | 5.51k  |   if (ARM_AM_rotr32(~255U, RotAmt) & Arg)  |  229  | 0  |     return -1;  |  230  |  |  |  231  |  |   // Encode this correctly.  |  232  | 5.51k  |   return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8);  |  233  | 5.51k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getSOImmVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getSOImmVal ARMInstPrinter.c:ARM_AM_getSOImmVal Line  | Count  | Source  |  219  | 7.07k  | { |  220  |  |   // 8-bit (or less) immediates are trivially shifter_operands with a rotate  |  221  |  |   // of zero.  |  222  | 7.07k  |   if ((Arg & ~255U) == 0)  |  223  | 1.56k  |     return Arg;  |  224  |  |  |  225  | 5.51k  |   unsigned RotAmt = ARM_AM_getSOImmValRotate(Arg);  |  226  |  |  |  227  |  |   // If this cannot be handled with a single shifter_op, bail out.  |  228  | 5.51k  |   if (ARM_AM_rotr32(~255U, RotAmt) & Arg)  |  229  | 0  |     return -1;  |  230  |  |  |  231  |  |   // Encode this correctly.  |  232  | 5.51k  |   return ARM_AM_rotl32(Arg, RotAmt) | ((RotAmt >> 1) << 8);  |  233  | 5.51k  | }  |  
  | 
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  | 33.4k  | { | 
494  | 33.4k  |   CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!");  | 
495  | 33.4k  |   bool isSub = Opc == ARM_AM_sub;  | 
496  | 33.4k  |   return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16);  | 
497  | 33.4k  | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM2Opc ARMDisassembler.c:ARM_AM_getAM2Opc Line  | Count  | Source  |  493  | 33.4k  | { |  494  | 33.4k  |   CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!");  |  495  |  |   bool isSub = Opc == ARM_AM_sub;  |  496  | 33.4k  |   return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16);  |  497  | 33.4k  | }  |  
 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  | 36.1k  | { | 
501  | 36.1k  |   return AM2Opc & ((1 << 12) - 1);  | 
502  | 36.1k  | } ARMMapping.c:ARM_AM_getAM2Offset Line  | Count  | Source  |  500  | 20.7k  | { |  501  | 20.7k  |   return AM2Opc & ((1 << 12) - 1);  |  502  | 20.7k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2Offset ARMInstPrinter.c:ARM_AM_getAM2Offset Line  | Count  | Source  |  500  | 15.4k  | { |  501  | 15.4k  |   return AM2Opc & ((1 << 12) - 1);  |  502  | 15.4k  | }  |  
  | 
503  |  |  | 
504  |  | static inline ARM_AM_AddrOpc ARM_AM_getAM2Op(unsigned AM2Opc)  | 
505  | 30.2k  | { | 
506  | 30.2k  |   return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add;  | 
507  | 30.2k  | } ARMMapping.c:ARM_AM_getAM2Op Line  | Count  | Source  |  505  | 15.1k  | { |  506  | 15.1k  |   return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add;  |  507  | 15.1k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2Op ARMInstPrinter.c:ARM_AM_getAM2Op Line  | Count  | Source  |  505  | 15.1k  | { |  506  | 15.1k  |   return ((AM2Opc >> 12) & 1) ? ARM_AM_sub : ARM_AM_add;  |  507  | 15.1k  | }  |  
  | 
508  |  |  | 
509  |  | static inline ARM_AM_ShiftOpc ARM_AM_getAM2ShiftOpc(unsigned AM2Opc)  | 
510  | 19.0k  | { | 
511  | 19.0k  |   return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7);  | 
512  | 19.0k  | } ARMMapping.c:ARM_AM_getAM2ShiftOpc Line  | Count  | Source  |  510  | 9.54k  | { |  511  | 9.54k  |   return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7);  |  512  | 9.54k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM2ShiftOpc Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM2ShiftOpc ARMInstPrinter.c:ARM_AM_getAM2ShiftOpc Line  | Count  | Source  |  510  | 9.54k  | { |  511  | 9.54k  |   return (ARM_AM_ShiftOpc)((AM2Opc >> 13) & 7);  |  512  | 9.54k  | }  |  
  | 
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  | 12.6k  | { | 
542  | 12.6k  |   return AM3Opc & 0xFF;  | 
543  | 12.6k  | } ARMMapping.c:ARM_AM_getAM3Offset Line  | Count  | Source  |  541  | 6.32k  | { |  542  | 6.32k  |   return AM3Opc & 0xFF;  |  543  | 6.32k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3Offset ARMInstPrinter.c:ARM_AM_getAM3Offset Line  | Count  | Source  |  541  | 6.32k  | { |  542  | 6.32k  |   return AM3Opc & 0xFF;  |  543  | 6.32k  | }  |  
  | 
544  |  |  | 
545  |  | static inline ARM_AM_AddrOpc ARM_AM_getAM3Op(unsigned AM3Opc)  | 
546  | 22.7k  | { | 
547  | 22.7k  |   return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  | 
548  | 22.7k  | } ARMMapping.c:ARM_AM_getAM3Op Line  | Count  | Source  |  546  | 11.3k  | { |  547  | 11.3k  |   return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  |  548  | 11.3k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM3Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM3Op ARMInstPrinter.c:ARM_AM_getAM3Op Line  | Count  | Source  |  546  | 11.3k  | { |  547  | 11.3k  |   return ((AM3Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  |  548  | 11.3k  | }  |  
  | 
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  | 31.1k  | { | 
593  | 31.1k  |   bool isSub = Opc == ARM_AM_sub;  | 
594  | 31.1k  |   return ((int)isSub << 8) | Offset;  | 
595  | 31.1k  | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5Opc ARMDisassembler.c:ARM_AM_getAM5Opc Line  | Count  | Source  |  592  | 31.1k  | { |  593  |  |   bool isSub = Opc == ARM_AM_sub;  |  594  | 31.1k  |   return ((int)isSub << 8) | Offset;  |  595  | 31.1k  | }  |  
 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  | 48.8k  | { | 
599  | 48.8k  |   return AM5Opc & 0xFF;  | 
600  | 48.8k  | } ARMMapping.c:ARM_AM_getAM5Offset Line  | Count  | Source  |  598  | 18.0k  | { |  599  | 18.0k  |   return AM5Opc & 0xFF;  |  600  | 18.0k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Offset Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5Offset ARMInstPrinter.c:ARM_AM_getAM5Offset Line  | Count  | Source  |  598  | 30.7k  | { |  599  | 30.7k  |   return AM5Opc & 0xFF;  |  600  | 30.7k  | }  |  
  | 
601  |  |  | 
602  |  | static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)  | 
603  | 48.8k  | { | 
604  | 48.8k  |   return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  | 
605  | 48.8k  | } ARMMapping.c:ARM_AM_getAM5Op Line  | Count  | Source  |  603  | 18.0k  | { |  604  | 18.0k  |   return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  |  605  | 18.0k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getAM5Op Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getAM5Op ARMInstPrinter.c:ARM_AM_getAM5Op Line  | Count  | Source  |  603  | 30.7k  | { |  604  | 30.7k  |   return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  |  605  | 30.7k  | }  |  
  | 
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  | 1.13k  | { | 
621  | 1.13k  |   bool isSub = Opc == ARM_AM_sub;  | 
622  | 1.13k  |   return ((int)isSub << 8) | Offset;  | 
623  | 1.13k  | } Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5FP16Opc ARMDisassembler.c:ARM_AM_getAM5FP16Opc Line  | Count  | Source  |  620  | 1.13k  | { |  621  |  |   bool isSub = Opc == ARM_AM_sub;  |  622  | 1.13k  |   return ((int)isSub << 8) | Offset;  |  623  | 1.13k  | }  |  
 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  | 680  | { | 
627  | 680  |   return AM5Opc & 0xFF;  | 
628  | 680  | } 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  | 680  | { |  627  | 680  |   return AM5Opc & 0xFF;  |  628  | 680  | }  |  
  | 
629  |  |  | 
630  |  | static inline ARM_AM_AddrOpc ARM_AM_getAM5FP16Op(unsigned AM5Opc)  | 
631  | 1.28k  | { | 
632  | 1.28k  |   return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  | 
633  | 1.28k  | } 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.28k  | { |  632  | 1.28k  |   return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;  |  633  | 1.28k  | }  |  
  | 
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  | 9.38k  | { | 
665  | 9.38k  |   return (ModImm >> 8) & 0x1f;  | 
666  | 9.38k  | } ARMMapping.c:ARM_AM_getVMOVModImmOpCmode Line  | Count  | Source  |  664  | 4.69k  | { |  665  | 4.69k  |   return (ModImm >> 8) & 0x1f;  |  666  | 4.69k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getVMOVModImmOpCmode Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getVMOVModImmOpCmode ARMInstPrinter.c:ARM_AM_getVMOVModImmOpCmode Line  | Count  | Source  |  664  | 4.69k  | { |  665  | 4.69k  |   return (ModImm >> 8) & 0x1f;  |  666  | 4.69k  | }  |  
  | 
667  |  |  | 
668  |  | static inline unsigned ARM_AM_getVMOVModImmVal(unsigned ModImm)  | 
669  | 9.38k  | { | 
670  | 9.38k  |   return ModImm & 0xff;  | 
671  | 9.38k  | } ARMMapping.c:ARM_AM_getVMOVModImmVal Line  | Count  | Source  |  669  | 4.69k  | { |  670  | 4.69k  |   return ModImm & 0xff;  |  671  | 4.69k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getVMOVModImmVal Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getVMOVModImmVal ARMInstPrinter.c:ARM_AM_getVMOVModImmVal Line  | Count  | Source  |  669  | 4.69k  | { |  670  | 4.69k  |   return ModImm & 0xff;  |  671  | 4.69k  | }  |  
  | 
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  | 9.38k  | { | 
679  | 9.38k  |   unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm);  | 
680  | 9.38k  |   unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm);  | 
681  | 9.38k  |   uint64_t Val = 0;  | 
682  |  |  | 
683  | 9.38k  |   if (OpCmode == 0xe) { | 
684  |  |     // 8-bit vector elements  | 
685  | 144  |     Val = Imm8;  | 
686  | 144  |     *EltBits = 8;  | 
687  | 9.23k  |   } else if ((OpCmode & 0xc) == 0x8) { | 
688  |  |     // 16-bit vector elements  | 
689  | 1.20k  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  | 
690  | 1.20k  |     Val = Imm8 << (8 * ByteNum);  | 
691  | 1.20k  |     *EltBits = 16;  | 
692  | 8.03k  |   } else if ((OpCmode & 0x8) == 0) { | 
693  |  |     // 32-bit vector elements, zero with one byte set  | 
694  | 3.72k  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  | 
695  | 3.72k  |     Val = Imm8 << (8 * ByteNum);  | 
696  | 3.72k  |     *EltBits = 32;  | 
697  | 4.30k  |   } else if ((OpCmode & 0xe) == 0xc) { | 
698  |  |     // 32-bit vector elements, one byte with low bits set  | 
699  | 3.49k  |     unsigned ByteNum = 1 + (OpCmode & 0x1);  | 
700  | 3.49k  |     Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));  | 
701  | 3.49k  |     *EltBits = 32;  | 
702  | 3.49k  |   } else if (OpCmode == 0x1e) { | 
703  |  |     // 64-bit vector elements  | 
704  | 7.34k  |     for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { | 
705  | 6.52k  |       if ((ModImm >> ByteNum) & 1)  | 
706  | 2.88k  |         Val |= (uint64_t)0xff << (8 * ByteNum);  | 
707  | 6.52k  |     }  | 
708  | 816  |     *EltBits = 64;  | 
709  | 816  |   } else { | 
710  | 0  |     CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0);  | 
711  | 0  |   }  | 
712  | 9.38k  |   return Val;  | 
713  | 9.38k  | } ARMMapping.c:ARM_AM_decodeVMOVModImm Line  | Count  | Source  |  678  | 4.69k  | { |  679  | 4.69k  |   unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm);  |  680  | 4.69k  |   unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm);  |  681  | 4.69k  |   uint64_t Val = 0;  |  682  |  |  |  683  | 4.69k  |   if (OpCmode == 0xe) { |  684  |  |     // 8-bit vector elements  |  685  | 72  |     Val = Imm8;  |  686  | 72  |     *EltBits = 8;  |  687  | 4.61k  |   } else if ((OpCmode & 0xc) == 0x8) { |  688  |  |     // 16-bit vector elements  |  689  | 601  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  |  690  | 601  |     Val = Imm8 << (8 * ByteNum);  |  691  | 601  |     *EltBits = 16;  |  692  | 4.01k  |   } else if ((OpCmode & 0x8) == 0) { |  693  |  |     // 32-bit vector elements, zero with one byte set  |  694  | 1.86k  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  |  695  | 1.86k  |     Val = Imm8 << (8 * ByteNum);  |  696  | 1.86k  |     *EltBits = 32;  |  697  | 2.15k  |   } else if ((OpCmode & 0xe) == 0xc) { |  698  |  |     // 32-bit vector elements, one byte with low bits set  |  699  | 1.74k  |     unsigned ByteNum = 1 + (OpCmode & 0x1);  |  700  | 1.74k  |     Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));  |  701  | 1.74k  |     *EltBits = 32;  |  702  | 1.74k  |   } else if (OpCmode == 0x1e) { |  703  |  |     // 64-bit vector elements  |  704  | 3.67k  |     for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { |  705  | 3.26k  |       if ((ModImm >> ByteNum) & 1)  |  706  | 1.44k  |         Val |= (uint64_t)0xff << (8 * ByteNum);  |  707  | 3.26k  |     }  |  708  | 408  |     *EltBits = 64;  |  709  | 408  |   } else { |  710  | 0  |     CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0);  |  711  | 0  |   }  |  712  | 4.69k  |   return Val;  |  713  | 4.69k  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_decodeVMOVModImm Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_decodeVMOVModImm ARMInstPrinter.c:ARM_AM_decodeVMOVModImm Line  | Count  | Source  |  678  | 4.69k  | { |  679  | 4.69k  |   unsigned OpCmode = ARM_AM_getVMOVModImmOpCmode(ModImm);  |  680  | 4.69k  |   unsigned Imm8 = ARM_AM_getVMOVModImmVal(ModImm);  |  681  | 4.69k  |   uint64_t Val = 0;  |  682  |  |  |  683  | 4.69k  |   if (OpCmode == 0xe) { |  684  |  |     // 8-bit vector elements  |  685  | 72  |     Val = Imm8;  |  686  | 72  |     *EltBits = 8;  |  687  | 4.61k  |   } else if ((OpCmode & 0xc) == 0x8) { |  688  |  |     // 16-bit vector elements  |  689  | 601  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  |  690  | 601  |     Val = Imm8 << (8 * ByteNum);  |  691  | 601  |     *EltBits = 16;  |  692  | 4.01k  |   } else if ((OpCmode & 0x8) == 0) { |  693  |  |     // 32-bit vector elements, zero with one byte set  |  694  | 1.86k  |     unsigned ByteNum = (OpCmode & 0x6) >> 1;  |  695  | 1.86k  |     Val = Imm8 << (8 * ByteNum);  |  696  | 1.86k  |     *EltBits = 32;  |  697  | 2.15k  |   } else if ((OpCmode & 0xe) == 0xc) { |  698  |  |     // 32-bit vector elements, one byte with low bits set  |  699  | 1.74k  |     unsigned ByteNum = 1 + (OpCmode & 0x1);  |  700  | 1.74k  |     Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum)));  |  701  | 1.74k  |     *EltBits = 32;  |  702  | 1.74k  |   } else if (OpCmode == 0x1e) { |  703  |  |     // 64-bit vector elements  |  704  | 3.67k  |     for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { |  705  | 3.26k  |       if ((ModImm >> ByteNum) & 1)  |  706  | 1.44k  |         Val |= (uint64_t)0xff << (8 * ByteNum);  |  707  | 3.26k  |     }  |  708  | 408  |     *EltBits = 64;  |  709  | 408  |   } else { |  710  | 0  |     CS_ASSERT_RET_VAL(0 && "Unsupported VMOV immediate", 0);  |  711  | 0  |   }  |  712  | 4.69k  |   return Val;  |  713  | 4.69k  | }  |  
  | 
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  | 1.64k  | { | 
773  |  |   // We expect an 8-bit binary encoding of a floating-point number here.  | 
774  |  |  | 
775  | 1.64k  |   uint32_t Sign = (Imm >> 7) & 0x1;  | 
776  | 1.64k  |   uint32_t Exp = (Imm >> 4) & 0x7;  | 
777  | 1.64k  |   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  | 1.64k  |   uint32_t I = 0;  | 
784  | 1.64k  |   I |= Sign << 31;  | 
785  | 1.64k  |   I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;  | 
786  | 1.64k  |   I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;  | 
787  | 1.64k  |   I |= (Exp & 0x3) << 23;  | 
788  | 1.64k  |   I |= Mantissa << 19;  | 
789  | 1.64k  |   return BitsToFloat(I);  | 
790  | 1.64k  | } ARMMapping.c:ARM_AM_getFPImmFloat Line  | Count  | Source  |  772  | 822  | { |  773  |  |   // We expect an 8-bit binary encoding of a floating-point number here.  |  774  |  |  |  775  | 822  |   uint32_t Sign = (Imm >> 7) & 0x1;  |  776  | 822  |   uint32_t Exp = (Imm >> 4) & 0x7;  |  777  | 822  |   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  | 822  |   uint32_t I = 0;  |  784  | 822  |   I |= Sign << 31;  |  785  | 822  |   I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;  |  786  | 822  |   I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;  |  787  | 822  |   I |= (Exp & 0x3) << 23;  |  788  | 822  |   I |= Mantissa << 19;  |  789  | 822  |   return BitsToFloat(I);  |  790  | 822  | }  |  
 Unexecuted instantiation: ARMDisassembler.c:ARM_AM_getFPImmFloat Unexecuted instantiation: ARMDisassemblerExtension.c:ARM_AM_getFPImmFloat ARMInstPrinter.c:ARM_AM_getFPImmFloat Line  | Count  | Source  |  772  | 822  | { |  773  |  |   // We expect an 8-bit binary encoding of a floating-point number here.  |  774  |  |  |  775  | 822  |   uint32_t Sign = (Imm >> 7) & 0x1;  |  776  | 822  |   uint32_t Exp = (Imm >> 4) & 0x7;  |  777  | 822  |   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  | 822  |   uint32_t I = 0;  |  784  | 822  |   I |= Sign << 31;  |  785  | 822  |   I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;  |  786  | 822  |   I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;  |  787  | 822  |   I |= (Exp & 0x3) << 23;  |  788  | 822  |   I |= Mantissa << 19;  |  789  | 822  |   return BitsToFloat(I);  |  790  | 822  | }  |  
  | 
791  |  |  | 
792  |  | #endif // CS_ARM_ADDRESSINGMODES_H  |