Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- EmulateInstructionARM64.cpp ---------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "EmulateInstructionARM64.h"
10
11
#include "lldb/Core/Address.h"
12
#include "lldb/Core/PluginManager.h"
13
#include "lldb/Symbol/UnwindPlan.h"
14
#include "lldb/Utility/ArchSpec.h"
15
#include "lldb/Utility/RegisterValue.h"
16
#include "lldb/Utility/Stream.h"
17
18
#include "llvm/Support/CheckedArithmetic.h"
19
20
#include "Plugins/Process/Utility/ARMDefines.h"
21
#include "Plugins/Process/Utility/ARMUtils.h"
22
#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
23
24
#include <algorithm>
25
#include <cstdlib>
26
#include <optional>
27
28
#define GPR_OFFSET(idx) ((idx)*8)
29
#define GPR_OFFSET_NAME(reg) 0
30
#define FPU_OFFSET(idx) ((idx)*16)
31
#define FPU_OFFSET_NAME(reg) 0
32
#define EXC_OFFSET_NAME(reg) 0
33
#define DBG_OFFSET_NAME(reg) 0
34
#define DBG_OFFSET_NAME(reg) 0
35
#define DEFINE_DBG(re, y)                                                      \
36
  "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex,                  \
37
      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,          \
38
       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},                              \
39
      nullptr, nullptr, nullptr
40
41
#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
42
43
#include "Plugins/Process/Utility/RegisterInfos_arm64.h"
44
45
#include "llvm/ADT/STLExtras.h"
46
#include "llvm/Support/MathExtras.h"
47
48
#include "Plugins/Process/Utility/InstructionUtils.h"
49
50
using namespace lldb;
51
using namespace lldb_private;
52
53
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM64, InstructionARM64)
54
55
331
static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) {
56
331
  if (reg_num >= std::size(g_register_infos_arm64_le))
57
0
    return {};
58
331
  return g_register_infos_arm64_le[reg_num];
59
331
}
60
61
7.95k
#define No_VFP 0
62
#define VFPv1 (1u << 1)
63
#define VFPv2 (1u << 2)
64
#define VFPv3 (1u << 3)
65
#define AdvancedSIMD (1u << 4)
66
67
#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
68
#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
69
#define VFPv2v3 (VFPv2 | VFPv3)
70
71
332
#define UInt(x) ((uint64_t)x)
72
90
#define SInt(x) ((int64_t)x)
73
31
#define bit bool
74
272
#define boolean bool
75
210
#define integer int64_t
76
77
34
static inline bool IsZero(uint64_t x) { return x == 0; }
78
79
17
static inline uint64_t NOT(uint64_t x) { return ~x; }
80
81
// LSL()
82
// =====
83
84
53
static inline uint64_t LSL(uint64_t x, integer shift) {
85
53
  if (shift == 0)
86
0
    return x;
87
53
  return x << shift;
88
53
}
89
90
// ConstrainUnpredictable()
91
// ========================
92
93
EmulateInstructionARM64::ConstraintType
94
0
ConstrainUnpredictable(EmulateInstructionARM64::Unpredictable which) {
95
0
  EmulateInstructionARM64::ConstraintType result =
96
0
      EmulateInstructionARM64::Constraint_UNKNOWN;
97
0
  switch (which) {
98
0
  case EmulateInstructionARM64::Unpredictable_WBOVERLAP:
99
0
  case EmulateInstructionARM64::Unpredictable_LDPOVERLAP:
100
    // TODO: don't know what to really do here? Pseudo code says:
101
    // set result to one of above Constraint behaviours or UNDEFINED
102
0
    break;
103
0
  }
104
0
  return result;
105
0
}
106
107
//
108
// EmulateInstructionARM implementation
109
//
110
111
3.93k
void EmulateInstructionARM64::Initialize() {
112
3.93k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
113
3.93k
                                GetPluginDescriptionStatic(), CreateInstance);
114
3.93k
}
115
116
3.92k
void EmulateInstructionARM64::Terminate() {
117
3.92k
  PluginManager::UnregisterPlugin(CreateInstance);
118
3.92k
}
119
120
3.93k
llvm::StringRef EmulateInstructionARM64::GetPluginDescriptionStatic() {
121
3.93k
  return "Emulate instructions for the ARM64 architecture.";
122
3.93k
}
123
124
EmulateInstruction *
125
EmulateInstructionARM64::CreateInstance(const ArchSpec &arch,
126
16.8k
                                        InstructionType inst_type) {
127
16.8k
  if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(
128
16.8k
          inst_type)) {
129
16.8k
    if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
130
16.8k
        
arch.GetTriple().getArch() == llvm::Triple::aarch64_3216.7k
) {
131
27
      return new EmulateInstructionARM64(arch);
132
27
    }
133
16.8k
  }
134
135
16.7k
  return nullptr;
