Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- EmulateInstructionMIPS.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 "EmulateInstructionMIPS.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/Symbol/UnwindPlan.h"
18
#include "lldb/Target/Target.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(EmulateInstructionMIPS, InstructionMIPS)
45
46
#define UInt(x) ((uint64_t)x)
47
#define integer int64_t
48
49
//
50
// EmulateInstructionMIPS 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
EmulateInstructionMIPS::EmulateInstructionMIPS(
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
150
0
  m_reg_info.reset(target->createMCRegInfo(triple.getTriple()));
151
0
  assert(m_reg_info.get());
152
153
0
  m_insn_info.reset(target->createMCInstrInfo());
154
0
  assert(m_insn_info.get());
155
156
0
  llvm::MCTargetOptions MCOptions;
157
0
  m_asm_info.reset(
158
0
      target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
159
0
  m_subtype_info.reset(
160
0
      target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
161
0
  assert(m_asm_info.get() && m_subtype_info.get());
162
163
0
  m_context = std::make_unique<llvm::MCContext>(
164
0
      triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
165
0
  assert(m_context.get());
166
167
0
  m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
168
0
  assert(m_disasm.get());
169
170
  /* Create alternate disassembler for microMIPS */
171
0
  if (arch_flags & ArchSpec::eMIPSAse_mips16)
172
0
    features += "+mips16,";
173
0
  else if (arch_flags & ArchSpec::eMIPSAse_micromips)
174
0
    features += "+micromips,";
175
176
0
  m_alt_subtype_info.reset(
177
0
      target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
178
0
  assert(m_alt_subtype_info.get());
179
180
0
  m_alt_disasm.reset(
181
0
      target->createMCDisassembler(*m_alt_subtype_info, *m_context));
182
0
  assert(m_alt_disasm.get());
183
184
0
  m_next_inst_size = 0;
185
0
  m_use_alt_disaasm = false;
186
0
}
187
188
3.92k
void EmulateInstructionMIPS::Initialize() {
189
3.92k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
190
3.92k
                                GetPluginDescriptionStatic(), CreateInstance);
191
3.92k
}
192
193
3.92k
void EmulateInstructionMIPS::Terminate() {
194
3.92k
  PluginManager::UnregisterPlugin(CreateInstance);
195
3.92k
}
196
197
3.92k
llvm::StringRef EmulateInstructionMIPS::GetPluginDescriptionStatic() {
198
3.92k
  return "Emulate instructions for the MIPS32 architecture.";
199
3.92k
}
200
201
EmulateInstruction *
202
EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch,
203
16.7k
                                       InstructionType inst_type) {
204
16.7k
  if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(
205
16.7k
          inst_type)) {
206
16.7k
    if (arch.GetTriple().getArch() == llvm::Triple::mips ||
207
16.7k
        arch.GetTriple().getArch() == llvm::Triple::mipsel) {
208
0
      return new EmulateInstructionMIPS(arch);
209
0
    }
210
16.7k
  }
211
212
16.7k
  return nullptr;
213
16.7k
}
214
215
0
bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {
216
0
  return arch.GetTriple().getArch() == llvm::Triple::mips ||
217
0
         arch.GetTriple().getArch() == llvm::Triple::mipsel;
218
0
}
219
220
const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,
221
0
                                                    bool alternate_name) {
222
0
  if (alternate_name) {
223
0
    switch (reg_num) {
224
0
    case dwarf_sp_mips:
225
0
      return "r29";
226
0
    case dwarf_r30_mips:
227
0
      return "r30";
228
0
    case dwarf_ra_mips:
229
0
      return "r31";
230
0
    case dwarf_f0_mips:
231
0
      return "f0";
232
0
    case dwarf_f1_mips:
233
0
      return "f1";
234
0
    case dwarf_f2_mips:
235
0
      return "f2";
236
0
    case dwarf_f3_mips:
237
0
      return "f3";
238
0
    case dwarf_f4_mips:
239
0
      return "f4";
240
0
    case dwarf_f5_mips:
241
0
      return "f5";
242
0
    case dwarf_f6_mips:
243
0
      return "f6";
244
0
    case dwarf_f7_mips:
245
0
      return "f7";
246
0
    case dwarf_f8_mips:
247
0
      return "f8";
248
0
    case dwarf_f9_mips:
249
0
      return "f9";
250
0
    case dwarf_f10_mips:
251
0
      return "f10";
252
0
    case dwarf_f11_mips:
253
0
      return "f11";
254
0
    case dwarf_f12_mips:
255
0
      return "f12";
256
0
    case dwarf_f13_mips:
257
0
      return "f13";
258
0
    case dwarf_f14_mips:
259
0
      return "f14";
260
0
    case dwarf_f15_mips:
261
0
      return "f15";
262
0
    case dwarf_f16_mips:
263
0
      return "f16";
264
0
    case dwarf_f17_mips:
265
0
      return "f17";
266
0
    case dwarf_f18_mips:
267
0
      return "f18";
268
0
    case dwarf_f19_mips:
269
0
      return "f19";
270
0
    case dwarf_f20_mips:
271
0
      return "f20";
272
0
    case dwarf_f21_mips:
273
0
      return "f21";
274
0
    case dwarf_f22_mips:
275
0
      return "f22";
276
0
    case dwarf_f23_mips:
277
0
      return "f23";
278
0
    case dwarf_f24_mips:
279
0
      return "f24";
280
0
    case dwarf_f25_mips:
281
0
      return "f25";
282
0
    case dwarf_f26_mips:
283
0
      return "f26";
284
0
    case dwarf_f27_mips:
285
0
      return "f27";
286
0
    case dwarf_f28_mips:
287
0
      return "f28";
288
0
    case dwarf_f29_mips:
289
0
      return "f29";
290
0
    case dwarf_f30_mips:
291
0
      return "f30";
292
0
    case dwarf_f31_mips:
293
0
      return "f31";
294
0
    case dwarf_w0_mips:
295
0
      return "w0";
296
0
    case dwarf_w1_mips:
297
0
      return "w1";
298
0
    case dwarf_w2_mips:
299
0
      return "w2";
300
0
    case dwarf_w3_mips:
301
0
      return "w3";
302
0
    case dwarf_w4_mips:
303
0
      return "w4";
304
0
    case dwarf_w5_mips:
305
0
      return "w5";
306
0
    case dwarf_w6_mips:
307
0
      return "w6";
308
0
    case dwarf_w7_mips:
309
0
      return "w7";
310
0
    case dwarf_w8_mips:
311
0
      return "w8";
312
0
    case dwarf_w9_mips:
313
0
      return "w9";
314
0
    case dwarf_w10_mips:
315
0
      return "w10";
316
0
    case dwarf_w11_mips:
317
0
      return "w11";
318
0
    case dwarf_w12_mips:
319
0
      return "w12";
320
0
    case dwarf_w13_mips:
321
0
      return "w13";
322
0
    case dwarf_w14_mips:
323
0
      return "w14";
324
0
    case dwarf_w15_mips:
325
0
      return "w15";
326
0
    case dwarf_w16_mips:
327
0
      return "w16";
328
0
    case dwarf_w17_mips:
329
0
      return "w17";
330
0
    case dwarf_w18_mips:
331
0
      return "w18";
332
0
    case dwarf_w19_mips:
333
0
      return "w19";
334
0
    case dwarf_w20_mips:
335
0
      return "w20";
336
0
    case dwarf_w21_mips:
337
0
      return "w21";
338
0
    case dwarf_w22_mips:
339
0
      return "w22";
340
0
    case dwarf_w23_mips:
341
0
      return "w23";
342
0
    case dwarf_w24_mips:
343
0
      return "w24";
344
0
    case dwarf_w25_mips:
345
0
      return "w25";
346
0
    case dwarf_w26_mips:
347
0
      return "w26";
348
0
    case dwarf_w27_mips:
349
0
      return "w27";
350
0
    case dwarf_w28_mips:
351
0
      return "w28";
352
0
    case dwarf_w29_mips:
353
0
      return "w29";
354
0
    case dwarf_w30_mips:
355
0
      return "w30";
356
0
    case dwarf_w31_mips:
357
0
      return "w31";
358
0
    case dwarf_mir_mips:
359
0
      return "mir";
360
0
    case dwarf_mcsr_mips:
361
0
      return "mcsr";
362
0
    case dwarf_config5_mips:
363
0
      return "config5";
364
0
    default:
365
0
      break;
366
0
    }
367
0
    return nullptr;
368
0
  }
369
370
0
  switch (reg_num) {
371
0
  case dwarf_zero_mips:
372
0
    return "r0";
373
0
  case dwarf_r1_mips:
374
0
    return "r1";
375
0
  case dwarf_r2_mips:
376
0
    return "r2";
377
0
  case dwarf_r3_mips:
378
0
    return "r3";
379
0
  case dwarf_r4_mips:
380
0
    return "r4";
381
0
  case dwarf_r5_mips:
382
0
    return "r5";
383
0
  case dwarf_r6_mips:
384
0
    return "r6";
385
0
  case dwarf_r7_mips:
386
0
    return "r7";
387
0
  case dwarf_r8_mips:
388
0
    return "r8";
389
0
  case dwarf_r9_mips:
390
0
    return "r9";
391
0
  case dwarf_r10_mips:
392
0
    return "r10";
393
0
  case dwarf_r11_mips:
394
0
    return "r11";
395
0
  case dwarf_r12_mips:
396
0
    return "r12";
397
0
  case dwarf_r13_mips:
398
0
    return "r13";
399
0
  case dwarf_r14_mips:
400
0
    return "r14";
401
0
  case dwarf_r15_mips:
402
0
    return "r15";
403
0
  case dwarf_r16_mips:
404
0
    return "r16";
405
0
  case dwarf_r17_mips:
406
0
    return "r17";
407
0
  case dwarf_r18_mips:
408
0
    return "r18";
409
0
  case dwarf_r19_mips:
410
0
    return "r19";
411
0
  case dwarf_r20_mips:
412
0
    return "r20";
413
0
  case dwarf_r21_mips:
414
0
    return "r21";
415
0
  case dwarf_r22_mips:
416
0
    return "r22";
417
0
  case dwarf_r23_mips:
418
0
    return "r23";
419
0
  case dwarf_r24_mips:
420
0
    return "r24";
421
0
  case dwarf_r25_mips:
422
0
    return "r25";
423
0
  case dwarf_r26_mips:
424
0
    return "r26";
425
0
  case dwarf_r27_mips:
426
0
    return "r27";
427
0
  case dwarf_gp_mips:
428
0
    return "gp";
429
0
  case dwarf_sp_mips:
430
0
    return "sp";
431
0
  case dwarf_r30_mips:
432
0
    return "fp";
433
0
  case dwarf_ra_mips:
434
0
    return "ra";
435
0
  case dwarf_sr_mips:
436
0
    return "sr";
437
0
  case dwarf_lo_mips:
438
0
    return "lo";
439
0
  case dwarf_hi_mips:
440
0
    return "hi";
441
0
  case dwarf_bad_mips:
442
0
    return "bad";
443
0
  case dwarf_cause_mips:
444
0
    return "cause";
445
0
  case dwarf_pc_mips:
446
0
    return "pc";
447
0
  case dwarf_f0_mips:
448
0
    return "f0";
449
0
  case dwarf_f1_mips:
450
0
    return "f1";
451
0
  case dwarf_f2_mips:
452
0
    return "f2";
453
0
  case dwarf_f3_mips:
454
0
    return "f3";
455
0
  case dwarf_f4_mips:
456
0
    return "f4";
457
0
  case dwarf_f5_mips:
458
0
    return "f5";
459
0
  case dwarf_f6_mips:
460
0
    return "f6";
461
0
  case dwarf_f7_mips:
462
0
    return "f7";
463
0
  case dwarf_f8_mips:
464
0
    return "f8";
465
0
  case dwarf_f9_mips:
466
0
    return "f9";
467
0
  case dwarf_f10_mips:
468
0
    return "f10";
469
0
  case dwarf_f11_mips:
470
0
    return "f11";
471
0
  case dwarf_f12_mips:
472
0
    return "f12";
473
0
  case dwarf_f13_mips:
474
0
    return "f13";
475
0
  case dwarf_f14_mips:
476
0
    return "f14";
477
0
  case dwarf_f15_mips:
478
0
    return "f15";
479
0
  case dwarf_f16_mips:
480
0
    return "f16";
481
0
  case dwarf_f17_mips:
482
0
    return "f17";
483
0
  case dwarf_f18_mips:
484
0
    return "f18";
485
0
  case dwarf_f19_mips:
486
0
    return "f19";
487
0
  case dwarf_f20_mips:
488
0
    return "f20";
489
0
  case dwarf_f21_mips:
490
0
    return "f21";
491
0
  case dwarf_f22_mips:
492
0
    return "f22";
493
0
  case dwarf_f23_mips:
494
0
    return "f23";
495
0
  case dwarf_f24_mips:
496
0
    return "f24";
497
0
  case dwarf_f25_mips:
498
0
    return "f25";
499
0
  case dwarf_f26_mips:
500
0
    return "f26";
501
0
  case dwarf_f27_mips:
502
0
    return "f27";
503
0
  case dwarf_f28_mips:
504
0
    return "f28";
505
0
  case dwarf_f29_mips:
506
0
    return "f29";
507
0
  case dwarf_f30_mips:
508
0
    return "f30";
509
0
  case dwarf_f31_mips:
510
0
    return "f31";
511
0
  case dwarf_fcsr_mips:
512
0
    return "fcsr";
513
0
  case dwarf_fir_mips:
514
0
    return "fir";
515
0
  case dwarf_w0_mips:
516
0
    return "w0";
517
0
  case dwarf_w1_mips:
518
0
    return "w1";
519
0
  case dwarf_w2_mips:
520
0
    return "w2";
521
0
  case dwarf_w3_mips:
522
0
    return "w3";
523
0
  case dwarf_w4_mips:
524
0
    return "w4";
525
0
  case dwarf_w5_mips:
526
0
    return "w5";
527
0
  case dwarf_w6_mips:
528
0
    return "w6";
529
0
  case dwarf_w7_mips:
530
0
    return "w7";
531
0
  case dwarf_w8_mips:
532
0
    return "w8";
533
0
  case dwarf_w9_mips:
534
0
    return "w9";
535
0
  case dwarf_w10_mips:
536
0
    return "w10";
537
0
  case dwarf_w11_mips:
538
0
    return "w11";
539
0
  case dwarf_w12_mips:
540
0
    return "w12";
541
0
  case dwarf_w13_mips:
542
0
    return "w13";
543
0
  case dwarf_w14_mips:
544
0
    return "w14";
545
0
  case dwarf_w15_mips:
546
0
    return "w15";
547
0
  case dwarf_w16_mips:
548
0
    return "w16";
549
0
  case dwarf_w17_mips:
550
0
    return "w17";
551
0
  case dwarf_w18_mips:
552
0
    return "w18";
553
0
  case dwarf_w19_mips:
554
0
    return "w19";
555
0
  case dwarf_w20_mips:
556
0
    return "w20";
557
0
  case dwarf_w21_mips:
558
0
    return "w21";
559
0
  case dwarf_w22_mips:
560
0
    return "w22";
561
0
  case dwarf_w23_mips:
562
0
    return "w23";
563
0
  case dwarf_w24_mips:
564
0
    return "w24";
565
0
  case dwarf_w25_mips:
566
0
    return "w25";
567
0
  case dwarf_w26_mips:
568
0
    return "w26";
569
0
  case dwarf_w27_mips:
570
0
    return "w27";
571
0
  case dwarf_w28_mips:
572
0
    return "w28";
573
0
  case dwarf_w29_mips:
574
0
    return "w29";
575
0
  case dwarf_w30_mips:
576
0
    return "w30";
577
0
  case dwarf_w31_mips:
578
0
    return "w31";
579
0
  case dwarf_mcsr_mips:
580
0
    return "mcsr";
581
0
  case dwarf_mir_mips:
582
0
    return "mir";
583
0
  case dwarf_config5_mips:
584
0
    return "config5";
585
0
  }
586
0
  return nullptr;
587
0
}
588
589
std::optional<RegisterInfo>
590
EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind,
591
0
                                        uint32_t reg_num) {
592
0
  if (reg_kind == eRegisterKindGeneric) {
593
0
    switch (reg_num) {
594
0
    case LLDB_REGNUM_GENERIC_PC:
595
0
      reg_kind = eRegisterKindDWARF;
596
0
      reg_num = dwarf_pc_mips;
597
0
      break;
598
0
    case LLDB_REGNUM_GENERIC_SP:
599
0
      reg_kind = eRegisterKindDWARF;
600
0
      reg_num = dwarf_sp_mips;
601
0
      break;
602
0
    case LLDB_REGNUM_GENERIC_FP:
603
0
      reg_kind = eRegisterKindDWARF;
604
0
      reg_num = dwarf_r30_mips;
605
0
      break;
606
0
    case LLDB_REGNUM_GENERIC_RA:
607
0
      reg_kind = eRegisterKindDWARF;
608
0
      reg_num = dwarf_ra_mips;
609
0
      break;
610
0
    case LLDB_REGNUM_GENERIC_FLAGS:
611
0
      reg_kind = eRegisterKindDWARF;
612
0
      reg_num = dwarf_sr_mips;
613
0
      break;
614
0
    default:
615
0
      return {};
616
0
    }
617
0
  }
618
619
0
  if (reg_kind == eRegisterKindDWARF) {
620
0
    RegisterInfo reg_info;
621
0
    ::memset(&reg_info, 0, sizeof(RegisterInfo));
622
0
    ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
623
624
0
    if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips ||
625
0
        reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips ||
626
0
        reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) {
627
0
      reg_info.byte_size = 4;
628
0
      reg_info.format = eFormatHex;
629
0
      reg_info.encoding = eEncodingUint;
630
0
    } else if ((int)reg_num >= dwarf_zero_mips &&
631
0
               (int)reg_num <= dwarf_f31_mips) {
632
0
      reg_info.byte_size = 4;
633
0
      reg_info.format = eFormatHex;
634
0
      reg_info.encoding = eEncodingUint;
635
0
    } else if ((int)reg_num >= dwarf_w0_mips &&
636
0
               (int)reg_num <= dwarf_w31_mips) {
637
0
      reg_info.byte_size = 16;
638
0
      reg_info.format = eFormatVectorOfUInt8;
639
0
      reg_info.encoding = eEncodingVector;
640
0
    } else {
641
0
      return {};
642
0
    }
643
644
0
    reg_info.name = GetRegisterName(reg_num, false);
645
0
    reg_info.alt_name = GetRegisterName(reg_num, true);
646
0
    reg_info.kinds[eRegisterKindDWARF] = reg_num;
647
648
0
    switch (reg_num) {
649
0
    case dwarf_r30_mips:
650
0
      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
651
0
      break;
652
0
    case dwarf_ra_mips:
653
0
      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
654
0
      break;
655
0
    case dwarf_sp_mips:
656
0
      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
657
0
      break;
658
0
    case dwarf_pc_mips:
659
0
      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
660
0
      break;
661
0
    case dwarf_sr_mips:
662
0
      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
663
0
      break;
664
0
    default:
665
0
      break;
666
0
    }
667
0
    return reg_info;
668
0
  }
