Coverage Report

Created: 2022-01-22 13:19

/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/ConstString.h"
16
#include "lldb/Utility/RegisterValue.h"
17
#include "lldb/Utility/Stream.h"
18
19
#include "llvm/Support/CheckedArithmetic.h"
20
21
#include "Plugins/Process/Utility/ARMDefines.h"
22
#include "Plugins/Process/Utility/ARMUtils.h"
23
#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
24
25
#include <cstdlib>
26
27
#define GPR_OFFSET(idx) ((idx)*8)
28
#define GPR_OFFSET_NAME(reg) 0
29
#define FPU_OFFSET(idx) ((idx)*16)
30
#define FPU_OFFSET_NAME(reg) 0
31
#define EXC_OFFSET_NAME(reg) 0
32
#define DBG_OFFSET_NAME(reg) 0
33
#define DBG_OFFSET_NAME(reg) 0
34
#define DEFINE_DBG(re, y)                                                      \
35
  "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex,                  \
36
      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,          \
37
       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},                              \
38
      nullptr, nullptr
39
40
#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
41
42
#include "Plugins/Process/Utility/RegisterInfos_arm64.h"
43
44
#include "llvm/ADT/STLExtras.h"
45
#include "llvm/Support/MathExtras.h"
46
47
#include "Plugins/Process/Utility/InstructionUtils.h"
48
49
using namespace lldb;
50
using namespace lldb_private;
51
52
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM64, InstructionARM64)
53
54
311
static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info) {
55
311
  if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le))
56
0
    return false;
57
311
  reg_info = g_register_infos_arm64_le[reg_num];
58
311
  return true;
59
311
}
60
61
7.61k
#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
308
#define UInt(x) ((uint64_t)x)
72
83
#define SInt(x) ((int64_t)x)
73
28
#define bit bool
74
256
#define boolean bool
75
200
#define integer int64_t
76
77
31
static inline bool IsZero(uint64_t x) { return x == 0; }
78
79
16
static inline uint64_t NOT(uint64_t x) { return ~x; }
80
81
// LSL()
82
// =====
83
84
51
static inline uint64_t LSL(uint64_t x, integer shift) {
85
51
  if (shift == 0)
86
0
    return x;
87
51
  return x << shift;
88
51
}
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.44k
void EmulateInstructionARM64::Initialize() {
112
3.44k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
113
3.44k
                                GetPluginDescriptionStatic(), CreateInstance);
114
3.44k
}
115
116
3.44k
void EmulateInstructionARM64::Terminate() {
117
3.44k
  PluginManager::UnregisterPlugin(CreateInstance);
118
3.44k
}
119
120
3.44k
llvm::StringRef EmulateInstructionARM64::GetPluginDescriptionStatic() {
121
3.44k
  return "Emulate instructions for the ARM64 architecture.";
122
3.44k
}
123
124
EmulateInstruction *
125
EmulateInstructionARM64::CreateInstance(const ArchSpec &arch,
126
21.0k
                                        InstructionType inst_type) {
127
21.0k
  if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(
128
21.0k
          inst_type)) {
129
21.0k
    if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
130
21.0k
        
arch.GetTriple().getArch() == llvm::Triple::aarch64_3221.0k
) {
131
26
      return new EmulateInstructionARM64(arch);
132
26
    }
133
21.0k
  }
134
135
21.0k
  return nullptr;
136
21.0k
}
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
bool EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind,
148
                                              uint32_t reg_num,
149
311
                                              RegisterInfo &reg_info) {
150
311
  if (reg_kind == eRegisterKindGeneric) {
151
20
    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
12
    case LLDB_REGNUM_GENERIC_SP:
157
12
      reg_kind = eRegisterKindLLDB;
158
12
      reg_num = gpr_sp_arm64;
159
12
      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 false;
175
20
    }
176
20
  }
177
178
311
  if (reg_kind == eRegisterKindLLDB)
179
311
    return LLDBTableGetRegisterInfo(reg_num, reg_info);
180
0
  return false;