136
16.8k
}
137
138
0
bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) {
139
0
  if (arch.GetTriple().getArch() == llvm::Triple::arm)
140
0
    return true;
141
0
  else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
142
0
    return true;
143
144
0
  return false;
145
0
}
146
147
std::optional<RegisterInfo>
148
EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind,
149
331
                                         uint32_t reg_num) {
150
331
  if (reg_kind == eRegisterKindGeneric) {
151
22
    switch (reg_num) {
152
8
    case LLDB_REGNUM_GENERIC_PC:
153
8
      reg_kind = eRegisterKindLLDB;
154
8
      reg_num = gpr_pc_arm64;
155
8
      break;
156
14
    case LLDB_REGNUM_GENERIC_SP:
157
14
      reg_kind = eRegisterKindLLDB;
158
14
      reg_num = gpr_sp_arm64;
159
14
      break;
160
0
    case LLDB_REGNUM_GENERIC_FP:
161
0
      reg_kind = eRegisterKindLLDB;
162
0
      reg_num = gpr_fp_arm64;
163
0
      break;
164
0
    case LLDB_REGNUM_GENERIC_RA:
165
0
      reg_kind = eRegisterKindLLDB;
166
0
      reg_num = gpr_lr_arm64;
167
0
      break;
168
0
    case LLDB_REGNUM_GENERIC_FLAGS:
169
0
      reg_kind = eRegisterKindLLDB;
170
0
      reg_num = gpr_cpsr_arm64;
171
0
      break;
172
173
0
    default:
174
0
      return {};
175
22
    }
176
22
  }
177
178
331
  if (reg_kind == eRegisterKindLLDB)
179
331
    return LLDBTableGetRegisterInfo(reg_num);
180
0
  return {};
181
331
}
182
183
EmulateInstructionARM64::Opcode *
184
142
EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) {
185
142
  static EmulateInstructionARM64::Opcode g_opcodes[] = {
186
      // Prologue instructions
187
188
      // push register(s)
189
142
      {0xff000000, 0xd1000000, No_VFP,
190
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
191
142
       "SUB  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},
192
142
      {0xff000000, 0xf1000000, No_VFP,
193
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
194
142
       "SUBS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"},
195
142
      {0xff000000, 0x91000000, No_VFP,
196
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
197
142
       "ADD  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},
198
142
      {0xff000000, 0xb1000000, No_VFP,
199
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
200
142
       "ADDS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"},
201
202
142
      {0xff000000, 0x51000000, No_VFP,
203
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
204
142
       "SUB  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},
205
142
      {0xff000000, 0x71000000, No_VFP,
206
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
207
142
       "SUBS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},
208
142
      {0xff000000, 0x11000000, No_VFP,
209
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
210
142
       "ADD  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},
211
142
      {0xff000000, 0x31000000, No_VFP,
212
142
       &EmulateInstructionARM64::EmulateADDSUBImm,
213
142
       "ADDS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},
214
215
142
      {0xffc00000, 0x29000000, No_VFP,
216
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
217
142
       "STP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},
218
142
      {0xffc00000, 0xa9000000, No_VFP,
219
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
220
142
       "STP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},
221
142
      {0xffc00000, 0x2d000000, No_VFP,
222
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
223
142
       "STP  <St>, <St2>, [<Xn|SP>{, #<imm>}]"},
224
142
      {0xffc00000, 0x6d000000, No_VFP,
225
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
226
142
       "STP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},
227
142
      {0xffc00000, 0xad000000, No_VFP,
228
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
229
142
       "STP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},
230
231
142
      {0xffc00000, 0x29800000, No_VFP,
232
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
233
142
       "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
234
142
      {0xffc00000, 0xa9800000, No_VFP,
235
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
236
142
       "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
237
142
      {0xffc00000, 0x2d800000, No_VFP,
238
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
239
142
       "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
240
142
      {0xffc00000, 0x6d800000, No_VFP,
241
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
242
142
       "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
243
142
      {0xffc00000, 0xad800000, No_VFP,
244
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
245
142
       "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
246
247
142
      {0xffc00000, 0x28800000, No_VFP,
248
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
249
142
       "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
250
142
      {0xffc00000, 0xa8800000, No_VFP,
251
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
252
142
       "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
253
142
      {0xffc00000, 0x2c800000, No_VFP,
254
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
255
142
       "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
256
142
      {0xffc00000, 0x6c800000, No_VFP,
257
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
258
142
       "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
259
142
      {0xffc00000, 0xac800000, No_VFP,
260
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
261
142
       "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
262
263
142
      {0xffc00000, 0x29400000, No_VFP,
264
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
265
142
       "LDP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},
266
142
      {0xffc00000, 0xa9400000, No_VFP,
267
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
268
142
       "LDP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},
269
142
      {0xffc00000, 0x2d400000, No_VFP,
270
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
271
142
       "LDP  <St>, <St2>, [<Xn|SP>{, #<imm>}]"},
272
142
      {0xffc00000, 0x6d400000, No_VFP,
273
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
274
142
       "LDP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},
275
142
      {0xffc00000, 0xad400000, No_VFP,
276
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
277
142
       "LDP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},
278
279
142
      {0xffc00000, 0x29c00000, No_VFP,
280
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
281
142
       "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
282
142
      {0xffc00000, 0xa9c00000, No_VFP,
283
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
284
142
       "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
285
142
      {0xffc00000, 0x2dc00000, No_VFP,
286
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
287
142
       "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
288
142
      {0xffc00000, 0x6dc00000, No_VFP,
289
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
290
142
       "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
291
142
      {0xffc00000, 0xadc00000, No_VFP,
292
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
293
142
       "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
294
295
142
      {0xffc00000, 0x28c00000, No_VFP,
296
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
297
142
       "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
298
142
      {0xffc00000, 0xa8c00000, No_VFP,
299
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
300
142
       "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
301
142
      {0xffc00000, 0x2cc00000, No_VFP,
302
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
303
142
       "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
304
142
      {0xffc00000, 0x6cc00000, No_VFP,
305
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
306
142
       "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
307
142
      {0xffc00000, 0xacc00000, No_VFP,
308
142
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
309
142
       "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
310
311
142
      {0xffe00c00, 0xb8000400, No_VFP,
312
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
313
142
       "STR <Wt>, [<Xn|SP>], #<simm>"},
314
142
      {0xffe00c00, 0xf8000400, No_VFP,
315
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
316
142
       "STR <Xt>, [<Xn|SP>], #<simm>"},
317
142
      {0xffe00c00, 0xb8000c00, No_VFP,
318
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
319
142
       "STR <Wt>, [<Xn|SP>, #<simm>]!"},
320
142
      {0xffe00c00, 0xf8000c00, No_VFP,
321
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
322
142
       "STR <Xt>, [<Xn|SP>, #<simm>]!"},
323
142
      {0xffc00000, 0xb9000000, No_VFP,
324
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
325
142
       "STR <Wt>, [<Xn|SP>{, #<pimm>}]"},
326
142
      {0xffc00000, 0xf9000000, No_VFP,
327
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
328
142
       "STR <Xt>, [<Xn|SP>{, #<pimm>}]"},
329
330
142
      {0xffe00c00, 0xb8400400, No_VFP,
331
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
332
142
       "LDR <Wt>, [<Xn|SP>], #<simm>"},
333
142
      {0xffe00c00, 0xf8400400, No_VFP,
334
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
335
142
       "LDR <Xt>, [<Xn|SP>], #<simm>"},
336
142
      {0xffe00c00, 0xb8400c00, No_VFP,
337
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
338
142
       "LDR <Wt>, [<Xn|SP>, #<simm>]!"},
339
142
      {0xffe00c00, 0xf8400c00, No_VFP,
340
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
341
142
       "LDR <Xt>, [<Xn|SP>, #<simm>]!"},
342
142
      {0xffc00000, 0xb9400000, No_VFP,
343
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
344
142
       "LDR <Wt>, [<Xn|SP>{, #<pimm>}]"},
345
142
      {0xffc00000, 0xf9400000, No_VFP,
346
142
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
347
142
       "LDR <Xt>, [<Xn|SP>{, #<pimm>}]"},
348
349
142
      {0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB,
350
142
       "B <label>"},
351
142
      {0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond,
352
142
       "B.<cond> <label>"},
353
142
      {0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,
354
142
       "CBZ <Wt>, <label>"},
355
142
      {0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,
356
142
       "CBNZ <Wt>, <label>"},
357
142
      {0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,
358
142
       "TBZ <R><t>, #<imm>, <label>"},
359
142
      {0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,
360
142
       "TBNZ <R><t>, #<imm>, <label>"},
361
362
142
  };
363
142
  static const size_t k_num_arm_opcodes = std::size(g_opcodes);
364
365
4.70k
  for (size_t i = 0; i < k_num_arm_opcodes; 
++i4.56k
) {
366
4.64k
    if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
367
88
      return &g_opcodes[i];
368
4.64k
  }
369
54
  return nullptr;
370
142
}
371
372
0
bool EmulateInstructionARM64::ReadInstruction() {
373
0
  bool success = false;
374
0
  m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
375
0
                                LLDB_INVALID_ADDRESS, &success);
376
0
  if (success) {
377
0
    Context read_inst_context;
378
0
    read_inst_context.type = eContextReadOpcode;
379
0
    read_inst_context.SetNoArgs();
380
0
    m_opcode.SetOpcode32(
381
0
        ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
382
0
        GetByteOrder());
383
0
  }
384
0
  if (!success)
385
0
    m_addr = LLDB_INVALID_ADDRESS;
386
0
  return success;
387
0
}
388
389
142
bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) {
390
142
  const uint32_t opcode = m_opcode.GetOpcode32();
391
142
  Opcode *opcode_data = GetOpcodeForInstruction(opcode);
392
142
  if (opcode_data == nullptr)
393
54
    return false;
394
395
88
  const bool auto_advance_pc =
396
88
      evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
397
88
  m_ignore_conditions =
398
88
      evaluate_options & eEmulateInstructionOptionIgnoreConditions;
399
400
88
  bool success = false;
401
402
  // Only return false if we are unable to read the CPSR if we care about
403
  // conditions
404
88
  if (!success && !m_ignore_conditions)
405
0
    return false;
406
407
88
  uint32_t orig_pc_value = 0;
408
88
  if (auto_advance_pc) {
409
0
    orig_pc_value =
410
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
411
0
    if (!success)
412
0
      return false;
413
0
  }
414
415
  // Call the Emulate... function.
416
88
  success = (this->*opcode_data->callback)(opcode);
417
88
  if (!success)
418
31
    return false;
419
420
57
  if (auto_advance_pc) {
421
0
    uint32_t new_pc_value =
422
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
423
0
    if (!success)
424
0
      return false;
425
426
0
    if (new_pc_value == orig_pc_value) {
427
0
      EmulateInstruction::Context context;
428
0
      context.type = eContextAdvancePC;
429
0
      context.SetNoArgs();
430
0
      if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64,
431
0
                                 orig_pc_value + 4))
432
0
        return false;
433
0
    }
434
0
  }
435
57
  return true;
436
57
}
437
438
bool EmulateInstructionARM64::CreateFunctionEntryUnwind(
439
13
    UnwindPlan &unwind_plan) {
440
13
  unwind_plan.Clear();
441
13
  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
442
443
13
  UnwindPlan::RowSP row(new UnwindPlan::Row);
444
445
  // Our previous Call Frame Address is the stack pointer
446
13
  row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0);
447
448
13
  unwind_plan.AppendRow(row);
449
13
  unwind_plan.SetSourceName("EmulateInstructionARM64");
450
13
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
451
13
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
452
13
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
453
13
  unwind_plan.SetReturnAddressRegister(gpr_lr_arm64);
454
13
  return true;
455
13
}
456
457
44
uint32_t EmulateInstructionARM64::GetFramePointerRegisterNumber() const {
458
44
  if (m_arch.GetTriple().isAndroid())
459
0
    return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
460
461
44
  return gpr_fp_arm64;
462
44
}
463
464
4
bool EmulateInstructionARM64::UsingAArch32() {
465
4
  bool aarch32 = m_opcode_pstate.RW == 1;
466
  // if !HaveAnyAArch32() then assert !aarch32;
467
  // if HighestELUsingAArch32() then assert aarch32;
468
4
  return aarch32;
469
4
}
470
471
bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
472
4
                                       addr_t target) {
473
#if 0
474
    // Set program counter to a new address, with a branch reason hint for
475
    // possible use by hardware fetching the next instruction.
476
    BranchTo(bits(N) target, BranchType branch_type)
477
        Hint_Branch(branch_type);
478
        if N == 32 then
479
            assert UsingAArch32();
480
            _PC = ZeroExtend(target);
481
        else
482
            assert N == 64 && !UsingAArch32();
483
            // Remove the tag bits from a tagged target
484
            case PSTATE.EL of
485
                when EL0, EL1
486
                    if target<55> == '1' && TCR_EL1.TBI1 == '1' then
487
                        target<63:56> = '11111111';
488
                    if target<55> == '0' && TCR_EL1.TBI0 == '1' then
489
                        target<63:56> = '00000000';
490
                when EL2
491
                    if TCR_EL2.TBI == '1' then
492
                        target<63:56> = '00000000';
493
                when EL3
494
                    if TCR_EL3.TBI == '1' then
495
                        target<63:56> = '00000000';
496
        _PC = target<63:0>;
497
        return;
498
#endif
499
500
4
  addr_t addr;
501
502
  // Hint_Branch(branch_type);
503
4
  if (N == 32) {
504
0
    if (!UsingAArch32())
505
0
      return false;
506
0
    addr = target;
507
4
  } else if (N == 64) {
508
4
    if (UsingAArch32())
509
0
      return false;
510
    // TODO: Remove the tag bits from a tagged target
511
4
    addr = target;
512
4
  } else
513
0
    return false;
514
515
4
  return WriteRegisterUnsigned(context, eRegisterKindGeneric,
516
4
                               LLDB_REGNUM_GENERIC_PC, addr);
517
4
}
518
519
2
bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) {
520
  // If we are ignoring conditions, then always return true. this allows us to
521
  // iterate over disassembly code and still emulate an instruction even if we
522
  // don't have all the right bits set in the CPSR register...
523
2
  if (m_ignore_conditions)
524
2
    return true;
525
526
0
  bool result = false;
527
0
  switch (UnsignedBits(cond, 3, 1)) {
528
0
  case 0:
529
0
    result = (m_opcode_pstate.Z == 1);
530
0
    break;
531
0
  case 1:
532
0
    result = (m_opcode_pstate.C == 1);
533
0
    break;
534
0
  case 2:
535
0
    result = (m_opcode_pstate.N == 1);
536
0
    break;
537
0
  case 3:
538
0
    result = (m_opcode_pstate.V == 1);
539
0
    break;
540
0
  case 4:
541
0
    result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0);
542
0
    break;
543
0
  case 5:
544
0
    result = (m_opcode_pstate.N == m_opcode_pstate.V);
545
0
    break;
546
0
  case 6:
547
0
    result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);
548
0
    break;
549
0
  case 7:
550
    // Always execute (cond == 0b1110, or the special 0b1111 which gives
551
    // opcodes different meanings, but always means execution happens.
552
0
    return true;
553
0
  }
554
555
0
  if (cond & 1)
556
0
    result = !result;
557
0
  return result;
558
0
}
559
560
uint64_t EmulateInstructionARM64::
561
AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in,
562
34
             EmulateInstructionARM64::ProcState &proc_state) {
563
34
  uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
564
34
  std::optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y));
565
34
  bool overflow = !signed_sum;
566
34
  if (!overflow)
567
22
    overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in));
568
34
  uint64_t result = unsigned_sum;
569
34
  if (N < 64)
570
1
    result = Bits64(result, N - 1, 0);
571
34
  proc_state.N = Bit64(result, N - 1);
572
34
  proc_state.Z = IsZero(result);
573
34
  proc_state.C = UInt(result) != unsigned_sum;
574
34
  proc_state.V = overflow;
575
34
  return result;
576
34
}
577
578
31
bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) {
579
  // integer d = UInt(Rd);
580
  // integer n = UInt(Rn);
581
  // integer datasize = if sf == 1 then 64 else 32;
582
  // boolean sub_op = (op == 1);
583
  // boolean setflags = (S == 1);
584
  // bits(datasize) imm;
585
  //
586
  // case shift of
587
  //     when '00' imm = ZeroExtend(imm12, datasize);
588
  //     when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize);
589
  //    when '1x' UNDEFINED;
590
  //
591
  //
592
  // bits(datasize) result;
593
  // bits(datasize) operand1 = if n == 31 then SP[] else X[n];
594
  // bits(datasize) operand2 = imm;
595
  // bits(4) nzcv;
596
  // bit carry_in;
597
  //
598
  // if sub_op then
599
  //     operand2 = NOT(operand2);
600
  //     carry_in = 1;
601
  // else
602
  //     carry_in = 0;
603
  //
604
  // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in);
605
  //
606
  // if setflags then
607
  //     PSTATE.NZCV = nzcv;
608
  //
609
  // if d == 31 && !setflags then
610
  //     SP[] = result;
611
  // else
612
  //     X[d] = result;
613
614
31
  const uint32_t sf = Bit32(opcode, 31);
615
31
  const uint32_t op = Bit32(opcode, 30);
616
31
  const uint32_t S = Bit32(opcode, 29);
617
31
  const uint32_t shift = Bits32(opcode, 23, 22);
618
31
  const uint32_t imm12 = Bits32(opcode, 21, 10);
619
31
  const uint32_t Rn = Bits32(opcode, 9, 5);
620
31
  const uint32_t Rd = Bits32(opcode, 4, 0);
621
622
31
  bool success = false;
623
624
31
  const uint32_t d = UInt(Rd);
625
31
  const uint32_t n = UInt(Rn);
626
31
  const uint32_t datasize = (sf == 1) ? 
6430
:
321
;
627
31
  boolean sub_op = op == 1;
628
31
  boolean setflags = S == 1;
629
31
  uint64_t imm;
630
631
31
  switch (shift) {
632
31
  case 0:
633
31
    imm = imm12;
634
31
    break;
635
0
  case 1:
636
0
    imm = static_cast<uint64_t>(imm12) << 12;
637
0
    break;
638
0
  default:
639
0
    return false; // UNDEFINED;
640
31
  }
641
31
  uint64_t result;
642
31
  uint64_t operand1 =
643
31
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
644
31
  uint64_t operand2 = imm;
645
31
  bit carry_in;
646
647
31
  if (sub_op) {
648
17
    operand2 = NOT(operand2);
649
17
    carry_in = true;
650
17
    imm = -imm; // For the Register plug offset context below
651
17
  } else {
652
14
    carry_in = false;
653
14
  }
654
655
31
  ProcState proc_state;
656
657
31
  result = AddWithCarry(datasize, operand1, operand2, carry_in, proc_state);
658
659
31
  if (setflags) {
660
0
    m_emulated_pstate.N = proc_state.N;
661
0
    m_emulated_pstate.Z = proc_state.Z;
662
0
    m_emulated_pstate.C = proc_state.C;
663
0
    m_emulated_pstate.V = proc_state.V;
664
0
  }
665
666
31
  Context context;
667
31
  std::optional<RegisterInfo> reg_info_Rn =
668
31
      GetRegisterInfo(eRegisterKindLLDB, n);
669
31
  if (reg_info_Rn)
670
31
    context.SetRegisterPlusOffset(*reg_info_Rn, imm);
671
672
31
  if (n == GetFramePointerRegisterNumber() && 
d == gpr_sp_arm646
&&
!setflags6
) {
673
    // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the
674
    // stack pointer, instead of frame pointer.
675
6
    context.type = EmulateInstruction::eContextRestoreStackPointer;
676
25
  } else if ((n == gpr_sp_arm64 || 
n == GetFramePointerRegisterNumber()2
) &&
677
25
             
d == gpr_sp_arm6423
&&
!setflags17
) {
678
17
    context.type = EmulateInstruction::eContextAdjustStackPointer;
679
17
  } else 
if (8
d == GetFramePointerRegisterNumber()8
&&
n == gpr_sp_arm646
&&
680
8
             
!setflags6
) {
681
6
    context.type = EmulateInstruction::eContextSetFramePointer;
682
6
  } else {
683
2
    context.type = EmulateInstruction::eContextImmediate;
684
2
  }
685
686
  // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP
687
31
  if (!setflags || 
d != gpr_sp_arm640
)
688
31
    WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result);
689
690
31
  return false;
691
31
}
692
693
template <EmulateInstructionARM64::AddrMode a_mode>
694
42
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
695
42
  uint32_t opc = Bits32(opcode, 31, 30);
696
42
  uint32_t V = Bit32(opcode, 26);
697
42
  uint32_t L = Bit32(opcode, 22);
698
42
  uint32_t imm7 = Bits32(opcode, 21, 15);
699
42
  uint32_t Rt2 = Bits32(opcode, 14, 10);
700
42
  uint32_t Rn = Bits32(opcode, 9, 5);
701
42
  uint32_t Rt = Bits32(opcode, 4, 0);
702
703
42
  integer n = UInt(Rn);
704
42
  integer t = UInt(Rt);
705
42
  integer t2 = UInt(Rt2);
706
42
  uint64_t idx;
707
708
42
  MemOp memop = L == 1 ? 
MemOp_LOAD22
:
MemOp_STORE20
;
709
42
  boolean vector = (V == 1);
710
  // AccType acctype = AccType_NORMAL;
711
42
  boolean is_signed = false;
712
42
  boolean wback = a_mode != AddrMode_OFF;
713
42
  boolean wb_unknown = false;
714
42
  boolean rt_unknown = false;
715
42
  integer scale;
716
42
  integer size;
717
718
42
  if (opc == 3)
719
0
    return false; // UNDEFINED
720
721
42
  if (vector) {
722
8
    scale = 2 + UInt(opc);
723
34
  } else {
724
34
    scale = (opc & 2) ? 3 : 
20
;
725
34
    is_signed = (opc & 1) != 0;
726
34
    if (is_signed && 
memop == MemOp_STORE0
)
727
0
      return false; // UNDEFINED
728
34
  }
729
730
42
  if (!vector && 
wback34
&&
(9
(t == n)9
||
(t2 == n)9
)) {
731
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
732
0
    case Constraint_UNKNOWN:
733
0
      wb_unknown = true; // writeback is UNKNOWN
734
0
      break;
735
736
0
    case Constraint_SUPPRESSWB:
737
0
      wback = false; // writeback is suppressed
738
0
      break;
739
740
0
    case Constraint_NOP:
741
0
      memop = MemOp_NOP; // do nothing
742
0
      wback = false;
743
0
      break;
744
745
0
    case Constraint_NONE:
746
0
      break;
747
0
    }
748
0
  }
749
750
42
  if (memop == MemOp_LOAD && 
t == t222
) {
751
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
752
0
    case Constraint_UNKNOWN:
753
0
      rt_unknown = true; // result is UNKNOWN
754
0
      break;
755
756
0
    case Constraint_NOP:
757
0
      memop = MemOp_NOP; // do nothing
758
0
      wback = false;
759
0
      break;
760
761
0
    default:
762
0
      break;
763
0
    }
764
0
  }
765
766
42
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
767
42
  size = (integer)1 << scale;
768
42
  uint64_t datasize = size * 8;
769
42
  uint64_t address;
770
42
  uint64_t wb_address;
771
772
42
  std::optional<RegisterInfo> reg_info_base =
773
42
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
774
42
  if (!reg_info_base)
775
0
    return false;
776
777
42
  std::optional<RegisterInfo> reg_info_Rt;
778
42
  std::optional<RegisterInfo> reg_info_Rt2;
779
780
42
  if (vector) {
781
8
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t);
782
8
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2);
783
34
  } else {
784
34
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
785
34
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2);
786
34
  }
787
788
42
  if (!reg_info_Rt || !reg_info_Rt2)
789
0
    return false;
790
791
42
  bool success = false;
792
42
  if (n == 31) {
793
    // CheckSPAlignment();
794
42
    address =
795
42
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
42
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
42
  wb_address = address + idx;
801
42
  if (a_mode != AddrMode_POST)
802
36
    address = wb_address;
803
804
42
  Context context_t;
805
42
  Context context_t2;
806
807
42
  RegisterValue::BytesContainer buffer;
808
42
  Status error;
809
810
42
  switch (memop) {
811
20
  case MemOp_STORE: {
812
20
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
20
    {
816
20
      context_t.type = eContextPushRegisterOnStack;
817
20
      context_t2.type = eContextPushRegisterOnStack;
818
20
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
20
    context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0);
823
20
    context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base,
824
20
                                               size);
825
826
20
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
827
20
    if (!data_Rt)
828
0
      return false;
829
830
20
    buffer.resize(reg_info_Rt->byte_size);
831
20
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
832
20
                                 reg_info_Rt->byte_size, eByteOrderLittle,
833
20
                                 error) == 0)
834
0
      return false;
835
836
20
    if (!WriteMemory(context_t, address + 0, buffer.data(),
837
20
                     reg_info_Rt->byte_size))
838
0
      return false;
839
840
20
    std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2);
841
20
    if (!data_Rt2)
842
0
      return false;
843
844
20
    buffer.resize(reg_info_Rt2->byte_size);
845
20
    if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer.data(),
846
20
                                  reg_info_Rt2->byte_size, eByteOrderLittle,
847
20
                                  error) == 0)
848
0
      return false;
849
850
20
    if (!WriteMemory(context_t2, address + size, buffer.data(),
851
20
                     reg_info_Rt2->byte_size))
852
0
      return false;
853
20
  } break;
854
855
22
  case MemOp_LOAD: {
856
22
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
857
                                                         // based off of the sp
858
                                                         // or fp register
859
22
    {
860
22
      context_t.type = eContextPopRegisterOffStack;
861
22
      context_t2.type = eContextPopRegisterOffStack;
862
22
    } else {
863
0
      context_t.type = eContextRegisterLoad;
864
0
      context_t2.type = eContextRegisterLoad;
865
0
    }
866
22
    context_t.SetAddress(address);
867
22
    context_t2.SetAddress(address + size);
868
869
22
    buffer.resize(reg_info_Rt->byte_size);
870
22
    if (rt_unknown)
871
0
      std::fill(buffer.begin(), buffer.end(), 'U');
872
22
    else {
873
22
      if (!ReadMemory(context_t, address, buffer.data(),
874
22
                      reg_info_Rt->byte_size))
875
0
        return false;
876
22
    }
877
878
22
    RegisterValue data_Rt;
879
22
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
880
22
                                  reg_info_Rt->byte_size, eByteOrderLittle,
881
22
                                  error) == 0)
882
0
      return false;
883
884
22
    if (!vector && 
is_signed18
&&
!data_Rt.SignExtend(datasize)0
)
885
0
      return false;
886
887
22
    if (!WriteRegister(context_t, *reg_info_Rt, data_Rt))
888
0
      return false;
889
890
22
    buffer.resize(reg_info_Rt2->byte_size);
891
22
    if (!rt_unknown)
892
22
      if (!ReadMemory(context_t2, address + size, buffer.data(),
893
22
                      reg_info_Rt2->byte_size))
894
0
        return false;
895
896
22
    RegisterValue data_Rt2;
897
22
    if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer.data(),
898
22
                                   reg_info_Rt2->byte_size, eByteOrderLittle,
899
22
                                   error) == 0)
900
0
      return false;
901
902
22
    if (!vector && 
is_signed18
&&
!data_Rt2.SignExtend(datasize)0
)
903
0
      return false;
904
905
22
    if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2))
906
0
      return false;
907
22
  } break;
908
909
22
  default:
910
0
    break;
911
42
  }
912
913
42
  if (wback) {
914
11
    if (wb_unknown)
915
0
      wb_address = LLDB_INVALID_ADDRESS;
916
11
    Context context;
917
11
    context.SetImmediateSigned(idx);
918
11
    if (n == 31)
919
11
      context.type = eContextAdjustStackPointer;
920
0
    else
921
0
      context.type = eContextAdjustBaseRegister;
922
11
    WriteRegisterUnsigned(context, *reg_info_base, wb_address);
923
11
  }
924
42
  return true;
925
42
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)0>(unsigned int)
Line
Count
Source
694
31
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
695
31
  uint32_t opc = Bits32(opcode, 31, 30);
696
31
  uint32_t V = Bit32(opcode, 26);
697
31
  uint32_t L = Bit32(opcode, 22);
698
31
  uint32_t imm7 = Bits32(opcode, 21, 15);
699
31
  uint32_t Rt2 = Bits32(opcode, 14, 10);
700
31
  uint32_t Rn = Bits32(opcode, 9, 5);
701
31
  uint32_t Rt = Bits32(opcode, 4, 0);
702
703
31
  integer n = UInt(Rn);
704
31
  integer t = UInt(Rt);
705
31
  integer t2 = UInt(Rt2);
706
31
  uint64_t idx;
707
708
31
  MemOp memop = L == 1 ? 
MemOp_LOAD16
:
MemOp_STORE15
;
709
31
  boolean vector = (V == 1);
710
  // AccType acctype = AccType_NORMAL;
711
31
  boolean is_signed = false;
712
31
  boolean wback = a_mode != AddrMode_OFF;
713
31
  boolean wb_unknown = false;
714
31
  boolean rt_unknown = false;
715
31
  integer scale;
716
31
  integer size;
717
718
31
  if (opc == 3)
719
0
    return false; // UNDEFINED
720
721
31
  if (vector) {
722
6
    scale = 2 + UInt(opc);
723
25
  } else {
724
25
    scale = (opc & 2) ? 3 : 
20
;
725
25
    is_signed = (opc & 1) != 0;
726
25
    if (is_signed && 
memop == MemOp_STORE0
)
727
0
      return false; // UNDEFINED
728
25
  }
729
730
31
  if (!vector && 
wback25
&&
(0
(t == n)0
||
(t2 == n)0
)) {
731
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
732
0
    case Constraint_UNKNOWN:
733
0
      wb_unknown = true; // writeback is UNKNOWN
734
0
      break;
735
736
0
    case Constraint_SUPPRESSWB:
737
0
      wback = false; // writeback is suppressed
738
0
      break;
739
740
0
    case Constraint_NOP:
741
0
      memop = MemOp_NOP; // do nothing
742
0
      wback = false;
743
0
      break;
744
745
0
    case Constraint_NONE:
746
0
      break;
747
0
    }
748
0
  }