669
0
  return {};
670
0
}
671
672
EmulateInstructionMIPS::MipsOpcode *
673
0
EmulateInstructionMIPS::GetOpcodeForInstruction(llvm::StringRef name) {
674
0
  static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = {
675
      // Prologue/Epilogue instructions
676
0
      {"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu,
677
0
       "ADDIU rt, rs, immediate"},
678
0
      {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"},
679
0
      {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"},
680
0
      {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"},
681
0
      {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"},
682
0
      {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"},
683
684
      // MicroMIPS Prologue/Epilogue instructions
685
0
      {"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,
686
0
       "ADDIU immediate"},
687
0
      {"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,
688
0
       "ADDIUS5 rd,immediate"},
689
0
      {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"},
690
0
      {"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
691
0
       "SWM16 reglist,offset(sp)"},
692
0
      {"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
693
0
       "SWM32 reglist,offset(base)"},
694
0
      {"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32,
695
0
       "SWP rs1,offset(base)"},
696
0
      {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"},
697
0
      {"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
698
0
       "LWM16 reglist,offset(sp)"},
699
0
      {"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
700
0
       "LWM32 reglist,offset(base)"},
701
0
      {"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32,
702
0
       "LWP rd,offset(base)"},
703
0
      {"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP,
704
0
       "JRADDIUSP immediate"},
705
706
      // Load/Store  instructions
707
      /* Following list of emulated instructions are required by implementation
708
         of hardware watchpoint
709
         for MIPS in lldb. As we just need the address accessed by instructions,
710
         we have generalised
711
         all these instructions in 2 functions depending on their addressing
712
         modes */
713
714
0
      {"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
715
0
       "LB    rt, offset(base)"},
716
0
      {"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
717
0
       "LBE   rt, offset(base)"},
718
0
      {"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
719
0
       "LBU   rt, offset(base)"},
720
0
      {"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
721
0
       "LBUE  rt, offset(base)"},
722
0
      {"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
723
0
       "LDC1  ft, offset(base)"},
724
0
      {"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
725
0
       "LD    rt, offset(base)"},
726
0
      {"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
727
0
       "LDL   rt, offset(base)"},
728
0
      {"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
729
0
       "LDR   rt, offset(base)"},
730
0
      {"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
731
0
       "LLD   rt, offset(base)"},
732
0
      {"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
733
0
       "LDC2  rt, offset(base)"},
734
0
      {"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
735
0
       "LDXC1 fd, index (base)"},
736
0
      {"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
737
0
       "LH    rt, offset(base)"},
738
0
      {"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
739
0
       "LHE   rt, offset(base)"},
740
0
      {"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm,
741
0
       "LHU   rt, offset(base)"},
742
0
      {"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
743
0
       "LHUE  rt, offset(base)"},
744
0
      {"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
745
0
       "LL    rt, offset(base)"},
746
0
      {"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
747
0
       "LLE   rt, offset(base)"},
748
0
      {"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
749
0
       "LUXC1 fd, index (base)"},
750
0
      {"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm,
751
0
       "LW    rt, offset(base)"},
752
0
      {"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
753
0
       "LWC1  ft, offset(base)"},
754
0
      {"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
755
0
       "LWC2  rt, offset(base)"},
756
0
      {"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
757
0
       "LWE   rt, offset(base)"},
758
0
      {"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
759
0
       "LWL   rt, offset(base)"},
760
0
      {"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
761
0
       "LWLE  rt, offset(base)"},
762
0
      {"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
763
0
       "LWR   rt, offset(base)"},
764
0
      {"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
765
0
       "LWRE  rt, offset(base)"},
766
0
      {"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
767
0
       "LWXC1 fd, index (base)"},
768
0
      {"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
769
0
       "LLX   rt, offset(base)"},
770
0
      {"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
771
0
       "LLXE  rt, offset(base)"},
772
0
      {"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
773
0
       "LLDX  rt, offset(base)"},
774
775
0
      {"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm,
776
0
       "SB    rt, offset(base)"},
777
0
      {"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
778
0
       "SBE   rt, offset(base)"},
779
0
      {"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm,
780
0
       "SC    rt, offset(base)"},
781
0
      {"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
782
0
       "SCE   rt, offset(base)"},
783
0
      {"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
784
0
       "SCD   rt, offset(base)"},
785
0
      {"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm,
786
0
       "SD    rt, offset(base)"},
787
0
      {"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
788
0
       "SDL   rt, offset(base)"},
789
0
      {"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
790
0
       "SDR   rt, offset(base)"},
791
0
      {"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
792
0
       "SDC1  ft, offset(base)"},
793
0
      {"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
794
0
       "SDC2  rt, offset(base)"},
795
0
      {"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
796
0
       "SDXC1 fs, index(base)"},
797
0
      {"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm,
798
0
       "SH    rt, offset(base)"},
799
0
      {"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
800
0
       "SHE   rt, offset(base)"},
801
0
      {"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
802
0
       "SUXC1 fs, index (base)"},
803
0
      {"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm,
804
0
       "SWC1  ft, offset(base)"},
805
0
      {"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm,
806
0
       "SWC2  rt, offset(base)"},
807
0
      {"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
808
0
       "SWE   rt, offset(base)"},
809
0
      {"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm,
810
0
       "SWL   rt, offset(base)"},
811
0
      {"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
812
0
       "SWLE  rt, offset(base)"},
813
0
      {"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm,
814
0
       "SWR   rt, offset(base)"},
815
0
      {"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
816
0
       "SWRE  rt, offset(base)"},
817
0
      {"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg,
818
0
       "SWXC1 fs, index (base)"},
819
0
      {"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
820
0
       "SCX   rt, offset(base)"},
821
0
      {"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm,
822
0
       "SCXE  rt, offset(base)"},
823
0
      {"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm,
824
0
       "SCDX  rt, offset(base)"},
825
826
      // MicroMIPS Load/Store instructions
827
0
      {"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
828
0
       "LBU16 rt, decoded_offset(base)"},
829
0
      {"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
830
0
       "LHU16 rt, left_shifted_offset(base)"},
831
0
      {"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
832
0
       "LW16  rt, left_shifted_offset(base)"},
833
0
      {"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
834
0
       "LWGP  rt, left_shifted_offset(gp)"},
835
0
      {"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
836
0
       "SH16  rt, left_shifted_offset(base)"},
837
0
      {"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
838
0
       "SW16  rt, left_shifted_offset(base)"},
839
0
      {"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
840
0
       "SWSP  rt, left_shifted_offset(base)"},
841
0
      {"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm,
842
0
       "SB16  rt, offset(base)"},
843
844
      // Branch instructions
845
0
      {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"},
846
0
      {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"},
847
0
      {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"},
848
0
      {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"},
849
0
      {"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
850
0
       "BGEZALL rt,offset"},
851
0
      {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"},
852
0
      {"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
853
0
       "BGEZAL rs,offset"},
854
0
      {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"},
855
0
      {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"},
856
0
      {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"},
857
0
      {"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
858
0
       "BLEZALC rs,offset"},
859
0
      {"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
860
0
       "BGEZALC rs,offset"},
861
0
      {"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
862
0
       "BLTZALC rs,offset"},
863
0
      {"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
864
0
       "BGTZALC rs,offset"},
865
0
      {"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
866
0
       "BEQZALC rs,offset"},
867
0
      {"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,
868
0
       "BNEZALC rs,offset"},
869
0
      {"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
870
0
       "BEQC rs,rt,offset"},
871
0
      {"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
872
0
       "BNEC rs,rt,offset"},
873
0
      {"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
874
0
       "BLTC rs,rt,offset"},
875
0
      {"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
876
0
       "BGEC rs,rt,offset"},
877
0
      {"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
878
0
       "BLTUC rs,rt,offset"},
879
0
      {"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
880
0
       "BGEUC rs,rt,offset"},
881
0
      {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"},
882
0
      {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"},
883
0
      {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"},
884
0
      {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"},
885
0
      {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"},
886
0
      {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"},
887
0
      {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"},
888
0
      {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"},
889
0
      {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"},
890
0
      {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"},
891
0
      {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"},
892
0
      {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"},
893
0
      {"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
894
0
       "BLTZAL rt,offset"},
895
0
      {"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link,
896
0
       "BLTZALL rt,offset"},
897
0
      {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"},
898
0
      {"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
899
0
       "BOVC rs,rt,offset"},
900
0
      {"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C,
901
0
       "BNVC rs,rt,offset"},
902
0
      {"J", &EmulateInstructionMIPS::Emulate_J, "J target"},
903
0
      {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"},
904
0
      {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"},
905
0
      {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"},
906
0
      {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"},
907
0
      {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"},
908
0
      {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"},
909
0
      {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"},
910
0
      {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"},
911
0
      {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"},
912
0
      {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"},
913
0
      {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"},
914
0
      {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"},
915
0
      {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"},
916
0
      {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"},
917
0
      {"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch,
918
0
       "BC1ANY2F cc, offset"},
919
0
      {"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch,
920
0
       "BC1ANY2T cc, offset"},
921
0
      {"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch,
922
0
       "BC1ANY4F cc, offset"},
923
0
      {"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch,
924
0
       "BC1ANY4T cc, offset"},
925
0
      {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"},
926
0
      {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"},
927
0
      {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"},
928
0
      {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"},
929
0
      {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"},
930
0
      {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"},
931
0
      {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"},
932
0
      {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"},
933
0
      {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"},
934
0
      {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"},
935
936
      // MicroMIPS Branch instructions
937
0
      {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"},
938
0
      {"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
939
0
       "BEQZ16 rs, offset"},
940
0
      {"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
941
0
       "BNEZ16 rs, offset"},
942
0
      {"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
943
0
       "BEQZC rs, offset"},
944
0
      {"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
945
0
       "BNEZC rs, offset"},
946
0
      {"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
947
0
       "BGEZALS rs, offset"},
948
0
      {"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,
949
0
       "BLTZALS rs, offset"},
950
0
      {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"},
951
0
      {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"},
952
0
      {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"},
953
0
      {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"},
954
0
      {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"},
955
0
      {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"},
956
0
      {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"},
957
0
  };
958
959
0
  for (MipsOpcode &opcode : g_opcodes) {
960
0
    if (name.equals_insensitive(opcode.op_name))
961
0
      return &opcode;
962
0
  }
963
0
  return nullptr;
964
0
}
965
966
uint32_t
967
EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,
968
0
                                             uint64_t inst_addr) {
969
0
  uint64_t next_inst_size = 0;
970
0
  llvm::MCInst mc_insn;
971
0
  llvm::MCDisassembler::DecodeStatus decode_status;
972
0
  llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
973
974
0
  if (m_use_alt_disaasm)
975
0
    decode_status = m_alt_disasm->getInstruction(
976
0
        mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
977
0
  else
978
0
    decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
979
0
                                             inst_addr, llvm::nulls());
980
981
0
  if (decode_status != llvm::MCDisassembler::Success)
982
0
    return false;
983
984
0
  return m_insn_info->get(mc_insn.getOpcode()).getSize();
985
0
}
986
987
bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
988
                                            const Address &inst_addr,
989
0
                                            Target *target) {
990
0
  m_use_alt_disaasm = false;
991
992
0
  if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
993
0
    if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {
994
0
      Status error;
995
0
      lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
996
997
      /*
998
       * The address belongs to microMIPS function. To find the size of
999
       * next instruction use microMIPS disassembler.
1000
      */
1001
0
      m_use_alt_disaasm = true;
1002
1003
0
      uint32_t current_inst_size = insn_opcode.GetByteSize();
1004
0
      uint8_t buf[sizeof(uint32_t)];
1005
0
      uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;
1006
0
      Address next_addr(next_inst_addr);
1007
1008
0
      const size_t bytes_read =
1009
0
          target->ReadMemory(next_addr, /* Address of next instruction */
1010
0
                             buf, sizeof(uint32_t), error, 
1011
0
                             false,  /* force_live_memory */
1012
0
                             &load_addr);
1013
1014
0
      if (bytes_read == 0)
1015
0
        return true;
1016
1017
0
      DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(),
1018
0
                         GetAddressByteSize());
1019
0
      m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr);
1020
0
      return true;
1021
0
    } else {
1022
      /*
1023
       * If the address class is not AddressClass::eCodeAlternateISA then
1024
       * the function is not microMIPS. In this case instruction size is
1025
       * always 4 bytes.
1026
      */
1027
0
      m_next_inst_size = 4;
1028
0
      return true;
1029
0
    }
1030
0
  }
1031
0
  return false;
1032
0
}
1033
1034
0
bool EmulateInstructionMIPS::ReadInstruction() {
1035
0
  bool success = false;
1036
0
  m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
1037
0
                                LLDB_INVALID_ADDRESS, &success);
1038
0
  if (success) {
1039
0
    Context read_inst_context;
1040
0
    read_inst_context.type = eContextReadOpcode;
1041
0
    read_inst_context.SetNoArgs();
1042
0
    m_opcode.SetOpcode32(
1043
0
        ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success),
1044
0
        GetByteOrder());
1045
0
  }
1046
0
  if (!success)
1047
0
    m_addr = LLDB_INVALID_ADDRESS;
1048
0
  return success;
1049
0
}
1050
1051
0
bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
1052
0
  bool success = false;
1053
0
  llvm::MCInst mc_insn;
1054
0
  uint64_t insn_size;
1055
0
  DataExtractor data;
1056
1057
  /* Keep the complexity of the decode logic with the llvm::MCDisassembler
1058
   * class. */
1059
0
  if (m_opcode.GetData(data)) {
1060
0
    llvm::MCDisassembler::DecodeStatus decode_status;
1061
0
    llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
1062
0
    if (m_use_alt_disaasm)
1063
0
      decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1064
0
                                                   m_addr, llvm::nulls());
1065
0
    else
1066
0
      decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
1067
0
                                               m_addr, llvm::nulls());
1068
1069
0
    if (decode_status != llvm::MCDisassembler::Success)
1070
0
      return false;
1071
0
  }
1072
1073
  /*
1074
   * mc_insn.getOpcode() returns decoded opcode. However to make use
1075
   * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
1076
  */
1077
0
  const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data();
1078
1079
0
  if (op_name == nullptr)
1080
0
    return false;
1081
1082
  /*
1083
   * Decoding has been done already. Just get the call-back function
1084
   * and emulate the instruction.
1085
  */
1086
0
  MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name);
1087
1088
0
  if (opcode_data == nullptr)
1089
0
    return false;
1090
1091
0
  uint64_t old_pc = 0, new_pc = 0;
1092
0
  const bool auto_advance_pc =
1093
0
      evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
1094
1095
0
  if (auto_advance_pc) {
1096
0
    old_pc =
1097
0
        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1098
0
    if (!success)
1099
0
      return false;
1100
0
  }
1101
1102
  /* emulate instruction */
1103
0
  success = (this->*opcode_data->callback)(mc_insn);
1104
0
  if (!success)
1105
0
    return false;
1106
1107
0
  if (auto_advance_pc) {
1108
0
    new_pc =
1109
0
        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1110
0
    if (!success)
1111
0
      return false;
1112
1113
    /* If we haven't changed the PC, change it here */
1114
0
    if (old_pc == new_pc) {
1115
0
      new_pc += 4;
1116
0
      Context context;
1117
0
      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1118
0
                                 new_pc))
1119
0
        return false;
1120
0
    }
1121
0
  }
1122
1123
0
  return true;
1124
0
}
1125
1126
bool EmulateInstructionMIPS::CreateFunctionEntryUnwind(
1127
0
    UnwindPlan &unwind_plan) {
1128
0
  unwind_plan.Clear();
1129
0
  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1130
1131
0
  UnwindPlan::RowSP row(new UnwindPlan::Row);
1132
0
  const bool can_replace = false;
1133
1134
  // Our previous Call Frame Address is the stack pointer
1135
0
  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);
1136
1137
  // Our previous PC is in the RA
1138
0
  row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
1139
1140
0
  unwind_plan.AppendRow(row);
1141
1142
  // All other registers are the same.
1143
0
  unwind_plan.SetSourceName("EmulateInstructionMIPS");
1144
0
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1145
0
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
1146
0
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1147
0
  unwind_plan.SetReturnAddressRegister(dwarf_ra_mips);
1148
1149
0
  return true;
1150
0
}
1151
1152
0
bool EmulateInstructionMIPS::nonvolatile_reg_p(uint32_t regnum) {
1153
0
  switch (regnum) {
1154
0
  case dwarf_r16_mips:
1155
0
  case dwarf_r17_mips:
1156
0
  case dwarf_r18_mips:
1157
0
  case dwarf_r19_mips:
1158
0
  case dwarf_r20_mips:
1159
0
  case dwarf_r21_mips:
1160
0
  case dwarf_r22_mips:
1161
0
  case dwarf_r23_mips:
1162
0
  case dwarf_gp_mips:
1163
0
  case dwarf_sp_mips:
1164
0
  case dwarf_r30_mips:
1165
0
  case dwarf_ra_mips:
1166
0
    return true;
1167
0
  default:
1168
0
    return false;
1169
0
  }
1170
0
  return false;
1171
0
}
1172
1173
0
bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {
1174
  // ADDIU rt, rs, immediate
1175
  // GPR[rt] <- GPR[rs] + sign_extend(immediate)
1176
1177
0
  uint8_t dst, src;
1178
0
  bool success = false;
1179
0
  const uint32_t imm16 = insn.getOperand(2).getImm();
1180
0
  int64_t imm = SignedBits(imm16, 15, 0);
1181
1182
0
  dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1183
0
  src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1184
1185
  // If immediate value is greater then 2^16 - 1 then clang generate LUI,
1186
  // ADDIU, SUBU instructions in prolog. Example lui    $1, 0x2 addiu $1, $1,
1187
  // -0x5920 subu  $sp, $sp, $1 In this case, ADDIU dst and src will be same
1188
  // and not equal to sp
1189
0
  if (dst == src) {
1190
0
    Context context;
1191
1192
    /* read <src> register */
1193
0
    const int64_t src_opd_val = ReadRegisterUnsigned(
1194
0
        eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1195
0
    if (!success)
1196
0
      return false;
1197
1198
    /* Check if this is daddiu sp, sp, imm16 */
1199
0
    if (dst == dwarf_sp_mips) {
1200
0
      uint64_t result = src_opd_val + imm;
1201
0
      std::optional<RegisterInfo> reg_info_sp =
1202
0
          GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1203
0
      if (reg_info_sp)
1204
0
        context.SetRegisterPlusOffset(*reg_info_sp, imm);
1205
1206
      /* We are allocating bytes on stack */
1207
0
      context.type = eContextAdjustStackPointer;
1208
1209
0
      WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1210
0
      return true;
1211
0
    }
1212
1213
0
    imm += src_opd_val;
1214
0
    context.SetImmediateSigned(imm);
1215
0
    context.type = eContextImmediate;
1216
1217
0
    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1218
0
                               dwarf_zero_mips + dst, imm))
1219
0
      return false;
1220
0
  }
1221
1222
0
  return true;
1223
0
}
1224
1225
0
bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) {
1226
0
  bool success = false;
1227
0
  uint32_t imm16 = insn.getOperand(2).getImm();
1228
0
  uint32_t imm = SignedBits(imm16, 15, 0);
1229
0
  uint32_t src, base;
1230
0
  int32_t address;
1231
0
  Context bad_vaddr_context;
1232
1233
0
  src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1234
0
  base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1235
1236
0
  std::optional<RegisterInfo> reg_info_base =
1237
0
      GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1238
0
  if (!reg_info_base)
1239
0
    return false;
1240
1241
  /* read base register */
1242
0
  address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1243
0
                                          dwarf_zero_mips + base, 0, &success);
1244
0
  if (!success)
1245
0
    return false;
1246
1247
  /* destination address */
1248
0
  address = address + imm;
1249
1250
  /* Set the bad_vaddr register with base address used in the instruction */
1251
0
  bad_vaddr_context.type = eContextInvalid;
1252
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1253
0
                        address);
1254
1255
  /* We look for sp based non-volatile register stores */
1256
0
  if (nonvolatile_reg_p(src)) {
1257
0
    std::optional<RegisterInfo> reg_info_src =
1258
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1259
0
    if (!reg_info_src)
1260
0
      return false;
1261
1262
0
    Context context;
1263
0
    context.type = eContextPushRegisterOnStack;
1264
0
    context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1265
1266
0
    RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1267
0
    Status error;
1268
1269
0
    std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1270
0
    if (!data_src)
1271
0
      return false;
1272
1273
0
    if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1274
0
                                  reg_info_src->byte_size, eByteOrderLittle,
1275
0
                                  error) == 0)
1276
0
      return false;
1277
1278
0
    if (!WriteMemory(context, address, buffer.data(), reg_info_src->byte_size))
1279
0
      return false;
1280
1281
0
    return true;
1282
0
  }
1283
1284
0
  return false;
1285
0
}
1286
1287
0
bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {
1288
0
  bool success = false;
1289
0
  uint32_t src, base;
1290
0
  int32_t imm, address;
1291
0
  Context bad_vaddr_context;
1292
1293
0
  src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1294
0
  base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1295
0
  imm = insn.getOperand(2).getImm();
1296
1297
0
  if (GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1298
0
    return false;
1299
1300
  /* read base register */
1301
0
  address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1302
0
                                          dwarf_zero_mips + base, 0, &success);
1303
0
  if (!success)
1304
0
    return false;
1305
1306
  /* destination address */
1307
0
  address = address + imm;
1308
1309
  /* Set the bad_vaddr register with base address used in the instruction */
1310
0
  bad_vaddr_context.type = eContextInvalid;
1311
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1312
0
                        address);
1313
1314
0
  if (nonvolatile_reg_p(src)) {
1315
0
    RegisterValue data_src;
1316
0
    std::optional<RegisterInfo> reg_info_src =
1317
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1318
0
    if (!reg_info_src)
1319
0
      return false;
1320
1321
0
    Context context;
1322
0
    context.type = eContextPopRegisterOffStack;
1323
0
    context.SetAddress(address);
1324
1325
0
    return WriteRegister(context, *reg_info_src, data_src);
1326
0
  }
1327
1328
0
  return false;
1329
0
}
1330
1331
0
bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) {
1332
  // SUBU sp, <src>, <rt>
1333
  // ADDU sp, <src>, <rt>
1334
  // ADDU dst, sp, <rt>
1335
1336
0
  bool success = false;
1337
0
  uint64_t result;
1338
0
  uint8_t src, dst, rt;
1339
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1340
1341
0
  dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1342
0
  src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1343
1344
  /* Check if sp is destination register */
1345
0
  if (dst == dwarf_sp_mips) {
1346
0
    rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1347
1348
    /* read <src> register */
1349
0
    uint64_t src_opd_val = ReadRegisterUnsigned(
1350
0
        eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1351
0
    if (!success)
1352
0
      return false;
1353
1354
    /* read <rt > register */
1355
0
    uint64_t rt_opd_val = ReadRegisterUnsigned(
1356
0
        eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1357
0
    if (!success)
1358
0
      return false;
1359
1360
0
    if (op_name.equals_insensitive("SUBU"))
1361
0
      result = src_opd_val - rt_opd_val;
1362
0
    else
1363
0
      result = src_opd_val + rt_opd_val;
1364
1365
0
    Context context;
1366
0
    std::optional<RegisterInfo> reg_info_sp =
1367
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1368
0
    if (reg_info_sp)
1369
0
      context.SetRegisterPlusOffset(*reg_info_sp, rt_opd_val);
1370
1371
    /* We are allocating bytes on stack */
1372
0
    context.type = eContextAdjustStackPointer;
1373
1374
0
    WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1375
1376
0
    return true;
1377
0
  } else if (src == dwarf_sp_mips) {
1378
0
    rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg());
1379
1380
    /* read <src> register */
1381
0
    uint64_t src_opd_val = ReadRegisterUnsigned(
1382
0
        eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
1383
0
    if (!success)
1384
0
      return false;
1385
1386
    /* read <rt> register */
1387
0
    uint64_t rt_opd_val = ReadRegisterUnsigned(
1388
0
        eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
1389
0
    if (!success)
1390
0
      return false;
1391
1392
0
    Context context;
1393
1394
0
    if (op_name.equals_insensitive("SUBU"))
1395
0
      result = src_opd_val - rt_opd_val;
1396
0
    else
1397
0
      result = src_opd_val + rt_opd_val;
1398
1399
0
    context.SetImmediateSigned(result);
1400
0
    context.type = eContextImmediate;
1401
1402
0
    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
1403
0
                               dwarf_zero_mips + dst, result))
1404
0
      return false;
1405
0
  }
1406
1407
0
  return true;
1408
0
}
1409
1410
0
bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {
1411
  // LUI rt, immediate
1412
  // GPR[rt] <- sign_extend(immediate << 16)
1413
1414
0
  const uint32_t imm32 = insn.getOperand(1).getImm() << 16;
1415
0
  int64_t imm = SignedBits(imm32, 31, 0);
1416
0
  uint8_t rt;
1417
0
  Context context;
1418
1419
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1420
0
  context.SetImmediateSigned(imm);
1421
0
  context.type = eContextImmediate;
1422
1423
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF,
1424
0
                               dwarf_zero_mips + rt, imm);
1425
0
}
1426
1427
0
bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {
1428
0
  bool success = false;
1429
0
  const uint32_t imm9 = insn.getOperand(0).getImm();
1430
0
  uint64_t result;
1431
1432
  // This instruction operates implicitly on stack pointer, so read <sp>
1433
  // register.
1434
0
  uint64_t src_opd_val =
1435
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
1436
0
  if (!success)
1437
0
    return false;
1438
1439
0
  result = src_opd_val + imm9;
1440
1441
0
  Context context;
1442
0
  std::optional<RegisterInfo> reg_info_sp =
1443
0
      GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1444
0
  if (reg_info_sp)
1445
0
    context.SetRegisterPlusOffset(*reg_info_sp, imm9);
1446
1447
  // We are adjusting the stack.
1448
0
  context.type = eContextAdjustStackPointer;
1449
1450
0
  WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1451
0
  return true;
1452
0
}
1453
1454
0
bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) {
1455
0
  bool success = false;
1456
0
  uint32_t base;
1457
0
  const uint32_t imm4 = insn.getOperand(2).getImm();
1458
0
  uint64_t result;
1459
1460
  // The source and destination register is same for this instruction.
1461
0
  base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1462
1463
  // We are looking for stack adjustment only
1464
0
  if (base == dwarf_sp_mips) {
1465
    // Read stack pointer register
1466
0
    uint64_t src_opd_val = ReadRegisterUnsigned(
1467
0
        eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1468
0
    if (!success)
1469
0
      return false;
1470
1471
0
    result = src_opd_val + imm4;
1472
1473
0
    Context context;
1474
0
    std::optional<RegisterInfo> reg_info_sp =
1475
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1476
0
    if (reg_info_sp)
1477
0
      context.SetRegisterPlusOffset(*reg_info_sp, imm4);
1478
1479
    // We are adjusting the stack.
1480
0
    context.type = eContextAdjustStackPointer;
1481
1482
0
    WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result);
1483
0
  }
1484
1485
0
  return true;
1486
0
}
1487
1488
0
bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {
1489
0
  bool success = false;
1490
0
  uint32_t imm5 = insn.getOperand(2).getImm();
1491
0
  uint32_t src, base;
1492
0
  Context bad_vaddr_context;
1493
0
  uint32_t address;
1494
1495
0
  src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1496
0
  base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1497
1498
0
  std::optional<RegisterInfo> reg_info_base =
1499
0
      GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1500
0
  if (!reg_info_base)
1501
0
    return false;
1502
1503
  // read base register
1504
0
  address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0,
1505
0
                                 &success);
1506
0
  if (!success)
1507
0
    return false;
1508
1509
  // destination address
1510
0
  address = address + imm5;
1511
1512
  // We use bad_vaddr_context to store base address which is used by H/W
1513
  // watchpoint Set the bad_vaddr register with base address used in the
1514
  // instruction
1515
0
  bad_vaddr_context.type = eContextInvalid;
1516
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1517
0
                        address);
1518
1519
  // We look for sp based non-volatile register stores.
1520
0
  if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1521
0
    RegisterInfo reg_info_src = {};
1522
0
    Context context;
1523
0
    context.type = eContextPushRegisterOnStack;
1524
0
    context.SetRegisterToRegisterPlusOffset(reg_info_src, *reg_info_base, 0);
1525
1526
0
    RegisterValue::BytesContainer buffer(reg_info_src.byte_size);
1527
0
    Status error;
1528
1529
0
    std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1530
0
    if (!data_src)
1531
0
      return false;
1532
1533
0
    if (data_src->GetAsMemoryData(reg_info_src, buffer.data(),
1534
0
                                  reg_info_src.byte_size, eByteOrderLittle,
1535
0
                                  error) == 0)
1536
0
      return false;
1537
1538
0
    if (!WriteMemory(context, address, buffer.data(), reg_info_src.byte_size))
1539
0
      return false;
1540
1541
0
    return true;
1542
0
  }
1543
1544
0
  return false;
1545
0
}
1546
1547
/* Emulate SWM16,SWM32 and SWP instruction.
1548
1549
   SWM16 always has stack pointer as a base register (but it is still available
1550
   in MCInst as an operand).
1551
   SWM32 and SWP can have base register other than stack pointer.
1552
*/
1553
0
bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) {
1554
0
  bool success = false;
1555
0
  uint32_t src, base;
1556
0
  uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1557
                                                 // no of regs to store.
1558
1559
  // Base register is second last operand of the instruction.
1560
0
  base =
1561
0
      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1562
1563
  // We are looking for sp based stores so if base is not a stack pointer then
1564
  // don't proceed.
1565
0
  if (base != dwarf_sp_mips)
1566
0
    return false;
1567
1568
  // offset is always the last operand.
1569
0
  uint32_t offset = insn.getOperand(num_operands - 1).getImm();
1570
1571
0
  std::optional<RegisterInfo> reg_info_base =
1572
0
      GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base);
1573
0
  if (!reg_info_base)
1574
0
    return false;
1575
1576
  // read SP
1577
0
  uint32_t base_address = ReadRegisterUnsigned(
1578
0
      eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1579
0
  if (!success)
1580
0
    return false;
1581
1582
  // Resulting base addrss
1583
0
  base_address = base_address + offset;
1584
1585
  // Total no of registers to be stored are num_operands-2.
1586
0
  for (uint32_t i = 0; i < num_operands - 2; i++) {
1587
    // Get the register number to be stored.
1588
0
    src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1589
1590
    /*
1591
        Record only non-volatile stores.
1592
        This check is required for SWP instruction because source operand could
1593
       be any register.
1594
        SWM16 and SWM32 instruction always has saved registers as source
1595
       operands.
1596
    */
1597
0
    if (!nonvolatile_reg_p(src))
1598
0
      return false;
1599
1600
0
    std::optional<RegisterInfo> reg_info_src =
1601
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1602
0
    if (!reg_info_src)
1603
0
      return false;
1604
1605
0
    Context context;
1606
0
    context.type = eContextPushRegisterOnStack;
1607
0
    context.SetRegisterToRegisterPlusOffset(*reg_info_src, *reg_info_base, 0);
1608
1609
0
    RegisterValue::BytesContainer buffer(reg_info_src->byte_size);
1610
0
    Status error;
1611
1612
0
    std::optional<RegisterValue> data_src = ReadRegister(*reg_info_base);
1613
0
    if (!data_src)
1614
0
      return false;
1615
1616
0
    if (data_src->GetAsMemoryData(*reg_info_src, buffer.data(),
1617
0
                                  reg_info_src->byte_size, eByteOrderLittle,
1618
0
                                  error) == 0)
1619
0
      return false;
1620
1621
0
    if (!WriteMemory(context, base_address, buffer.data(),
1622
0
                     reg_info_src->byte_size))
1623
0
      return false;
1624
1625
    // Stack address for next register
1626
0
    base_address = base_address + reg_info_src->byte_size;
1627
0
  }
1628
0
  return true;
1629
0
}
1630
1631
0
bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
1632
0
  bool success = false;
1633
0
  uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1634
0
  uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1635
0
  uint32_t imm5 = insn.getOperand(2).getImm();
1636
0
  Context bad_vaddr_context;
1637
1638
0
  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
1639
0
    return false;
1640
1641
  // read base register
1642
0
  uint32_t base_address = ReadRegisterUnsigned(
1643
0
      eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1644
0
  if (!success)
1645
0
    return false;
1646
1647
0
  base_address = base_address + imm5;
1648
1649
  // We use bad_vaddr_context to store base address which is used by H/W
1650
  // watchpoint Set the bad_vaddr register with base address used in the
1651
  // instruction
1652
0
  bad_vaddr_context.type = eContextInvalid;
1653
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
1654
0
                        base_address);
1655
1656
0
  if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) {
1657
0
    RegisterValue data_src;
1658
0
    std::optional<RegisterInfo> reg_info_src =
1659
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src);
1660
0
    if (!reg_info_src)
1661
0
      return false;
1662
1663
0
    Context context;
1664
0
    context.type = eContextPopRegisterOffStack;
1665
0
    context.SetAddress(base_address);
1666
1667
0
    return WriteRegister(context, *reg_info_src, data_src);
1668
0
  }
1669
1670
0
  return false;
1671
0
}
1672
1673
/* Emulate LWM16, LWM32 and LWP instructions.
1674
1675
   LWM16 always has stack pointer as a base register (but it is still available
1676
   in MCInst as an operand).
1677
   LWM32 and LWP can have base register other than stack pointer.
1678
*/
1679
0
bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) {
1680
0
  bool success = false;
1681
0
  uint32_t dst, base;
1682
0
  uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on
1683
                                                 // no of regs to store.
1684
0
  uint32_t imm = insn.getOperand(num_operands - 1)
1685
0
                     .getImm(); // imm is the last operand in the instruction.
1686
1687
  // Base register is second last operand of the instruction.
1688
0
  base =
1689
0
      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
1690
1691
  // We are looking for sp based loads so if base is not a stack pointer then
1692
  // don't proceed.
1693
0
  if (base != dwarf_sp_mips)
1694
0
    return false;
1695
1696
0
  uint32_t base_address = ReadRegisterUnsigned(
1697
0
      eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
1698
0
  if (!success)
1699
0
    return false;
1700
1701
0
  base_address = base_address + imm;
1702
1703
0
  RegisterValue data_dst;
1704
1705
  // Total no of registers to be re-stored are num_operands-2.
1706
0
  for (uint32_t i = 0; i < num_operands - 2; i++) {
1707
    // Get the register number to be re-stored.
1708
0
    dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg());
1709
1710
    /*
1711
        Record only non-volatile loads.
1712
        This check is required for LWP instruction because destination operand
1713
       could be any register.
1714
        LWM16 and LWM32 instruction always has saved registers as destination
1715
       operands.
1716
    */
1717
0
    if (!nonvolatile_reg_p(dst))
1718
0
      return false;
1719
1720
0
    std::optional<RegisterInfo> reg_info_dst =
1721
0
        GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst);
1722
0
    if (!reg_info_dst)
1723
0
      return false;
1724
1725
0
    Context context;
1726
0
    context.type = eContextPopRegisterOffStack;
1727
0
    context.SetAddress(base_address + (i * 4));
1728
1729
0
    if (!WriteRegister(context, *reg_info_dst, data_dst))
1730
0
      return false;
1731
0
  }
1732
1733
0
  return true;
1734
0
}
1735
1736
0
bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {
1737
0
  bool success = false;
1738
0
  int32_t imm5 = insn.getOperand(0).getImm();
1739
1740
  /* JRADDIUSP immediate
1741
  *       PC <- RA
1742
  *       SP <- SP + zero_extend(Immediate << 2)
1743
  */
1744
1745
  // This instruction operates implicitly on stack pointer, so read <sp>
1746
  // register.
1747
0
  int32_t src_opd_val =
1748
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
1749
0
  if (!success)
1750
0
    return false;
1751
1752
0
  int32_t ra_val =
1753
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
1754
0
  if (!success)
1755
0
    return false;
1756
1757
0
  int32_t result = src_opd_val + imm5;
1758
1759
0
  Context context;
1760
1761
  // Update the PC
1762
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1763
0
                             ra_val))
1764
0
    return false;
1765
1766
0
  std::optional<RegisterInfo> reg_info_sp =
1767
0
      GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips);
1768
0
  if (reg_info_sp)
1769
0
    context.SetRegisterPlusOffset(*reg_info_sp, imm5);
1770
1771
  // We are adjusting stack
1772
0
  context.type = eContextAdjustStackPointer;
1773
1774
  // update SP
1775
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
1776
0
                               result);
1777
0
}
1778
1779
0
static int IsAdd64bitOverflow(int32_t a, int32_t b) {
1780
0
  int32_t r = (uint32_t)a + (uint32_t)b;
1781
0
  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
1782
0
}
1783
1784
/*
1785
    Emulate below MIPS branch instructions.
1786
    BEQ, BNE : Branch on condition
1787
    BEQL, BNEL : Branch likely
1788
*/
1789
0
bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {
1790
0
  bool success = false;
1791
0
  uint32_t rs, rt;
1792
0
  int32_t offset, pc, target = 0, rs_val, rt_val;
1793
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1794
1795
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1796
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1797
0
  offset = insn.getOperand(2).getImm();
1798
1799
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1800
0
  if (!success)
1801
0
    return false;
1802
1803
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1804
0
                                         dwarf_zero_mips + rs, 0, &success);
1805
0
  if (!success)
1806
0
    return false;
1807
1808
0
  rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1809
0
                                         dwarf_zero_mips + rt, 0, &success);
1810
0
  if (!success)
1811
0
    return false;
1812
1813
0
  if (op_name.equals_insensitive("BEQ") || op_name.equals_insensitive("BEQL")) {
1814
0
    if (rs_val == rt_val)
1815
0
      target = pc + offset;
1816
0
    else
1817
0
      target = pc + 8;
1818
0
  } else if (op_name.equals_insensitive("BNE") ||
1819
0
             op_name.equals_insensitive("BNEL")) {
1820
0
    if (rs_val != rt_val)
1821
0
      target = pc + offset;
1822
0
    else
1823
0
      target = pc + 8;
1824
0
  }
1825
1826
0
  Context context;
1827
0
  context.type = eContextRelativeBranchImmediate;
1828
0
  context.SetImmediate(offset);
1829
1830
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1831
0
                               target);
1832
0
}
1833
1834
/*
1835
    Emulate below MIPS branch instructions.
1836
    BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch
1837
   instructions with no delay slot
1838
*/
1839
0
bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
1840
0
  bool success = false;
1841
0
  uint32_t rs, rt;
1842
0
  int32_t offset, pc, target = 0, rs_val, rt_val;
1843
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1844
0
  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
1845
1846
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1847
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
1848
0
  offset = insn.getOperand(2).getImm();
1849
1850
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1851
0
  if (!success)
1852
0
    return false;
1853
1854
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1855
0
                                         dwarf_zero_mips + rs, 0, &success);
1856
0
  if (!success)
1857
0
    return false;
1858
1859
0
  rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1860
0
                                         dwarf_zero_mips + rt, 0, &success);
1861
0
  if (!success)
1862
0
    return false;
1863
1864
0
  if (op_name.equals_insensitive("BEQC")) {
1865
0
    if (rs_val == rt_val)
1866
0
      target = pc + offset;
1867
0
    else
1868
0
      target = pc + 4;
1869
0
  } else if (op_name.equals_insensitive("BNEC")) {
1870
0
    if (rs_val != rt_val)
1871
0
      target = pc + offset;
1872
0
    else
1873
0
      target = pc + 4;
1874
0
  } else if (op_name.equals_insensitive("BLTC")) {
1875
0
    if (rs_val < rt_val)
1876
0
      target = pc + offset;
1877
0
    else
1878
0
      target = pc + 4;
1879
0
  } else if (op_name.equals_insensitive("BGEC")) {
1880
0
    if (rs_val >= rt_val)
1881
0
      target = pc + offset;
1882
0
    else
1883
0
      target = pc + 4;
1884
0
  } else if (op_name.equals_insensitive("BLTUC")) {
1885
0
    if (rs_val < rt_val)
1886
0
      target = pc + offset;
1887
0
    else
1888
0
      target = pc + 4;
1889
0
  } else if (op_name.equals_insensitive("BGEUC")) {
1890
0
    if ((uint32_t)rs_val >= (uint32_t)rt_val)
1891
0
      target = pc + offset;
1892
0
    else
1893
0
      target = pc + 4;
1894
0
  } else if (op_name.equals_insensitive("BOVC")) {
1895
0
    if (IsAdd64bitOverflow(rs_val, rt_val))
1896
0
      target = pc + offset;
1897
0
    else
1898
0
      target = pc + 4;
1899
0
  } else if (op_name.equals_insensitive("BNVC")) {
1900
0
    if (!IsAdd64bitOverflow(rs_val, rt_val))
1901
0
      target = pc + offset;
1902
0
    else
1903
0
      target = pc + 4;
1904
0
  }
1905
1906
0
  Context context;
1907
0
  context.type = eContextRelativeBranchImmediate;
1908
0
  context.SetImmediate(current_inst_size + offset);
1909
1910
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1911
0
                               target);
1912
0
}
1913
1914
/*
1915
    Emulate below MIPS conditional branch and link instructions.
1916
    BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
1917
*/
1918
0
bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) {
1919
0
  bool success = false;
1920
0
  uint32_t rs;
1921
0
  int32_t offset, pc, target = 0;
1922
0
  int32_t rs_val;
1923
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1924
1925
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1926
0
  offset = insn.getOperand(1).getImm();
1927
1928
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1929
0
  if (!success)
1930
0
    return false;
1931
1932
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
1933
0
                                         dwarf_zero_mips + rs, 0, &success);
1934
0
  if (!success)
1935
0
    return false;
1936
1937
0
  if (op_name.equals_insensitive("BLEZALC")) {
1938
0
    if (rs_val <= 0)
1939
0
      target = pc + offset;
1940
0
    else
1941
0
      target = pc + 4;
1942
0
  } else if (op_name.equals_insensitive("BGEZALC")) {
1943
0
    if (rs_val >= 0)
1944
0
      target = pc + offset;
1945
0
    else
1946
0
      target = pc + 4;
1947
0
  } else if (op_name.equals_insensitive("BLTZALC")) {
1948
0
    if (rs_val < 0)
1949
0
      target = pc + offset;
1950
0
    else
1951
0
      target = pc + 4;
1952
0
  } else if (op_name.equals_insensitive("BGTZALC")) {
1953
0
    if (rs_val > 0)
1954
0
      target = pc + offset;
1955
0
    else
1956
0
      target = pc + 4;
1957
0
  } else if (op_name.equals_insensitive("BEQZALC")) {
1958
0
    if (rs_val == 0)
1959
0
      target = pc + offset;
1960
0
    else
1961
0
      target = pc + 4;
1962
0
  } else if (op_name.equals_insensitive("BNEZALC")) {
1963
0
    if (rs_val != 0)
1964
0
      target = pc + offset;
1965
0
    else
1966
0
      target = pc + 4;
1967
0
  }
1968
1969
0
  Context context;
1970
1971
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
1972
0
                             target))
1973
0
    return false;
1974
1975
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
1976
0
                             pc + 4))
1977
0
    return false;
1978
1979
0
  return true;
1980
0
}
1981
1982
/*
1983
    Emulate below MIPS Non-Compact conditional branch and link instructions.
1984
    BLTZAL, BGEZAL      :
1985
    BLTZALL, BGEZALL    : Branch likely
1986
*/
1987
0
bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) {
1988
0
  bool success = false;
1989
0
  uint32_t rs;
1990
0
  int32_t offset, pc, target = 0;
1991
0
  int32_t rs_val;
1992
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
1993
1994
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
1995
0
  offset = insn.getOperand(1).getImm();
1996
1997
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
1998
0
  if (!success)
1999
0
    return false;
2000
2001
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2002
0
                                         dwarf_zero_mips + rs, 0, &success);
2003
0
  if (!success)
2004
0
    return false;
2005
2006
0
  if (op_name.equals_insensitive("BLTZAL") ||
2007
0
      op_name.equals_insensitive("BLTZALL")) {
2008
0
    if ((int32_t)rs_val < 0)
2009
0
      target = pc + offset;
2010
0
    else
2011
0
      target = pc + 8;
2012
0
  } else if (op_name.equals_insensitive("BGEZAL") ||
2013
0
             op_name.equals_insensitive("BGEZALL")) {
2014
0
    if ((int32_t)rs_val >= 0)
2015
0
      target = pc + offset;
2016
0
    else
2017
0
      target = pc + 8;
2018
0
  }
2019
2020
0
  Context context;
2021
2022
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2023
0
                             target))
2024
0
    return false;
2025
2026
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2027
0
                             pc + 8))
2028
0
    return false;
2029
2030
0
  return true;
2031
0
}
2032
2033
/*
2034
    Emulate below MIPS branch instructions.
2035
    BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
2036
    BLTZ, BGEZ, BGTZ, BLEZ     : Non-compact branches
2037
*/
2038
0
bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {
2039
0
  bool success = false;
2040
0
  uint32_t rs;
2041
0
  int32_t offset, pc, target = 0;
2042
0
  int32_t rs_val;
2043
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2044
2045
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2046
0
  offset = insn.getOperand(1).getImm();
2047
2048
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2049
0
  if (!success)
2050
0
    return false;
2051
2052
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2053
0
                                         dwarf_zero_mips + rs, 0, &success);
2054
0
  if (!success)
2055
0
    return false;
2056
2057
0
  if (op_name.equals_insensitive("BLTZL") ||
2058
0
      op_name.equals_insensitive("BLTZ")) {
2059
0
    if (rs_val < 0)
2060
0
      target = pc + offset;
2061
0
    else
2062
0
      target = pc + 8;
2063
0
  } else if (op_name.equals_insensitive("BGEZL") ||
2064
0
             op_name.equals_insensitive("BGEZ")) {
2065
0
    if (rs_val >= 0)
2066
0
      target = pc + offset;
2067
0
    else
2068
0
      target = pc + 8;
2069
0
  } else if (op_name.equals_insensitive("BGTZL") ||
2070
0
             op_name.equals_insensitive("BGTZ")) {
2071
0
    if (rs_val > 0)
2072
0
      target = pc + offset;
2073
0
    else
2074
0
      target = pc + 8;
2075
0
  } else if (op_name.equals_insensitive("BLEZL") ||
2076
0
             op_name.equals_insensitive("BLEZ")) {
2077
0
    if (rs_val <= 0)
2078
0
      target = pc + offset;
2079
0
    else
2080
0
      target = pc + 8;
2081
0
  }
2082
2083
0
  Context context;
2084
0
  context.type = eContextRelativeBranchImmediate;
2085
0
  context.SetImmediate(offset);
2086
2087
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2088
0
                               target);
2089
0
}
2090
2091
/*
2092
    Emulate below MIPS branch instructions.
2093
    BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
2094
*/
2095
0
bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
2096
0
  bool success = false;
2097
0
  uint32_t rs;
2098
0
  int32_t offset, pc, target = 0;
2099
0
  int32_t rs_val;
2100
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2101
0
  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2102
2103
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2104
0
  offset = insn.getOperand(1).getImm();
2105
2106
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2107
0
  if (!success)
2108
0
    return false;
2109
2110
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2111
0
                                         dwarf_zero_mips + rs, 0, &success);
2112
0
  if (!success)
2113
0
    return false;
2114
2115
0
  if (op_name.equals_insensitive("BLTZC")) {
2116
0
    if (rs_val < 0)
2117
0
      target = pc + offset;
2118
0
    else
2119
0
      target = pc + 4;
2120
0
  } else if (op_name.equals_insensitive("BLEZC")) {
2121
0
    if (rs_val <= 0)
2122
0
      target = pc + offset;
2123
0
    else
2124
0
      target = pc + 4;
2125
0
  } else if (op_name.equals_insensitive("BGEZC")) {
2126
0
    if (rs_val >= 0)
2127
0
      target = pc + offset;
2128
0
    else
2129
0
      target = pc + 4;
2130
0
  } else if (op_name.equals_insensitive("BGTZC")) {
2131
0
    if (rs_val > 0)
2132
0
      target = pc + offset;
2133
0
    else
2134
0
      target = pc + 4;
2135
0
  } else if (op_name.equals_insensitive("BEQZC")) {
2136
0
    if (rs_val == 0)
2137
0
      target = pc + offset;
2138
0
    else
2139
0
      target = pc + 4;
2140
0
  } else if (op_name.equals_insensitive("BNEZC")) {
2141
0
    if (rs_val != 0)
2142
0
      target = pc + offset;
2143
0
    else
2144
0
      target = pc + 4;
2145
0
  }
2146
2147
0
  Context context;
2148
0
  context.type = eContextRelativeBranchImmediate;
2149
0
  context.SetImmediate(current_inst_size + offset);
2150
2151
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2152
0
                               target);
2153
0
}
2154
2155
0
bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {
2156
0
  bool success = false;
2157
0
  int32_t offset, pc, target;
2158
0
  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2159
2160
0
  offset = insn.getOperand(0).getImm();
2161
2162
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2163
0
  if (!success)
2164
0
    return false;
2165
2166
  // unconditional branch
2167
0
  target = pc + offset;
2168
2169
0
  Context context;
2170
0
  context.type = eContextRelativeBranchImmediate;
2171
0
  context.SetImmediate(current_inst_size + offset);
2172
2173
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2174
0
                               target);