181
311
}
182
183
EmulateInstructionARM64::Opcode *
184
136
EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) {
185
136
  static EmulateInstructionARM64::Opcode g_opcodes[] = {
186
      // Prologue instructions
187
188
      // push register(s)
189
136
      {0xff000000, 0xd1000000, No_VFP,
190
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
191
136
       "SUB  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},
192
136
      {0xff000000, 0xf1000000, No_VFP,
193
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
194
136
       "SUBS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"},
195
136
      {0xff000000, 0x91000000, No_VFP,
196
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
197
136
       "ADD  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"},
198
136
      {0xff000000, 0xb1000000, No_VFP,
199
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
200
136
       "ADDS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"},
201
202
136
      {0xff000000, 0x51000000, No_VFP,
203
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
204
136
       "SUB  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},
205
136
      {0xff000000, 0x71000000, No_VFP,
206
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
207
136
       "SUBS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},
208
136
      {0xff000000, 0x11000000, No_VFP,
209
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
210
136
       "ADD  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"},
211
136
      {0xff000000, 0x31000000, No_VFP,
212
136
       &EmulateInstructionARM64::EmulateADDSUBImm,
213
136
       "ADDS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"},
214
215
136
      {0xffc00000, 0x29000000, No_VFP,
216
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
217
136
       "STP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},
218
136
      {0xffc00000, 0xa9000000, No_VFP,
219
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
220
136
       "STP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},
221
136
      {0xffc00000, 0x2d000000, No_VFP,
222
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
223
136
       "STP  <St>, <St2>, [<Xn|SP>{, #<imm>}]"},
224
136
      {0xffc00000, 0x6d000000, No_VFP,
225
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
226
136
       "STP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},
227
136
      {0xffc00000, 0xad000000, No_VFP,
228
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
229
136
       "STP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},
230
231
136
      {0xffc00000, 0x29800000, No_VFP,
232
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
233
136
       "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
234
136
      {0xffc00000, 0xa9800000, No_VFP,
235
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
236
136
       "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
237
136
      {0xffc00000, 0x2d800000, No_VFP,
238
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
239
136
       "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
240
136
      {0xffc00000, 0x6d800000, No_VFP,
241
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
242
136
       "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
243
136
      {0xffc00000, 0xad800000, No_VFP,
244
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
245
136
       "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
246
247
136
      {0xffc00000, 0x28800000, No_VFP,
248
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
249
136
       "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
250
136
      {0xffc00000, 0xa8800000, No_VFP,
251
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
252
136
       "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
253
136
      {0xffc00000, 0x2c800000, No_VFP,
254
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
255
136
       "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
256
136
      {0xffc00000, 0x6c800000, No_VFP,
257
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
258
136
       "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
259
136
      {0xffc00000, 0xac800000, No_VFP,
260
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
261
136
       "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
262
263
136
      {0xffc00000, 0x29400000, No_VFP,
264
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
265
136
       "LDP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"},
266
136
      {0xffc00000, 0xa9400000, No_VFP,
267
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
268
136
       "LDP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"},
269
136
      {0xffc00000, 0x2d400000, No_VFP,
270
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
271
136
       "LDP  <St>, <St2>, [<Xn|SP>{, #<imm>}]"},
272
136
      {0xffc00000, 0x6d400000, No_VFP,
273
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
274
136
       "LDP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"},
275
136
      {0xffc00000, 0xad400000, No_VFP,
276
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>,
277
136
       "LDP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"},
278
279
136
      {0xffc00000, 0x29c00000, No_VFP,
280
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
281
136
       "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
282
136
      {0xffc00000, 0xa9c00000, No_VFP,
283
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
284
136
       "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
285
136
      {0xffc00000, 0x2dc00000, No_VFP,
286
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
287
136
       "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
288
136
      {0xffc00000, 0x6dc00000, No_VFP,
289
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
290
136
       "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
291
136
      {0xffc00000, 0xadc00000, No_VFP,
292
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>,
293
136
       "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
294
295
136
      {0xffc00000, 0x28c00000, No_VFP,
296
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
297
136
       "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"},
298
136
      {0xffc00000, 0xa8c00000, No_VFP,
299
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
300
136
       "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"},
301
136
      {0xffc00000, 0x2cc00000, No_VFP,
302
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
303
136
       "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!"},
304
136
      {0xffc00000, 0x6cc00000, No_VFP,
305
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
306
136
       "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"},
307
136
      {0xffc00000, 0xacc00000, No_VFP,
308
136
       &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>,
309
136
       "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"},
310
311
136
      {0xffe00c00, 0xb8000400, No_VFP,
312
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
313
136
       "STR <Wt>, [<Xn|SP>], #<simm>"},
314
136
      {0xffe00c00, 0xf8000400, No_VFP,
315
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
316
136
       "STR <Xt>, [<Xn|SP>], #<simm>"},
317
136
      {0xffe00c00, 0xb8000c00, No_VFP,
318
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
319
136
       "STR <Wt>, [<Xn|SP>, #<simm>]!"},
320
136
      {0xffe00c00, 0xf8000c00, No_VFP,
321
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
322
136
       "STR <Xt>, [<Xn|SP>, #<simm>]!"},
323
136
      {0xffc00000, 0xb9000000, No_VFP,
324
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
325
136
       "STR <Wt>, [<Xn|SP>{, #<pimm>}]"},
326
136
      {0xffc00000, 0xf9000000, No_VFP,
327
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
328
136
       "STR <Xt>, [<Xn|SP>{, #<pimm>}]"},
329
330
136
      {0xffe00c00, 0xb8400400, No_VFP,
331
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
332
136
       "LDR <Wt>, [<Xn|SP>], #<simm>"},
333
136
      {0xffe00c00, 0xf8400400, No_VFP,
334
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>,
335
136
       "LDR <Xt>, [<Xn|SP>], #<simm>"},
336
136
      {0xffe00c00, 0xb8400c00, No_VFP,
337
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
338
136
       "LDR <Wt>, [<Xn|SP>, #<simm>]!"},
339
136
      {0xffe00c00, 0xf8400c00, No_VFP,
340
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,
341
136
       "LDR <Xt>, [<Xn|SP>, #<simm>]!"},
342
136
      {0xffc00000, 0xb9400000, No_VFP,
343
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
344
136
       "LDR <Wt>, [<Xn|SP>{, #<pimm>}]"},
345
136
      {0xffc00000, 0xf9400000, No_VFP,
346
136
       &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,
347
136
       "LDR <Xt>, [<Xn|SP>{, #<pimm>}]"},
348
349
136
      {0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB,
350
136
       "B <label>"},
351
136
      {0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond,
352
136
       "B.<cond> <label>"},
353
136
      {0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,
354
136
       "CBZ <Wt>, <label>"},
355
136
      {0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,
356
136
       "CBNZ <Wt>, <label>"},
357
136
      {0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,
358
136
       "TBZ <R><t>, #<imm>, <label>"},
359
136
      {0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,
360
136
       "TBNZ <R><t>, #<imm>, <label>"},
361
362
136
  };
363
136
  static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes);
364
365
4.60k
  for (size_t i = 0; i < k_num_arm_opcodes; 
++i4.46k
) {
366
4.55k
    if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
367
83
      return &g_opcodes[i];
368
4.55k
  }
369
53
  return nullptr;
370
136
}
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
136
bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) {
390
136
  const uint32_t opcode = m_opcode.GetOpcode32();
391
136
  Opcode *opcode_data = GetOpcodeForInstruction(opcode);
392
136
  if (opcode_data == nullptr)
393
53
    return false;
394
395
83
  const bool auto_advance_pc =
396
83
      evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
397
83
  m_ignore_conditions =
398
83
      evaluate_options & eEmulateInstructionOptionIgnoreConditions;
399
400
83
  bool success = false;
401
402
  // Only return false if we are unable to read the CPSR if we care about
403
  // conditions
404
83
  if (!success && !m_ignore_conditions)
405
0
    return false;
406
407
83
  uint32_t orig_pc_value = 0;
408
83
  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
83
  success = (this->*opcode_data->callback)(opcode);
417
83
  if (!success)
418
28
    return false;
419
420
55
  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
55
  return true;
436
55
}
437
438
bool EmulateInstructionARM64::CreateFunctionEntryUnwind(
439
12
    UnwindPlan &unwind_plan) {
440
12
  unwind_plan.Clear();
441
12
  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
442
443
12
  UnwindPlan::RowSP row(new UnwindPlan::Row);
444
445
  // Our previous Call Frame Address is the stack pointer
446
12
  row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0);
447
448
12
  unwind_plan.AppendRow(row);
449
12
  unwind_plan.SetSourceName("EmulateInstructionARM64");
450
12
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
451
12
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
452
12
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
453
12
  unwind_plan.SetReturnAddressRegister(gpr_lr_arm64);
454
12
  return true;
455
12
}
456
457
40
uint32_t EmulateInstructionARM64::GetFramePointerRegisterNumber() const {
458
40
  if (m_arch.GetTriple().isAndroid())
459
0
    return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
460
461
40
  return gpr_fp_arm64;
462
40
}
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
31
             EmulateInstructionARM64::ProcState &proc_state) {
563
31
  uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in);
564
31
  llvm::Optional<int64_t> signed_sum = llvm::checkedAdd(SInt(x), SInt(y));
565
31
  bool overflow = !signed_sum;
566
31
  if (!overflow)
567
21
    overflow |= !llvm::checkedAdd(*signed_sum, SInt(carry_in));
568
31
  uint64_t result = unsigned_sum;
569
31
  if (N < 64)
570
1
    result = Bits64(result, N - 1, 0);
571
31
  proc_state.N = Bit64(result, N - 1);
572
31
  proc_state.Z = IsZero(result);
573
31
  proc_state.C = UInt(result) != unsigned_sum;
574
31
  proc_state.V = overflow;
575
31
  return result;
576
31
}
577
578
28
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
28
  const uint32_t sf = Bit32(opcode, 31);
615
28
  const uint32_t op = Bit32(opcode, 30);
616
28
  const uint32_t S = Bit32(opcode, 29);
617
28
  const uint32_t shift = Bits32(opcode, 23, 22);
618
28
  const uint32_t imm12 = Bits32(opcode, 21, 10);
619
28
  const uint32_t Rn = Bits32(opcode, 9, 5);
620
28
  const uint32_t Rd = Bits32(opcode, 4, 0);
621
622
28
  bool success = false;
623
624
28
  const uint32_t d = UInt(Rd);
625
28
  const uint32_t n = UInt(Rn);
626
28
  const uint32_t datasize = (sf == 1) ? 
6427
:
321
;
627
28
  boolean sub_op = op == 1;
628
28
  boolean setflags = S == 1;
629
28
  uint64_t imm;
630
631
28
  switch (shift) {
632
28
  case 0:
633
28
    imm = imm12;
634
28
    break;
635
0
  case 1:
636
0
    imm = imm12 << 12;
637
0
    break;
638
0
  default:
639
0
    return false; // UNDEFINED;
640
28
  }
641
28
  uint64_t result;
642
28
  uint64_t operand1 =
643
28
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
644
28
  uint64_t operand2 = imm;
645
28
  bit carry_in;
646
647
28
  if (sub_op) {
648
16
    operand2 = NOT(operand2);
649
16
    carry_in = true;
650
16
    imm = -imm; // For the Register plug offset context below
651
16
  } else {
652
12
    carry_in = false;
653
12
  }
654
655
28
  ProcState proc_state;
656
657
28
  result = AddWithCarry(datasize, operand1, operand2, carry_in, proc_state);
658
659
28
  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
28
  Context context;
667
28
  RegisterInfo reg_info_Rn;
668
28
  if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn))
669
28
    context.SetRegisterPlusOffset(reg_info_Rn, imm);
670
671
28
  if (n == GetFramePointerRegisterNumber() && 
d == gpr_sp_arm646
&&
!setflags6
) {
672
    // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the
673
    // stack pointer, instead of frame pointer.
674
6
    context.type = EmulateInstruction::eContextRestoreStackPointer;
675
22
  } else if ((n == gpr_sp_arm64 || 
n == GetFramePointerRegisterNumber()2
) &&
676
22
             
d == gpr_sp_arm6420
&&
!setflags15
) {
677
15
    context.type = EmulateInstruction::eContextAdjustStackPointer;
678
15
  } else 
if (7
d == GetFramePointerRegisterNumber()7
&&
n == gpr_sp_arm645
&&
679
7
             
!setflags5
) {
680
5
    context.type = EmulateInstruction::eContextSetFramePointer;
681
5
  } else {
682
2
    context.type = EmulateInstruction::eContextImmediate;
683
2
  }
684
685
  // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP
686
28
  if (!setflags || 
d != gpr_sp_arm640
)
687
28
    WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result);
688
689
28
  return false;
690
28
}
691
692
template <EmulateInstructionARM64::AddrMode a_mode>
693
40
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
694
40
  uint32_t opc = Bits32(opcode, 31, 30);
695
40
  uint32_t V = Bit32(opcode, 26);
696
40
  uint32_t L = Bit32(opcode, 22);
697
40
  uint32_t imm7 = Bits32(opcode, 21, 15);
698
40
  uint32_t Rt2 = Bits32(opcode, 14, 10);
699
40
  uint32_t Rn = Bits32(opcode, 9, 5);
700
40
  uint32_t Rt = Bits32(opcode, 4, 0);
701
702
40
  integer n = UInt(Rn);
703
40
  integer t = UInt(Rt);
704
40
  integer t2 = UInt(Rt2);
705
40
  uint64_t idx;
706
707
40
  MemOp memop = L == 1 ? 
MemOp_LOAD21
:
MemOp_STORE19
;
708
40
  boolean vector = (V == 1);
709
  // AccType acctype = AccType_NORMAL;
710
40
  boolean is_signed = false;
711
40
  boolean wback = a_mode != AddrMode_OFF;
712
40
  boolean wb_unknown = false;
713
40
  boolean rt_unknown = false;
714
40
  integer scale;
715
40
  integer size;
716
717
40
  if (opc == 3)
718
0
    return false; // UNDEFINED
719
720
40
  if (vector) {
721
8
    scale = 2 + UInt(opc);
722
32
  } else {
723
32
    scale = (opc & 2) ? 3 : 
20
;
724
32
    is_signed = (opc & 1) != 0;
725
32
    if (is_signed && 
memop == MemOp_STORE0
)
726
0
      return false; // UNDEFINED
727
32
  }
728
729
40
  if (!vector && 
wback32
&&
(9
(t == n)9
||
(t2 == n)9
)) {
730
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
731
0
    case Constraint_UNKNOWN:
732
0
      wb_unknown = true; // writeback is UNKNOWN
733
0
      break;
734
735
0
    case Constraint_SUPPRESSWB:
736
0
      wback = false; // writeback is suppressed
737
0
      break;
738
739
0
    case Constraint_NOP:
740
0
      memop = MemOp_NOP; // do nothing
741
0
      wback = false;
742
0
      break;
743
744
0
    case Constraint_NONE:
745
0
      break;
746
0
    }
747
0
  }
748
749
40
  if (memop == MemOp_LOAD && 
t == t221
) {
750
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
751
0
    case Constraint_UNKNOWN:
752
0
      rt_unknown = true; // result is UNKNOWN
753
0
      break;
754
755
0
    case Constraint_NOP:
756
0
      memop = MemOp_NOP; // do nothing
757
0
      wback = false;
758
0
      break;
759
760
0
    default:
761
0
      break;
762
0
    }
763
0
  }
764
765
40
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
766
40
  size = (integer)1 << scale;
767
40
  uint64_t datasize = size * 8;
768
40
  uint64_t address;
769
40
  uint64_t wb_address;
770
771
40
  RegisterValue data_Rt;
772
40
  RegisterValue data_Rt2;
773
40
  RegisterInfo reg_info_base;
774
40
  RegisterInfo reg_info_Rt;
775
40
  RegisterInfo reg_info_Rt2;
776
40
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
777
0
    return false;
778
779
40
  if (vector) {
780
8
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt))
781
0
      return false;
782
8
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2))
783
0
      return false;
784
32
  } else {
785
32
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
786
0
      return false;
787
32
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2))
788
0
      return false;
789
32
  }
790
791
40
  bool success = false;
792
40
  if (n == 31) {
793
    // CheckSPAlignment();
794
40
    address =
795
40
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
40
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
40
  wb_address = address + idx;
801
40
  if (a_mode != AddrMode_POST)
802
34
    address = wb_address;
803
804
40
  Context context_t;
805
40
  Context context_t2;
806
807
40
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
808
40
  Status error;
809
810
40
  switch (memop) {
811
19
  case MemOp_STORE: {
812
19
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
19
    {
816
19
      context_t.type = eContextPushRegisterOnStack;
817
19
      context_t2.type = eContextPushRegisterOnStack;
818
19
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
19
    context_t.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, 0);
823
19
    context_t2.SetRegisterToRegisterPlusOffset(reg_info_Rt2, reg_info_base,
824
19
                                               size);
825
826
19
    if (!ReadRegister(&reg_info_Rt, data_Rt))
827
0
      return false;
828
829
19
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
830
19
                                eByteOrderLittle, error) == 0)
831
0
      return false;
832
833
19
    if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size))
834
0
      return false;
835
836
19
    if (!ReadRegister(&reg_info_Rt2, data_Rt2))
837
0
      return false;
838
839
19
    if (data_Rt2.GetAsMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size,
840
19
                                 eByteOrderLittle, error) == 0)
841
0
      return false;
842
843
19
    if (!WriteMemory(context_t2, address + size, buffer,
844
19
                     reg_info_Rt2.byte_size))
845
0
      return false;
846
19
  } break;
847
848
21
  case MemOp_LOAD: {
849
21
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
850
                                                         // based off of the sp
851
                                                         // or fp register
852
21
    {
853
21
      context_t.type = eContextPopRegisterOffStack;
854
21
      context_t2.type = eContextPopRegisterOffStack;
855
21
    } else {
856
0
      context_t.type = eContextRegisterLoad;
857
0
      context_t2.type = eContextRegisterLoad;
858
0
    }
859
21
    context_t.SetAddress(address);
860
21
    context_t2.SetAddress(address + size);
861
862
21
    if (rt_unknown)
863
0
      memset(buffer, 'U', reg_info_Rt.byte_size);
864
21
    else {
865
21
      if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size))
866
0
        return false;
867
21
    }
868
869
21
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
870
21
                                  eByteOrderLittle, error) == 0)
