Coverage Report

Created: 2023-09-25 06:24

/src/capstonenext/arch/ARM/ARMDisassemblerExtension.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
/*    Rot127 <unisono@quyllur.org>, 2022-2023 */
4
5
#include "ARMDisassemblerExtension.h"
6
#include "ARMBaseInfo.h"
7
8
bool ITBlock_push_back(ARM_ITBlock *it, char v)
9
40.8k
{
10
40.8k
  if (it->size >= sizeof(it->ITStates)) {
11
    // TODO: consider warning user.
12
1.62k
    it->size = 0;
13
1.62k
  }
14
40.8k
  it->ITStates[it->size] = v;
15
40.8k
  it->size++;
16
17
40.8k
  return true;
18
40.8k
}
19
20
// Returns true if the current instruction is in an IT block
21
bool ITBlock_instrInITBlock(ARM_ITBlock *it)
22
1.43M
{
23
1.43M
  return (it->size > 0);
24
1.43M
}
25
26
// Returns true if current instruction is the last instruction in an IT block
27
bool ITBlock_instrLastInITBlock(ARM_ITBlock *it)
28
1.46k
{
29
1.46k
  return (it->size == 1);
30
1.46k
}
31
32
// Returns the condition code for instruction in IT block
33
unsigned ITBlock_getITCC(ARM_ITBlock *it)
34
40.9k
{
35
40.9k
  unsigned CC = ARMCC_AL;
36
37
40.9k
  if (ITBlock_instrInITBlock(it))
38
27.2k
    CC = it->ITStates[it->size - 1];
39
40
40.9k
  return CC;
41
40.9k
}
42
43
// Advances the IT block state to the next T or E
44
void ITBlock_advanceITState(ARM_ITBlock *it)
45
27.2k
{
46
27.2k
  it->size--;
47
27.2k
}
48
49
// Called when decoding an IT instruction. Sets the IT state for the following
50
// instructions that for the IT block. Firstcond and Mask correspond to the
51
// fields in the IT instruction encoding.
52
void ITBlock_setITState(ARM_ITBlock *it, char Firstcond, char Mask)
53
11.2k
{
54
  // (3 - the number of trailing zeros) is the number of then / else.
55
11.2k
  unsigned NumTZ = CountTrailingZeros_8(Mask);
56
11.2k
  unsigned char CCBits = (unsigned char)(Firstcond & 0xf);
57
11.2k
  assert(NumTZ <= 3 && "Invalid IT mask!");
58
  // push condition codes onto the stack the correct order for the pops
59
40.8k
  for (unsigned Pos = NumTZ + 1; Pos <= 3; ++Pos) {
60
29.5k
    unsigned Else = (Mask >> Pos) & 1;
61
29.5k
    ITBlock_push_back(it, CCBits ^ Else);
62
29.5k
  }
63
11.2k
  ITBlock_push_back(it, CCBits);
64
11.2k
}
65
66
bool VPTBlock_push_back(ARM_VPTBlock *it, char v)
67
34.3k
{
68
34.3k
  if (it->size >= sizeof(it->VPTStates)) {
69
    // TODO: consider warning user.
70
1.05k
    it->size = 0;
71
1.05k
  }
72
34.3k
  it->VPTStates[it->size] = v;
73
34.3k
  it->size++;
74
75
34.3k
  return true;
76
34.3k
}
77
78
bool VPTBlock_instrInVPTBlock(ARM_VPTBlock *VPT)
79
1.83M
{
80
1.83M
  return VPT->size > 0;
81
1.83M
}
82
83
unsigned VPTBlock_getVPTPred(ARM_VPTBlock *VPT)
84
25.3k
{
85
25.3k
  unsigned Pred = ARMVCC_None;
86
25.3k
  if (VPTBlock_instrInVPTBlock(VPT))
87
25.3k
    Pred = VPT->VPTStates[VPT->size - 1];
88
25.3k
  return Pred;
89
25.3k
}
90
91
void VPTBlock_advanceVPTState(ARM_VPTBlock *VPT)
92
25.3k
{
93
25.3k
  VPT->size--;
94
25.3k
}
95
96
void VPTBlock_setVPTState(ARM_VPTBlock *VPT, char Mask)
97
9.69k
{
98
  // (3 - the number of trailing zeros) is the number of then / else.
99
9.69k
  unsigned NumTZ = CountTrailingZeros_8(Mask);
100
9.69k
  assert(NumTZ <= 3 && "Invalid VPT mask!");
101
  // push predicates onto the stack the correct order for the pops
102
34.3k
  for (unsigned Pos = NumTZ + 1; Pos <= 3; ++Pos) {
103
24.6k
    bool T = ((Mask >> Pos) & 1) == 0;
104
24.6k
    if (T)
105
12.2k
      VPTBlock_push_back(VPT, ARMVCC_Then);
106
12.3k
    else
107
12.3k
      VPTBlock_push_back(VPT, ARMVCC_Else);
108
24.6k
  }
109
9.69k
  VPTBlock_push_back(VPT, ARMVCC_Then);
110
9.69k
}
111
112
/// ThumbDisassembler - Thumb disassembler for all Thumb platforms.
113
114
bool Check(DecodeStatus *Out, DecodeStatus In)
115
4.97M
{
116
4.97M
  switch (In) {
117
4.77M
  case MCDisassembler_Success:
118
    // Out stays the same.
119
4.77M
    return true;
120
164k
  case MCDisassembler_SoftFail:
121
164k
    *Out = In;
122
164k
    return true;
123
35.8k
  case MCDisassembler_Fail:
124
35.8k
    *Out = In;
125
35.8k
    return false;
126
0
  default: // never reached
127
0
    return false;
128
4.97M
  }
129
4.97M
}
130
131
// Imported from ARMBaseInstrInfo.h
132
//
133
/// isValidCoprocessorNumber - decide whether an explicit coprocessor
134
/// number is legal in generic instructions like CDP. The answer can
135
/// vary with the subtarget.
136
bool isValidCoprocessorNumber(MCInst *Inst, unsigned Num)
137
41.0k
{
138
  // In Armv7 and Armv8-M CP10 and CP11 clash with VFP/NEON, however, the
139
  // coprocessor is still valid for CDP/MCR/MRC and friends. Allowing it is
140
  // useful for code which is shared with older architectures which do not
141
  // know the new VFP/NEON mnemonics.
142
143
  // Armv8-A disallows everything *other* than 111x (CP14 and CP15).
144
41.0k
  if (ARM_getFeatureBits(Inst->csh->mode, ARM_HasV8Ops) &&
145
41.0k
      (Num & 0xE) != 0xE)
146
31
    return false;
147
148
  // Armv8.1-M disallows 100x (CP8,CP9) and 111x (CP14,CP15)
149
  // which clash with MVE.
150
40.9k
  if (ARM_getFeatureBits(Inst->csh->mode, ARM_HasV8_1MMainlineOps) &&
151
40.9k
      ((Num & 0xE) == 0x8 || (Num & 0xE) == 0xE))
152
8
    return false;
153
154
40.9k
  return true;
155
40.9k
}
156
157
// Imported from ARMMCTargetDesc.h
158
bool ARM_isVpred(arm_op_type op)
159
19.6M
{
160
19.6M
  return op == ARM_OP_VPRED_R || op == ARM_OP_VPRED_N;
161
19.6M
}
162
163
// Imported from ARMBaseInstrInfo.h
164
//
165
// This table shows the VPT instruction variants, i.e. the different
166
// mask field encodings, see also B5.6. Predication/conditional execution in
167
// the ArmARM.
168
bool isVPTOpcode(int Opc)
169
102k
{
170
102k
  return Opc == ARM_MVE_VPTv16i8 || Opc == ARM_MVE_VPTv16u8 ||
171
102k
         Opc == ARM_MVE_VPTv16s8 || Opc == ARM_MVE_VPTv8i16 ||
172
102k
         Opc == ARM_MVE_VPTv8u16 || Opc == ARM_MVE_VPTv8s16 ||
173
102k
         Opc == ARM_MVE_VPTv4i32 || Opc == ARM_MVE_VPTv4u32 ||
174
102k
         Opc == ARM_MVE_VPTv4s32 || Opc == ARM_MVE_VPTv4f32 ||
175
102k
         Opc == ARM_MVE_VPTv8f16 || Opc == ARM_MVE_VPTv16i8r ||
176
102k
         Opc == ARM_MVE_VPTv16u8r || Opc == ARM_MVE_VPTv16s8r ||
177
102k
         Opc == ARM_MVE_VPTv8i16r || Opc == ARM_MVE_VPTv8u16r ||
178
102k
         Opc == ARM_MVE_VPTv8s16r || Opc == ARM_MVE_VPTv4i32r ||
179
102k
         Opc == ARM_MVE_VPTv4u32r || Opc == ARM_MVE_VPTv4s32r ||
180
102k
         Opc == ARM_MVE_VPTv4f32r || Opc == ARM_MVE_VPTv8f16r ||
181
102k
         Opc == ARM_MVE_VPST;
182
102k
}
183
184
// Imported from ARMMCTargetDesc.cpp
185
bool ARM_isCDECoproc(size_t Coproc, const MCInst *MI)
186
62.1k
{
187
  // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
188
  // to rely on feature bits.
189
62.1k
  if (Coproc >= 8)
190
42.4k
    return false;
191
192
19.6k
  return ARM_getFeatureBits(MI->csh->mode,
193
19.6k
          ARM_FeatureCoprocCDE0 + Coproc);
194
62.1k
}
195
196
// Hacky: enable all features for disassembler
197
bool ARM_getFeatureBits(unsigned int mode, unsigned int feature)
198
3.99M
{
199
3.99M
  if (feature == ARM_ModeThumb) {
200
2.06M
    if (mode & CS_MODE_THUMB)
201
1.85M
      return true;
202
204k
    return false;
203
2.06M
  }
204
205
1.93M
  if (feature == ARM_FeatureDFB)
206
70
    return false;
207
208
1.93M
  if (feature == ARM_FeatureRAS)
209
1.94k
    return false;
210
211
1.93M
  if (feature == ARM_FeatureMClass && (mode & CS_MODE_MCLASS) == 0)
212
81.1k
    return false;
213
214
1.85M
  if ((feature == ARM_HasMVEIntegerOps || feature == ARM_HasMVEFloatOps ||
215
1.85M
       feature == ARM_FeatureMVEVectorCostFactor1 ||
216
1.85M
       feature == ARM_FeatureMVEVectorCostFactor2 ||
217
1.85M
       feature == ARM_FeatureMVEVectorCostFactor4) &&
218
1.85M
      (mode & CS_MODE_MCLASS) == 0)
219
14.5k
    return false;
220
221
1.83M
  if ((feature == ARM_HasV8Ops || feature == ARM_HasV8_1MMainlineOps ||
222
1.83M
       feature == ARM_HasV8_1aOps || feature == ARM_HasV8_2aOps ||
223
1.83M
       feature == ARM_HasV8_3aOps || feature == ARM_HasV8_4aOps ||
224
1.83M
       feature == ARM_HasV8_5aOps || feature == ARM_HasV8_6aOps ||
225
1.83M
       feature == ARM_HasV8_7aOps || feature == ARM_HasV8_8aOps ||
226
1.83M
       feature == ARM_HasV8_9aOps) &&
227
1.83M
      (mode & CS_MODE_V8) == 0)
228
262k
    return false;
229
230
1.57M
  if (feature >= ARM_FeatureCoprocCDE0 &&
231
1.57M
      feature <= ARM_FeatureCoprocCDE7)
232
    // We currently have no way to detect CDE (Custom-Datapath-Extension)
233
    // coprocessors.
234
19.6k
    return false;
235
236
  // we support everything
237
1.55M
  return true;
238
1.57M
}