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