871
0
      return false;
872
873
21
    if (!vector && 
is_signed17
&&
!data_Rt.SignExtend(datasize)0
)
874
0
      return false;
875
876
21
    if (!WriteRegister(context_t, &reg_info_Rt, data_Rt))
877
0
      return false;
878
879
21
    if (!rt_unknown) {
880
21
      if (!ReadMemory(context_t2, address + size, buffer,
881
21
                      reg_info_Rt2.byte_size))
882
0
        return false;
883
21
    }
884
885
21
    if (data_Rt2.SetFromMemoryData(&reg_info_Rt2, buffer,
886
21
                                   reg_info_Rt2.byte_size, eByteOrderLittle,
887
21
                                   error) == 0)
888
0
      return false;
889
890
21
    if (!vector && 
is_signed17
&&
!data_Rt2.SignExtend(datasize)0
)
891
0
      return false;
892
893
21
    if (!WriteRegister(context_t2, &reg_info_Rt2, data_Rt2))
894
0
      return false;
895
21
  } break;
896
897
21
  default:
898
0
    break;
899
40
  }
900
901
40
  if (wback) {
902
11
    if (wb_unknown)
903
0
      wb_address = LLDB_INVALID_ADDRESS;
904
11
    Context context;
905
11
    context.SetImmediateSigned(idx);
906
11
    if (n == 31)
907
11
      context.type = eContextAdjustStackPointer;
908
0
    else
909
0
      context.type = eContextAdjustBaseRegister;
910
11
    WriteRegisterUnsigned(context, &reg_info_base, wb_address);
911
11
  }
