Coverage Report

Created: 2025-07-01 07:03

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