Coverage Report

Created: 2022-01-25 06:29

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