912
40
  return true;
913
40
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)0>(unsigned int)
Line
Count
Source
693
29
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
694
29
  uint32_t opc = Bits32(opcode, 31, 30);
695
29
  uint32_t V = Bit32(opcode, 26);
696
29
  uint32_t L = Bit32(opcode, 22);
697
29
  uint32_t imm7 = Bits32(opcode, 21, 15);
698
29
  uint32_t Rt2 = Bits32(opcode, 14, 10);
699
29
  uint32_t Rn = Bits32(opcode, 9, 5);
700
29
  uint32_t Rt = Bits32(opcode, 4, 0);
701
702
29
  integer n = UInt(Rn);
703
29
  integer t = UInt(Rt);
704
29
  integer t2 = UInt(Rt2);
705
29
  uint64_t idx;
706
707
29
  MemOp memop = L == 1 ? 
MemOp_LOAD15
:
MemOp_STORE14
;
708
29
  boolean vector = (V == 1);
709
  // AccType acctype = AccType_NORMAL;
710
29
  boolean is_signed = false;
711
29
  boolean wback = a_mode != AddrMode_OFF;
712
29
  boolean wb_unknown = false;
713
29
  boolean rt_unknown = false;
714
29
  integer scale;
715
29
  integer size;
716
717
29
  if (opc == 3)
718
0
    return false; // UNDEFINED
719
720
29
  if (vector) {
721
6
    scale = 2 + UInt(opc);
722
23
  } else {
723
23
    scale = (opc & 2) ? 3 : 
20
;
724
23
    is_signed = (opc & 1) != 0;
725
23
    if (is_signed && 
memop == MemOp_STORE0
)
726
0
      return false; // UNDEFINED
727
23
  }
728
729
29
  if (!vector && 
wback23
&&
(0
(t == n)0
||
(t2 == n)0
)) {
730
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
731
0
    case Constraint_UNKNOWN:
732
0
      wb_unknown = true; // writeback is UNKNOWN
733
0
      break;
734
735
0
    case Constraint_SUPPRESSWB:
736
0
      wback = false; // writeback is suppressed
737
0
      break;
738
739
0
    case Constraint_NOP:
740
0
      memop = MemOp_NOP; // do nothing
741
0
      wback = false;
742
0
      break;
743
744
0
    case Constraint_NONE:
745
0
      break;
746
0
    }
747
0
  }
748
749
29
  if (memop == MemOp_LOAD && 
t == t215
) {
750
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
751
0
    case Constraint_UNKNOWN:
752
0
      rt_unknown = true; // result is UNKNOWN
753
0
      break;
754
755
0
    case Constraint_NOP:
756
0
      memop = MemOp_NOP; // do nothing
757
0
      wback = false;
758
0
      break;
759
760
0
    default:
761
0
      break;
762
0
    }
763
0
  }
764
765
29
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
766
29
  size = (integer)1 << scale;
767
29
  uint64_t datasize = size * 8;
768
29
  uint64_t address;
769
29
  uint64_t wb_address;
770
771
29
  RegisterValue data_Rt;
772
29
  RegisterValue data_Rt2;
773
29
  RegisterInfo reg_info_base;
774
29
  RegisterInfo reg_info_Rt;
775
29
  RegisterInfo reg_info_Rt2;
776
29
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
777
0
    return false;
778
779
29
  if (vector) {
780
6
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt))
781
0
      return false;
782
6
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2))
783
0
      return false;
784
23
  } else {
785
23
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
786
0
      return false;
787
23
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2))
788
0
      return false;
789
23
  }
790
791
29
  bool success = false;
792
29
  if (n == 31) {
793
    // CheckSPAlignment();
794
29
    address =
795
29
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
796
29
  } else
797
0
    address =
798
0
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
799
800
29
  wb_address = address + idx;
801
29
  if (a_mode != AddrMode_POST)
802
29
    address = wb_address;
803
804
29
  Context context_t;
805
29
  Context context_t2;
806
807
29
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
808
29
  Status error;
809
810
29
  switch (memop) {
811
14
  case MemOp_STORE: {
812
14
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
813
                                                         // based off of the sp
814
                                                         // or fp register
815
14
    {
816
14
      context_t.type = eContextPushRegisterOnStack;
817
14
      context_t2.type = eContextPushRegisterOnStack;
818
14
    } else {
819
0
      context_t.type = eContextRegisterStore;
820
0
      context_t2.type = eContextRegisterStore;
821
0
    }
822
14
    context_t.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, 0);
823
14
    context_t2.SetRegisterToRegisterPlusOffset(reg_info_Rt2, reg_info_base,
824
14
                                               size);
825
826
14
    if (!ReadRegister(&reg_info_Rt, data_Rt))
827
0
      return false;
828
829
14
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
830
14
                                eByteOrderLittle, error) == 0)
831
0
      return false;
832
833
14
    if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size))
834
0
      return false;
835
836
14
    if (!ReadRegister(&reg_info_Rt2, data_Rt2))