2175
0
}
2176
2177
/*
2178
   BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
2179
   BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
2180
   BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
2181
*/
2182
0
bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) {
2183
0
  bool success = false;
2184
0
  int32_t target = 0;
2185
0
  uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
2186
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2187
0
  bool update_ra = false;
2188
0
  uint32_t ra_offset = 0;
2189
2190
  /*
2191
   * BEQZ16 rs, offset
2192
   *      condition <- (GPR[rs] = 0)
2193
   *      if condition then
2194
   *          PC = PC + sign_ext (offset || 0)
2195
   *
2196
   * BNEZ16 rs, offset
2197
   *      condition <- (GPR[rs] != 0)
2198
   *      if condition then
2199
   *          PC = PC + sign_ext (offset || 0)
2200
   *
2201
   * BEQZC rs, offset     (compact instruction: No delay slot)
2202
   *      condition <- (GPR[rs] == 0)
2203
   *      if condition then
2204
   *         PC = PC + 4 + sign_ext (offset || 0)
2205
  */
2206
2207
0
  uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2208
0
  int32_t offset = insn.getOperand(1).getImm();
2209
2210
0
  int32_t pc =
2211
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2212
0
  if (!success)
2213
0
    return false;
2214
2215
0
  int32_t rs_val = (int32_t)ReadRegisterUnsigned(
2216
0
      eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
2217
0
  if (!success)
2218
0
    return false;
2219
2220
0
  if (op_name.equals_insensitive("BEQZ16_MM")) {
2221
0
    if (rs_val == 0)
2222
0
      target = pc + offset;
2223
0
    else
2224
0
      target = pc + current_inst_size +
2225
0
               m_next_inst_size; // Skip delay slot instruction.
2226
0
  } else if (op_name.equals_insensitive("BNEZ16_MM")) {
2227
0
    if (rs_val != 0)
2228
0
      target = pc + offset;
2229
0
    else
2230
0
      target = pc + current_inst_size +
2231
0
               m_next_inst_size; // Skip delay slot instruction.
2232
0
  } else if (op_name.equals_insensitive("BEQZC_MM")) {
2233
0
    if (rs_val == 0)
2234
0
      target = pc + 4 + offset;
2235
0
    else
2236
0
      target =
2237
0
          pc +
2238
0
          4; // 32 bit instruction and does not have delay slot instruction.
2239
0
  } else if (op_name.equals_insensitive("BNEZC_MM")) {
2240
0
    if (rs_val != 0)
2241
0
      target = pc + 4 + offset;
2242
0
    else
2243
0
      target =
2244
0
          pc +
2245
0
          4; // 32 bit instruction and does not have delay slot instruction.
2246
0
  } else if (op_name.equals_insensitive("BGEZALS_MM")) {
2247
0
    if (rs_val >= 0)
2248
0
      target = pc + offset;
2249
0
    else
2250
0
      target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2251
2252
0
    update_ra = true;
2253
0
    ra_offset = 6;
2254
0
  } else if (op_name.equals_insensitive("BLTZALS_MM")) {
2255
0
    if (rs_val >= 0)
2256
0
      target = pc + offset;
2257
0
    else
2258
0
      target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
2259
2260
0
    update_ra = true;
2261
0
    ra_offset = 6;
2262
0
  }
2263
2264
0
  Context context;
2265
0
  context.type = eContextRelativeBranchImmediate;
2266
0
  context.SetImmediate(current_inst_size + offset);
2267
2268
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2269
0
                             target))
