Coverage Report

Created: 2022-01-25 06:29

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