749
750
31
  if (memop == MemOp_LOAD && 
t == t216
) {
751
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
752
0
    case Constraint_UNKNOWN:
753
0
      rt_unknown = true; // result is UNKNOWN
754
0
      break;
755
756
0
    case Constraint_NOP:
757
0
      memop = MemOp_NOP; // do nothing
758
0
      wback = false;
759
0
      break;
760
761
0
    default:
762
0
      break;
763
0
    }
764
0
  }
765
766
31
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
767
31
  size = (integer)1 << scale;
768
31
  uint64_t datasize = size * 8;
769
31
  uint64_t address;
770
31
  uint64_t wb_address;
771
772
31
  std::optional<RegisterInfo> reg_info_base =
773
31
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
774
31
  if (!reg_info_base)
775
0
    return false;
776
777
31
  std::optional<RegisterInfo> reg_info_Rt;
778
31
  std::optional<RegisterInfo> reg_info_Rt2;
779
780
31
  if (vector) {
781
6
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t);
782
6
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2);
783
25
  } else {
784
25
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
785
25
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2);
786
25
  }
787
788
31
  if (!reg_info_Rt || !reg_info_Rt2)
789
0
    return false;
790
791
31
  bool success = false;
792
31
  if (n == 31) {
793
    // CheckSPAlignment();
794
31
    address =
795
31
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
31
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
31
  wb_address = address + idx;
801
31
  if (a_mode != AddrMode_POST)
802
31
    address = wb_address;
803
804
31
  Context context_t;
805
31
  Context context_t2;
806
807
31
  RegisterValue::BytesContainer buffer;
808
31
  Status error;
809
810
31
  switch (memop) {
811
15
  case MemOp_STORE: {
812
15
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
15
    {
816
15
      context_t.type = eContextPushRegisterOnStack;
817
15
      context_t2.type = eContextPushRegisterOnStack;
818
15
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
15
    context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0);
823
15
    context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base,
824
15
                                               size);
825
826
15
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
827
15
    if (!data_Rt)
828
0
      return false;
829
830
15
    buffer.resize(reg_info_Rt->byte_size);
831
15
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
832
15
                                 reg_info_Rt->byte_size, eByteOrderLittle,
833
15
                                 error) == 0)