837
0
      return false;
838
839
14
    if (data_Rt2.GetAsMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size,
840
14
                                 eByteOrderLittle, error) == 0)
841
0
      return false;
842
843
14
    if (!WriteMemory(context_t2, address + size, buffer,
844
14
                     reg_info_Rt2.byte_size))
845
0
      return false;
846
14
  } break;
847
848
15
  case MemOp_LOAD: {
849
15
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
850
                                                         // based off of the sp
851
                                                         // or fp register
852
15
    {
853
15
      context_t.type = eContextPopRegisterOffStack;
854
15
      context_t2.type = eContextPopRegisterOffStack;
855
15
    } else {
856
0
      context_t.type = eContextRegisterLoad;
857
0
      context_t2.type = eContextRegisterLoad;
858
0
    }
859
15
    context_t.SetAddress(address);
860
15
    context_t2.SetAddress(address + size);
861
862
15
    if (rt_unknown)
863
0
      memset(buffer, 'U', reg_info_Rt.byte_size);
864
15
    else {
865
15
      if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size))
866
0
        return false;
867
15
    }
868
869
15
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
870
15
                                  eByteOrderLittle, error) == 0)
871
0
      return false;
872
873
15
    if (!vector && 
is_signed12
&&
!data_Rt.SignExtend(datasize)0
)
874
0
      return false;
875
876
15
    if (!WriteRegister(context_t, &reg_info_Rt, data_Rt))
877
0
      return false;
878
879
15
    if (!rt_unknown) {
880
15
      if (!ReadMemory(context_t2, address + size, buffer,
881
15
                      reg_info_Rt2.byte_size))
882
0
        return false;
883
15
    }
884
885
15
    if (data_Rt2.SetFromMemoryData(&reg_info_Rt2, buffer,
886
15
                                   reg_info_Rt2.byte_size, eByteOrderLittle,
887
15
                                   error) == 0)
888
0
      return false;
889
890
15
    if (!vector && 
is_signed12
&&
!data_Rt2.SignExtend(datasize)0
)
891
0
      return false;
892
893
15
    if (!WriteRegister(context_t2, &reg_info_Rt2, data_Rt2))
894
0
      return false;
895
15
  } break;
896
897
15
  default:
898
0
    break;
899
29
  }
900
901
29
  if (wback) {
902
0
    if (wb_unknown)
903
0
      wb_address = LLDB_INVALID_ADDRESS;
904
0
    Context context;
905
0
    context.SetImmediateSigned(idx);
906
0
    if (n == 31)
907
0
      context.type = eContextAdjustStackPointer;
908
0
    else
909
0
      context.type = eContextAdjustBaseRegister;
910
0
    WriteRegisterUnsigned(context, &reg_info_base, wb_address);
911
0
  }
912
29
  return true;
913
29
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)1>(unsigned int)
Line
Count
Source
693
5
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
694
5
  uint32_t opc = Bits32(opcode, 31, 30);
695
5
  uint32_t V = Bit32(opcode, 26);
696
5
  uint32_t L = Bit32(opcode, 22);
697
5
  uint32_t imm7 = Bits32(opcode, 21, 15);
698
5
  uint32_t Rt2 = Bits32(opcode, 14, 10);
699
5
  uint32_t Rn = Bits32(opcode, 9, 5);
700
5
  uint32_t Rt = Bits32(opcode, 4, 0);
701
702
5
  integer n = UInt(Rn);
703
5
  integer t = UInt(Rt);
704
5
  integer t2 = UInt(Rt2);
705
5
  uint64_t idx;
706
707
5
  MemOp memop = L == 1 ? 
MemOp_LOAD0
: MemOp_STORE;
708
5
  boolean vector = (V == 1);
709
  // AccType acctype = AccType_NORMAL;
710
5
  boolean is_signed = false;
711
5
  boolean wback = a_mode != AddrMode_OFF;
712
5
  boolean wb_unknown = false;
713
5
  boolean rt_unknown = false;
714
5
  integer scale;
715
5
  integer size;
716
717
5
  if (opc == 3)
718
0
    return false; // UNDEFINED
719
720
5
  if (vector) {
721
1
    scale = 2 + UInt(opc);
722
4
  } else {
723
4
    scale = (opc & 2) ? 3 : 
20
;
724
4
    is_signed = (opc & 1) != 0;
725
4
    if (is_signed && 
memop == MemOp_STORE0
)
726
0
      return false; // UNDEFINED
727
4
  }
728
729
5
  if (!vector && 
wback4
&&
(4
(t == n)4
||
(t2 == n)4
)) {
730
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
731
0
    case Constraint_UNKNOWN:
732
0
      wb_unknown = true; // writeback is UNKNOWN
733
0
      break;
734
735
0
    case Constraint_SUPPRESSWB:
736
0
      wback = false; // writeback is suppressed
737
0
      break;
738
739
0
    case Constraint_NOP:
740
0
      memop = MemOp_NOP; // do nothing
741
0
      wback = false;
742
0
      break;
743
744
0
    case Constraint_NONE:
745
0
      break;
746
0
    }
747
0
  }
748
749
5
  if (memop == MemOp_LOAD && 
t == t20
) {
750
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
751
0
    case Constraint_UNKNOWN:
752
0
      rt_unknown = true; // result is UNKNOWN
753
0
      break;
754
755
0
    case Constraint_NOP:
756
0
      memop = MemOp_NOP; // do nothing
757
0
      wback = false;
758
0
      break;
759
760
0
    default:
761
0
      break;
762
0
    }
763
0
  }
764
765
5
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
766
5
  size = (integer)1 << scale;
767
5
  uint64_t datasize = size * 8;
768
5
  uint64_t address;
769
5
  uint64_t wb_address;
770
771
5
  RegisterValue data_Rt;
772
5
  RegisterValue data_Rt2;
773
5
  RegisterInfo reg_info_base;
774
5
  RegisterInfo reg_info_Rt;
775
5
  RegisterInfo reg_info_Rt2;
776
5
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
777
0
    return false;
778
779
5
  if (vector) {
780
1
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt))
781
0
      return false;
782
1
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2))
783
0
      return false;
784
4
  } else {
785
4
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
786
0
      return false;
787
4
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2))
788
0
      return false;
789
4
  }
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
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
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
    if (!ReadRegister(&reg_info_Rt, data_Rt))
827
0
      return false;
828
829
5
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
830
5
                                eByteOrderLittle, error) == 0)
831
0
      return false;
832
833
5
    if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size))
834
0
      return false;
835
836
5
    if (!ReadRegister(&reg_info_Rt2, data_Rt2))
837
0
      return false;
838
839
5
    if (data_Rt2.GetAsMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size,
840
5
                                 eByteOrderLittle, error) == 0)
841
0
      return false;
842
843
5
    if (!WriteMemory(context_t2, address + size, buffer,
844
5
                     reg_info_Rt2.byte_size))
845
0
      return false;
846
5
  } break;