2270
0
    return false;
2271
2272
0
  if (update_ra) {
2273
0
    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2274
0
                               pc + ra_offset))
2275
0
      return false;
2276
0
  }
2277
0
  return true;
2278
0
}
2279
2280
/* Emulate micromips jump instructions.
2281
   JALR16,JALRS16
2282
*/
2283
0
bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) {
2284
0
  bool success = false;
2285
0
  uint32_t ra_offset = 0;
2286
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2287
2288
0
  uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2289
2290
0
  uint32_t pc =
2291
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2292
0
  if (!success)
2293
0
    return false;
2294
2295
0
  uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF,
2296
0
                                         dwarf_zero_mips + rs, 0, &success);
2297
0
  if (!success)
2298
0
    return false;
2299
2300
0
  if (op_name.equals_insensitive("JALR16_MM"))
2301
0
    ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
2302
0
  else if (op_name.equals_insensitive("JALRS16_MM"))
2303
0
    ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
2304
2305
0
  Context context;
2306
2307
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2308
0
                             rs_val))
2309
0
    return false;
2310
2311
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2312
0
                             pc + ra_offset))
2313
0
    return false;
2314
2315
0
  return true;
2316
0
}
2317
2318
/* Emulate JALS and JALX instructions.
2319
    JALS 32 bit instruction with short (2-byte) delay slot.
2320
    JALX 32 bit instruction with 4-byte delay slot.
2321
*/
2322
0
bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) {
2323
0
  bool success = false;
2324
0
  uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0;
2325
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2326
2327
  /*
2328
   * JALS target
2329
   *      RA = PC + 6
2330
   *      offset = sign_ext (offset << 1)
2331
   *      PC = PC[31-27] | offset
2332
   * JALX target
2333
   *      RA = PC + 8
2334
   *      offset = sign_ext (offset << 2)
2335
   *      PC = PC[31-28] | offset
2336
  */
2337
0
  offset = insn.getOperand(0).getImm();
2338
2339
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2340
0
  if (!success)
2341
0
    return false;
2342
2343
  // These are PC-region branches and not PC-relative.
2344
0
  if (op_name.equals_insensitive("JALS_MM")) {
2345
    // target address is in the “current” 128 MB-aligned region
2346
0
    target = (pc & 0xF8000000UL) | offset;
2347
0
    ra_offset = 6;
2348
0
  } else if (op_name.equals_insensitive("JALX_MM")) {
2349
    // target address is in the “current” 256 MB-aligned region
2350
0
    target = (pc & 0xF0000000UL) | offset;
2351
0
    ra_offset = 8;
2352
0
  }
2353
2354
0
  Context context;
2355
2356
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2357
0
                             target))
