Coverage Report

Created: 2024-09-08 06:22

/src/capstonenext/arch/Mips/MipsInstPrinter.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
3
/*    Rot127 <unisono@quyllur.org> 2022-2023 */
4
/* Automatically translated source file from LLVM. */
5
6
/* LLVM-commit: <commit> */
7
/* LLVM-tag: <tag> */
8
9
/* Only small edits allowed. */
10
/* For multiple similar edits, please create a Patch for the translator. */
11
12
/* Capstone's C++ file translator: */
13
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
14
15
//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
16
//
17
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
18
// See https://llvm.org/LICENSE.txt for license information.
19
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
20
//
21
//===----------------------------------------------------------------------===//
22
//
23
// This class prints an Mips MCInst to a .s file.
24
//
25
//===----------------------------------------------------------------------===//
26
27
#include <stdio.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <capstone/platform.h>
31
32
#include "MipsMapping.h"
33
#include "MipsInstPrinter.h"
34
35
#define GET_SUBTARGETINFO_ENUM
36
#include "MipsGenSubtargetInfo.inc"
37
38
#define GET_INSTRINFO_ENUM
39
#include "MipsGenInstrInfo.inc"
40
41
#define GET_REGINFO_ENUM
42
#include "MipsGenRegisterInfo.inc"
43
44
13.7k
#define CONCAT(a, b) CONCAT_(a, b)
45
13.7k
#define CONCAT_(a, b) a##_##b
46
47
#define DEBUG_TYPE "asm-printer"
48
49
#define PRINT_ALIAS_INSTR
50
#include "MipsGenAsmWriter.inc"
51
52
static bool isReg(const MCInst *MI, unsigned OpNo, unsigned R)
53
4.83k
{
54
4.83k
  return MCOperand_getReg(MCInst_getOperand((MCInst *)MI, (OpNo))) == R;
55
4.83k
}
56
57
static const char *MipsFCCToString(Mips_CondCode CC)
58
0
{
59
0
  switch (CC) {
60
0
  case Mips_FCOND_F:
61
0
  case Mips_FCOND_T:
62
0
    return "f";
63
0
  case Mips_FCOND_UN:
64
0
  case Mips_FCOND_OR:
65
0
    return "un";
66
0
  case Mips_FCOND_OEQ:
67
0
  case Mips_FCOND_UNE:
68
0
    return "eq";
69
0
  case Mips_FCOND_UEQ:
70
0
  case Mips_FCOND_ONE:
71
0
    return "ueq";
72
0
  case Mips_FCOND_OLT:
73
0
  case Mips_FCOND_UGE:
74
0
    return "olt";
75
0
  case Mips_FCOND_ULT:
76
0
  case Mips_FCOND_OGE:
77
0
    return "ult";
78
0
  case Mips_FCOND_OLE:
79
0
  case Mips_FCOND_UGT:
80
0
    return "ole";
81
0
  case Mips_FCOND_ULE:
82
0
  case Mips_FCOND_OGT:
83
0
    return "ule";
84
0
  case Mips_FCOND_SF:
85
0
  case Mips_FCOND_ST:
86
0
    return "sf";
87
0
  case Mips_FCOND_NGLE:
88
0
  case Mips_FCOND_GLE:
89
0
    return "ngle";
90
0
  case Mips_FCOND_SEQ:
91
0
  case Mips_FCOND_SNE:
92
0
    return "seq";
93
0
  case Mips_FCOND_NGL:
94
0
  case Mips_FCOND_GL:
95
0
    return "ngl";
96
0
  case Mips_FCOND_LT:
97
0
  case Mips_FCOND_NLT:
98
0
    return "lt";
99
0
  case Mips_FCOND_NGE:
100
0
  case Mips_FCOND_GE:
101
0
    return "nge";
102
0
  case Mips_FCOND_LE:
103
0
  case Mips_FCOND_NLE:
104
0
    return "le";
105
0
  case Mips_FCOND_NGT:
106
0
  case Mips_FCOND_GT:
107
0
    return "ngt";
108
0
  }
109
0
  assert(0 && "Impossible condition code!");
110
0
  return "";
111
0
}
112
113
const char *Mips_LLVM_getRegisterName(unsigned RegNo, bool noRegName);
114
115
static void printRegName(MCInst *MI, SStream *OS, MCRegister Reg)
116
117k
{
117
117k
  int syntax_opt = MI->csh->syntax;
118
117k
  if (!(syntax_opt & CS_OPT_SYNTAX_NO_DOLLAR)) {
119
117k
    SStream_concat1(OS, '$');
120
117k
  }
121
117k
  SStream_concat0(OS, Mips_LLVM_getRegisterName(Reg, syntax_opt & CS_OPT_SYNTAX_NOREGNAME));
122
117k
}
123
124
67.9k
void Mips_LLVM_printInst(MCInst *MI, uint64_t Address, SStream *O) {
125
67.9k
  bool useAliasDetails = map_use_alias_details(MI);
126
67.9k
  if (!useAliasDetails) {
127
0
    SStream_Close(O);
128
0
    printInstruction(MI, Address, O);
129
0
    SStream_Open(O);
130
0
    map_set_fill_detail_ops(MI, false);
131
0
  }
132
133
67.9k
  if (printAliasInstr(MI, Address, O) ||
134
67.9k
    printAlias4(MI, Address, O)) {
135
5.94k
    MCInst_setIsAlias(MI, true);
136
62.0k
  } else {
137
62.0k
    printInstruction(MI, Address, O);
138
62.0k
  }
139
140
67.9k
  if (!useAliasDetails) {
141
0
    map_set_fill_detail_ops(MI, true);
142
0
  }
143
67.9k
}
144
145
void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
146
140k
{
147
140k
  switch (MCInst_getOpcode(MI)) {
148
140k
  default:
149
140k
    break;
150
140k
  case Mips_AND16_NM:
151
0
  case Mips_XOR16_NM:
152
0
  case Mips_OR16_NM:
153
0
    if (MCInst_getNumOperands(MI) == 2 && OpNo == 2)
154
0
      OpNo = 0; // rt, rs -> rt, rs, rt
155
0
    break;
156
0
  case Mips_ADDu4x4_NM:
157
0
  case Mips_MUL4x4_NM:
158
0
    if (MCInst_getNumOperands(MI) == 2 && OpNo > 0)
159
0
      OpNo = OpNo - 1; // rt, rs -> rt, rt, rs
160
0
    break;
161
140k
  }
162
163
140k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
164
140k
  if (MCOperand_isReg(Op)) {
165
115k
    add_cs_detail(MI, Mips_OP_GROUP_Operand, OpNo);
166
115k
    printRegName(MI, O, MCOperand_getReg(Op));
167
115k
    return;
168
115k
  }
169
170
171
24.7k
  if (MCOperand_isImm(Op)) {
172
24.7k
    switch (MCInst_getOpcode(MI)) {
173
0
    case Mips_LI48_NM:
174
0
    case Mips_ANDI16_NM:
175
0
    case Mips_ANDI_NM:
176
0
    case Mips_ORI_NM:
177
0
    case Mips_XORI_NM:
178
0
    case Mips_TEQ_NM:
179
0
    case Mips_TNE_NM:
180
0
    case Mips_SIGRIE_NM:
181
0
    case Mips_SDBBP_NM:
182
0
    case Mips_SDBBP16_NM:
183
0
    case Mips_BREAK_NM:
184
0
    case Mips_BREAK16_NM:
185
0
    case Mips_SYSCALL_NM:
186
0
    case Mips_SYSCALL16_NM:
187
0
    case Mips_WAIT_NM:
188
0
      CONCAT(printUImm, CONCAT(32, 0))
189
0
      (MI, OpNo, O);
190
0
      break;
191
24.7k
    default:
192
24.7k
      add_cs_detail(MI, Mips_OP_GROUP_Operand, OpNo);
193
24.7k
      printInt64(O, MCOperand_getImm(Op));
194
24.7k
      break;
195
24.7k
    }
196
24.7k
    return;
197
24.7k
  }
198
24.7k
}
199
200
static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O)
201
1.95k
{
202
1.95k
  add_cs_detail(MI, Mips_OP_GROUP_JumpOperand, OpNo);
203
1.95k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
204
1.95k
  if (MCOperand_isReg(Op))
205
0
    return printRegName(MI, O, MCOperand_getReg(Op));
206
207
1.95k
  printInt64(O, MCOperand_getImm(Op));
208
1.95k
}
209
210
static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O)
211
12.1k
{
212
12.1k
  add_cs_detail(MI, Mips_OP_GROUP_BranchOperand, OpNo);
213
12.1k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
214
12.1k
  if (MCOperand_isReg(Op))
215
267
    return printRegName(MI, O, MCOperand_getReg(Op));
216
217
11.8k
    uint64_t Target = Address + MCOperand_getImm(Op);
218
11.8k
  printInt64(O, Target);
219
11.8k
}
220
221
#define DEFINE_printUImm(Bits) \
222
  static void CONCAT(printUImm, CONCAT(Bits, 0))(MCInst * MI, int opNum, \
223
                 SStream *O) \