847
848
5
  case MemOp_LOAD: {
849
0
    if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is
850
                                                         // based off of the sp
851
                                                         // or fp register
852
0
    {
853
0
      context_t.type = eContextPopRegisterOffStack;
854
0
      context_t2.type = eContextPopRegisterOffStack;
855
0
    } else {
856
0
      context_t.type = eContextRegisterLoad;
857
0
      context_t2.type = eContextRegisterLoad;
858
0
    }
859
0
    context_t.SetAddress(address);
860
0
    context_t2.SetAddress(address + size);
861
862
0
    if (rt_unknown)
863
0
      memset(buffer, 'U', reg_info_Rt.byte_size);
864
0
    else {
865
0
      if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size))
866
0
        return false;
867
0
    }
868
869
0
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
870
0
                                  eByteOrderLittle, error) == 0)
871
0
      return false;
872
873
0
    if (!vector && is_signed && !data_Rt.SignExtend(datasize))
874
0
      return false;
875
876
0
    if (!WriteRegister(context_t, &reg_info_Rt, data_Rt))
877
0
      return false;
878
879
0
    if (!rt_unknown) {
880
0
      if (!ReadMemory(context_t2, address + size, buffer,
881
0
                      reg_info_Rt2.byte_size))
882
0
        return false;
883
0
    }
884
885
0
    if (data_Rt2.SetFromMemoryData(&reg_info_Rt2, buffer,
886
0
                                   reg_info_Rt2.byte_size, eByteOrderLittle,
887
0
                                   error) == 0)
888
0
      return false;
889
890
0
    if (!vector && is_signed && !data_Rt2.SignExtend(datasize))
891
0
      return false;
892
893
0
    if (!WriteRegister(context_t2, &reg_info_Rt2, data_Rt2))
894
0
      return false;
895
0
  } break;
896
897
0
  default:
898
0
    break;
899
5
  }
900
901
5
  if (wback) {
902
5
    if (wb_unknown)
903
0
      wb_address = LLDB_INVALID_ADDRESS;
904
5
    Context context;
905
5
    context.SetImmediateSigned(idx);
906
5
    if (n == 31)
907
5
      context.type = eContextAdjustStackPointer;
908
0
    else
909
0
      context.type = eContextAdjustBaseRegister;
910
5
    WriteRegisterUnsigned(context, &reg_info_base, wb_address);
911
5
  }
912
5
  return true;
913
5
}
bool EmulateInstructionARM64::EmulateLDPSTP<(EmulateInstructionARM64::AddrMode)2>(unsigned int)
Line
Count
Source
693
6
bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) {
694
6
  uint32_t opc = Bits32(opcode, 31, 30);
695
6
  uint32_t V = Bit32(opcode, 26);
696
6
  uint32_t L = Bit32(opcode, 22);
697
6
  uint32_t imm7 = Bits32(opcode, 21, 15);
698
6
  uint32_t Rt2 = Bits32(opcode, 14, 10);
699
6
  uint32_t Rn = Bits32(opcode, 9, 5);
700
6
  uint32_t Rt = Bits32(opcode, 4, 0);
701
702
6
  integer n = UInt(Rn);
703
6
  integer t = UInt(Rt);
704
6
  integer t2 = UInt(Rt2);
705
6
  uint64_t idx;
706
707
6
  MemOp memop = L == 1 ? MemOp_LOAD : 
MemOp_STORE0
;
708
6
  boolean vector = (V == 1);
709
  // AccType acctype = AccType_NORMAL;
710
6
  boolean is_signed = false;
711
6
  boolean wback = a_mode != AddrMode_OFF;
712
6
  boolean wb_unknown = false;
713
6
  boolean rt_unknown = false;
714
6
  integer scale;
715
6
  integer size;
716
717
6
  if (opc == 3)
718
0
    return false; // UNDEFINED
719
720
6
  if (vector) {
721
1
    scale = 2 + UInt(opc);
722
5
  } else {
723
5
    scale = (opc & 2) ? 3 : 
20
;
724
5
    is_signed = (opc & 1) != 0;
725
5
    if (is_signed && 
memop == MemOp_STORE0
)
726
0
      return false; // UNDEFINED
727
5
  }
728
729
6
  if (!vector && 
wback5
&&
(5
(t == n)5
||
(t2 == n)5
)) {
730
0
    switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) {
731
0
    case Constraint_UNKNOWN:
732
0
      wb_unknown = true; // writeback is UNKNOWN
733
0
      break;
734
735
0
    case Constraint_SUPPRESSWB:
736
0
      wback = false; // writeback is suppressed
737
0
      break;
738
739
0
    case Constraint_NOP:
740
0
      memop = MemOp_NOP; // do nothing
741
0
      wback = false;
742
0
      break;
743
744
0
    case Constraint_NONE:
745
0
      break;
746
0
    }
747
0
  }
748
749
6
  if (memop == MemOp_LOAD && t == t2) {
750
0
    switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) {
751
0
    case Constraint_UNKNOWN:
752
0
      rt_unknown = true; // result is UNKNOWN
753
0
      break;
754
755
0
    case Constraint_NOP:
756
0
      memop = MemOp_NOP; // do nothing
757
0
      wback = false;
758
0
      break;
759
760
0
    default:
761
0
      break;
762
0
    }
763
0
  }
764
765
6
  idx = LSL(llvm::SignExtend64<7>(imm7), scale);
766
6
  size = (integer)1 << scale;
767
6
  uint64_t datasize = size * 8;
768
6
  uint64_t address;
769
6
  uint64_t wb_address;
770
771
6
  RegisterValue data_Rt;
772
6
  RegisterValue data_Rt2;
773
6
  RegisterInfo reg_info_base;
774
6
  RegisterInfo reg_info_Rt;
775
6
  RegisterInfo reg_info_Rt2;
776
6
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
777
0
    return false;
778
779
6
  if (vector) {
780
1
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt))
781
0
      return false;
782
1
    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2))
783
0
      return false;
784
5
  } else {
785
5
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
786
0
      return false;
787
5
    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2))
788
0
      return false;
789
5
  }
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
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
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
    if (!ReadRegister(&reg_info_Rt, data_Rt))
827
0
      return false;
828
829
0
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
830
0
                                eByteOrderLittle, error) == 0)
831
0
      return false;
832
833
0
    if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size))
834
0
      return false;
835
836
0
    if (!ReadRegister(&reg_info_Rt2, data_Rt2))
837
0
      return false;
838
839
0
    if (data_Rt2.GetAsMemoryData(&reg_info_Rt2, buffer, reg_info_Rt2.byte_size,
840
0
                                 eByteOrderLittle, error) == 0)
841
0
      return false;
842
843
0
    if (!WriteMemory(context_t2, address + size, buffer,
844
0
                     reg_info_Rt2.byte_size))
845
0
      return false;
846
0
  } break;
847
848
6
  case MemOp_LOAD: {
849
6
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this load is
850
                                                         // based off of the sp
851
                                                         // or fp register
852
6
    {
853
6
      context_t.type = eContextPopRegisterOffStack;
854
6
      context_t2.type = eContextPopRegisterOffStack;
855
6
    } else {
856
0
      context_t.type = eContextRegisterLoad;
857
0
      context_t2.type = eContextRegisterLoad;
858
0
    }
859
6
    context_t.SetAddress(address);
860
6
    context_t2.SetAddress(address + size);
861
862
6
    if (rt_unknown)
863
0
      memset(buffer, 'U', reg_info_Rt.byte_size);
864
6
    else {
865
6
      if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size))
866
0
        return false;
867
6
    }
868
869
6
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
870
6
                                  eByteOrderLittle, error) == 0)
