Coverage Report

Created: 2023-09-30 09:22

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