2358
0
    return false;
2359
2360
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2361
0
                             pc + ra_offset))
2362
0
    return false;
2363
2364
0
  return true;
2365
0
}
2366
2367
0
bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) {
2368
0
  bool success = false;
2369
0
  uint32_t rs = 0, rt = 0;
2370
0
  int32_t pc = 0, rs_val = 0;
2371
2372
  /*
2373
      JALRS rt, rs
2374
          GPR[rt] <- PC + 6
2375
          PC <- GPR[rs]
2376
  */
2377
2378
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2379
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2380
2381
0
  rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2382
0
                                         dwarf_zero_mips + rs, 0, &success);
2383
0
  if (!success)
2384
0
    return false;
2385
2386
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2387
0
  if (!success)
2388
0
    return false;
2389
2390
0
  Context context;
2391
2392
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2393
0
                             rs_val))
2394
0
    return false;
2395
2396
  // This is 4-byte instruction with 2-byte delay slot.
2397
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2398
0
                             pc + 6))
2399
0
    return false;
2400
2401
0
  return true;
2402
0
}
2403
2404
0
bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) {
2405
0
  bool success = false;
2406
0
  int32_t offset, pc, target;
2407
2408
  /*
2409
   * BAL offset
2410
   *      offset = sign_ext (offset << 2)
2411
   *      RA = PC + 8
2412
   *      PC = PC + offset
2413
  */
2414
0
  offset = insn.getOperand(0).getImm();
2415
2416
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2417
0
  if (!success)
2418
0
    return false;
2419
2420
0
  target = pc + offset;
2421
2422
0
  Context context;
2423
2424
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2425
0
                             target))