871
0
      return false;
872
873
6
    if (!vector && 
is_signed5
&&
!data_Rt.SignExtend(datasize)0
)
874
0
      return false;
875
876
6
    if (!WriteRegister(context_t, &reg_info_Rt, data_Rt))
877
0
      return false;
878
879
6
    if (!rt_unknown) {
880
6
      if (!ReadMemory(context_t2, address + size, buffer,
881
6
                      reg_info_Rt2.byte_size))
882
0
        return false;
883
6
    }
884
885
6
    if (data_Rt2.SetFromMemoryData(&reg_info_Rt2, buffer,
886
6
                                   reg_info_Rt2.byte_size, eByteOrderLittle,
887
6
                                   error) == 0)
888
0
      return false;
889
890
6
    if (!vector && 
is_signed5
&&
!data_Rt2.SignExtend(datasize)0
)
891
0
      return false;
892
893
6
    if (!WriteRegister(context_t2, &reg_info_Rt2, data_Rt2))
894
0
      return false;
895
6
  } break;
896
897
6
  default:
898
0
    break;
899
6
  }
900
901
6
  if (wback) {
902
6
    if (wb_unknown)
903
0
      wb_address = LLDB_INVALID_ADDRESS;
904
6
    Context context;
905
6
    context.SetImmediateSigned(idx);
906
6
    if (n == 31)
907
6
      context.type = eContextAdjustStackPointer;
908
0
    else
909
0
      context.type = eContextAdjustBaseRegister;
910
6
    WriteRegisterUnsigned(context, &reg_info_base, wb_address);
911
6
  }
912
6
  return true;
913
6
}
914
915
template <EmulateInstructionARM64::AddrMode a_mode>
916
11
bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) {
917
11
  uint32_t size = Bits32(opcode, 31, 30);
918
11
  uint32_t opc = Bits32(opcode, 23, 22);
919
11
  uint32_t n = Bits32(opcode, 9, 5);
920
11
  uint32_t t = Bits32(opcode, 4, 0);
921
922
11
  bool wback;
923
11
  bool postindex;
924
11
  uint64_t offset;
925
926
11
  switch (a_mode) {
927
0
  case AddrMode_POST:
928
0
    wback = true;
929
0
    postindex = true;
930
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
931
0
    break;
932
0
  case AddrMode_PRE:
933
0
    wback = true;
934
0
    postindex = false;
935
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
936
0
    break;
937
11
  case AddrMode_OFF:
938
11
    wback = false;
939
11
    postindex = false;
940
11
    offset = LSL(Bits32(opcode, 21, 10), size);
941
11
    break;
942
11
  }
943
944
11
  MemOp memop;
945
946
11
  if (Bit32(opc, 1) == 0) {
947
11
    memop = Bit32(opc, 0) == 1 ? 
MemOp_LOAD4
:
MemOp_STORE7
;
948
11
  } else {
949
0
    memop = MemOp_LOAD;
950
0
    if (size == 2 && Bit32(opc, 0) == 1)
951
0
      return false;
952
0
  }
953
954
11
  Status error;
955
11
  bool success = false;
956
11
  uint64_t address;
957
11
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
958
11
  RegisterValue data_Rt;
959
960
11
  if (n == 31)
961
8
    address =
962
8
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
963
3
  else
964
3
    address =
965
3
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
966
967
11
  if (!success)
968
0
    return false;
969
970
11
  if (!postindex)
971
11
    address += offset;
972
973
11
  RegisterInfo reg_info_base;
974
11
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
975
0
    return false;
976
977
11
  RegisterInfo reg_info_Rt;
978
11
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
979
0
    return false;
980
981
11
  Context context;
982
11
  switch (memop) {
983
7
  case MemOp_STORE:
984
7
    if (n == 31 || 
n == GetFramePointerRegisterNumber()3
) // if this store is
985
                                                         // based off of the sp
986
                                                         // or fp register
987
4
      context.type = eContextPushRegisterOnStack;
988
3
    else
989
3
      context.type = eContextRegisterStore;
990
7
    context.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base,
991
7
                                            postindex ? 
00
: offset);
992
993
7
    if (!ReadRegister(&reg_info_Rt, data_Rt))
994
0
      return false;
995
996
7
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
997
7
                                eByteOrderLittle, error) == 0)
998
0
      return false;
999
1000
7
    if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size))
1001
0
      return false;
1002
7
    break;
1003
1004
7
  case MemOp_LOAD:
1005
4
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
1006
                                                         // based off of the sp
1007
                                                         // or fp register
1008
4
      context.type = eContextPopRegisterOffStack;
1009
0
    else
1010
0
      context.type = eContextRegisterLoad;
1011
4
    context.SetAddress(address);
1012
1013
4
    if (!ReadMemory(context, address, buffer, reg_info_Rt.byte_size))
1014
0
      return false;
1015
1016
4
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
1017
4
                                  eByteOrderLittle, error) == 0)
1018
0
      return false;
1019
1020
4
    if (!WriteRegister(context, &reg_info_Rt, data_Rt))
1021
0
      return false;
1022
4
    break;
1023
4
  default:
1024
0
    return false;
1025
11
  }
1026
1027
11
  if (wback) {
1028
0
    if (postindex)
1029
0
      address += offset;
1030
1031
0
    if (n == 31)
1032
0
      context.type = eContextAdjustStackPointer;
1033
0
    else
1034
0
      context.type = eContextAdjustBaseRegister;
1035
0
    context.SetImmediateSigned(offset);
1036
1037
0
    if (!WriteRegisterUnsigned(context, &reg_info_base, address))
1038
0
      return false;
1039
0
  }
1040
11
  return true;
1041
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
916
11
bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) {
917
11
  uint32_t size = Bits32(opcode, 31, 30);
918
11
  uint32_t opc = Bits32(opcode, 23, 22);
919
11
  uint32_t n = Bits32(opcode, 9, 5);
920
11
  uint32_t t = Bits32(opcode, 4, 0);
921
922
11
  bool wback;
923
11
  bool postindex;
924
11
  uint64_t offset;
925
926
11
  switch (a_mode) {
927
0
  case AddrMode_POST:
928
0
    wback = true;
929
0
    postindex = true;
930
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
931
0
    break;
932
0
  case AddrMode_PRE:
933
0
    wback = true;
934
0
    postindex = false;
935
0
    offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
936
0
    break;
937
11
  case AddrMode_OFF:
938
11
    wback = false;
939
11
    postindex = false;
940
11
    offset = LSL(Bits32(opcode, 21, 10), size);
941
11
    break;
942
11
  }
943
944
11
  MemOp memop;
945
946
11
  if (Bit32(opc, 1) == 0) {
947
11
    memop = Bit32(opc, 0) == 1 ? 
MemOp_LOAD4
:
MemOp_STORE7
;
948
11
  } else {
949
0
    memop = MemOp_LOAD;
950
0
    if (size == 2 && Bit32(opc, 0) == 1)
951
0
      return false;
952
0
  }
953
954
11
  Status error;
955
11
  bool success = false;
956
11
  uint64_t address;
957
11
  uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
958
11
  RegisterValue data_Rt;
959
960
11
  if (n == 31)
961
8
    address =
962
8
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
963
3
  else
964
3
    address =
965
3
        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
966
967
11
  if (!success)
968
0
    return false;
969
970
11
  if (!postindex)
971
11
    address += offset;
972
973
11
  RegisterInfo reg_info_base;
974
11
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
975
0
    return false;
976
977
11
  RegisterInfo reg_info_Rt;
978
11
  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
979
0
    return false;
980
981
11
  Context context;
982
11
  switch (memop) {
983
7
  case MemOp_STORE:
984
7
    if (n == 31 || 
n == GetFramePointerRegisterNumber()3
) // if this store is
985
                                                         // based off of the sp
986
                                                         // or fp register
987
4
      context.type = eContextPushRegisterOnStack;
988
3
    else
989
3
      context.type = eContextRegisterStore;
990
7
    context.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base,
991
7
                                            postindex ? 
00
: offset);
992
993
7
    if (!ReadRegister(&reg_info_Rt, data_Rt))
994
0
      return false;
995
996
7
    if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
997
7
                                eByteOrderLittle, error) == 0)