834
0
      return false;
835
836
15
    if (!WriteMemory(context_t, address + 0, buffer.data(),
837
15
                     reg_info_Rt->byte_size))
838
0
      return false;
839
840
15
    std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2);
841
15
    if (!data_Rt2)
842
0
      return false;
843
844
15
    buffer.resize(reg_info_Rt2->byte_size);
845
15
    if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer.data(),
846
15
                                  reg_info_Rt2->byte_size, eByteOrderLittle,
847
15
                                  error) == 0)
848
0
      return false;
849
850
15
    if (!WriteMemory(context_t2, address + size, buffer.data(),
851
15
                     reg_info_Rt2->byte_size))
852
0
      return false;
853
15
  } break;
854
855
16
  case MemOp_LOAD: {
856
16
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
857
                                                         // based off of the sp
858
                                                         // or fp register
859
16
    {
860
16
      context_t.type = eContextPopRegisterOffStack;
861
16
      context_t2.type = eContextPopRegisterOffStack;
862
16
    } else {
863
0
      context_t.type = eContextRegisterLoad;
864
0
      context_t2.type = eContextRegisterLoad;
865
0
    }
866
16
    context_t.SetAddress(address);
867
16
    context_t2.SetAddress(address + size);
868
869
16
    buffer.resize(reg_info_Rt->byte_size);
870
16
    if (rt_unknown)
871
0
      std::fill(buffer.begin(), buffer.end(), 'U');
872
16
    else {
873
16
      if (!ReadMemory(context_t, address, buffer.data(),
874
16
                      reg_info_Rt->byte_size))
875
0
        return false;
876
16
    }
877
878
16
    RegisterValue data_Rt;
879
16
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
880
16
                                  reg_info_Rt->byte_size, eByteOrderLittle,
881
16
                                  error) == 0)