2426
0
    return false;
2427
2428
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2429
0
                             pc + 8))
2430
0
    return false;
2431
2432
0
  return true;
2433
0
}
2434
2435
0
bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) {
2436
0
  bool success = false;
2437
0
  int32_t offset, pc, target;
2438
2439
  /*
2440
   * BALC offset
2441
   *      offset = sign_ext (offset << 2)
2442
   *      RA = PC + 4
2443
   *      PC = PC + 4 + offset
2444
  */
2445
0
  offset = insn.getOperand(0).getImm();
2446
2447
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2448
0
  if (!success)
2449
0
    return false;
2450
2451
0
  target = pc + offset;
2452
2453
0
  Context context;
2454
2455
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2456
0
                             target))
2457
0
    return false;
2458
2459
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2460
0
                             pc + 4))
2461
0
    return false;
2462
2463
0
  return true;
2464
0
}
2465
2466
0
bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
2467
0
  bool success = false;
2468
0
  int32_t offset, pc, target;
2469
2470
  /*
2471
   * BC offset
2472
   *      offset = sign_ext (offset << 2)
2473
   *      PC = PC + 4 + offset
2474
  */
2475
0
  offset = insn.getOperand(0).getImm();
2476
2477
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2478
0
  if (!success)
2479
0
    return false;
