Coverage Report

Created: 2025-07-01 07:03

/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
29.2k
{
56
29.2k
  return Op == ARM_AM_sub ? "-" : "";
57
29.2k
}
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
29.2k
{
56
29.2k
  return Op == ARM_AM_sub ? "-" : "";
57
29.2k
}
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
35.7k
{
160
35.7k
  return (ARM_AM_ShiftOpc)(Op & 7);
161
35.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
16.2k
{
160
16.2k
  return (ARM_AM_ShiftOpc)(Op & 7);
161
16.2k
}
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
12.6k
{
494
12.6k
  CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!");
495
12.6k
  bool isSub = Opc == ARM_AM_sub;
496
12.6k
  return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16);
497
12.6k
}
Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM2Opc
ARMDisassembler.c:ARM_AM_getAM2Opc
Line
Count
Source
493
12.6k
{
494
12.6k
  CS_ASSERT(Imm12 < (1 << 12) && "Imm too large!");
495
12.6k
  bool isSub = Opc == ARM_AM_sub;
496
12.6k
  return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16);
497
12.6k
}
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
12.0k
{
593
12.0k
  bool isSub = Opc == ARM_AM_sub;
594
12.0k
  return ((int)isSub << 8) | Offset;
595
12.0k
}
Unexecuted instantiation: ARMMapping.c:ARM_AM_getAM5Opc
ARMDisassembler.c:ARM_AM_getAM5Opc
Line
Count
Source
592
12.0k
{
593
12.0k
  bool isSub = Opc == ARM_AM_sub;
594
12.0k
  return ((int)isSub << 8) | Offset;
595
12.0k
}
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
24.6k
{
599
24.6k
  return AM5Opc & 0xFF;
600
24.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
12.0k
{
599
12.0k
  return AM5Opc & 0xFF;
600
12.0k
}
601
602
static inline ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)
603
24.6k
{
604
24.6k
  return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
605
24.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
12.0k
{
604
12.0k
  return ((AM5Opc >> 8) & 1) ? ARM_AM_sub : ARM_AM_add;
605
12.0k
}
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