882
0
      return false;
883
884
16
    if (!vector && 
is_signed13
&&
!data_Rt.SignExtend(datasize)0
)
885
0
      return false;
886
887
16
    if (!WriteRegister(context_t, *reg_info_Rt, data_Rt))
888
0
      return false;
889
890
16
    buffer.resize(reg_info_Rt2->byte_size);
891
16
    if (!rt_unknown)
892
16
      if (!ReadMemory(context_t2, address + size, buffer.data(),
893
16
                      reg_info_Rt2->byte_size))
894
0
        return false;
895
896
16
    RegisterValue data_Rt2;
897
16
    if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer.data(),
898
16
                                   reg_info_Rt2->byte_size, eByteOrderLittle,
899
16
                                   error) == 0)
900
0
      return false;
901
902
16
    if (!vector && 
is_signed13
&&
!data_Rt2.SignExtend(datasize)0
)
903
0
      return false;
904
905
16
    if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2))
906
0
      return false;
907
16
  } break;
908
909
16
  default:
910
0
    break;
911
31
  }
912
913
31
  if (wback) {
914
0
    if (wb_unknown)
915
0
      wb_address = LLDB_INVALID_ADDRESS;
916
0
    Context context;
917
0
    context.SetImmediateSigned(idx);
918
0
    if (n == 31)
919
0
      context.type = eContextAdjustStackPointer;
920
0
    else
921
0
      context.type = eContextAdjustBaseRegister;
922
0
    WriteRegisterUnsigned(context, *reg_info_base, wb_address);
923
0
  }
924
31
  return true;
925
31
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)1>(unsigned int)
Line
Count
Source
694
5
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
695
5
  uint32_t opc = Bits32(opcode, 31, 30);
696
5
  uint32_t V = Bit32(opcode, 26);
697
5
  uint32_t L = Bit32(opcode, 22);
698
5
  uint32_t imm7 = Bits32(opcode, 21, 15);
699
5
  uint32_t Rt2 = Bits32(opcode, 14, 10);
700
5
  uint32_t Rn = Bits32(opcode, 9, 5);
701
5
  uint32_t Rt = Bits32(opcode, 4, 0);
702
703
5
  integer n = UInt(Rn);
704
5
  integer t = UInt(Rt);
705
5
  integer t2 = UInt(Rt2);
706
5
  uint64_t idx;
707
708
5
  MemOp memop = L == 1 ? 
MemOp_LOAD0
: MemOp_STORE;
709
5
  boolean vector = (V == 1);
710
  // AccType acctype = AccType_NORMAL;
711
5
  boolean is_signed = false;
712
5
  boolean wback = a_mode != AddrMode_OFF;
713
5
  boolean wb_unknown = false;
714
5
  boolean rt_unknown = false;
715
5
  integer scale;
716
5
  integer size;
717
718
5
  if (opc == 3)
719
0
    return false; // UNDEFINED
720
721
5
  if (vector) {
722
1
    scale = 2 + UInt(opc);
723
4
  } else {
724
4
    scale = (opc & 2) ? 3 : 
20
;
725
4
    is_signed = (opc & 1) != 0;
726
4
    if (is_signed && 
memop == MemOp_STORE0
)
727
0
      return false; // UNDEFINED
728
4
  }
729
730
5
  if (!vector && 
wback4
&&
(4
(t == n)4
||
(t2 == n)4
)) {
731
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
732
0
    case Constraint_UNKNOWN:
733
0
      wb_unknown = true; // writeback is UNKNOWN
734
0
      break;
735
736
0
    case Constraint_SUPPRESSWB:
737
0
      wback = false; // writeback is suppressed
738
0
      break;
739
740
0
    case Constraint_NOP:
741
0
      memop = MemOp_NOP; // do nothing
742
0
      wback = false;
743
0
      break;
744
745
0
    case Constraint_NONE:
746
0
      break;
747
0
    }
748
0
  }
749
750
5
  if (memop == MemOp_LOAD && 
t == t20
) {
751
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
752
0
    case Constraint_UNKNOWN:
753
0
      rt_unknown = true; // result is UNKNOWN
754
0
      break;
755
756
0
    case Constraint_NOP:
757
0
      memop = MemOp_NOP; // do nothing
758
0
      wback = false;
759
0
      break;
760
761
0
    default:
762
0
      break;
763
0
    }
764
0
  }
765
766
5
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
767
5
  size = (integer)1 << scale;
768
5
  uint64_t datasize = size * 8;
769
5
  uint64_t address;
770
5
  uint64_t wb_address;
771
772
5
  std::optional<RegisterInfo> reg_info_base =
773
5
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
774
5
  if (!reg_info_base)
775
0
    return false;
776
777
5
  std::optional<RegisterInfo> reg_info_Rt;
778
5
  std::optional<RegisterInfo> reg_info_Rt2;
779
780
5
  if (vector) {
781
1
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t);
782
1
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2);
783
4
  } else {
784
4
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
785
4
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2);
786
4
  }
787
788
5
  if (!reg_info_Rt || !reg_info_Rt2)
789
0
    return false;
790
791
5
  bool success = false;