2480
2481
0
  target = pc + offset;
2482
2483
0
  Context context;
2484
2485
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2486
0
                               target);
2487
0
}
2488
2489
0
bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
2490
0
  bool success = false;
2491
0
  uint32_t offset, pc;
2492
2493
  /*
2494
   * J offset
2495
   *      offset = sign_ext (offset << 2)
2496
   *      PC = PC[63-28] | offset
2497
  */
2498
0
  offset = insn.getOperand(0).getImm();
2499
2500
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2501
0
  if (!success)
2502
0
    return false;
2503
2504
  /* This is a PC-region branch and not PC-relative */
2505
0
  pc = (pc & 0xF0000000UL) | offset;
2506
2507
0
  Context context;
2508
2509
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);
2510
0
}
2511
2512
0
bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
2513
0
  bool success = false;
2514
0
  uint32_t offset, target, pc;
2515
2516
  /*
2517
   * JAL offset
2518
   *      offset = sign_ext (offset << 2)
2519
   *      PC = PC[63-28] | offset
2520
  */
2521
0
  offset = insn.getOperand(0).getImm();
2522
2523
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2524
0
  if (!success)
2525
0
    return false;
2526
2527
  /* This is a PC-region branch and not PC-relative */
2528
0
  target = (pc & 0xF0000000UL) | offset;
2529
2530
0
  Context context;
2531
2532
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2533
0
                             target))
2534
0
    return false;
2535
2536
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2537
0
                             pc + 8))
2538
0
    return false;
2539
2540
0
  return true;
2541
0
}
2542
2543
0
bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) {
2544
0
  bool success = false;
2545
0
  uint32_t rs, rt;
2546
0
  uint32_t pc, rs_val;
2547
2548
  /*
2549
   * JALR rt, rs
2550
   *      GPR[rt] = PC + 8
2551
   *      PC = GPR[rs]
2552
  */
2553
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2554
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
2555
2556
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2557
0
  if (!success)
2558
0
    return false;
2559
2560
0
  rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2561
0
                                &success);
2562
0
  if (!success)
2563
0
    return false;
2564
2565
0
  Context context;
2566
2567
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2568
0
                             rs_val))
2569
0
    return false;
2570
2571
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
2572
0
                             pc + 8))
2573
0
    return false;
2574
2575
0
  return true;
2576
0
}
2577
2578
0
bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) {
2579
0
  bool success = false;
2580
0
  uint32_t rt;
2581
0
  int32_t target, offset, pc, rt_val;
2582
2583
  /*
2584
   * JIALC rt, offset
2585
   *      offset = sign_ext (offset)
2586
   *      PC = GPR[rt] + offset
2587
   *      RA = PC + 4
2588
  */
2589
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2590
0
  offset = insn.getOperand(1).getImm();
2591
2592
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2593
0
  if (!success)
2594
0
    return false;
2595
2596
0
  rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2597
0
                                         dwarf_zero_mips + rt, 0, &success);
2598
0
  if (!success)
2599
0
    return false;
2600
2601
0
  target = rt_val + offset;
2602
2603
0
  Context context;
2604
2605
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2606
0
                             target))
2607
0
    return false;
2608
2609
0
  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips,
2610
0
                             pc + 4))
2611
0
    return false;
2612
2613
0
  return true;
2614
0
}
2615
2616
0
bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
2617
0
  bool success = false;
2618
0
  uint32_t rt;
2619
0
  int32_t target, offset, rt_val;
2620
2621
  /*
2622
   * JIC rt, offset
2623
   *      offset = sign_ext (offset)
2624
   *      PC = GPR[rt] + offset
2625
  */
2626
0
  rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2627
0
  offset = insn.getOperand(1).getImm();
2628
2629
0
  rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2630
0
                                         dwarf_zero_mips + rt, 0, &success);
2631
0
  if (!success)
2632
0
    return false;
2633
2634
0
  target = rt_val + offset;
2635
2636
0
  Context context;
2637
2638
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2639
0
                               target);
2640
0
}
2641
2642
0
bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
2643
0
  bool success = false;
2644
0
  uint32_t rs;
2645
0
  uint32_t rs_val;
2646
2647
  /*
2648
   * JR rs
2649
   *      PC = GPR[rs]
2650
  */
2651
0
  rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2652
2653
0
  rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0,
2654
0
                                &success);
2655
0
  if (!success)
2656
0
    return false;
2657
2658
0
  Context context;
2659
2660
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2661
0
                               rs_val);