224
12.9k
  { \
225
12.9k
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
12.9k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
12.9k
    if (MCOperand_isImm(MO)) { \
228
12.9k
      uint64_t Imm = MCOperand_getImm(MO); \
229
12.9k
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
12.9k
      printUInt64(O, Imm); \
231
12.9k
      return; \
232
12.9k
    } \
233
12.9k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_10_0
Line
Count
Source
224
1.80k
  { \
225
1.80k
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
1.80k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
1.80k
    if (MCOperand_isImm(MO)) { \
228
1.80k
      uint64_t Imm = MCOperand_getImm(MO); \
229
1.80k
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
1.80k
      printUInt64(O, Imm); \
231
1.80k
      return; \
232
1.80k
    } \
233
1.80k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_4_0
Line
Count
Source
224
850
  { \
225
850
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
850
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
850
    if (MCOperand_isImm(MO)) { \
228
850
      uint64_t Imm = MCOperand_getImm(MO); \
229
850
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
850
      printUInt64(O, Imm); \
231
850
      return; \
232
850
    } \
233
850
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_5_0
Line
Count
Source
224
3.61k
  { \
225
3.61k
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
3.61k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
3.61k
    if (MCOperand_isImm(MO)) { \
228
3.61k
      uint64_t Imm = MCOperand_getImm(MO); \
229
3.61k
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
3.61k
      printUInt64(O, Imm); \
231
3.61k
      return; \
232
3.61k
    } \
233
3.61k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_26_0
MipsInstPrinter.c:printUImm_8_0
Line
Count
Source
224
377
  { \
225
377
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
377
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
377
    if (MCOperand_isImm(MO)) { \
228
377
      uint64_t Imm = MCOperand_getImm(MO); \
229
377
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
377
      printUInt64(O, Imm); \
231
377
      return; \
232
377
    } \
233
377
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_12_0
MipsInstPrinter.c:printUImm_20_0
Line
Count
Source
224
317
  { \
225
317
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
317
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
317
    if (MCOperand_isImm(MO)) { \
228
317
      uint64_t Imm = MCOperand_getImm(MO); \
229
317
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
317
      printUInt64(O, Imm); \
231
317
      return; \
232
317
    } \
233
317
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_16_0
Line
Count
Source
224
4.02k
  { \
225
4.02k
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
4.02k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
4.02k
    if (MCOperand_isImm(MO)) { \
228
4.02k
      uint64_t Imm = MCOperand_getImm(MO); \
229
4.02k
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
4.02k
      printUInt64(O, Imm); \
231
4.02k
      return; \
232
4.02k
    } \
233
4.02k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_32_0
Unexecuted instantiation: MipsInstPrinter.c:printUImm_7_0
MipsInstPrinter.c:printUImm_2_0
Line
Count
Source
224
218
  { \
225
218
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
218
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
218
    if (MCOperand_isImm(MO)) { \
228
218
      uint64_t Imm = MCOperand_getImm(MO); \
229
218
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
218
      printUInt64(O, Imm); \
231
218
      return; \
232
218
    } \
233
218
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_1_0
Line
Count
Source
224
244
  { \
225
244
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
244
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
244
    if (MCOperand_isImm(MO)) { \
228
244
      uint64_t Imm = MCOperand_getImm(MO); \
229
244
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
244
      printUInt64(O, Imm); \
231
244
      return; \
232
244
    } \
233
244
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_3_0
Line
Count
Source
224
1.11k
  { \
225
1.11k
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
1.11k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
1.11k
    if (MCOperand_isImm(MO)) { \
228
1.11k
      uint64_t Imm = MCOperand_getImm(MO); \
229
1.11k
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
1.11k
      printUInt64(O, Imm); \
231
1.11k
      return; \
232
1.11k
    } \
233
1.11k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_0_0
Line
Count
Source
224
83
  { \
225
83
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
83
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
83
    if (MCOperand_isImm(MO)) { \
228
83
      uint64_t Imm = MCOperand_getImm(MO); \
229
83
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
83
      printUInt64(O, Imm); \
231
83
      return; \
232
83
    } \
233
83
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
MipsInstPrinter.c:printUImm_6_0
Line
Count
Source
224
278
  { \
225
278
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), opNum); \
226
278
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
227
278
    if (MCOperand_isImm(MO)) { \
228
278
      uint64_t Imm = MCOperand_getImm(MO); \
229
278
      Imm &= (((uint64_t)1) << Bits) - 1; \
230
278
      printUInt64(O, Imm); \
231
278
      return; \
232
278
    } \
233
278
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
234
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
235
0
  }
236
237
#define DEFINE_printUImm_2(Bits, Offset) \
238
  static void CONCAT(printUImm, CONCAT(Bits, Offset))(MCInst * MI, int opNum, \
239
                 SStream *O) \
240
856
  { \
241
856
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
242
856
            opNum); \
243
856
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
244
856
    if (MCOperand_isImm(MO)) { \
245
856
      uint64_t Imm = MCOperand_getImm(MO); \
246
856
      Imm -= Offset; \
247
856
      Imm &= (1 << Bits) - 1; \
248
856
      Imm += Offset; \
249
856
      printUInt64(O, Imm); \
250
856
      return; \
251
856
    } \
252
856
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
253
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
254
0
  }
MipsInstPrinter.c:printUImm_2_1
Line
Count
Source
240
535
  { \
241
535
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
242
535
            opNum); \
243
535
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
244
535
    if (MCOperand_isImm(MO)) { \
245
535
      uint64_t Imm = MCOperand_getImm(MO); \
246
535
      Imm -= Offset; \
247
535
      Imm &= (1 << Bits) - 1; \
248
535
      Imm += Offset; \
249
535
      printUInt64(O, Imm); \
250
535
      return; \
251
535
    } \
252
535
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
253
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
254
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_5_32
MipsInstPrinter.c:printUImm_5_1
Line
Count
Source
240
321
  { \
241
321
    add_cs_detail(MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
242
321
            opNum); \
243
321
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
244
321
    if (MCOperand_isImm(MO)) { \
245
321
      uint64_t Imm = MCOperand_getImm(MO); \
246
321
      Imm -= Offset; \
247
321
      Imm &= (1 << Bits) - 1; \
248
321
      Imm += Offset; \
249
321
      printUInt64(O, Imm); \
250
321
      return; \
251
321
    } \
252
321
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
253
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
254
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_6_1
Unexecuted instantiation: MipsInstPrinter.c:printUImm_5_33
Unexecuted instantiation: MipsInstPrinter.c:printUImm_6_2
255
256
DEFINE_printUImm(0);
257
DEFINE_printUImm(1);
258
DEFINE_printUImm(10);
259
DEFINE_printUImm(12);
260
DEFINE_printUImm(16);
261
DEFINE_printUImm(2);
262
DEFINE_printUImm(20);
263
DEFINE_printUImm(26);
264
DEFINE_printUImm(3);
265
DEFINE_printUImm(32);
266
DEFINE_printUImm(4);
267
DEFINE_printUImm(5);
268
DEFINE_printUImm(6);
269
DEFINE_printUImm(7);
270
DEFINE_printUImm(8);
271
DEFINE_printUImm_2(2, 1);
272
DEFINE_printUImm_2(5, 1);
273
DEFINE_printUImm_2(5, 32);
274
DEFINE_printUImm_2(5, 33);
275
DEFINE_printUImm_2(6, 1);
276
DEFINE_printUImm_2(6, 2);
277
278
static void printMemOperand(MCInst *MI, int opNum, SStream *O)
279
16.4k
{
280
  // Load/Store memory operands -- imm($reg)
281
  // If PIC target the target is loaded as the
282
  // pattern lw $25,%call16($28)
283
284
  // opNum can be invalid if instruction had reglist as operand.
285
  // MemOperand is always last operand of instruction (base + offset).
286
16.4k
  switch (MCInst_getOpcode(MI)) {
287
15.9k
  default:
288
15.9k
    break;
289
15.9k
  case Mips_SWM32_MM:
290
287
  case Mips_LWM32_MM:
291
325
  case Mips_SWM16_MM:
292
325
  case Mips_SWM16_MMR6:
293
462
  case Mips_LWM16_MM:
294
464
  case Mips_LWM16_MMR6:
295
464
    opNum = MCInst_getNumOperands(MI) - 2;
296
464
    break;
297
16.4k
  }
298
299
16.4k
  set_mem_access(MI, true);
300
  // Index register is encoded as immediate value
301
  // in case of nanoMIPS indexed instructions
302
16.4k
  switch (MCInst_getOpcode(MI)) {
303
  // No offset needed for paired LL/SC
304
0
  case Mips_LLWP_NM:
305
0
  case Mips_SCWP_NM:
306
0
    break;
307
0
  case Mips_LWX_NM:
308
0
  case Mips_LWXS_NM:
309
0
  case Mips_LWXS16_NM:
310
0
  case Mips_LBX_NM:
311
0
  case Mips_LBUX_NM:
312
0
  case Mips_LHX_NM:
313
0
  case Mips_LHUX_NM:
314
0
  case Mips_LHXS_NM:
315
0
  case Mips_LHUXS_NM:
316
0
  case Mips_SWX_NM:
317
0
  case Mips_SWXS_NM:
318
0
  case Mips_SBX_NM:
319
0
  case Mips_SHX_NM:
320
0
  case Mips_SHXS_NM:
321
0
    if (!MCOperand_isReg(MCInst_getOperand(MI, (opNum + 1)))) {
322
0
      add_cs_detail(MI, Mips_OP_GROUP_MemOperand, (opNum + 1));
323
0
      printRegName(MI, O, MCOperand_getImm(MCInst_getOperand(
324
0
            MI, (opNum + 1))));
325
0
      break;
326
0
    }
327
    // Fall through
328
16.4k
  default:
329
16.4k
    printOperand((MCInst *)MI, opNum + 1, O);
330
16.4k
    break;
331
16.4k
  }
332
16.4k
  SStream_concat0(O, "(");
333
16.4k
  printOperand((MCInst *)MI, opNum, O);
334
16.4k
  SStream_concat0(O, ")");
335
16.4k
  set_mem_access(MI, false);
336
16.4k
}
337
338
static void printMemOperandEA(MCInst *MI, int opNum, SStream *O)
339
0
{
340
  // when using stack locations for not load/store instructions
341
  // print the same way as all normal 3 operand instructions.
342
0
  printOperand((MCInst *)MI, opNum, O);
343
0
  SStream_concat0(O, ", ");
344
0
  printOperand((MCInst *)MI, opNum + 1, O);
345
0
}
346
347
static void printFCCOperand(MCInst *MI, int opNum, SStream *O)
348
0
{
349
0
  MCOperand *MO = MCInst_getOperand(MI, (opNum));
350
0
  SStream_concat0(O,
351
0
      MipsFCCToString((Mips_CondCode)MCOperand_getImm(MO)));
352
0
}
353
354
static bool printAlias(const char *Str, const MCInst *MI, uint64_t Address,
355
    unsigned OpNo, SStream *OS, bool IsBranch)
356
638
{
357
638
  SStream_concat(OS, "%s%s", "\t", Str);
358
638
  SStream_concat0(OS, "\t");
359
638
  if (IsBranch)
360
527
    printBranchOperand((MCInst *)MI, Address, OpNo, OS);
361
111
  else
362
111
    printOperand((MCInst *)MI, OpNo, OS);
363
638
  return true;
364
638
}
365
366
static bool printAlias2(const char *Str, const MCInst *MI, uint64_t Address,
367
    unsigned OpNo0, unsigned OpNo1, SStream *OS, bool IsBranch)
368
378
{
369
378
  printAlias(Str, MI, Address, OpNo0, OS, IsBranch);
370
378
  SStream_concat0(OS, ", ");
371
378
  if (IsBranch)
372
267
    printBranchOperand((MCInst *)MI, Address, OpNo1, OS);
373
111
  else
374
111
    printOperand((MCInst *)MI, OpNo1, OS);
375
378
  return true;
376
378
}
377
378
static bool printAlias3(const char *Str, const MCInst *MI, uint64_t Address,
379
    unsigned OpNo0, unsigned OpNo1, unsigned OpNo2, SStream *OS)
380
0
{
381
0
  printAlias(Str, MI, Address, OpNo0, OS, false);
382
0
  SStream_concat0(OS, ", ");
383
0
  printOperand((MCInst *)MI, OpNo1, OS);
384
0
  SStream_concat0(OS, ", ");
385
0
  printOperand((MCInst *)MI, OpNo2, OS);
386
0
  return true;
387
0
}
388
389
static bool printAlias4(const MCInst *MI, uint64_t Address, SStream *OS)
390
62.6k
{
391
62.6k
  switch (MCInst_getOpcode(MI)) {
392
1.47k
  case Mips_BEQ:
393
1.59k
  case Mips_BEQ_MM:
394
    // beq $zero, $zero, $L2 => b $L2
395
    // beq $r0, $zero, $L2 => beqz $r0, $L2
396
1.59k
    return (isReg(MI, 0, Mips_ZERO) &&
397
1.59k
      isReg(MI, 1, Mips_ZERO) &&
398
1.59k
      printAlias("b", MI, Address, 2, OS, true)) ||
399
1.59k
           (isReg(MI, 1, Mips_ZERO) &&
400
1.33k
      printAlias2("beqz", MI, Address, 0, 2, OS, true));
401
0
  case Mips_BEQ64:
402
    // beq $r0, $zero, $L2 => beqz $r0, $L2
403
0
    return isReg(MI, 1, Mips_ZERO_64) &&
404
0
           printAlias2("beqz", MI, Address, 0, 2, OS, true);
405
592
  case Mips_BNE:
406
597
  case Mips_BNE_MM:
407
    // bne $r0, $zero, $L2 => bnez $r0, $L2
408
597
    return isReg(MI, 1, Mips_ZERO) &&
409
597
           printAlias2("bnez", MI, Address, 0, 2, OS, true);
410
0
  case Mips_BNE64:
411
    // bne $r0, $zero, $L2 => bnez $r0, $L2
412
0
    return isReg(MI, 1, Mips_ZERO_64) &&
413
0
           printAlias2("bnez", MI, Address, 0, 2, OS, true);
414
298
  case Mips_BGEZAL:
415
    // bgezal $zero, $L1 => bal $L1
416
298
    return isReg(MI, 0, Mips_ZERO) &&
417
298
           printAlias("bal", MI, Address, 1, OS, true);
418
42
  case Mips_BC1T:
419
    // bc1t $fcc0, $L1 => bc1t $L1
420
42
    return isReg(MI, 0, Mips_FCC0) &&
421
42
           printAlias("bc1t", MI, Address, 1, OS, true);
422
194
  case Mips_BC1F:
423
    // bc1f $fcc0, $L1 => bc1f $L1
424
194
    return isReg(MI, 0, Mips_FCC0) &&
425
194
           printAlias("bc1f", MI, Address, 1, OS, true);
426
0
  case Mips_JALR:
427
    // jalr $zero, $r1 => jr $r1
428
    // jalr $ra, $r1 => jalr $r1
429
0
    return (isReg(MI, 0, Mips_ZERO) &&
430
0
      printAlias("jr", MI, Address, 1, OS, false)) ||
431
0
           (isReg(MI, 0, Mips_RA) &&
432
0
      printAlias("jalr", MI, Address, 1, OS, false));
433
0
  case Mips_JALR64:
434
    // jalr $zero, $r1 => jr $r1
435
    // jalr $ra, $r1 => jalr $r1
436
0
    return (isReg(MI, 0, Mips_ZERO_64) &&
437
0
      printAlias("jr", MI, Address, 1, OS, false)) ||
438
0
           (isReg(MI, 0, Mips_RA_64) &&
439
0
      printAlias("jalr", MI, Address, 1, OS, false));
440
27
  case Mips_NOR:
441
45
  case Mips_NOR_MM:
442
45
  case Mips_NOR_MMR6:
443
    // nor $r0, $r1, $zero => not $r0, $r1
444
45
    return isReg(MI, 2, Mips_ZERO) &&
445
45
           printAlias2("not", MI, Address, 0, 1, OS, false);
446
0
  case Mips_NOR64:
447
    // nor $r0, $r1, $zero => not $r0, $r1
448
0
    return isReg(MI, 2, Mips_ZERO_64) &&
449
0
           printAlias2("not", MI, Address, 0, 1, OS, false);
450
73
  case Mips_OR:
451
226
  case Mips_ADDu:
452
    // or $r0, $r1, $zero => move $r0, $r1
453
    // addu $r0, $r1, $zero => move $r0, $r1
454
226
    return isReg(MI, 2, Mips_ZERO) &&
455
226
           printAlias2("move", MI, Address, 0, 1, OS, false);
456
0
  case Mips_LI48_NM:
457
0
  case Mips_LI16_NM:
458
    // li[16/48] $r0, imm => li $r0, imm
459
0
    return printAlias2("li", MI, Address, 0, 1, OS, false);
460
0
  case Mips_ADDIU_NM:
461
0
  case Mips_ADDIUNEG_NM:
462
0
    if (isReg(MI, 1, Mips_ZERO_NM))
463
0
      return printAlias2("li", MI, Address, 0, 2, OS, false);
464
0
    else
465
0
      return printAlias3("addiu", MI, Address, 0, 1, 2, OS);
466
0
  case Mips_ADDIU48_NM:
467
0
  case Mips_ADDIURS5_NM:
468
0
  case Mips_ADDIUR1SP_NM:
469
0
  case Mips_ADDIUR2_NM:
470
0
  case Mips_ADDIUGPB_NM:
471
0
  case Mips_ADDIUGPW_NM:
472
0
    return printAlias3("addiu", MI, Address, 0, 1, 2, OS);
473
0
  case Mips_ANDI16_NM:
474
0
  case Mips_ANDI_NM:
475
    // andi[16/32] $r0, $r1, imm => andi $r0, $r1, imm
476
0
    return printAlias3("andi", MI, Address, 0, 1, 2, OS);
477
59.6k
  default:
478
59.6k
    return false;
479
62.6k
  }
480
62.6k
}
481
482
static void printRegisterList(MCInst *MI, int opNum, SStream *O)
483
464
{
484
  // - 2 because register List is always first operand of instruction and it is
485
  // always followed by memory operand (base + offset).
486
464
  add_cs_detail(MI, Mips_OP_GROUP_RegisterList, opNum);
487
1.91k
  for (int i = opNum, e = MCInst_getNumOperands(MI) - 2; i != e; ++i) {
488
1.45k
    if (i != opNum)
489
988
      SStream_concat0(O, ", ");
490
1.45k
    printRegName(MI, O, MCOperand_getReg(MCInst_getOperand(MI, (i))));
491
1.45k
  }
492
464
}
493
494
static void printNanoMipsRegisterList(MCInst *MI, int OpNum, SStream *O)
495
0
{
496
0
  add_cs_detail(MI, Mips_OP_GROUP_NanoMipsRegisterList, OpNum);
497
0
  for (unsigned I = OpNum; I < MCInst_getNumOperands(MI); I++) {
498
0
    SStream_concat0(O, ", ");
499
0
    printRegName(MI, O, MCOperand_getReg(MCInst_getOperand(MI, (I))));
500
0
  }
501
0
}
502
503
static void printHi20(MCInst *MI, int OpNum, SStream *O)
504
0
{
505
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
506
0
  if (MCOperand_isImm(MO)) {
507
0
    add_cs_detail(MI, Mips_OP_GROUP_Hi20, OpNum);
508
0
    SStream_concat0(O, "%hi(");
509
0
    printUInt64(O, MCOperand_getImm(MO));
510
0
    SStream_concat0(O, ")");
511
0
  } else
512
0
    printOperand(MI, OpNum, O);
513
0
}
514
515
static void printHi20PCRel(MCInst *MI, uint64_t Address, int OpNum, SStream *O)
516
0
{
517
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
518
0
  if (MCOperand_isImm(MO)) {
519
0
    add_cs_detail(MI, Mips_OP_GROUP_Hi20PCRel, OpNum);
520
0
    SStream_concat0(O, "%pcrel_hi(");
521
0
    printUInt64(O, MCOperand_getImm(MO) + Address);
522
0
    SStream_concat0(O, ")");
523
0
  } else
524
0
    printOperand(MI, OpNum, O);
525
0
}
526
527
static void printPCRel(MCInst *MI, uint64_t Address, int OpNum, SStream *O)
528
0
{
529
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
530
0
  if (MCOperand_isImm(MO)) {
531
0
    add_cs_detail(MI, Mips_OP_GROUP_PCRel, OpNum);
532
0
    printUInt64(O, MCOperand_getImm(MO) + Address);
533
0
  }
534
0
  else
535
0
    printOperand(MI, OpNum, O);
536
0
}
537
538
const char *Mips_LLVM_getRegisterName(unsigned RegNo, bool noRegName)
539
131k
{
540
131k
  if (!RegNo || RegNo >= MIPS_REG_ENDING) {
541
0
    return NULL;
542
0
  }
543
131k
  if (noRegName) {
544
0
    return getRegisterName(RegNo);
545
0
  }
546
131k
  switch(RegNo) {
547
13.9k
  case MIPS_REG_AT:
548
14.2k
  case MIPS_REG_AT_64:
549
14.2k
    return "at";
550
2.51k
  case MIPS_REG_A0:
551
2.75k
  case MIPS_REG_A0_64:
552
2.75k
    return "a0";
553
2.76k
  case MIPS_REG_A1:
554
2.88k
  case MIPS_REG_A1_64:
555
2.88k
    return "a1";
556
3.70k
  case MIPS_REG_A2:
557
3.77k
  case MIPS_REG_A2_64:
558
3.77k
    return "a2";
559
2.47k
  case MIPS_REG_A3:
560
2.66k
  case MIPS_REG_A3_64:
561
2.66k
    return "a3";
562
1.54k
  case MIPS_REG_K0:
563
1.58k
  case MIPS_REG_K0_64:
564
1.58k
    return "k0";
565
1.97k
  case MIPS_REG_K1:
566
2.16k
  case MIPS_REG_K1_64:
567
2.16k
    return "k1";
568
5.44k
  case MIPS_REG_S0:
569
5.46k
  case MIPS_REG_S0_64:
570
5.46k
    return "s0";
571
3.71k
  case MIPS_REG_S1:
572
3.73k
  case MIPS_REG_S1_64:
573
3.73k
    return "s1";
574
1.59k
  case MIPS_REG_S2:
575
1.60k
  case MIPS_REG_S2_64:
576
1.60k
    return "s2";
577
1.88k
  case MIPS_REG_S3:
578
2.07k
  case MIPS_REG_S3_64:
579
2.07k
    return "s3";
580
1.78k
  case MIPS_REG_S4:
581
1.79k
  case MIPS_REG_S4_64:
582
1.79k
    return "s4";
583
1.42k
  case MIPS_REG_S5:
584
1.42k
  case MIPS_REG_S5_64:
585
1.42k
    return "s5";
586
1.00k
  case MIPS_REG_S6:
587
1.02k
  case MIPS_REG_S6_64:
588
1.02k
    return "s6";
589
970
  case MIPS_REG_S7:
590
1.06k
  case MIPS_REG_S7_64:
591
1.06k
    return "s7";
592
3.65k
  case MIPS_REG_T0:
593
3.67k
  case MIPS_REG_T0_64:
594
3.67k
    return "t0";
595
1.81k
  case MIPS_REG_T1:
596
1.99k
  case MIPS_REG_T1_64:
597
1.99k
    return "t1";
598
1.47k
  case MIPS_REG_T2:
599
1.48k
  case MIPS_REG_T2_64:
600
1.48k
    return "t2";
601
1.40k
  case MIPS_REG_T3:
602
1.74k
  case MIPS_REG_T3_64:
603
1.74k
    return "t3";
604
2.54k
  case MIPS_REG_T4:
605
2.55k
  case MIPS_REG_T4_64:
606
2.55k
    return "t4";
607
1.81k
  case MIPS_REG_T5:
608
1.88k
  case MIPS_REG_T5_64:
609
1.88k
    return "t5";
610
1.00k
  case MIPS_REG_T6:
611
1.02k
  case MIPS_REG_T6_64:
612
1.02k
    return "t6";
613
1.98k
  case MIPS_REG_T7:
614
2.06k
  case MIPS_REG_T7_64:
615
2.06k
    return "t7";
616
3.11k
  case MIPS_REG_T8:
617
3.36k
  case MIPS_REG_T8_64:
618
3.36k
    return "t8";
619
2.73k
  case MIPS_REG_T9:
620
2.75k
  case MIPS_REG_T9_64:
621
2.75k
    return "t9";
622
4.70k
  case MIPS_REG_V0:
623
4.89k
  case MIPS_REG_V0_64:
624
4.89k
    return "v0";
625
2.31k
  case MIPS_REG_V1:
626
2.40k
  case MIPS_REG_V1_64:
627
2.40k
    return "v1";
628
53.8k
  default:
629
53.8k
    return getRegisterName(RegNo);
630
131k
  }
631
131k
}