792
5
  if (n == 31) {
793
    // CheckSPAlignment();
794
5
    address =
795
5
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
5
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
5
  wb_address = address + idx;
801
5
  if (a_mode != AddrMode_POST)
802
5
    address = wb_address;
803
804
5
  Context context_t;
805
5
  Context context_t2;
806
807
5
  RegisterValue::BytesContainer buffer;
808
5
  Status error;
809
810
5
  switch (memop) {
811
5
  case MemOp_STORE: {
812
5
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
5
    {
816
5
      context_t.type = eContextPushRegisterOnStack;
817
5
      context_t2.type = eContextPushRegisterOnStack;
818
5
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
5
    context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0);
823
5
    context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base,
824
5
                                               size);
825
826
5
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
827
5
    if (!data_Rt)
828
0
      return false;
829
830
5
    buffer.resize(reg_info_Rt->byte_size);
831
5
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
832
5
                                 reg_info_Rt->byte_size, eByteOrderLittle,
833
5
                                 error) == 0)
834
0
      return false;
835
836
5
    if (!WriteMemory(context_t, address + 0, buffer.data(),
837
5
                     reg_info_Rt->byte_size))
838
0
      return false;
839
840
5
    std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2);
841
5
    if (!data_Rt2)
842
0
      return false;
843
844
5
    buffer.resize(reg_info_Rt2->byte_size);
845
5
    if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer.data(),
846
5
                                  reg_info_Rt2->byte_size, eByteOrderLittle,
847
5
                                  error) == 0)
848
0
      return false;
849
850
5
    if (!WriteMemory(context_t2, address + size, buffer.data(),
851
5
                     reg_info_Rt2->byte_size))
852
0
      return false;
853
5
  } break;
854
855
5
  case MemOp_LOAD: {
856
0
    if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is
857
                                                         // based off of the sp
858
                                                         // or fp register
859
0
    {
860
0
      context_t.type = eContextPopRegisterOffStack;
861
0
      context_t2.type = eContextPopRegisterOffStack;
862
0
    } else {
863
0
      context_t.type = eContextRegisterLoad;
864
0
      context_t2.type = eContextRegisterLoad;
865
0
    }
866
0
    context_t.SetAddress(address);
867
0
    context_t2.SetAddress(address + size);
868
869
0
    buffer.resize(reg_info_Rt->byte_size);
870
0
    if (rt_unknown)
871
0
      std::fill(buffer.begin(), buffer.end(), 'U');
872
0
    else {
873
0
      if (!ReadMemory(context_t, address, buffer.data(),
874
0
                      reg_info_Rt->byte_size))
875
0
        return false;
876
0
    }
877
878
0
    RegisterValue data_Rt;
879
0
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
880
0
                                  reg_info_Rt->byte_size, eByteOrderLittle,
881
0
                                  error) == 0)
882
0
      return false;
883
884
0
    if (!vector && is_signed && !data_Rt.SignExtend(datasize))
885
0
      return false;
886
887
0
    if (!WriteRegister(context_t, *reg_info_Rt, data_Rt))
888
0
      return false;
889
890
0
    buffer.resize(reg_info_Rt2->byte_size);
891
0
    if (!rt_unknown)
892
0
      if (!ReadMemory(context_t2, address + size, buffer.data(),
893
0
                      reg_info_Rt2->byte_size))
894
0
        return false;
895
896
0
    RegisterValue data_Rt2;
897
0
    if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer.data(),
898
0
                                   reg_info_Rt2->byte_size, eByteOrderLittle,
899
0
                                   error) == 0)
900
0
      return false;
901
902
0
    if (!vector && is_signed && !data_Rt2.SignExtend(datasize))
903
0
      return false;
904
905
0
    if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2))
906
0
      return false;
907
0
  } break;
908
909
0
  default:
910
0
    break;
911
5
  }
912
913
5
  if (wback) {
914
5
    if (wb_unknown)
915
0
      wb_address = LLDB_INVALID_ADDRESS;
916
5
    Context context;
917
5
    context.SetImmediateSigned(idx);
918
5
    if (n == 31)
919
5
      context.type = eContextAdjustStackPointer;
920
0
    else
921
0
      context.type = eContextAdjustBaseRegister;
922
5
    WriteRegisterUnsigned(context, *reg_info_base, wb_address);
923
5
  }
924
5
  return true;
925
5
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)2>(unsigned int)
Line
Count
Source
694
6
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
695
6
  uint32_t opc = Bits32(opcode, 31, 30);
696
6
  uint32_t V = Bit32(opcode, 26);
697
6
  uint32_t L = Bit32(opcode, 22);
698
6
  uint32_t imm7 = Bits32(opcode, 21, 15);
699
6
  uint32_t Rt2 = Bits32(opcode, 14, 10);
700
6
  uint32_t Rn = Bits32(opcode, 9, 5);
701
6
  uint32_t Rt = Bits32(opcode, 4, 0);
702
703
6
  integer n = UInt(Rn);
704
6
  integer t = UInt(Rt);
705
6
  integer t2 = UInt(Rt2);
706
6
  uint64_t idx;
707
708
6
  MemOp memop = L == 1 ? MemOp_LOAD : 
MemOp_STORE0
;
709
6
  boolean vector = (V == 1);
710
  // AccType acctype = AccType_NORMAL;
711
6
  boolean is_signed = false;
712
6
  boolean wback = a_mode != AddrMode_OFF;
713
6
  boolean wb_unknown = false;
714
6
  boolean rt_unknown = false;
715
6
  integer scale;
716
6
  integer size;
717
718
6
  if (opc == 3)
719
0
    return false; // UNDEFINED
720
721
6
  if (vector) {
722
1
    scale = 2 + UInt(opc);
723
5
  } else {
724
5
    scale = (opc & 2) ? 3 : 
20
;
725
5
    is_signed = (opc & 1) != 0;
726
5
    if (is_signed && 
memop == MemOp_STORE0
)
727
0
      return false; // UNDEFINED
728
5
  }
729
730
6
  if (!vector && 
wback5
&&
(5
(t == n)5
||
(t2 == n)5
)) {
731
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
732
0
    case Constraint_UNKNOWN:
733
0
      wb_unknown = true; // writeback is UNKNOWN
734
0
      break;
735
736
0
    case Constraint_SUPPRESSWB:
737
0
      wback = false; // writeback is suppressed
738
0
      break;
739
740
0
    case Constraint_NOP:
741
0
      memop = MemOp_NOP; // do nothing
742
0
      wback = false;
743
0
      break;
744
745
0
    case Constraint_NONE:
746
0
      break;
747
0
    }
748
0
  }
749
750
6
  if (memop == MemOp_LOAD && t == t2) {
751
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
752
0
    case Constraint_UNKNOWN:
753
0
      rt_unknown = true; // result is UNKNOWN
754
0
      break;
755
756
0
    case Constraint_NOP:
757
0
      memop = MemOp_NOP; // do nothing
758
0
      wback = false;
759
0
      break;
760
761
0
    default:
762
0
      break;
763
0
    }
764
0
  }
765
766
6
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
767
6
  size = (integer)1 << scale;
768
6
  uint64_t datasize = size * 8;
769
6
  uint64_t address;
770
6
  uint64_t wb_address;
771
772
6
  std::optional<RegisterInfo> reg_info_base =
773
6
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
774
6
  if (!reg_info_base)
775
0
    return false;
776
777
6
  std::optional<RegisterInfo> reg_info_Rt;
778
6
  std::optional<RegisterInfo> reg_info_Rt2;
779
780
6
  if (vector) {
781
1
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t);
782
1
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2);
783
5
  } else {
784
5
    reg_info_Rt = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
785
5
    reg_info_Rt2 = GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2);
786
5
  }
787
788
6
  if (!reg_info_Rt || !reg_info_Rt2)
789
0
    return false;
790
791
6
  bool success = false;
792
6
  if (n == 31) {
793
    // CheckSPAlignment();
794
6
    address =
795
6
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
6
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
6
  wb_address = address + idx;
801
6
  if (a_mode != AddrMode_POST)
802
0
    address = wb_address;
803
804
6
  Context context_t;
805
6
  Context context_t2;
806
807
6
  RegisterValue::BytesContainer buffer;
808
6
  Status error;
809
810
6
  switch (memop) {
811
0
  case MemOp_STORE: {
812
0
    if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
0
    {
816
0
      context_t.type = eContextPushRegisterOnStack;
817
0
      context_t2.type = eContextPushRegisterOnStack;
818
0
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
0
    context_t.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base, 0);
823
0
    context_t2.SetRegisterToRegisterPlusOffset(*reg_info_Rt2, *reg_info_base,
824
0
                                               size);
825
826
0
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
827
0
    if (!data_Rt)
828
0
      return false;
829
830
0
    buffer.resize(reg_info_Rt->byte_size);
831
0
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
832
0
                                 reg_info_Rt->byte_size, eByteOrderLittle,
833
0
                                 error) == 0)
834
0
      return false;
835
836
0
    if (!WriteMemory(context_t, address + 0, buffer.data(),
837
0
                     reg_info_Rt->byte_size))
838
0
      return false;
839
840
0
    std::optional<RegisterValue> data_Rt2 = ReadRegister(*reg_info_Rt2);
841
0
    if (!data_Rt2)
842
0
      return false;
843
844
0
    buffer.resize(reg_info_Rt2->byte_size);
845
0
    if (data_Rt2->GetAsMemoryData(*reg_info_Rt2, buffer.data(),
846
0
                                  reg_info_Rt2->byte_size, eByteOrderLittle,
847
0
                                  error) == 0)
848
0
      return false;
849
850
0
    if (!WriteMemory(context_t2, address + size, buffer.data(),
851
0
                     reg_info_Rt2->byte_size))
852
0
      return false;
853
0
  } break;