998
0
      return false;
999
1000
7
    if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size))
1001
0
      return false;
1002
7
    break;
1003
1004
7
  case MemOp_LOAD:
1005
4
    if (n == 31 || 
n == GetFramePointerRegisterNumber()0
) // if this store is
1006
                                                         // based off of the sp
1007
                                                         // or fp register
1008
4
      context.type = eContextPopRegisterOffStack;
1009
0
    else
1010
0
      context.type = eContextRegisterLoad;
1011
4
    context.SetAddress(address);
1012
1013
4
    if (!ReadMemory(context, address, buffer, reg_info_Rt.byte_size))
1014
0
      return false;
1015
1016
4
    if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size,
1017
4
                                  eByteOrderLittle, error) == 0)
1018
0
      return false;
1019
1020
4
    if (!WriteRegister(context, &reg_info_Rt, data_Rt))
1021
0
      return false;
1022
4
    break;
1023
4
  default:
1024
0
    return false;
1025
11
  }
1026
1027
11
  if (wback) {
1028
0
    if (postindex)
1029
0
      address += offset;
1030
1031
0
    if (n == 31)
1032
0
      context.type = eContextAdjustStackPointer;
1033
0
    else
1034
0
      context.type = eContextAdjustBaseRegister;
1035
0
    context.SetImmediateSigned(offset);
1036
1037
0
    if (!WriteRegisterUnsigned(context, &reg_info_base, address))
1038
0
      return false;
1039
0
  }
1040
11
  return true;
1041
11
}
1042
1043
2
bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) {
1044
#if 0
1045
    // ARM64 pseudo code...
1046
    if branch_type == BranchType_CALL then X[30] = PC[] + 4;
1047
    BranchTo(PC[] + offset, branch_type);
1048
#endif
1049
1050
2
  bool success = false;
1051
1052
2
  EmulateInstruction::Context context;
1053
2
  context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1054
2
  const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric,
1055
2
                                           LLDB_REGNUM_GENERIC_PC, 0, &success);
1056
2
  if (!success)
1057
0
    return false;
1058
1059
2
  int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2);
1060
2
  BranchType branch_type = Bit32(opcode, 31) ? 
BranchType_CALL0
: BranchType_JMP;
1061
2
  addr_t target = pc + offset;
1062
2
  context.SetImmediateSigned(offset);
1063
1064
2
  switch (branch_type) {
1065
0
  case BranchType_CALL: {
1066
0
    addr_t x30 = pc + 4;
1067
0
    if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30))
1068
0
      return false;
1069
0
  } break;
1070
2
  case BranchType_JMP:
1071
2
    break;
1072
0
  default:
1073
0
    return false;
1074
2
  }
1075
1076
2
  return BranchTo(context, 64, target);
1077
2
}
1078
1079
2
bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) {
1080
#if 0
1081
    // ARM64 pseudo code...
1082
    bits(64) offset = SignExtend(imm19:'00', 64);
1083
    bits(4) condition = cond;
1084
    if ConditionHolds(condition) then
1085
        BranchTo(PC[] + offset, BranchType_JMP);
1086
#endif
1087
1088
2
  if (ConditionHolds(Bits32(opcode, 3, 0))) {
1089
2
    bool success = false;
1090
1091
2
    const uint64_t pc = ReadRegisterUnsigned(
1092
2
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1093
2
    if (!success)
1094
0
      return false;
1095
1096
2
    int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
1097
2
    addr_t target = pc + offset;
1098
1099
2
    EmulateInstruction::Context context;
1100
2
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1101
2
    context.SetImmediateSigned(offset);
1102
2
    if (!BranchTo(context, 64, target))
1103
0
      return false;
1104
2
  }
1105
2
  return true;
1106
2
}
1107
1108
0
bool EmulateInstructionARM64::EmulateCBZ(const uint32_t opcode) {
1109
#if 0
1110
    integer t = UInt(Rt);
1111
    integer datasize = if sf == '1' then 64 else 32;
1112
    boolean iszero = (op == '0');
1113
    bits(64) offset = SignExtend(imm19:'00', 64);
1114
1115
    bits(datasize) operand1 = X[t];
1116
    if IsZero(operand1) == iszero then
1117
        BranchTo(PC[] + offset, BranchType_JMP);
1118
#endif
1119
1120
0
  bool success = false;
1121
1122
0
  uint32_t t = Bits32(opcode, 4, 0);
1123
0
  bool is_zero = Bit32(opcode, 24) == 0;
1124
0
  int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
1125
1126
0
  const uint64_t operand =
1127
0
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
1128
0
  if (!success)
1129
0
    return false;
1130
1131
0
  if (m_ignore_conditions || ((operand == 0) == is_zero)) {
1132
0
    const uint64_t pc = ReadRegisterUnsigned(
1133
0
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1134
0
    if (!success)
1135
0
      return false;
1136
1137
0
    EmulateInstruction::Context context;
1138
0
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1139
0
    context.SetImmediateSigned(offset);
1140
0
    if (!BranchTo(context, 64, pc + offset))
1141
0
      return false;
1142
0
  }
1143
0
  return true;
1144
0
}
1145
1146
0
bool EmulateInstructionARM64::EmulateTBZ(const uint32_t opcode) {
1147
#if 0
1148
    integer t = UInt(Rt);
1149
    integer datasize = if b5 == '1' then 64 else 32;
1150
    integer bit_pos = UInt(b5:b40);
1151
    bit bit_val = op;
1152
    bits(64) offset = SignExtend(imm14:'00', 64);
1153
#endif
1154
1155
0
  bool success = false;
1156
1157
0
  uint32_t t = Bits32(opcode, 4, 0);
1158
0
  uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19));
1159
0
  uint32_t bit_val = Bit32(opcode, 24);
1160
0
  int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2);
1161
1162
0
  const uint64_t operand =
1163
0
      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
1164
0
  if (!success)
1165
0
    return false;
1166
1167
0
  if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) {
1168
0
    const uint64_t pc = ReadRegisterUnsigned(
1169
0
        eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
1170
0
    if (!success)
1171
0
      return false;
1172
1173
0
    EmulateInstruction::Context context;
1174
0
    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1175
0
    context.SetImmediateSigned(offset);
1176
0
    if (!BranchTo(context, 64, pc + offset))
1177
0
      return false;
1178
0
  }
1179
0
  return true;
1180
0
}