2662
0
}
2663
2664
/*
2665
    Emulate Branch on FP True/False
2666
    BC1F, BC1FL :   Branch on FP False (L stands for branch likely)
2667
    BC1T, BC1TL :   Branch on FP True  (L stands for branch likely)
2668
*/
2669
0
bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {
2670
0
  bool success = false;
2671
0
  uint32_t cc, fcsr;
2672
0
  int32_t pc, offset, target = 0;
2673
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2674
2675
0
  cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2676
0
  offset = insn.getOperand(1).getImm();
2677
2678
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2679
0
  if (!success)
2680
0
    return false;
2681
2682
0
  fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
2683
0
  if (!success)
2684
0
    return false;
2685
2686
  /* fcsr[23], fcsr[25-31] are vaild condition bits */
2687
0
  fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2688
2689
0
  if (op_name.equals_insensitive("BC1F") ||
2690
0
      op_name.equals_insensitive("BC1FL")) {
2691
0
    if ((fcsr & (1 << cc)) == 0)
2692
0
      target = pc + offset;
2693
0
    else
2694
0
      target = pc + 8;
2695
0
  } else if (op_name.equals_insensitive("BC1T") ||
2696
0
             op_name.equals_insensitive("BC1TL")) {
2697
0
    if ((fcsr & (1 << cc)) != 0)
2698
0
      target = pc + offset;
2699
0
    else
2700
0
      target = pc + 8;
2701
0
  }
2702
0
  Context context;
2703
2704
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2705
0
                               target);
2706
0
}
2707
2708
0
bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {
2709
0
  bool success = false;
2710
0
  uint32_t ft;
2711
0
  uint32_t ft_val;
2712
0
  int32_t target, pc, offset;
2713
2714
  /*
2715
   * BC1EQZ ft, offset
2716
   *  condition <- (FPR[ft].bit0 == 0)
2717
   *      if condition then
2718
   *          offset = sign_ext (offset)
2719
   *          PC = PC + 4 + offset
2720
  */
2721
0
  ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2722
0
  offset = insn.getOperand(1).getImm();
2723
2724
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2725
0
  if (!success)
2726
0
    return false;
2727
2728
0
  ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2729
0
                                &success);
2730
0
  if (!success)
2731
0
    return false;
2732
2733
0
  if ((ft_val & 1) == 0)
2734
0
    target = pc + 4 + offset;
2735
0
  else
2736
0
    target = pc + 8;
2737
2738
0
  Context context;
2739
2740
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2741
0
                               target);
2742
0
}
2743
2744
0
bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {
2745
0
  bool success = false;
2746
0
  uint32_t ft;
2747
0
  uint32_t ft_val;
2748
0
  int32_t target, pc, offset;
2749
2750
  /*
2751
   * BC1NEZ ft, offset
2752
   *  condition <- (FPR[ft].bit0 != 0)
2753
   *      if condition then
2754
   *          offset = sign_ext (offset)
2755
   *          PC = PC + 4 + offset
2756
  */
2757
0
  ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2758
0
  offset = insn.getOperand(1).getImm();
2759
2760
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2761
0
  if (!success)
2762
0
    return false;
2763
2764
0
  ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0,
2765
0
                                &success);
2766
0
  if (!success)
2767
0
    return false;
2768
2769
0
  if ((ft_val & 1) != 0)
2770
0
    target = pc + 4 + offset;
2771
0
  else
2772
0
    target = pc + 8;
2773
2774
0
  Context context;
2775
2776
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2777
0
                               target);
2778
0
}
2779
2780
/*
2781
    Emulate MIPS-3D Branch instructions
2782
    BC1ANY2F, BC1ANY2T  : Branch on Any of Two Floating Point Condition Codes
2783
   False/True
2784
    BC1ANY4F, BC1ANY4T  : Branch on Any of Four Floating Point Condition Codes
2785
   False/True
2786
*/
2787
0
bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {
2788
0
  bool success = false;
2789
0
  uint32_t cc, fcsr;
2790
0
  int32_t pc, offset, target = 0;
2791
0
  llvm::StringRef op_name = m_insn_info->getName(insn.getOpcode());
2792
2793
0
  cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2794
0
  offset = insn.getOperand(1).getImm();
2795
2796
0
  pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2797
0
  if (!success)
2798
0
    return false;
2799
2800
0
  fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0,
2801
0
                                        &success);
2802
0
  if (!success)
2803
0
    return false;
2804
2805
  /* fcsr[23], fcsr[25-31] are vaild condition bits */
2806
0
  fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
2807
2808
0
  if (op_name.equals_insensitive("BC1ANY2F")) {
2809
    /* if any one bit is 0 */
2810
0
    if (((fcsr >> cc) & 3) != 3)
2811
0
      target = pc + offset;
2812
0
    else
2813
0
      target = pc + 8;
2814
0
  } else if (op_name.equals_insensitive("BC1ANY2T")) {
2815
    /* if any one bit is 1 */
2816
0
    if (((fcsr >> cc) & 3) != 0)
2817
0
      target = pc + offset;
2818
0
    else
2819
0
      target = pc + 8;
2820
0
  } else if (op_name.equals_insensitive("BC1ANY4F")) {
2821
    /* if any one bit is 0 */
2822
0
    if (((fcsr >> cc) & 0xf) != 0xf)
2823
0
      target = pc + offset;
2824
0
    else
2825
0
      target = pc + 8;
2826
0
  } else if (op_name.equals_insensitive("BC1ANY4T")) {
2827
    /* if any one bit is 1 */
2828
0
    if (((fcsr >> cc) & 0xf) != 0)
2829
0
      target = pc + offset;
2830
0
    else
2831
0
      target = pc + 8;
2832
0
  }
2833
0
  Context context;
2834
2835
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2836
0
                               target);
2837
0
}
2838
2839
0
bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {
2840
0
  return Emulate_MSA_Branch_DF(insn, 1, true);
2841
0
}
2842
2843
0
bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) {
2844
0
  return Emulate_MSA_Branch_DF(insn, 2, true);
2845
0
}
2846
2847
0
bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) {
2848
0
  return Emulate_MSA_Branch_DF(insn, 4, true);
2849
0
}
2850
2851
0
bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) {
2852
0
  return Emulate_MSA_Branch_DF(insn, 8, true);
2853
0
}
2854
2855
0
bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) {
2856
0
  return Emulate_MSA_Branch_DF(insn, 1, false);
2857
0
}
2858
2859
0
bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) {
2860
0
  return Emulate_MSA_Branch_DF(insn, 2, false);
2861
0
}
2862
2863
0
bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) {
2864
0
  return Emulate_MSA_Branch_DF(insn, 4, false);
2865
0
}
2866
2867
0
bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) {
2868
0
  return Emulate_MSA_Branch_DF(insn, 8, false);
2869
0
}
2870
2871
bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
2872
                                                   int element_byte_size,
2873
0
                                                   bool bnz) {
2874
0
  bool success = false, branch_hit = true;
2875
0
  int32_t target = 0;
2876
0
  RegisterValue reg_value;
2877
0
  const uint8_t *ptr = nullptr;
2878
2879
0
  uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2880
0
  int32_t offset = insn.getOperand(1).getImm();
2881
2882
0
  int32_t pc =
2883
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2884
0
  if (!success)
2885
0
    return false;
2886
2887
0
  if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2888
0
    ptr = (const uint8_t *)reg_value.GetBytes();
2889
0
  else
2890
0
    return false;
2891
2892
0
  for (int i = 0; i < 16 / element_byte_size; i++) {
2893
0
    switch (element_byte_size) {
2894
0
    case 1:
2895
0
      if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz))
2896
0
        branch_hit = false;
2897
0
      break;
2898
0
    case 2:
2899
0
      if ((*(const uint16_t *)ptr == 0 && bnz) ||
2900
0
          (*(const uint16_t *)ptr != 0 && !bnz))
2901
0
        branch_hit = false;
2902
0
      break;
2903
0
    case 4:
2904
0
      if ((*(const uint32_t *)ptr == 0 && bnz) ||
2905
0
          (*(const uint32_t *)ptr != 0 && !bnz))
2906
0
        branch_hit = false;
2907
0
      break;
2908
0
    case 8:
2909
0
      if ((*(const uint64_t *)ptr == 0 && bnz) ||
2910
0
          (*(const uint64_t *)ptr != 0 && !bnz))
2911
0
        branch_hit = false;
2912
0
      break;
2913
0
    }
2914
0
    if (!branch_hit)
2915
0
      break;
2916
0
    ptr = ptr + element_byte_size;
2917
0
  }
2918
2919
0
  if (branch_hit)
2920
0
    target = pc + offset;
2921
0
  else
2922
0
    target = pc + 8;
2923
2924
0
  Context context;
2925
0
  context.type = eContextRelativeBranchImmediate;
2926
2927
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2928
0
                               target);
2929
0
}
2930
2931
0
bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {
2932
0
  return Emulate_MSA_Branch_V(insn, true);
2933
0
}
2934
2935
0
bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) {
2936
0
  return Emulate_MSA_Branch_V(insn, false);
2937
0
}
2938
2939
bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,
2940
0
                                                  bool bnz) {
2941
0
  bool success = false;
2942
0
  int32_t target = 0;
2943
0
  llvm::APInt wr_val = llvm::APInt::getZero(128);
2944
0
  llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
2945
0
  llvm::APInt zero_value = llvm::APInt::getZero(128);
2946
0
  RegisterValue reg_value;
2947
2948
0
  uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
2949
0
  int32_t offset = insn.getOperand(1).getImm();
2950
2951
0
  int32_t pc =
2952
0
      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
2953
0
  if (!success)
2954
0
    return false;
2955
2956
0
  if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
2957
0
    wr_val = reg_value.GetAsUInt128(fail_value);
2958
0
  else
2959
0
    return false;
2960
2961
0
  if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) ||
2962
0
      (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
2963
0
    target = pc + offset;
2964
0
  else
2965
0
    target = pc + 8;
2966
2967
0
  Context context;
2968
0
  context.type = eContextRelativeBranchImmediate;
2969
2970
0
  return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
2971
0
                               target);
2972
0
}
2973
2974
0
bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {
2975
0
  bool success = false;
2976
0
  uint32_t base;
2977
0
  int32_t imm, address;
2978
0
  Context bad_vaddr_context;
2979
2980
0
  uint32_t num_operands = insn.getNumOperands();
2981
0
  base =
2982
0
      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
2983
0
  imm = insn.getOperand(num_operands - 1).getImm();
2984
2985
0
  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
2986
0
    return false;
2987
2988
  /* read base register */
2989
0
  address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
2990
0
                                          dwarf_zero_mips + base, 0, &success);
2991
0
  if (!success)
2992
0
    return false;
2993
2994
  /* destination address */
2995
0
  address = address + imm;
2996
2997
  /* Set the bad_vaddr register with base address used in the instruction */
2998
0
  bad_vaddr_context.type = eContextInvalid;
2999
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
3000
0
                        address);
3001
3002
0
  return true;
3003
0
}
3004
3005
0
bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) {
3006
0
  bool success = false;
3007
0
  uint32_t base, index;
3008
0
  int32_t address, index_address;
3009
0
  Context bad_vaddr_context;
3010
3011
0
  uint32_t num_operands = insn.getNumOperands();
3012
0
  base =
3013
0
      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg());
3014
0
  index =
3015
0
      m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg());
3016
3017
0
  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base))
3018
0
    return false;
3019
3020
0
  if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index))
3021
0
    return false;
3022
3023
  /* read base register */
3024
0
  address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF,
3025
0
                                          dwarf_zero_mips + base, 0, &success);
3026
0
  if (!success)
3027
0
    return false;
3028
3029
  /* read index register */
3030
0
  index_address = (int32_t)ReadRegisterUnsigned(
3031
0
      eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
3032
0
  if (!success)
3033
0
    return false;
3034
3035
  /* destination address */
3036
0
  address = address + index_address;
3037
3038
  /* Set the bad_vaddr register with base address used in the instruction */
3039
0
  bad_vaddr_context.type = eContextInvalid;
3040
0
  WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
3041
0
                        address);
3042
3043
0
  return true;
3044
0
}