854
855
6
  case MemOp_LOAD: {
856
6
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
857
                                                         // based off of the sp
858
                                                         // or fp register
859
6
    {
860
6
      context_t.type = eContextPopRegisterOffStack;
861
6
      context_t2.type = eContextPopRegisterOffStack;
862
6
    } else {
863
0
      context_t.type = eContextRegisterLoad;
864
0
      context_t2.type = eContextRegisterLoad;
865
0
    }
866
6
    context_t.SetAddress(address);
867
6
    context_t2.SetAddress(address + size);
868
869
6
    buffer.resize(reg_info_Rt->byte_size);
870
6
    if (rt_unknown)
871
0
      std::fill(buffer.begin(), buffer.end(), 'U');
872
6
    else {
873
6
      if (!ReadMemory(context_t, address, buffer.data(),
874
6
                      reg_info_Rt->byte_size))
875
0
        return false;
876
6
    }
877
878
6
    RegisterValue data_Rt;
879
6
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
880
6
                                  reg_info_Rt->byte_size, eByteOrderLittle,
881
6
                                  error) == 0)
882
0
      return false;
883
884
6
    if (!vector && 
is_signed5
&&
!data_Rt.SignExtend(datasize)0
)
885
0
      return false;
886
887
6
    if (!WriteRegister(context_t, *reg_info_Rt, data_Rt))
888
0
      return false;
889
890
6
    buffer.resize(reg_info_Rt2->byte_size);
891
6
    if (!rt_unknown)
892
6
      if (!ReadMemory(context_t2, address + size, buffer.data(),
893
6
                      reg_info_Rt2->byte_size))
894
0
        return false;
895
896
6
    RegisterValue data_Rt2;
897
6
    if (data_Rt2.SetFromMemoryData(*reg_info_Rt2, buffer.data(),
898
6
                                   reg_info_Rt2->byte_size, eByteOrderLittle,
899
6
                                   error) == 0)
900
0
      return false;
901
902
6
    if (!vector && 
is_signed5
&&
!data_Rt2.SignExtend(datasize)0
)
903
0
      return false;
904
905
6
    if (!WriteRegister(context_t2, *reg_info_Rt2, data_Rt2))
906
0
      return false;
907
6
  } break;
908
909
6
  default:
910
0
    break;
911
6
  }
912
913
6
  if (wback) {
914
6
    if (wb_unknown)
915
0
      wb_address = LLDB_INVALID_ADDRESS;
916
6
    Context context;
917
6
    context.SetImmediateSigned(idx);
918
6
    if (n == 31)
919
6
      context.type = eContextAdjustStackPointer;
920
0
    else
921
0
      context.type = eContextAdjustBaseRegister;
922
6
    WriteRegisterUnsigned(context, *reg_info_base, wb_address);
923
6
  }
924
6
  return true;
925
6
}
926
927
template <EmulateInstructionARM64::AddrMode a_mode>
928
11
bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) {
929
11
  uint32_t size = Bits32(opcode, 31, 30);
930
11
  uint32_t opc = Bits32(opcode, 23, 22);
931
11
  uint32_t n = Bits32(opcode, 9, 5);
932
11
  uint32_t t = Bits32(opcode, 4, 0);
933
934
11
  bool wback;
935
11
  bool postindex;
936
11
  uint64_t offset;
937
938
11
  switch (a_mode) {
939
0
  case AddrMode_POST:
940
0
    wback = true;
941
0
    postindex = true;
942
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
943
0
    break;
944
0
  case AddrMode_PRE:
945
0
    wback = true;
946
0
    postindex = false;
947
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
948
0
    break;
949
11
  case AddrMode_OFF:
950
11
    wback = false;
951
11
    postindex = false;
952
11
    offset = LSL(Bits32(opcode, 21, 10), size);
953
11
    break;
954
11
  }
955
956
11
  MemOp memop;
957
958
11
  if (Bit32(opc, 1) == 0) {
959
11
    memop = Bit32(opc, 0) == 1 ? 
MemOp_LOAD4
:
MemOp_STORE7
;
960
11
  } else {
961
0
    memop = MemOp_LOAD;
962
0
    if (size == 2 && Bit32(opc, 0) == 1)
963
0
      return false;
964
0
  }
965
966
11
  Status error;
967
11
  bool success = false;
968
11
  uint64_t address;
969
11
  RegisterValue::BytesContainer buffer;
970
971
11
  if (n == 31)
972
8
    address =
973
8
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
974
3
  else
975
3
    address =
976
3
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
977
978
11
  if (!success)
979
0
    return false;
980
981
11
  if (!postindex)
982
11
    address += offset;
983
984
11
  std::optional<RegisterInfo> reg_info_base =
985
11
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
986
11
  if (!reg_info_base)
987
0
    return false;
988
989
11
  std::optional<RegisterInfo> reg_info_Rt =
990
11
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
991
11
  if (!reg_info_Rt)
992
0
    return false;
993
994
11
  Context context;
995
11
  switch (memop) {
996
7
  case MemOp_STORE: {
997
7
    if (n == 31 || 
n == GetFramePointerRegisterNumber()3
) // if this store is
998
                                                         // based off of the sp
999
                                                         // or fp register
1000
4
      context.type = eContextPushRegisterOnStack;
1001
3
    else
1002
3
      context.type = eContextRegisterStore;
1003
7
    context.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base,
1004
7
                                            postindex ? 
00
: offset);
1005
1006
7
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
1007
7
    if (!data_Rt)
1008
0
      return false;
1009
1010
7
    buffer.resize(reg_info_Rt->byte_size);
1011
7
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
1012
7
                                 reg_info_Rt->byte_size, eByteOrderLittle,
1013
7
                                 error) == 0)
1014
0
      return false;
1015
1016
7
    if (!WriteMemory(context, address, buffer.data(), reg_info_Rt->byte_size))
1017
0
      return false;
1018
7
  } break;
1019
1020
7
  case MemOp_LOAD: {
1021
4
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
1022
                                                         // based off of the sp
1023
                                                         // or fp register
1024
4
      context.type = eContextPopRegisterOffStack;
1025
0
    else
1026
0
      context.type = eContextRegisterLoad;
1027
4
    context.SetAddress(address);
1028
1029
4
    buffer.resize(reg_info_Rt->byte_size);
1030
4
    if (!ReadMemory(context, address, buffer.data(), reg_info_Rt->byte_size))
1031
0
      return false;
1032
1033
4
    RegisterValue data_Rt;
1034
4
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
1035
4
                                  reg_info_Rt->byte_size, eByteOrderLittle,
1036
4
                                  error) == 0)
1037
0
      return false;
1038
1039
4
    if (!WriteRegister(context, *reg_info_Rt, data_Rt))
1040
0
      return false;
1041
4
  } break;
1042
4
  default:
1043
0
    return false;
1044
11
  }
1045
1046
11
  if (wback) {
1047
0
    if (postindex)
1048
0
      address += offset;
1049
1050
0
    if (n == 31)
1051
0
      context.type = eContextAdjustStackPointer;
1052
0
    else
1053
0
      context.type = eContextAdjustBaseRegister;
1054
0
    context.SetImmediateSigned(offset);
1055
1056
0
    if (!WriteRegisterUnsigned(context, *reg_info_base, address))
1057
0
      return false;
1058
0
  }
1059
11
  return true;
