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/MIPS64/EmulateInstructionMIPS64.cpp
39653 views
1
//===-- EmulateInstructionMIPS64.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 "EmulateInstructionMIPS64.h"
10
11
#include <cstdlib>
12
#include <optional>
13
14
#include "lldb/Core/Address.h"
15
#include "lldb/Core/Opcode.h"
16
#include "lldb/Core/PluginManager.h"
17
#include "lldb/Host/PosixApi.h"
18
#include "lldb/Symbol/UnwindPlan.h"
19
#include "lldb/Utility/ArchSpec.h"
20
#include "lldb/Utility/ConstString.h"
21
#include "lldb/Utility/DataExtractor.h"
22
#include "lldb/Utility/RegisterValue.h"
23
#include "lldb/Utility/Stream.h"
24
#include "llvm-c/Disassembler.h"
25
#include "llvm/MC/MCAsmInfo.h"
26
#include "llvm/MC/MCContext.h"
27
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
28
#include "llvm/MC/MCInst.h"
29
#include "llvm/MC/MCInstrInfo.h"
30
#include "llvm/MC/MCRegisterInfo.h"
31
#include "llvm/MC/MCSubtargetInfo.h"
32
#include "llvm/MC/MCTargetOptions.h"
33
#include "llvm/MC/TargetRegistry.h"
34
#include "llvm/Support/TargetSelect.h"
35
36
#include "llvm/ADT/STLExtras.h"
37
38
#include "Plugins/Process/Utility/InstructionUtils.h"
39
#include "Plugins/Process/Utility/RegisterContext_mips.h"
40
41
using namespace lldb;
42
using namespace lldb_private;
43
44
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionMIPS64, InstructionMIPS64)
45
46
#define UInt(x) ((uint64_t)x)
47
#define integer int64_t
48
49
//
50
// EmulateInstructionMIPS64 implementation
51
//
52
53
#ifdef __mips__
54
extern "C" {
55
void LLVMInitializeMipsTargetInfo();
56
void LLVMInitializeMipsTarget();
57
void LLVMInitializeMipsAsmPrinter();
58
void LLVMInitializeMipsTargetMC();
59
void LLVMInitializeMipsDisassembler();
60
}
61
#endif
62
63
EmulateInstructionMIPS64::EmulateInstructionMIPS64(
64
const lldb_private::ArchSpec &arch)
65
: EmulateInstruction(arch) {
66
/* Create instance of llvm::MCDisassembler */
67
std::string Status;
68
llvm::Triple triple = arch.GetTriple();
69
const llvm::Target *target =
70
llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
71
72
/*
73
* If we fail to get the target then we haven't registered it. The
74
* SystemInitializerCommon
75
* does not initialize targets, MCs and disassemblers. However we need the
76
* MCDisassembler
77
* to decode the instructions so that the decoding complexity stays with LLVM.
78
* Initialize the MIPS targets and disassemblers.
79
*/
80
#ifdef __mips__
81
if (!target) {
82
LLVMInitializeMipsTargetInfo();
83
LLVMInitializeMipsTarget();
84
LLVMInitializeMipsAsmPrinter();
85
LLVMInitializeMipsTargetMC();
86
LLVMInitializeMipsDisassembler();
87
target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Status);
88
}
89
#endif
90
91
assert(target);
92
93
llvm::StringRef cpu;
94
95
switch (arch.GetCore()) {
96
case ArchSpec::eCore_mips32:
97
case ArchSpec::eCore_mips32el:
98
cpu = "mips32";
99
break;
100
case ArchSpec::eCore_mips32r2:
101
case ArchSpec::eCore_mips32r2el:
102
cpu = "mips32r2";
103
break;
104
case ArchSpec::eCore_mips32r3:
105
case ArchSpec::eCore_mips32r3el:
106
cpu = "mips32r3";
107
break;
108
case ArchSpec::eCore_mips32r5:
109
case ArchSpec::eCore_mips32r5el:
110
cpu = "mips32r5";
111
break;
112
case ArchSpec::eCore_mips32r6:
113
case ArchSpec::eCore_mips32r6el:
114
cpu = "mips32r6";
115
break;
116
case ArchSpec::eCore_mips64:
117
case ArchSpec::eCore_mips64el:
118
cpu = "mips64";
119
break;
120
case ArchSpec::eCore_mips64r2:
121
case ArchSpec::eCore_mips64r2el:
122
cpu = "mips64r2";
123
break;
124
case ArchSpec::eCore_mips64r3:
125
case ArchSpec::eCore_mips64r3el:
126
cpu = "mips64r3";
127
break;
128
case ArchSpec::eCore_mips64r5:
129
case ArchSpec::eCore_mips64r5el:
130
cpu = "mips64r5";
131
break;
132
case ArchSpec::eCore_mips64r6:
133
case ArchSpec::eCore_mips64r6el:
134
cpu = "mips64r6";
135
break;
136
default:
137
cpu = "generic";
138
break;
139
}
140
141
std::string features;
142
uint32_t arch_flags = arch.GetFlags();
143
if (arch_flags & ArchSpec::eMIPSAse_msa)
144
features += "+msa,";
145
if (arch_flags & ArchSpec::eMIPSAse_dsp)
146
features += "+dsp,";
147
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
148
features += "+dspr2,";
149
if (arch_flags & ArchSpec::eMIPSAse_mips16)
150
features += "+mips16,";
151
if (arch_flags & ArchSpec::eMIPSAse_micromips)
152
features += "+micromips,";
153
154
m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
155
assert(m_reg_info.get());
156
157
m_insn_info.reset(target->createMCInstrInfo());
158
assert(m_insn_info.get());
159
160
llvm::MCTargetOptions MCOptions;
161
m_asm_info.reset(
162
target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
163
m_subtype_info.reset(
164
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
165
assert(m_asm_info.get() && m_subtype_info.get());
166
167
m_context = std::make_unique<llvm::MCContext>(
168
triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
169
assert(m_context.get());
170
171
m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
172
assert(m_disasm.get());
173
}
174
175
void EmulateInstructionMIPS64::Initialize() {
176
PluginManager::RegisterPlugin(GetPluginNameStatic(),
177
GetPluginDescriptionStatic(), CreateInstance);
178
}
179
180
void EmulateInstructionMIPS64::Terminate() {
181
PluginManager::UnregisterPlugin(CreateInstance);
182
}
183
184
llvm::StringRef EmulateInstructionMIPS64::GetPluginDescriptionStatic() {
185
return "Emulate instructions for the MIPS64 architecture.";
186
}
187
188
EmulateInstruction *
189
EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
190
InstructionType inst_type) {
191
if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(
192
inst_type)) {
193
if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
194
arch.GetTriple().getArch() == llvm::Triple::mips64el) {
195
return new EmulateInstructionMIPS64(arch);
196
}
197
}
198
199
return nullptr;
200
}
201
202
bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
203
return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
204
arch.GetTriple().getArch() == llvm::Triple::mips64el;
205
}
206
207
const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
208
bool alternate_name) {
209
if (alternate_name) {
210
switch (reg_num) {
211
case dwarf_sp_mips64:
212
return "r29";
213
case dwarf_r30_mips64:
214
return "r30";
215
case dwarf_ra_mips64:
216
return "r31";
217
case dwarf_f0_mips64:
218
return "f0";
219
case dwarf_f1_mips64:
220
return "f1";
221
case dwarf_f2_mips64:
222
return "f2";
223
case dwarf_f3_mips64:
224
return "f3";
225
case dwarf_f4_mips64:
226
return "f4";
227
case dwarf_f5_mips64:
228
return "f5";
229
case dwarf_f6_mips64:
230
return "f6";
231
case dwarf_f7_mips64:
232
return "f7";
233
case dwarf_f8_mips64:
234
return "f8";
235
case dwarf_f9_mips64:
236
return "f9";
237
case dwarf_f10_mips64:
238
return "f10";
239
case dwarf_f11_mips64:
240
return "f11";
241
case dwarf_f12_mips64:
242
return "f12";
243
case dwarf_f13_mips64:
244
return "f13";
245
case dwarf_f14_mips64:
246
return "f14";
247
case dwarf_f15_mips64:
248
return "f15";
249
case dwarf_f16_mips64:
250
return "f16";
251
case dwarf_f17_mips64:
252
return "f17";
253
case dwarf_f18_mips64:
254
return "f18";
255
case dwarf_f19_mips64:
256
return "f19";
257
case dwarf_f20_mips64:
258
return "f20";
259
case dwarf_f21_mips64:
260
return "f21";
261
case dwarf_f22_mips64:
262
return "f22";
263
case dwarf_f23_mips64:
264
return "f23";
265
case dwarf_f24_mips64:
266
return "f24";
267
case dwarf_f25_mips64:
268
return "f25";
269
case dwarf_f26_mips64:
270
return "f26";
271
case dwarf_f27_mips64:
272
return "f27";
273
case dwarf_f28_mips64:
274
return "f28";
275
case dwarf_f29_mips64:
276
return "f29";
277
case dwarf_f30_mips64:
278
return "f30";
279
case dwarf_f31_mips64:
280
return "f31";
281
case dwarf_w0_mips64:
282
return "w0";
283
case dwarf_w1_mips64:
284
return "w1";
285
case dwarf_w2_mips64:
286
return "w2";
287
case dwarf_w3_mips64:
288
return "w3";
289
case dwarf_w4_mips64:
290
return "w4";
291
case dwarf_w5_mips64:
292
return "w5";
293
case dwarf_w6_mips64:
294
return "w6";
295
case dwarf_w7_mips64:
296
return "w7";
297
case dwarf_w8_mips64:
298
return "w8";
299
case dwarf_w9_mips64:
300
return "w9";
301
case dwarf_w10_mips64:
302
return "w10";
303
case dwarf_w11_mips64:
304
return "w11";
305
case dwarf_w12_mips64:
306
return "w12";
307
case dwarf_w13_mips64:
308
return "w13";
309
case dwarf_w14_mips64:
310
return "w14";
311
case dwarf_w15_mips64:
312
return "w15";
313
case dwarf_w16_mips64:
314
return "w16";
315
case dwarf_w17_mips64:
316
return "w17";
317
case dwarf_w18_mips64:
318
return "w18";
319
case dwarf_w19_mips64:
320
return "w19";
321
case dwarf_w20_mips64:
322
return "w20";
323
case dwarf_w21_mips64:
324
return "w21";
325
case dwarf_w22_mips64:
326
return "w22";
327
case dwarf_w23_mips64:
328
return "w23";
329
case dwarf_w24_mips64:
330
return "w24";
331
case dwarf_w25_mips64:
332
return "w25";
333
case dwarf_w26_mips64:
334
return "w26";
335
case dwarf_w27_mips64:
336
return "w27";
337
case dwarf_w28_mips64:
338
return "w28";
339
case dwarf_w29_mips64:
340
return "w29";
341
case dwarf_w30_mips64:
342
return "w30";
343
case dwarf_w31_mips64:
344
return "w31";
345
case dwarf_mir_mips64:
346
return "mir";
347
case dwarf_mcsr_mips64:
348
return "mcsr";
349
case dwarf_config5_mips64:
350
return "config5";
351
default:
352
break;
353
}
354
return nullptr;
355
}
356
357
switch (reg_num) {
358
case dwarf_zero_mips64:
359
return "r0";
360
case dwarf_r1_mips64:
361
return "r1";
362
case dwarf_r2_mips64:
363
return "r2";
364
case dwarf_r3_mips64:
365
return "r3";
366
case dwarf_r4_mips64:
367
return "r4";
368
case dwarf_r5_mips64:
369
return "r5";
370
case dwarf_r6_mips64:
371
return "r6";
372
case dwarf_r7_mips64:
373
return "r7";
374
case dwarf_r8_mips64:
375
return "r8";
376
case dwarf_r9_mips64:
377
return "r9";
378
case dwarf_r10_mips64:
379
return "r10";
380
case dwarf_r11_mips64:
381
return "r11";
382
case dwarf_r12_mips64:
383
return "r12";
384
case dwarf_r13_mips64:
385
return "r13";
386
case dwarf_r14_mips64:
387
return "r14";
388
case dwarf_r15_mips64:
389
return "r15";
390
case dwarf_r16_mips64:
391
return "r16";
392
case dwarf_r17_mips64:
393
return "r17";
394
case dwarf_r18_mips64:
395
return "r18";
396
case dwarf_r19_mips64:
397
return "r19";
398
case dwarf_r20_mips64:
399
return "r20";
400
case dwarf_r21_mips64:
401
return "r21";
402
case dwarf_r22_mips64:
403
return "r22";
404
case dwarf_r23_mips64:
405
return "r23";
406
case dwarf_r24_mips64:
407
return "r24";
408
case dwarf_r25_mips64:
409
return "r25";
410
case dwarf_r26_mips64:
411
return "r26";
412
case dwarf_r27_mips64:
413
return "r27";
414
case dwarf_gp_mips64:
415
return "gp";
416
case dwarf_sp_mips64:
417
return "sp";
418
case dwarf_r30_mips64:
419
return "fp";
420
case dwarf_ra_mips64:
421
return "ra";
422
case dwarf_sr_mips64:
423
return "sr";
424
case dwarf_lo_mips64:
425
return "lo";
426
case dwarf_hi_mips64:
427
return "hi";
428
case dwarf_bad_mips64:
429
return "bad";
430
case dwarf_cause_mips64:
431
return "cause";
432
case dwarf_pc_mips64:
433
return "pc";
434
case dwarf_f0_mips64:
435
return "f0";
436
case dwarf_f1_mips64:
437
return "f1";
438
case dwarf_f2_mips64:
439
return "f2";
440
case dwarf_f3_mips64:
441
return "f3";
442
case dwarf_f4_mips64:
443
return "f4";
444
case dwarf_f5_mips64:
445
return "f5";
446
case dwarf_f6_mips64:
447
return "f6";
448
case dwarf_f7_mips64:
449
return "f7";
450
case dwarf_f8_mips64:
451
return "f8";
452
case dwarf_f9_mips64:
453
return "f9";
454
case dwarf_f10_mips64:
455
return "f10";
456
case dwarf_f11_mips64:
457
return "f11";
458
case dwarf_f12_mips64:
459
return "f12";
460
case dwarf_f13_mips64:
461
return "f13";
462
case dwarf_f14_mips64:
463
return "f14";
464
case dwarf_f15_mips64:
465
return "f15";
466
case dwarf_f16_mips64:
467
return "f16";
468
case dwarf_f17_mips64:
469
return "f17";
470
case dwarf_f18_mips64:
471
return "f18";
472
case dwarf_f19_mips64:
473
return "f19";
474
case dwarf_f20_mips64:
475
return "f20";
476
case dwarf_f21_mips64:
477
return "f21";
478
case dwarf_f22_mips64:
479
return "f22";
480
case dwarf_f23_mips64:
481
return "f23";
482
case dwarf_f24_mips64:
483
return "f24";
484
case dwarf_f25_mips64:
485
return "f25";
486
case dwarf_f26_mips64:
487
return "f26";
488
case dwarf_f27_mips64:
489
return "f27";
490
case dwarf_f28_mips64:
491
return "f28";
492
case dwarf_f29_mips64:
493
return "f29";
494
case dwarf_f30_mips64:
495
return "f30";
496
case dwarf_f31_mips64:
497
return "f31";
498
case dwarf_fcsr_mips64:
499
return "fcsr";
500
case dwarf_fir_mips64:
501
return "fir";
502
case dwarf_w0_mips64:
503
return "w0";
504
case dwarf_w1_mips64:
505
return "w1";
506
case dwarf_w2_mips64:
507
return "w2";
508
case dwarf_w3_mips64:
509
return "w3";
510
case dwarf_w4_mips64:
511
return "w4";
512
case dwarf_w5_mips64:
513
return "w5";
514
case dwarf_w6_mips64:
515
return "w6";
516
case dwarf_w7_mips64:
517
return "w7";
518
case dwarf_w8_mips64:
519
return "w8";
520
case dwarf_w9_mips64:
521
return "w9";
522
case dwarf_w10_mips64:
523
return "w10";
524
case dwarf_w11_mips64:
525
return "w11";
526
case dwarf_w12_mips64:
527
return "w12";
528
case dwarf_w13_mips64:
529
return "w13";
530
case dwarf_w14_mips64:
531
return "w14";
532
case dwarf_w15_mips64:
533
return "w15";
534
case dwarf_w16_mips64:
535
return "w16";
536
case dwarf_w17_mips64:
537
return "w17";
538
case dwarf_w18_mips64:
539
return "w18";
540
case dwarf_w19_mips64:
541
return "w19";
542
case dwarf_w20_mips64:
543
return "w20";
544
case dwarf_w21_mips64:
545
return "w21";
546
case dwarf_w22_mips64:
547
return "w22";
548
case dwarf_w23_mips64:
549
return "w23";
550
case dwarf_w24_mips64:
551
return "w24";
552
case dwarf_w25_mips64:
553
return "w25";
554
case dwarf_w26_mips64:
555
return "w26";
556
case dwarf_w27_mips64:
557
return "w27";
558
case dwarf_w28_mips64:
559
return "w28";
560
case dwarf_w29_mips64:
561
return "w29";
562
case dwarf_w30_mips64:
563
return "w30";
564
case dwarf_w31_mips64:
565
return "w31";
566
case dwarf_mcsr_mips64:
567
return "mcsr";
568
case dwarf_mir_mips64:
569
return "mir";
570
case dwarf_config5_mips64:
571
return "config5";
572
}
573
return nullptr;
574
}
575
576
std::optional<RegisterInfo>
577
EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind,
578
uint32_t reg_num) {
579
if (reg_kind == eRegisterKindGeneric) {
580
switch (reg_num) {
581
case LLDB_REGNUM_GENERIC_PC:
582
reg_kind = eRegisterKindDWARF;
583
reg_num = dwarf_pc_mips64;
584
break;
585
case LLDB_REGNUM_GENERIC_SP:
586
reg_kind = eRegisterKindDWARF;
587
reg_num = dwarf_sp_mips64;
588
break;
589
case LLDB_REGNUM_GENERIC_FP:
590
reg_kind = eRegisterKindDWARF;
591
reg_num = dwarf_r30_mips64;
592
break;
593
case LLDB_REGNUM_GENERIC_RA:
594
reg_kind = eRegisterKindDWARF;
595
reg_num = dwarf_ra_mips64;
596
break;
597
case LLDB_REGNUM_GENERIC_FLAGS:
598
reg_kind = eRegisterKindDWARF;
599
reg_num = dwarf_sr_mips64;
600
break;
601
default:
602
return {};
603
}
604
}
605
606
if (reg_kind == eRegisterKindDWARF) {
607
RegisterInfo reg_info;
608
::memset(&reg_info, 0, sizeof(RegisterInfo));
609
::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
610
611
if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 ||
612
reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 ||
613
reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) {
614
reg_info.byte_size = 4;
615
reg_info.format = eFormatHex;
616
reg_info.encoding = eEncodingUint;
617
} else if ((int)reg_num >= dwarf_zero_mips64 &&
618
(int)reg_num <= dwarf_f31_mips64) {
619
reg_info.byte_size = 8;
620
reg_info.format = eFormatHex;
621
reg_info.encoding = eEncodingUint;
622
} else if ((int)reg_num >= dwarf_w0_mips64 &&
623
(int)reg_num <= dwarf_w31_mips64) {
624
reg_info.byte_size = 16;
625
reg_info.format = eFormatVectorOfUInt8;
626
reg_info.encoding = eEncodingVector;
627
} else {
628
return {};
629
}
630
631
reg_info.name = GetRegisterName(reg_num, false);
632
reg_info.alt_name = GetRegisterName(reg_num, true);
633
reg_info.kinds[eRegisterKindDWARF] = reg_num;
634
635
switch (reg_num) {
636
case dwarf_r30_mips64:
637
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
638
break;
639
case dwarf_ra_mips64:
640
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
641
break;
642
case dwarf_sp_mips64:
643
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
644
break;
645
case dwarf_pc_mips64:
646
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
647
break;
648
case dwarf_sr_mips64:
649
reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
650
break;
651
default:
652
break;
653
}
654
return reg_info;
655
}
656
return {};
657
}
658
659
EmulateInstructionMIPS64::MipsOpcode *
660
EmulateInstructionMIPS64::GetOpcodeForInstruction(llvm::StringRef op_name) {
661
static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = {
662
// Prologue/Epilogue instructions
663
{"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
664
"DADDIU rt, rs, immediate"},
665
{"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu,
666
"ADDIU rt, rs, immediate"},
667
{"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"},
668
{"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"},
669
{"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
670
"DSUBU rd, rs, rt"},
671
{"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
672
"SUBU rd, rs, rt"},
673
{"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
674
"DADDU rd, rs, rt"},
675
{"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU,
676
"ADDU rd, rs, rt"},
677
{"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"},
678
679
// Load/Store instructions
680
/* Following list of emulated instructions are required by implementation
681
of hardware watchpoint
682
for MIPS in lldb. As we just need the address accessed by instructions,
683
we have generalised
684
all these instructions in 2 functions depending on their addressing
685
modes */
686
687
{"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
688
"LB rt, offset(base)"},
689
{"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
690
"LBE rt, offset(base)"},
691
{"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
692
"LBU rt, offset(base)"},
693
{"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
694
"LBUE rt, offset(base)"},
695
{"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
696
"LDC1 ft, offset(base)"},
697
{"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
698
"LDL rt, offset(base)"},
699
{"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
700
"LDR rt, offset(base)"},
701
{"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
702
"LLD rt, offset(base)"},
703
{"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
704
"LDC2 rt, offset(base)"},
705
{"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
706
"LDXC1 fd, index (base)"},
707
{"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
708
"LH rt, offset(base)"},
709
{"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
710
"LHE rt, offset(base)"},
711
{"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
712
"LHU rt, offset(base)"},
713
{"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
714
"LHUE rt, offset(base)"},
715
{"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
716
"LL rt, offset(base)"},
717
{"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
718
"LLE rt, offset(base)"},
719
{"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
720
"LUXC1 fd, index (base)"},
721
{"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
722
"LW rt, offset(rs)"},
723
{"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
724
"LWC1 ft, offset(base)"},
725
{"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
726
"LWC2 rt, offset(base)"},
727
{"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
728
"LWE rt, offset(base)"},
729
{"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
730
"LWL rt, offset(base)"},
731
{"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
732
"LWLE rt, offset(base)"},
733
{"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
734
"LWR rt, offset(base)"},
735
{"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
736
"LWRE rt, offset(base)"},
737
{"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
738
"LWXC1 fd, index (base)"},
739
740
{"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
741
"SB rt, offset(base)"},
742
{"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
743
"SBE rt, offset(base)"},
744
{"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
745
"SC rt, offset(base)"},
746
{"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
747
"SCE rt, offset(base)"},
748
{"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
749
"SCD rt, offset(base)"},
750
{"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
751
"SDL rt, offset(base)"},
752
{"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
753
"SDR rt, offset(base)"},
754
{"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
755
"SDC1 ft, offset(base)"},
756
{"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
757
"SDC2 rt, offset(base)"},
758
{"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
759
"SDXC1 fs, index (base)"},
760
{"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
761
"SH rt, offset(base)"},
762
{"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
763
"SHE rt, offset(base)"},
764
{"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
765
"SUXC1 fs, index (base)"},
766
{"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
767
"SW rt, offset(rs)"},
768
{"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
769
"SWC1 ft, offset(base)"},
770
{"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
771
"SWC2 rt, offset(base)"},
772
{"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
773
"SWE rt, offset(base)"},
774
{"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
775
"SWL rt, offset(base)"},
776
{"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
777
"SWLE rt, offset(base)"},
778
{"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
779
"SWR rt, offset(base)"},
780
{"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm,
781
"SWRE rt, offset(base)"},
782
{"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg,
783
"SWXC1 fs, index (base)"},
784
785
// Branch instructions
786
{"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
787
{"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
788
{"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
789
{"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"},
790
{"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
791
"BEQL rs,rt,offset"},
792
{"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops,
793
"BNEL rs,rt,offset"},
794
{"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
795
"BGEZALL rt,offset"},
796
{"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"},
797
{"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
798
"BGEZAL rs,offset"},
799
{"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"},
800
{"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"},
801
{"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
802
{"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"},
803
{"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
804
"BLEZALC rs,offset"},
805
{"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
806
"BGEZALC rs,offset"},
807
{"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
808
"BLTZALC rs,offset"},
809
{"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
810
"BGTZALC rs,offset"},
811
{"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
812
"BEQZALC rs,offset"},
813
{"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,
814
"BNEZALC rs,offset"},
815
{"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
816
"BEQC rs,rt,offset"},
817
{"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
818
"BEQC rs,rt,offset"},
819
{"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
820
"BNEC rs,rt,offset"},
821
{"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
822
"BNEC rs,rt,offset"},
823
{"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
824
"BLTC rs,rt,offset"},
825
{"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
826
"BLTC rs,rt,offset"},
827
{"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
828
"BGEC rs,rt,offset"},
829
{"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
830
"BGEC rs,rt,offset"},
831
{"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
832
"BLTUC rs,rt,offset"},
833
{"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
834
"BLTUC rs,rt,offset"},
835
{"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
836
"BGEUC rs,rt,offset"},
837
{"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
838
"BGEUC rs,rt,offset"},
839
{"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
840
"BLTZC rt,offset"},
841
{"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
842
"BLTZC rt,offset"},
843
{"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
844
"BLEZC rt,offset"},
845
{"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
846
"BLEZC rt,offset"},
847
{"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
848
"BGEZC rt,offset"},
849
{"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
850
"BGEZC rt,offset"},
851
{"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
852
"BGTZC rt,offset"},
853
{"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
854
"BGTZC rt,offset"},
855
{"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
856
"BEQZC rt,offset"},
857
{"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
858
"BEQZC rt,offset"},
859
{"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
860
"BNEZC rt,offset"},
861
{"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C,
862
"BNEZC rt,offset"},
863
{"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"},
864
{"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
865
{"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"},
866
{"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"},
867
{"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
868
{"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"},
869
{"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"},
870
{"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
871
{"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"},
872
{"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
873
"BLTZAL rt,offset"},
874
{"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link,
875
"BLTZALL rt,offset"},
876
{"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"},
877
{"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
878
"BOVC rs,rt,offset"},
879
{"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C,
880
"BNVC rs,rt,offset"},
881
{"J", &EmulateInstructionMIPS64::Emulate_J, "J target"},
882
{"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"},
883
{"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"},
884
{"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
885
{"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"},
886
{"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"},
887
{"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
888
{"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"},
889
{"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
890
{"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"},
891
{"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
892
{"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"},
893
{"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"},
894
{"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"},
895
{"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"},
896
{"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch,
897
"BC1FL cc, offset"},
898
{"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch,
899
"BC1TL cc, offset"},
900
{"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ,
901
"BC1EQZ ft, offset"},
902
{"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ,
903
"BC1NEZ ft, offset"},
904
{"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch,
905
"BC1ANY2F cc, offset"},
906
{"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch,
907
"BC1ANY2T cc, offset"},
908
{"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch,
909
"BC1ANY4F cc, offset"},
910
{"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch,
911
"BC1ANY4T cc, offset"},
912
{"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"},
913
{"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"},
914
{"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"},
915
{"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"},
916
{"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"},
917
{"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"},
918
{"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"},
919
{"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"},
920
{"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"},
921
{"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"},
922
};
923
924
for (MipsOpcode &opcode : g_opcodes) {
925
if (op_name.equals_insensitive(opcode.op_name))
926
return &opcode;
927
}
928
return nullptr;
929
}
930
931
bool EmulateInstructionMIPS64::ReadInstruction() {
932
bool success = false;
933
m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
934
LLDB_INVALID_ADDRESS, &success);
935
if (success) {
936
Context read_inst_context;
937
read_inst_context.type = eContextReadOpcode;
938
read_inst_context.SetNoArgs();
939
m_opcode.SetOpcode32(
940
ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
941
GetByteOrder());
942
}
943
if (!success)
944
m_addr = LLDB_INVALID_ADDRESS;
945
return success;
946
}
947
948
bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
949
bool success = false;
950
llvm::MCInst mc_insn;
951
uint64_t insn_size;
952
DataExtractor data;
953
954
/* Keep the complexity of the decode logic with the llvm::MCDisassembler
955
* class. */
956
if (m_opcode.GetData(data)) {
957
llvm::MCDisassembler::DecodeStatus decode_status;
958
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
959
decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
960
m_addr, llvm::nulls());
961
if (decode_status != llvm::MCDisassembler::Success)
962
return false;
963
}
964
965
/*
966
* mc_insn.getOpcode() returns decoded opcode. However to make use
967
* of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
968
*/
969
llvm::StringRef op_name = m_insn_info->getName(mc_insn.getOpcode());
970
971
/*
972
* Decoding has been done already. Just get the call-back function
973
* and emulate the instruction.
974
*/
975
MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
976
977
if (opcode_data == nullptr)
978
return false;
979
980
uint64_t old_pc = 0, new_pc = 0;
981
const bool auto_advance_pc =
982
evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
983
984
if (auto_advance_pc) {
985
old_pc =
986
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
987
if (!success)
988
return false;
989
}
990
991
/* emulate instruction */
992
success = (this->*opcode_data->callback)(mc_insn);
993
if (!success)
994
return false;
995
996
if (auto_advance_pc) {
997
new_pc =
998
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
999
if (!success)
1000
return false;
1001
1002
/* If we haven't changed the PC, change it here */
1003
if (old_pc == new_pc) {
1004
new_pc += 4;
1005
Context context;
1006
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1007
new_pc))
1008
return false;
1009
}
1010
}
1011
1012
return true;
1013
}
1014
1015
bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind(
1016
UnwindPlan &unwind_plan) {
1017
unwind_plan.Clear();
1018
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1019
1020
UnwindPlan::RowSP row(new UnwindPlan::Row);
1021
const bool can_replace = false;
1022
1023
// Our previous Call Frame Address is the stack pointer
1024
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
1025
1026
// Our previous PC is in the RA
1027
row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64,
1028
can_replace);
1029
1030
unwind_plan.AppendRow(row);
1031
1032
// All other registers are the same.
1033
unwind_plan.SetSourceName("EmulateInstructionMIPS64");
1034
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1035
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1036
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1037
unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64);
1038
1039
return true;
1040
}
1041
1042
bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) {
1043
switch (regnum) {
1044
case dwarf_r16_mips64:
1045
case dwarf_r17_mips64:
1046
case dwarf_r18_mips64:
1047
case dwarf_r19_mips64:
1048
case dwarf_r20_mips64:
1049
case dwarf_r21_mips64:
1050
case dwarf_r22_mips64:
1051
case dwarf_r23_mips64:
1052
case dwarf_gp_mips64:
1053
case dwarf_sp_mips64:
1054
case dwarf_r30_mips64:
1055
case dwarf_ra_mips64:
1056
return true;
1057
default:
1058
return false;
1059
}
1060
return false;
1061
}
1062
1063
bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
1064
// DADDIU rt, rs, immediate
1065
// GPR[rt] <- GPR[rs] + sign_extend(immediate)
1066
1067
uint8_t dst, src;
1068
bool success = false;
1069
const uint32_t imm16 = insn.getOperand(2).getImm();
1070
int64_t imm = SignedBits(imm16, 15, 0);
1071
1072
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1073
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1074
1075
// If immediate is greater than 2^16 - 1 then clang generate LUI,
1076
// (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
1077
// $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
1078
// same and not equal to sp
1079
if (dst == src) {
1080
Context context;
1081
1082
/* read <src> register */
1083
const uint64_t src_opd_val = ReadRegisterUnsigned(
1084
eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1085
if (!success)
1086
return false;
1087
1088
/* Check if this is daddiu sp, sp, imm16 */
1089
if (dst == dwarf_sp_mips64) {
1090
/*
1091
* From the MIPS IV spec:
1092
*
1093
* The term “unsigned” in the instruction name is a misnomer; this
1094
* operation is 64-bit modulo arithmetic that does not trap on overflow.
1095
* It is appropriate for arithmetic which is not signed, such as address
1096
* arithmetic, or integer arithmetic environments that ignore overflow,
1097
* such as “C” language arithmetic.
1098
*
1099
* Assume 2's complement and rely on unsigned overflow here.
1100
*/
1101
uint64_t result = src_opd_val + imm;
1102
std::optional<RegisterInfo> reg_info_sp =
1103
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);
1104
if (reg_info_sp)
1105
context.SetRegisterPlusOffset(*reg_info_sp, imm);
1106
1107
/* We are allocating bytes on stack */
1108
context.type = eContextAdjustStackPointer;
1109
1110
WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64,
1111
result);
1112
return true;
1113
}
1114
1115
imm += src_opd_val;
1116
context.SetImmediateSigned(imm);
1117
context.type = eContextImmediate;
1118
1119
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1120
dwarf_zero_mips64 + dst, imm))
1121
return false;
1122
}
1123
1124
return true;
1125
}
1126
1127
bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) {
1128
uint64_t address;
1129
bool success = false;
1130
uint32_t imm16 = insn.getOperand(2).getImm();
1131
uint64_t imm = SignedBits(imm16, 15, 0);
1132
uint32_t src, base;
1133
Context bad_vaddr_context;
1134
1135
src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1136
base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1137
1138
std::optional<RegisterInfo> reg_info_base =
1139
GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base);
1140
std::optional<RegisterInfo> reg_info_src =
1141
GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);
1142
if (!reg_info_base || !reg_info_src)
1143
return false;
1144
1145
/* read SP */
1146
address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1147
0, &success);
1148
if (!success)
1149
return false;
1150
1151
/* destination address */
1152
address = address + imm;
1153
1154
/* We look for sp based non-volatile register stores */
1155
if (nonvolatile_reg_p(src)) {
1156
Context context;
1157
context.type = eContextPushRegisterOnStack;
1158
context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1159
1160
std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1161
if (!data_src)
1162
return false;
1163
1164
Status error;
1165
RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1166
if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1167
reg_info_src->byte_size, eByteOrderLittle,
1168
error) == 0)
1169
return false;
1170
1171
if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1172
return false;
1173
}
1174
1175
/* Set the bad_vaddr register with base address used in the instruction */
1176
bad_vaddr_context.type = eContextInvalid;
1177
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1178
address);
1179
1180
return true;
1181
}
1182
1183
bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
1184
bool success = false;
1185
uint32_t src, base;
1186
int64_t imm, address;
1187
Context bad_vaddr_context;
1188
1189
src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1190
base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1191
imm = insn.getOperand(2).getImm();
1192
1193
if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base))
1194
return false;
1195
1196
/* read base register */
1197
address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base,
1198
0, &success);
1199
if (!success)
1200
return false;
1201
1202
/* destination address */
1203
address = address + imm;
1204
1205
/* Set the bad_vaddr register with base address used in the instruction */
1206
bad_vaddr_context.type = eContextInvalid;
1207
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64,
1208
address);
1209
1210
if (nonvolatile_reg_p(src)) {
1211
RegisterValue data_src;
1212
std::optional<RegisterInfo> reg_info_src =
1213
GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src);
1214
if (!reg_info_src)
1215
return false;
1216
1217
Context context;
1218
context.type = eContextRegisterLoad;
1219
1220
return WriteRegister(context, *reg_info_src, data_src);
1221
}
1222
1223
return false;
1224
}
1225
1226
bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
1227
// LUI rt, immediate
1228
// GPR[rt] <- sign_extend(immediate << 16)
1229
1230
const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1231
int64_t imm = SignedBits(imm32, 31, 0);
1232
uint8_t rt;
1233
Context context;
1234
1235
rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1236
context.SetImmediateSigned(imm);
1237
context.type = eContextImmediate;
1238
1239
return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1240
dwarf_zero_mips64 + rt, imm);
1241
}
1242
1243
bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
1244
// DSUBU sp, <src>, <rt>
1245
// DADDU sp, <src>, <rt>
1246
// DADDU dst, sp, <rt>
1247
1248
bool success = false;
1249
uint64_t result;
1250
uint8_t src, dst, rt;
1251
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1252
1253
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1254
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1255
1256
/* Check if sp is destination register */
1257
if (dst == dwarf_sp_mips64) {
1258
rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1259
1260
/* read <src> register */
1261
uint64_t src_opd_val = ReadRegisterUnsigned(
1262
eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1263
if (!success)
1264
return false;
1265
1266
/* read <rt > register */
1267
uint64_t rt_opd_val = ReadRegisterUnsigned(
1268
eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1269
if (!success)
1270
return false;
1271
1272
if (op_name.equals_insensitive("DSUBU") ||
1273
op_name.equals_insensitive("SUBU"))
1274
result = src_opd_val - rt_opd_val;
1275
else
1276
result = src_opd_val + rt_opd_val;
1277
1278
Context context;
1279
std::optional<RegisterInfo> reg_info_sp =
1280
GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64);
1281
if (reg_info_sp)
1282
context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1283
1284
/* We are allocating bytes on stack */
1285
context.type = eContextAdjustStackPointer;
1286
1287
WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result);
1288
1289
return true;
1290
} else if (src == dwarf_sp_mips64) {
1291
rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1292
1293
/* read <src> register */
1294
uint64_t src_opd_val = ReadRegisterUnsigned(
1295
eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
1296
if (!success)
1297
return false;
1298
1299
/* read <rt> register */
1300
uint64_t rt_opd_val = ReadRegisterUnsigned(
1301
eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
1302
if (!success)
1303
return false;
1304
1305
Context context;
1306
1307
if (op_name.equals_insensitive("DSUBU") ||
1308
op_name.equals_insensitive("SUBU"))
1309
result = src_opd_val - rt_opd_val;
1310
else
1311
result = src_opd_val + rt_opd_val;
1312
1313
context.SetImmediateSigned(result);
1314
context.type = eContextImmediate;
1315
1316
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1317
dwarf_zero_mips64 + dst, result))
1318
return false;
1319
}
1320
1321
return true;
1322
}
1323
1324
/*
1325
Emulate below MIPS branch instructions.
1326
BEQ, BNE : Branch on condition
1327
BEQL, BNEL : Branch likely
1328
*/
1329
bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
1330
bool success = false;
1331
uint32_t rs, rt;
1332
int64_t offset, pc, rs_val, rt_val, target = 0;
1333
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1334
1335
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1336
rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1337
offset = insn.getOperand(2).getImm();
1338
1339
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1340
if (!success)
1341
return false;
1342
1343
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1344
dwarf_zero_mips64 + rs, 0, &success);
1345
if (!success)
1346
return false;
1347
1348
rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1349
dwarf_zero_mips64 + rt, 0, &success);
1350
if (!success)
1351
return false;
1352
1353
if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL") ||
1354
op_name.equals_insensitive("BEQ64")) {
1355
if (rs_val == rt_val)
1356
target = pc + offset;
1357
else
1358
target = pc + 8;
1359
} else if (op_name.equals_insensitive("BNE") ||
1360
op_name.equals_insensitive("BNEL") ||
1361
op_name.equals_insensitive("BNE64")) {
1362
if (rs_val != rt_val)
1363
target = pc + offset;
1364
else
1365
target = pc + 8;
1366
}
1367
1368
Context context;
1369
context.type = eContextRelativeBranchImmediate;
1370
context.SetImmediate(offset);
1371
1372
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1373
target);
1374
}
1375
1376
/*
1377
Emulate below MIPS Non-Compact conditional branch and link instructions.
1378
BLTZAL, BGEZAL :
1379
BLTZALL, BGEZALL : Branch likely
1380
*/
1381
bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) {
1382
bool success = false;
1383
uint32_t rs;
1384
int64_t offset, pc, target = 0;
1385
int64_t rs_val;
1386
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1387
1388
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1389
offset = insn.getOperand(1).getImm();
1390
1391
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1392
if (!success)
1393
return false;
1394
1395
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1396
dwarf_zero_mips64 + rs, 0, &success);
1397
if (!success)
1398
return false;
1399
1400
if (op_name.equals_insensitive("BLTZAL") ||
1401
op_name.equals_insensitive("BLTZALL")) {
1402
if (rs_val < 0)
1403
target = pc + offset;
1404
else
1405
target = pc + 8;
1406
} else if (op_name.equals_insensitive("BGEZAL") ||
1407
op_name.equals_insensitive("BGEZALL")) {
1408
if (rs_val >= 0)
1409
target = pc + offset;
1410
else
1411
target = pc + 8;
1412
}
1413
1414
Context context;
1415
1416
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1417
target))
1418
return false;
1419
1420
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1421
pc + 8))
1422
return false;
1423
1424
return true;
1425
}
1426
1427
bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) {
1428
bool success = false;
1429
int64_t offset, pc, target;
1430
1431
/*
1432
* BAL offset
1433
* offset = sign_ext (offset << 2)
1434
* RA = PC + 8
1435
* PC = PC + offset
1436
*/
1437
offset = insn.getOperand(0).getImm();
1438
1439
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1440
if (!success)
1441
return false;
1442
1443
target = pc + offset;
1444
1445
Context context;
1446
1447
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1448
target))
1449
return false;
1450
1451
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1452
pc + 8))
1453
return false;
1454
1455
return true;
1456
}
1457
1458
bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) {
1459
bool success = false;
1460
int64_t offset, pc, target;
1461
1462
/*
1463
* BALC offset
1464
* offset = sign_ext (offset << 2)
1465
* RA = PC + 4
1466
* PC = PC + 4 + offset
1467
*/
1468
offset = insn.getOperand(0).getImm();
1469
1470
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1471
if (!success)
1472
return false;
1473
1474
target = pc + offset;
1475
1476
Context context;
1477
1478
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1479
target))
1480
return false;
1481
1482
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1483
pc + 4))
1484
return false;
1485
1486
return true;
1487
}
1488
1489
/*
1490
Emulate below MIPS conditional branch and link instructions.
1491
BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1492
*/
1493
bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1494
bool success = false;
1495
uint32_t rs;
1496
int64_t offset, pc, rs_val, target = 0;
1497
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1498
1499
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1500
offset = insn.getOperand(1).getImm();
1501
1502
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1503
if (!success)
1504
return false;
1505
1506
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1507
dwarf_zero_mips64 + rs, 0, &success);
1508
if (!success)
1509
return false;
1510
1511
if (op_name.equals_insensitive("BLEZALC")) {
1512
if (rs_val <= 0)
1513
target = pc + offset;
1514
else
1515
target = pc + 4;
1516
} else if (op_name.equals_insensitive("BGEZALC")) {
1517
if (rs_val >= 0)
1518
target = pc + offset;
1519
else
1520
target = pc + 4;
1521
} else if (op_name.equals_insensitive("BLTZALC")) {
1522
if (rs_val < 0)
1523
target = pc + offset;
1524
else
1525
target = pc + 4;
1526
} else if (op_name.equals_insensitive("BGTZALC")) {
1527
if (rs_val > 0)
1528
target = pc + offset;
1529
else
1530
target = pc + 4;
1531
} else if (op_name.equals_insensitive("BEQZALC")) {
1532
if (rs_val == 0)
1533
target = pc + offset;
1534
else
1535
target = pc + 4;
1536
} else if (op_name.equals_insensitive("BNEZALC")) {
1537
if (rs_val != 0)
1538
target = pc + offset;
1539
else
1540
target = pc + 4;
1541
}
1542
1543
Context context;
1544
1545
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1546
target))
1547
return false;
1548
1549
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1550
pc + 4))
1551
return false;
1552
1553
return true;
1554
}
1555
1556
/*
1557
Emulate below MIPS branch instructions.
1558
BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
1559
BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
1560
*/
1561
bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
1562
bool success = false;
1563
uint32_t rs;
1564
int64_t offset, pc, rs_val, target = 0;
1565
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1566
1567
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1568
offset = insn.getOperand(1).getImm();
1569
1570
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1571
if (!success)
1572
return false;
1573
1574
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1575
dwarf_zero_mips64 + rs, 0, &success);
1576
if (!success)
1577
return false;
1578
1579
if (op_name.equals_insensitive("BLTZL") ||
1580
op_name.equals_insensitive("BLTZ") ||
1581
op_name.equals_insensitive("BLTZ64")) {
1582
if (rs_val < 0)
1583
target = pc + offset;
1584
else
1585
target = pc + 8;
1586
} else if (op_name.equals_insensitive("BGEZL") ||
1587
op_name.equals_insensitive("BGEZ") ||
1588
op_name.equals_insensitive("BGEZ64")) {
1589
if (rs_val >= 0)
1590
target = pc + offset;
1591
else
1592
target = pc + 8;
1593
} else if (op_name.equals_insensitive("BGTZL") ||
1594
op_name.equals_insensitive("BGTZ") ||
1595
op_name.equals_insensitive("BGTZ64")) {
1596
if (rs_val > 0)
1597
target = pc + offset;
1598
else
1599
target = pc + 8;
1600
} else if (op_name.equals_insensitive("BLEZL") ||
1601
op_name.equals_insensitive("BLEZ") ||
1602
op_name.equals_insensitive("BLEZ64")) {
1603
if (rs_val <= 0)
1604
target = pc + offset;
1605
else
1606
target = pc + 8;
1607
}
1608
1609
Context context;
1610
context.type = eContextRelativeBranchImmediate;
1611
context.SetImmediate(offset);
1612
1613
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1614
target);
1615
}
1616
1617
bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
1618
bool success = false;
1619
int64_t offset, pc, target;
1620
1621
/*
1622
* BC offset
1623
* offset = sign_ext (offset << 2)
1624
* PC = PC + 4 + offset
1625
*/
1626
offset = insn.getOperand(0).getImm();
1627
1628
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1629
if (!success)
1630
return false;
1631
1632
target = pc + offset;
1633
1634
Context context;
1635
1636
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1637
target);
1638
}
1639
1640
static int IsAdd64bitOverflow(int64_t a, int64_t b) {
1641
int64_t r = (uint64_t)a + (uint64_t)b;
1642
return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1643
}
1644
1645
/*
1646
Emulate below MIPS branch instructions.
1647
BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1648
instructions with no delay slot
1649
*/
1650
bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1651
bool success = false;
1652
uint32_t rs, rt;
1653
int64_t offset, pc, rs_val, rt_val, target = 0;
1654
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1655
uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1656
1657
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1658
rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1659
offset = insn.getOperand(2).getImm();
1660
1661
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1662
if (!success)
1663
return false;
1664
1665
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1666
dwarf_zero_mips64 + rs, 0, &success);
1667
if (!success)
1668
return false;
1669
1670
rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1671
dwarf_zero_mips64 + rt, 0, &success);
1672
if (!success)
1673
return false;
1674
1675
if (op_name.equals_insensitive("BEQC") ||
1676
op_name.equals_insensitive("BEQC64")) {
1677
if (rs_val == rt_val)
1678
target = pc + offset;
1679
else
1680
target = pc + 4;
1681
} else if (op_name.equals_insensitive("BNEC") ||
1682
op_name.equals_insensitive("BNEC64")) {
1683
if (rs_val != rt_val)
1684
target = pc + offset;
1685
else
1686
target = pc + 4;
1687
} else if (op_name.equals_insensitive("BLTC") ||
1688
op_name.equals_insensitive("BLTC64")) {
1689
if (rs_val < rt_val)
1690
target = pc + offset;
1691
else
1692
target = pc + 4;
1693
} else if (op_name.equals_insensitive("BGEC64") ||
1694
op_name.equals_insensitive("BGEC")) {
1695
if (rs_val >= rt_val)
1696
target = pc + offset;
1697
else
1698
target = pc + 4;
1699
} else if (op_name.equals_insensitive("BLTUC") ||
1700
op_name.equals_insensitive("BLTUC64")) {
1701
if (rs_val < rt_val)
1702
target = pc + offset;
1703
else
1704
target = pc + 4;
1705
} else if (op_name.equals_insensitive("BGEUC") ||
1706
op_name.equals_insensitive("BGEUC64")) {
1707
if ((uint32_t)rs_val >= (uint32_t)rt_val)
1708
target = pc + offset;
1709
else
1710
target = pc + 4;
1711
} else if (op_name.equals_insensitive("BOVC")) {
1712
if (IsAdd64bitOverflow(rs_val, rt_val))
1713
target = pc + offset;
1714
else
1715
target = pc + 4;
1716
} else if (op_name.equals_insensitive("BNVC")) {
1717
if (!IsAdd64bitOverflow(rs_val, rt_val))
1718
target = pc + offset;
1719
else
1720
target = pc + 4;
1721
}
1722
1723
Context context;
1724
context.type = eContextRelativeBranchImmediate;
1725
context.SetImmediate(current_inst_size + offset);
1726
1727
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1728
target);
1729
}
1730
1731
/*
1732
Emulate below MIPS branch instructions.
1733
BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
1734
*/
1735
bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
1736
bool success = false;
1737
uint32_t rs;
1738
int64_t offset, pc, target = 0;
1739
int64_t rs_val;
1740
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1741
uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1742
1743
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1744
offset = insn.getOperand(1).getImm();
1745
1746
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1747
if (!success)
1748
return false;
1749
1750
rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1751
dwarf_zero_mips64 + rs, 0, &success);
1752
if (!success)
1753
return false;
1754
1755
if (op_name.equals_insensitive("BLTZC") ||
1756
op_name.equals_insensitive("BLTZC64")) {
1757
if (rs_val < 0)
1758
target = pc + offset;
1759
else
1760
target = pc + 4;
1761
} else if (op_name.equals_insensitive("BLEZC") ||
1762
op_name.equals_insensitive("BLEZC64")) {
1763
if (rs_val <= 0)
1764
target = pc + offset;
1765
else
1766
target = pc + 4;
1767
} else if (op_name.equals_insensitive("BGEZC") ||
1768
op_name.equals_insensitive("BGEZC64")) {
1769
if (rs_val >= 0)
1770
target = pc + offset;
1771
else
1772
target = pc + 4;
1773
} else if (op_name.equals_insensitive("BGTZC") ||
1774
op_name.equals_insensitive("BGTZC64")) {
1775
if (rs_val > 0)
1776
target = pc + offset;
1777
else
1778
target = pc + 4;
1779
} else if (op_name.equals_insensitive("BEQZC") ||
1780
op_name.equals_insensitive("BEQZC64")) {
1781
if (rs_val == 0)
1782
target = pc + offset;
1783
else
1784
target = pc + 4;
1785
} else if (op_name.equals_insensitive("BNEZC") ||
1786
op_name.equals_insensitive("BNEZC64")) {
1787
if (rs_val != 0)
1788
target = pc + offset;
1789
else
1790
target = pc + 4;
1791
}
1792
1793
Context context;
1794
context.type = eContextRelativeBranchImmediate;
1795
context.SetImmediate(current_inst_size + offset);
1796
1797
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1798
target);
1799
}
1800
1801
bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
1802
bool success = false;
1803
uint64_t offset, pc;
1804
1805
/*
1806
* J offset
1807
* offset = sign_ext (offset << 2)
1808
* PC = PC[63-28] | offset
1809
*/
1810
offset = insn.getOperand(0).getImm();
1811
1812
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1813
if (!success)
1814
return false;
1815
1816
/* This is a PC-region branch and not PC-relative */
1817
pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1818
1819
Context context;
1820
1821
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1822
pc);
1823
}
1824
1825
bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
1826
bool success = false;
1827
uint64_t offset, target, pc;
1828
1829
/*
1830
* JAL offset
1831
* offset = sign_ext (offset << 2)
1832
* PC = PC[63-28] | offset
1833
*/
1834
offset = insn.getOperand(0).getImm();
1835
1836
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1837
if (!success)
1838
return false;
1839
1840
/* This is a PC-region branch and not PC-relative */
1841
target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
1842
1843
Context context;
1844
1845
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1846
target))
1847
return false;
1848
1849
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1850
pc + 8))
1851
return false;
1852
1853
return true;
1854
}
1855
1856
bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) {
1857
bool success = false;
1858
uint32_t rs, rt;
1859
uint64_t pc, rs_val;
1860
1861
/*
1862
* JALR rt, rs
1863
* GPR[rt] = PC + 8
1864
* PC = GPR[rs]
1865
*/
1866
rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1867
rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1868
1869
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1870
if (!success)
1871
return false;
1872
1873
rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1874
&success);
1875
if (!success)
1876
return false;
1877
1878
Context context;
1879
1880
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1881
rs_val))
1882
return false;
1883
1884
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1885
dwarf_zero_mips64 + rt, pc + 8))
1886
return false;
1887
1888
return true;
1889
}
1890
1891
bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) {
1892
bool success = false;
1893
uint32_t rt;
1894
int64_t target, offset, pc, rt_val;
1895
1896
/*
1897
* JIALC rt, offset
1898
* offset = sign_ext (offset)
1899
* PC = GPR[rt] + offset
1900
* RA = PC + 4
1901
*/
1902
rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1903
offset = insn.getOperand(1).getImm();
1904
1905
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1906
if (!success)
1907
return false;
1908
1909
rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1910
dwarf_zero_mips64 + rt, 0, &success);
1911
if (!success)
1912
return false;
1913
1914
target = rt_val + offset;
1915
1916
Context context;
1917
1918
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1919
target))
1920
return false;
1921
1922
if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64,
1923
pc + 4))
1924
return false;
1925
1926
return true;
1927
}
1928
1929
bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
1930
bool success = false;
1931
uint32_t rt;
1932
int64_t target, offset, rt_val;
1933
1934
/*
1935
* JIC rt, offset
1936
* offset = sign_ext (offset)
1937
* PC = GPR[rt] + offset
1938
*/
1939
rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1940
offset = insn.getOperand(1).getImm();
1941
1942
rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1943
dwarf_zero_mips64 + rt, 0, &success);
1944
if (!success)
1945
return false;
1946
1947
target = rt_val + offset;
1948
1949
Context context;
1950
1951
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1952
target);
1953
}
1954
1955
bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
1956
bool success = false;
1957
uint32_t rs;
1958
uint64_t rs_val;
1959
1960
/*
1961
* JR rs
1962
* PC = GPR[rs]
1963
*/
1964
rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1965
1966
rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0,
1967
&success);
1968
if (!success)
1969
return false;
1970
1971
Context context;
1972
1973
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
1974
rs_val);
1975
}
1976
1977
/*
1978
Emulate Branch on FP True/False
1979
BC1F, BC1FL : Branch on FP False (L stands for branch likely)
1980
BC1T, BC1TL : Branch on FP True (L stands for branch likely)
1981
*/
1982
bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
1983
bool success = false;
1984
uint32_t cc, fcsr;
1985
int64_t pc, offset, target = 0;
1986
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1987
1988
/*
1989
* BC1F cc, offset
1990
* condition <- (FPConditionCode(cc) == 0)
1991
* if condition then
1992
* offset = sign_ext (offset)
1993
* PC = PC + offset
1994
*/
1995
cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1996
offset = insn.getOperand(1).getImm();
1997
1998
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
1999
if (!success)
2000
return false;
2001
2002
fcsr =
2003
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
2004
if (!success)
2005
return false;
2006
2007
/* fcsr[23], fcsr[25-31] are vaild condition bits */
2008
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2009
2010
if (op_name.equals_insensitive("BC1F") ||
2011
op_name.equals_insensitive("BC1FL")) {
2012
if ((fcsr & (1 << cc)) == 0)
2013
target = pc + offset;
2014
else
2015
target = pc + 8;
2016
} else if (op_name.equals_insensitive("BC1T") ||
2017
op_name.equals_insensitive("BC1TL")) {
2018
if ((fcsr & (1 << cc)) != 0)
2019
target = pc + offset;
2020
else
2021
target = pc + 8;
2022
}
2023
2024
Context context;
2025
2026
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2027
target);
2028
}
2029
2030
bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
2031
bool success = false;
2032
uint32_t ft;
2033
uint64_t ft_val;
2034
int64_t target, pc, offset;
2035
2036
/*
2037
* BC1EQZ ft, offset
2038
* condition <- (FPR[ft].bit0 == 0)
2039
* if condition then
2040
* offset = sign_ext (offset)
2041
* PC = PC + 4 + offset
2042
*/
2043
ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2044
offset = insn.getOperand(1).getImm();
2045
2046
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2047
if (!success)
2048
return false;
2049
2050
ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2051
&success);
2052
if (!success)
2053
return false;
2054
2055
if ((ft_val & 1) == 0)
2056
target = pc + 4 + offset;
2057
else
2058
target = pc + 8;
2059
2060
Context context;
2061
2062
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2063
target);
2064
}
2065
2066
bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
2067
bool success = false;
2068
uint32_t ft;
2069
uint64_t ft_val;
2070
int64_t target, pc, offset;
2071
2072
/*
2073
* BC1NEZ ft, offset
2074
* condition <- (FPR[ft].bit0 != 0)
2075
* if condition then
2076
* offset = sign_ext (offset)
2077
* PC = PC + 4 + offset
2078
*/
2079
ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2080
offset = insn.getOperand(1).getImm();
2081
2082
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2083
if (!success)
2084
return false;
2085
2086
ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0,
2087
&success);
2088
if (!success)
2089
return false;
2090
2091
if ((ft_val & 1) != 0)
2092
target = pc + 4 + offset;
2093
else
2094
target = pc + 8;
2095
2096
Context context;
2097
2098
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2099
target);
2100
}
2101
2102
/*
2103
Emulate MIPS-3D Branch instructions
2104
BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes
2105
False/True
2106
BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes
2107
False/True
2108
*/
2109
bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
2110
bool success = false;
2111
uint32_t cc, fcsr;
2112
int64_t pc, offset, target = 0;
2113
llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2114
2115
cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2116
offset = insn.getOperand(1).getImm();
2117
2118
pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2119
if (!success)
2120
return false;
2121
2122
fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64,
2123
0, &success);
2124
if (!success)
2125
return false;
2126
2127
/* fcsr[23], fcsr[25-31] are vaild condition bits */
2128
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2129
2130
if (op_name.equals_insensitive("BC1ANY2F")) {
2131
/* if any one bit is 0 */
2132
if (((fcsr >> cc) & 3) != 3)
2133
target = pc + offset;
2134
else
2135
target = pc + 8;
2136
} else if (op_name.equals_insensitive("BC1ANY2T")) {
2137
/* if any one bit is 1 */
2138
if (((fcsr >> cc) & 3) != 0)
2139
target = pc + offset;
2140
else
2141
target = pc + 8;
2142
} else if (op_name.equals_insensitive("BC1ANY4F")) {
2143
/* if any one bit is 0 */
2144
if (((fcsr >> cc) & 0xf) != 0xf)
2145
target = pc + offset;
2146
else
2147
target = pc + 8;
2148
} else if (op_name.equals_insensitive("BC1ANY4T")) {
2149
/* if any one bit is 1 */
2150
if (((fcsr >> cc) & 0xf) != 0)
2151
target = pc + offset;
2152
else
2153
target = pc + 8;
2154
}
2155
2156
Context context;
2157
2158
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2159
target);
2160
}
2161
2162
bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
2163
return Emulate_MSA_Branch_DF(insn, 1, true);
2164
}
2165
2166
bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) {
2167
return Emulate_MSA_Branch_DF(insn, 2, true);
2168
}
2169
2170
bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) {
2171
return Emulate_MSA_Branch_DF(insn, 4, true);
2172
}
2173
2174
bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) {
2175
return Emulate_MSA_Branch_DF(insn, 8, true);
2176
}
2177
2178
bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) {
2179
return Emulate_MSA_Branch_DF(insn, 1, false);
2180
}
2181
2182
bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) {
2183
return Emulate_MSA_Branch_DF(insn, 2, false);
2184
}
2185
2186
bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) {
2187
return Emulate_MSA_Branch_DF(insn, 4, false);
2188
}
2189
2190
bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) {
2191
return Emulate_MSA_Branch_DF(insn, 8, false);
2192
}
2193
2194
bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2195
int element_byte_size,
2196
bool bnz) {
2197
bool success = false, branch_hit = true;
2198
int64_t target = 0;
2199
RegisterValue reg_value;
2200
const uint8_t *ptr = nullptr;
2201
2202
uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2203
int64_t offset = insn.getOperand(1).getImm();
2204
2205
int64_t pc =
2206
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2207
if (!success)
2208
return false;
2209
2210
if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2211
ptr = (const uint8_t *)reg_value.GetBytes();
2212
else
2213
return false;
2214
2215
for (int i = 0; i < 16 / element_byte_size; i++) {
2216
switch (element_byte_size) {
2217
case 1:
2218
if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2219
branch_hit = false;
2220
break;
2221
case 2:
2222
if ((*(const uint16_t *)ptr == 0 && bnz) ||
2223
(*(const uint16_t *)ptr != 0 && !bnz))
2224
branch_hit = false;
2225
break;
2226
case 4:
2227
if ((*(const uint32_t *)ptr == 0 && bnz) ||
2228
(*(const uint32_t *)ptr != 0 && !bnz))
2229
branch_hit = false;
2230
break;
2231
case 8:
2232
if ((*(const uint64_t *)ptr == 0 && bnz) ||
2233
(*(const uint64_t *)ptr != 0 && !bnz))
2234
branch_hit = false;
2235
break;
2236
}
2237
if (!branch_hit)
2238
break;
2239
ptr = ptr + element_byte_size;
2240
}
2241
2242
if (branch_hit)
2243
target = pc + offset;
2244
else
2245
target = pc + 8;
2246
2247
Context context;
2248
context.type = eContextRelativeBranchImmediate;
2249
2250
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2251
target);
2252
}
2253
2254
bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
2255
return Emulate_MSA_Branch_V(insn, true);
2256
}
2257
2258
bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) {
2259
return Emulate_MSA_Branch_V(insn, false);
2260
}
2261
2262
bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2263
bool bnz) {
2264
bool success = false;
2265
int64_t target = 0;
2266
llvm::APInt wr_val = llvm::APInt::getZero(128);
2267
llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2268
llvm::APInt zero_value = llvm::APInt::getZero(128);
2269
RegisterValue reg_value;
2270
2271
uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2272
int64_t offset = insn.getOperand(1).getImm();
2273
2274
int64_t pc =
2275
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
2276
if (!success)
2277
return false;
2278
2279
if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
2280
wr_val = reg_value.GetAsUInt128(fail_value);
2281
else
2282
return false;
2283
2284
if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2285
(!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2286
target = pc + offset;
2287
else
2288
target = pc + 8;
2289
2290
Context context;
2291
context.type = eContextRelativeBranchImmediate;
2292
2293
return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
2294
target);
2295
}
2296
2297
bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
2298
bool success = false;
2299
uint32_t base;
2300
int64_t imm, address;
2301
Context bad_vaddr_context;
2302
2303
uint32_t num_operands = insn.getNumOperands();
2304
base =
2305
m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2306
imm = insn.getOperand(num_operands - 1).getImm();
2307
2308
if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2309
return false;
2310
2311
/* read base register */
2312
address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2313
&success);
2314
if (!success)
2315
return false;
2316
2317
/* destination address */
2318
address = address + imm;
2319
2320
/* Set the bad_vaddr register with base address used in the instruction */
2321
bad_vaddr_context.type = eContextInvalid;
2322
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2323
address);
2324
2325
return true;
2326
}
2327
2328
bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) {
2329
bool success = false;
2330
uint32_t base, index;
2331
int64_t address, index_address;
2332
Context bad_vaddr_context;
2333
2334
uint32_t num_operands = insn.getNumOperands();
2335
base =
2336
m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2337
index =
2338
m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
2339
2340
if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2341
return false;
2342
2343
if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
2344
return false;
2345
2346
/* read base register */
2347
address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
2348
&success);
2349
if (!success)
2350
return false;
2351
2352
/* read index register */
2353
index_address = ReadRegisterUnsigned(eRegisterKindDWARF,
2354
dwarf_zero_mips + index, 0, &success);
2355
if (!success)
2356
return false;
2357
2358
/* destination address */
2359
address = address + index_address;
2360
2361
/* Set the bad_vaddr register with base address used in the instruction */
2362
bad_vaddr_context.type = eContextInvalid;
2363
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
2364
address);
2365
2366
return true;
2367
}
2368
2369