1060
11
}
Unexecuted instantiation: bool EmulateInstructionARM64::EmulateLDRSTRImm<(EmulateInstructionARM64::AddrMode)2>(unsigned int)
Unexecuted instantiation: bool EmulateInstructionARM64::EmulateLDRSTRImm<(EmulateInstructionARM64::AddrMode)1>(unsigned int)
bool EmulateInstructionARM64::EmulateLDRSTRImm<(EmulateInstructionARM64::AddrMode)0>(unsigned int)
Line
Count
Source
928
11
bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) {
929
11
  uint32_t size = Bits32(opcode, 31, 30);
930
11
  uint32_t opc = Bits32(opcode, 23, 22);
931
11
  uint32_t n = Bits32(opcode, 9, 5);
932
11
  uint32_t t = Bits32(opcode, 4, 0);
933
934
11
  bool wback;
935
11
  bool postindex;
936
11
  uint64_t offset;
937
938
11
  switch (a_mode) {
939
0
  case AddrMode_POST:
940
0
    wback = true;
941
0
    postindex = true;
942
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
943
0
    break;
944
0
  case AddrMode_PRE:
945
0
    wback = true;
946
0
    postindex = false;
947
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
948
0
    break;
949
11
  case AddrMode_OFF:
950
11
    wback = false;
951
11
    postindex = false;
952
11
    offset = LSL(Bits32(opcode, 21, 10), size);
953
11
    break;
954
11
  }
955
956
11
  MemOp memop;
957
958
11
  if (Bit32(opc, 1) == 0) {
959
11
    memop = Bit32(opc, 0) == 1 ? 
MemOp_LOAD4
:
MemOp_STORE7
;
960
11
  } else {
961
0
    memop = MemOp_LOAD;
962
0
    if (size == 2 && Bit32(opc, 0) == 1)
963
0
      return false;
964
0
  }
965
966
11
  Status error;
967
11
  bool success = false;
968
11
  uint64_t address;
969
11
  RegisterValue::BytesContainer buffer;
970
971
11
  if (n == 31)
972
8
    address =
973
8
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
974
3
  else
975
3
    address =
976
3
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
977
978
11
  if (!success)
979
0
    return false;
980
981
11
  if (!postindex)
982
11
    address += offset;
983
984
11
  std::optional<RegisterInfo> reg_info_base =
985
11
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n);
986
11
  if (!reg_info_base)
987
0
    return false;
988
989
11
  std::optional<RegisterInfo> reg_info_Rt =
990
11
      GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t);
991
11
  if (!reg_info_Rt)
992
0
    return false;
993
994
11
  Context context;
995
11
  switch (memop) {
996
7
  case MemOp_STORE: {
997
7
    if (n == 31 || 
n == GetFramePointerRegisterNumber()3
) // if this store is
998
                                                         // based off of the sp
999
                                                         // or fp register
1000
4
      context.type = eContextPushRegisterOnStack;
1001
3
    else
1002
3
      context.type = eContextRegisterStore;
1003
7
    context.SetRegisterToRegisterPlusOffset(*reg_info_Rt, *reg_info_base,
1004
7
                                            postindex ? 
00
: offset);
1005
1006
7
    std::optional<RegisterValue> data_Rt = ReadRegister(*reg_info_Rt);
1007
7
    if (!data_Rt)
1008
0
      return false;
1009
1010
7
    buffer.resize(reg_info_Rt->byte_size);
1011
7
    if (data_Rt->GetAsMemoryData(*reg_info_Rt, buffer.data(),
1012
7
                                 reg_info_Rt->byte_size, eByteOrderLittle,
1013
7
                                 error) == 0)
1014
0
      return false;
1015
1016
7
    if (!WriteMemory(context, address, buffer.data(), reg_info_Rt->byte_size))
1017
0
      return false;
1018
7
  } break;
1019
1020
7
  case MemOp_LOAD: {
1021
4
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
1022
                                                         // based off of the sp
1023
                                                         // or fp register
1024
4
      context.type = eContextPopRegisterOffStack;
1025
0
    else
1026
0
      context.type = eContextRegisterLoad;
1027
4
    context.SetAddress(address);
1028
1029
4
    buffer.resize(reg_info_Rt->byte_size);
1030
4
    if (!ReadMemory(context, address, buffer.data(), reg_info_Rt->byte_size))
1031
0
      return false;
1032
1033
4
    RegisterValue data_Rt;
1034
4
    if (data_Rt.SetFromMemoryData(*reg_info_Rt, buffer.data(),
1035
4
                                  reg_info_Rt->byte_size, eByteOrderLittle,
1036
4
                                  error) == 0)
1037
0
      return false;
1038
1039
4
    if (!WriteRegister(context, *reg_info_Rt, data_Rt))
1040
0
      return false;
1041
4
  } break;
1042
4
  default:
1043
0
    return false;
1044
11
  }
1045
1046
11
  if (wback) {
1047
0
    if (postindex)
1048
0
      address += offset;
1049
1050
0
    if (n == 31)
1051
0
      context.type = eContextAdjustStackPointer;
1052
0
    else
1053
0
      context.type = eContextAdjustBaseRegister;
1054
0
    context.SetImmediateSigned(offset);
1055
1056
0
    if (!WriteRegisterUnsigned(context, *reg_info_base, address))
1057
0
      return false;
1058
0
  }
1059
11
  return true;
1060
11
}
1061
1062
2
bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) {
1063
#if 0
1064
    // ARM64 pseudo code...
1065
    if branch_type == BranchType_CALL then X[30] = PC[] + 4;
1066
    BranchTo(PC[] + offset, branch_type);
1067
#endif
1068
1069
2
  bool success = false;
1070
1071
2
  EmulateInstruction::Context context;
1072
2
  context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1073
2
  const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric,
1074
2
                                           LLDB_REGNUM_GENERIC_PC, 0, &success);
1075
2
  if (!success)
1076
0
    return false;
1077
1078
2
  int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2);
1079
2
  BranchType branch_type = Bit32(opcode, 31) ? 
BranchType_CALL0
: BranchType_JMP;
1080
2
  addr_t target = pc + offset;
1081
2
  context.SetImmediateSigned(offset);
1082
1083
2
  switch (branch_type) {
1084
0
  case BranchType_CALL: {
1085
0
    addr_t x30 = pc + 4;
1086
0
    if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30))
1087
0
      return false;
1088
0
  } break;
1089
2
  case BranchType_JMP:
1090
2
    break;
1091
0
  default:
1092
0
    return false;
1093
2
  }
1094
1095
2
  return BranchTo(context, 64, target);
1096
2
}
1097
1098
2
bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) {
1099
#if 0
1100
    // ARM64 pseudo code...
1101
    bits(64) offset = SignExtend(imm19:'00', 64);
1102
    bits(4) condition = cond;
1103
    if ConditionHolds(condition) then
1104
        BranchTo(PC[] + offset, BranchType_JMP);
1105
#endif
1106
1107
2
  if (ConditionHolds(Bits32(opcode, 3, 0))) {
1108
2
    bool success = false;
1109
1110
2
    const uint64_t pc = ReadRegisterUnsigned(
1111
2
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1112
2
    if (!success)
1113
0
      return false;
1114
1115
2
    int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
1116
2
    addr_t target = pc + offset;
1117
1118
2
    EmulateInstruction::Context context;
1119
2
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1120
2
    context.SetImmediateSigned(offset);
1121
2
    if (!BranchTo(context, 64, target))
1122
0
      return false;
1123
2
  }
1124
2
  return true;
1125
2
}
1126
1127
0
bool EmulateInstructionARM64::EmulateCBZ(const uint32_t opcode) {
1128
#if 0
1129
    integer t = UInt(Rt);
1130
    integer datasize = if sf == '1' then 64 else 32;
1131
    boolean iszero = (op == '0');
1132
    bits(64) offset = SignExtend(imm19:'00', 64);
1133
1134
    bits(datasize) operand1 = X[t];
1135
    if IsZero(operand1) == iszero then
1136
        BranchTo(PC[] + offset, BranchType_JMP);
1137
#endif
1138
1139
0
  bool success = false;
1140
1141
0
  uint32_t t = Bits32(opcode, 4, 0);
1142
0
  bool is_zero = Bit32(opcode, 24) == 0;
1143
0
  int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
1144
1145
0
  const uint64_t operand =
1146
0
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
1147
0
  if (!success)
1148
0
    return false;
1149
1150
0
  if (m_ignore_conditions || ((operand == 0) == is_zero)) {
1151
0
    const uint64_t pc = ReadRegisterUnsigned(
1152
0
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1153
0
    if (!success)
1154
0
      return false;
1155
1156
0
    EmulateInstruction::Context context;
1157
0
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1158
0
    context.SetImmediateSigned(offset);
1159
0
    if (!BranchTo(context, 64, pc + offset))
1160
0
      return false;
1161
0
  }
1162
0
  return true;
1163
0
}
1164
1165
0
bool EmulateInstructionARM64::EmulateTBZ(const uint32_t opcode) {
1166
#if 0
1167
    integer t = UInt(Rt);
1168
    integer datasize = if b5 == '1' then 64 else 32;
1169
    integer bit_pos = UInt(b5:b40);
1170
    bit bit_val = op;
1171
    bits(64) offset = SignExtend(imm14:'00', 64);
1172
#endif
1173
1174
0
  bool success = false;
1175
1176
0
  uint32_t t = Bits32(opcode, 4, 0);
1177
0
  uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19));
1178
0
  uint32_t bit_val = Bit32(opcode, 24);
1179
0
  int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2);
1180
1181
0
  const uint64_t operand =
1182
0
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
1183
0
  if (!success)
1184
0
    return false;
1185
1186
0
  if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) {
1187
0
    const uint64_t pc = ReadRegisterUnsigned(
1188
0
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1189
0
    if (!success)
1190
0
      return false;
1191
1192
0
    EmulateInstruction::Context context;
1193
0
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1194
0
    context.SetImmediateSigned(offset);
1195
0
    if (!BranchTo(context, 64, pc + offset))
1196
0
      return false;
1197
0
  }
1198
0
  return true;
1199
0
}