Coverage Report

Created: 2026-11-12 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/Mips/MipsInstPrinter.c
Line
Count
Source
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
26.1k
#define CONCAT(a, b) CONCAT_(a, b)
45
26.1k
#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
6.87k
{
54
6.87k
  return MCOperand_getReg(MCInst_getOperand((MCInst *)MI, (OpNo))) == R;
55
6.87k
}
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
  CS_ASSERT_RET_VAL(0 && "Impossible condition code!", NULL);
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
258k
{
117
258k
  int syntax_opt = MI->csh->syntax;
118
258k
  if (!(syntax_opt & CS_OPT_SYNTAX_NO_DOLLAR)) {
119
258k
    SStream_concat1(OS, '$');
120
258k
  }
121
258k
  SStream_concat0(OS, Mips_LLVM_getRegisterName(
122
258k
            Reg, syntax_opt & CS_OPT_SYNTAX_NOREGNAME));
123
258k
}
124
125
static void patch_cs_printer(MCInst *MI, SStream *O)
126
142k
{
127
  // replace '# 16 bit inst' to empty.
128
142k
  SStream_replc(O, '#', 0);
129
142k
  SStream_trimls(O);
130
131
142k
  if (MI->csh->syntax & CS_OPT_SYNTAX_NO_DOLLAR) {
132
0
    char *dollar = strchr(O->buffer, '$');
133
0
    if (!dollar) {
134
0
      return;
135
0
    }
136
0
    size_t dollar_len = strlen(dollar + 1);
137
    // to include `\0`
138
0
    memmove(dollar, dollar + 1, dollar_len + 1);
139
0
  }
140
142k
}
141
142
static void patch_cs_detail_operand_reg(cs_mips_op *op, unsigned reg,
143
          unsigned access)
144
1.13k
{
145
1.13k
  op->type = MIPS_OP_REG;
146
1.13k
  op->reg = reg;
147
1.13k
  op->is_reglist = false;
148
1.13k
  op->access = access;
149
1.13k
}
150
151
static void patch_cs_details(MCInst *MI)
152
142k
{
153
142k
  if (!detail_is_set(MI))
154
0
    return;
155
156
142k
  cs_mips_op *op0 = NULL, *op1 = NULL, *op2 = NULL;
157
142k
  unsigned opcode = MCInst_getOpcode(MI);
158
142k
  unsigned n_ops = MCInst_getNumOperands(MI);
159
160
142k
  switch (opcode) {
161
  /* mips r2 to r5 only 64bit */
162
248
  case Mips_DSDIV: /// ddiv $$zero, $rs, $rt
163
    /* fall-thru */
164
324
  case Mips_DUDIV: /// ddivu $$zero, $rs, $rt
165
324
    if (n_ops != 2) {
166
0
      return;
167
0
    }
168
324
    Mips_inc_op_count(MI);
169
324
    op0 = Mips_get_detail_op(MI, -3);
170
324
    op1 = Mips_get_detail_op(MI, -2);
171
324
    op2 = Mips_get_detail_op(MI, -1);
172
    // move all details by one and add $zero reg
173
324
    *op2 = *op1;
174
324
    *op1 = *op0;
175
324
    patch_cs_detail_operand_reg(op0, MIPS_REG_ZERO_64, CS_AC_WRITE);
176
324
    return;
177
178
  /* mips r2 to r5 only */
179
69
  case Mips_SDIV: /// div $$zero, $rs, $rt
180
    /* fall-thru */
181
267
  case Mips_UDIV: /// divu $$zero, $rs, $rt
182
    /* fall-thru */
183
  /* microMIPS only */
184
617
  case Mips_SDIV_MM: /// div $$zero, $rs, $rt
185
    /* fall-thru */
186
811
  case Mips_UDIV_MM: /// divu $$zero, $rs, $rt
187
    /* fall-thru */
188
189
  /* MIPS16 only */
190
811
  case Mips_DivRxRy16: /// div $$zero, $rx, $ry
191
    /* fall-thru */
192
811
  case Mips_DivuRxRy16: /// divu $$zero, $rx, $ry
193
811
    if (n_ops != 2) {
194
0
      return;
195
0
    }
196
811
    Mips_inc_op_count(MI);
197
811
    op0 = Mips_get_detail_op(MI, -3);
198
811
    op1 = Mips_get_detail_op(MI, -2);
199
811
    op2 = Mips_get_detail_op(MI, -1);
200
    // move all details by one and add $zero reg
201
811
    *op2 = *op1;
202
811
    *op1 = *op0;
203
811
    patch_cs_detail_operand_reg(op0, MIPS_REG_ZERO, CS_AC_WRITE);
204
811
    return;
205
0
  case Mips_AddiuSpImm16: /// addiu $$sp, imm8
206
    /* fall-thru */
207
0
  case Mips_AddiuSpImmX16: /// addiu $$sp, imm8
208
0
    if (n_ops != 1) {
209
0
      return;
210
0
    }
211
0
    Mips_inc_op_count(MI);
212
0
    op0 = Mips_get_detail_op(MI, -2);
213
0
    op1 = Mips_get_detail_op(MI, -1);
214
    // move all details by one and add $sp reg
215
0
    *op1 = *op0;
216
0
    patch_cs_detail_operand_reg(op0, MIPS_REG_SP, CS_AC_READ_WRITE);
217
0
    return;
218
0
  case Mips_JrcRa16: /// jrc $ra
219
    /* fall-thru */
220
0
  case Mips_JrRa16: /// jr $ra
221
0
    if (n_ops > 0) {
222
0
      return;
223
0
    }
224
0
    Mips_inc_op_count(MI);
225
0
    op0 = Mips_get_detail_op(MI, -1);
226
0
    patch_cs_detail_operand_reg(op0, MIPS_REG_RA, CS_AC_READ);
227
0
    return;
228
141k
  default:
229
141k
    return;
230
142k
  }
231
142k
}
232
233
void Mips_LLVM_printInst(MCInst *MI, uint64_t Address, SStream *O)
234
142k
{
235
142k
  bool useAliasDetails = map_use_alias_details(MI);
236
142k
  if (!useAliasDetails) {
237
0
    SStream_Close(O);
238
0
    printInstruction(MI, Address, O);
239
0
    SStream_Open(O);
240
0
    map_set_fill_detail_ops(MI, false);
241
0
  }
242
243
142k
  if (printAliasInstr(MI, Address, O) || printAlias4(MI, Address, O)) {
244
7.75k
    MCInst_setIsAlias(MI, true);
245
134k
  } else {
246
134k
    printInstruction(MI, Address, O);
247
134k
  }
248
249
142k
  patch_cs_printer(MI, O);
250
142k
  patch_cs_details(MI);
251
252
142k
  if (!useAliasDetails) {
253
0
    map_set_fill_detail_ops(MI, true);
254
0
  }
255
142k
}
256
257
void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
258
304k
{
259
304k
  switch (MCInst_getOpcode(MI)) {
260
304k
  default:
261
304k
    break;
262
304k
  case Mips_AND16_NM:
263
0
  case Mips_XOR16_NM:
264
0
  case Mips_OR16_NM:
265
0
    if (MCInst_getNumOperands(MI) == 2 && OpNo == 2)
266
0
      OpNo = 0; // rt, rs -> rt, rs, rt
267
0
    break;
268
0
  case Mips_ADDu4x4_NM:
269
0
  case Mips_MUL4x4_NM:
270
0
    if (MCInst_getNumOperands(MI) == 2 && OpNo > 0)
271
0
      OpNo = OpNo - 1; // rt, rs -> rt, rt, rs
272
0
    break;
273
304k
  }
274
275
304k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
276
304k
  if (MCOperand_isReg(Op)) {
277
253k
    Mips_add_cs_detail_0(MI, Mips_OP_GROUP_Operand, OpNo);
278
253k
    printRegName(MI, O, MCOperand_getReg(Op));
279
253k
    return;
280
253k
  }
281
282
50.7k
  if (MCOperand_isImm(Op)) {
283
50.7k
    switch (MCInst_getOpcode(MI)) {
284
0
    case Mips_LI48_NM:
285
0
    case Mips_ANDI16_NM:
286
0
    case Mips_ANDI_NM:
287
0
    case Mips_ORI_NM:
288
0
    case Mips_XORI_NM:
289
0
    case Mips_TEQ_NM:
290
0
    case Mips_TNE_NM:
291
0
    case Mips_SIGRIE_NM:
292
0
    case Mips_SDBBP_NM:
293
0
    case Mips_SDBBP16_NM:
294
0
    case Mips_BREAK_NM:
295
0
    case Mips_BREAK16_NM:
296
0
    case Mips_SYSCALL_NM:
297
0
    case Mips_SYSCALL16_NM:
298
0
    case Mips_WAIT_NM:
299
0
      CONCAT(printUImm, CONCAT(32, 0))
300
0
      (MI, OpNo, O);
301
0
      break;
302
50.7k
    default:
303
50.7k
      Mips_add_cs_detail_0(MI, Mips_OP_GROUP_Operand, OpNo);
304
50.7k
      printInt64(O, MCOperand_getImm(Op));
305
50.7k
      break;
306
50.7k
    }
307
50.7k
    return;
308
50.7k
  }
309
50.7k
}
310
311
static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O)
312
3.37k
{
313
3.37k
  Mips_add_cs_detail_0(MI, Mips_OP_GROUP_JumpOperand, OpNo);
314
3.37k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
315
3.37k
  if (MCOperand_isReg(Op))
316
0
    return printRegName(MI, O, MCOperand_getReg(Op));
317
318
  // only the upper bits are needed.
319
3.37k
  uint64_t Base = MI->address & ~0x0fffffffull;
320
3.37k
  uint64_t Target = MCOperand_getImm(Op);
321
3.37k
  printInt64(O, Base | Target);
322
3.37k
}
323
324
static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo,
325
             SStream *O)
326
24.6k
{
327
24.6k
  Mips_add_cs_detail_0(MI, Mips_OP_GROUP_BranchOperand, OpNo);
328
24.6k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
329
24.6k
  if (MCOperand_isReg(Op))
330
575
    return printRegName(MI, O, MCOperand_getReg(Op));
331
332
24.0k
  uint64_t Target = Address + MCOperand_getImm(Op);
333
24.0k
  printInt64(O, Target);
334
24.0k
}
335
336
#define DEFINE_printUImm(Bits) \
337
  static void CONCAT(printUImm, CONCAT(Bits, 0))(MCInst * MI, int opNum, \
338
                   SStream *O) \
339
25.2k
  { \
340
25.2k
    Mips_add_cs_detail_0( \
341
25.2k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
25.2k
      opNum); \
343
25.2k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
25.2k
    if (MCOperand_isImm(MO)) { \
345
25.2k
      uint64_t Imm = MCOperand_getImm(MO); \
346
25.2k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
25.2k
      printUInt64(O, Imm); \
348
25.2k
      return; \
349
25.2k
    } \
350
25.2k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_10_0
Line
Count
Source
339
1.25k
  { \
340
1.25k
    Mips_add_cs_detail_0( \
341
1.25k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.25k
      opNum); \
343
1.25k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.25k
    if (MCOperand_isImm(MO)) { \
345
1.25k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.25k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.25k
      printUInt64(O, Imm); \
348
1.25k
      return; \
349
1.25k
    } \
350
1.25k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_4_0
Line
Count
Source
339
2.03k
  { \
340
2.03k
    Mips_add_cs_detail_0( \
341
2.03k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
2.03k
      opNum); \
343
2.03k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
2.03k
    if (MCOperand_isImm(MO)) { \
345
2.03k
      uint64_t Imm = MCOperand_getImm(MO); \
346
2.03k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
2.03k
      printUInt64(O, Imm); \
348
2.03k
      return; \
349
2.03k
    } \
350
2.03k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_5_0
Line
Count
Source
339
5.94k
  { \
340
5.94k
    Mips_add_cs_detail_0( \
341
5.94k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
5.94k
      opNum); \
343
5.94k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
5.94k
    if (MCOperand_isImm(MO)) { \
345
5.94k
      uint64_t Imm = MCOperand_getImm(MO); \
346
5.94k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
5.94k
      printUInt64(O, Imm); \
348
5.94k
      return; \
349
5.94k
    } \
350
5.94k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_26_0
MipsInstPrinter.c:printUImm_8_0
Line
Count
Source
339
1.38k
  { \
340
1.38k
    Mips_add_cs_detail_0( \
341
1.38k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.38k
      opNum); \
343
1.38k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.38k
    if (MCOperand_isImm(MO)) { \
345
1.38k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.38k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.38k
      printUInt64(O, Imm); \
348
1.38k
      return; \
349
1.38k
    } \
350
1.38k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_12_0
MipsInstPrinter.c:printUImm_20_0
Line
Count
Source
339
231
  { \
340
231
    Mips_add_cs_detail_0( \
341
231
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
231
      opNum); \
343
231
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
231
    if (MCOperand_isImm(MO)) { \
345
231
      uint64_t Imm = MCOperand_getImm(MO); \
346
231
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
231
      printUInt64(O, Imm); \
348
231
      return; \
349
231
    } \
350
231
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_16_0
Line
Count
Source
339
3.57k
  { \
340
3.57k
    Mips_add_cs_detail_0( \
341
3.57k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
3.57k
      opNum); \
343
3.57k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
3.57k
    if (MCOperand_isImm(MO)) { \
345
3.57k
      uint64_t Imm = MCOperand_getImm(MO); \
346
3.57k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
3.57k
      printUInt64(O, Imm); \
348
3.57k
      return; \
349
3.57k
    } \
350
3.57k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_32_0
MipsInstPrinter.c:printUImm_7_0
Line
Count
Source
339
1.15k
  { \
340
1.15k
    Mips_add_cs_detail_0( \
341
1.15k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.15k
      opNum); \
343
1.15k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.15k
    if (MCOperand_isImm(MO)) { \
345
1.15k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.15k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.15k
      printUInt64(O, Imm); \
348
1.15k
      return; \
349
1.15k
    } \
350
1.15k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_2_0
Line
Count
Source
339
1.91k
  { \
340
1.91k
    Mips_add_cs_detail_0( \
341
1.91k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.91k
      opNum); \
343
1.91k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.91k
    if (MCOperand_isImm(MO)) { \
345
1.91k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.91k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.91k
      printUInt64(O, Imm); \
348
1.91k
      return; \
349
1.91k
    } \
350
1.91k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_1_0
Line
Count
Source
339
1.87k
  { \
340
1.87k
    Mips_add_cs_detail_0( \
341
1.87k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.87k
      opNum); \
343
1.87k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.87k
    if (MCOperand_isImm(MO)) { \
345
1.87k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.87k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.87k
      printUInt64(O, Imm); \
348
1.87k
      return; \
349
1.87k
    } \
350
1.87k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_3_0
Line
Count
Source
339
3.54k
  { \
340
3.54k
    Mips_add_cs_detail_0( \
341
3.54k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
3.54k
      opNum); \
343
3.54k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
3.54k
    if (MCOperand_isImm(MO)) { \
345
3.54k
      uint64_t Imm = MCOperand_getImm(MO); \
346
3.54k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
3.54k
      printUInt64(O, Imm); \
348
3.54k
      return; \
349
3.54k
    } \
350
3.54k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_0_0
Line
Count
Source
339
1.48k
  { \
340
1.48k
    Mips_add_cs_detail_0( \
341
1.48k
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
1.48k
      opNum); \
343
1.48k
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
1.48k
    if (MCOperand_isImm(MO)) { \
345
1.48k
      uint64_t Imm = MCOperand_getImm(MO); \
346
1.48k
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
1.48k
      printUInt64(O, Imm); \
348
1.48k
      return; \
349
1.48k
    } \
350
1.48k
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
MipsInstPrinter.c:printUImm_6_0
Line
Count
Source
339
885
  { \
340
885
    Mips_add_cs_detail_0( \
341
885
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, 0)), \
342
885
      opNum); \
343
885
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
344
885
    if (MCOperand_isImm(MO)) { \
345
885
      uint64_t Imm = MCOperand_getImm(MO); \
346
885
      Imm &= (((uint64_t)1) << Bits) - 1; \
347
885
      printUInt64(O, Imm); \
348
885
      return; \
349
885
    } \
350
885
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
351
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
352
0
  }
353
354
#define DEFINE_printUImm_2(Bits, Offset) \
355
  static void CONCAT(printUImm, CONCAT(Bits, Offset))( \
356
    MCInst * MI, int opNum, SStream *O) \
357
828
  { \
358
828
    Mips_add_cs_detail_0( \
359
828
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
360
828
      opNum); \
361
828
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
362
828
    if (MCOperand_isImm(MO)) { \
363
828
      uint64_t Imm = MCOperand_getImm(MO); \
364
828
      Imm -= Offset; \
365
828
      Imm &= (1 << Bits) - 1; \
366
828
      Imm += Offset; \
367
828
      printUInt64(O, Imm); \
368
828
      return; \
369
828
    } \
370
828
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
371
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
372
0
  }
MipsInstPrinter.c:printUImm_2_1
Line
Count
Source
357
406
  { \
358
406
    Mips_add_cs_detail_0( \
359
406
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
360
406
      opNum); \
361
406
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
362
406
    if (MCOperand_isImm(MO)) { \
363
406
      uint64_t Imm = MCOperand_getImm(MO); \
364
406
      Imm -= Offset; \
365
406
      Imm &= (1 << Bits) - 1; \
366
406
      Imm += Offset; \
367
406
      printUInt64(O, Imm); \
368
406
      return; \
369
406
    } \
370
406
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
371
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
372
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_5_32
MipsInstPrinter.c:printUImm_5_1
Line
Count
Source
357
422
  { \
358
422
    Mips_add_cs_detail_0( \
359
422
      MI, CONCAT(Mips_OP_GROUP_UImm, CONCAT(Bits, Offset)), \
360
422
      opNum); \
361
422
    MCOperand *MO = MCInst_getOperand(MI, (opNum)); \
362
422
    if (MCOperand_isImm(MO)) { \
363
422
      uint64_t Imm = MCOperand_getImm(MO); \
364
422
      Imm -= Offset; \
365
422
      Imm &= (1 << Bits) - 1; \
366
422
      Imm += Offset; \
367
422
      printUInt64(O, Imm); \
368
422
      return; \
369
422
    } \
370
422
    MCOperand *Op = MCInst_getOperand(MI, (opNum)); \
371
0
    printRegName(MI, O, MCOperand_getReg(Op)); \
372
0
  }
Unexecuted instantiation: MipsInstPrinter.c:printUImm_6_1
Unexecuted instantiation: MipsInstPrinter.c:printUImm_5_33
Unexecuted instantiation: MipsInstPrinter.c:printUImm_6_2
373
374
DEFINE_printUImm(0);
375
DEFINE_printUImm(1);
376
DEFINE_printUImm(10);
377
DEFINE_printUImm(12);
378
DEFINE_printUImm(16);
379
DEFINE_printUImm(2);
380
DEFINE_printUImm(20);
381
DEFINE_printUImm(26);
382
DEFINE_printUImm(3);
383
DEFINE_printUImm(32);
384
DEFINE_printUImm(4);
385
DEFINE_printUImm(5);
386
DEFINE_printUImm(6);
387
DEFINE_printUImm(7);
388
DEFINE_printUImm(8);
389
DEFINE_printUImm_2(2, 1);
390
DEFINE_printUImm_2(5, 1);
391
DEFINE_printUImm_2(5, 32);
392
DEFINE_printUImm_2(5, 33);
393
DEFINE_printUImm_2(6, 1);
394
DEFINE_printUImm_2(6, 2);
395
396
static void printMemOperand(MCInst *MI, int opNum, SStream *O)
397
33.4k
{
398
  // Load/Store memory operands -- imm($reg)
399
  // If PIC target the target is loaded as the
400
  // pattern lw $25,%call16($28)
401
402
  // opNum can be invalid if instruction had reglist as operand.
403
  // MemOperand is always last operand of instruction (base + offset).
404
33.4k
  switch (MCInst_getOpcode(MI)) {
405
31.7k
  default:
406
31.7k
    break;
407
31.7k
  case Mips_SWM32_MM:
408
645
  case Mips_LWM32_MM:
409
934
  case Mips_SWM16_MM:
410
1.22k
  case Mips_SWM16_MMR6:
411
1.42k
  case Mips_LWM16_MM:
412
1.63k
  case Mips_LWM16_MMR6:
413
1.63k
    opNum = MCInst_getNumOperands(MI) - 2;
414
1.63k
    break;
415
33.4k
  }
416
417
33.4k
  set_mem_access(MI, true);
418
  // Index register is encoded as immediate value
419
  // in case of nanoMIPS indexed instructions
420
33.4k
  switch (MCInst_getOpcode(MI)) {
421
  // No offset needed for paired LL/SC
422
0
  case Mips_LLWP_NM:
423
0
  case Mips_SCWP_NM:
424
0
    break;
425
0
  case Mips_LWX_NM:
426
0
  case Mips_LWXS_NM:
427
0
  case Mips_LWXS16_NM:
428
0
  case Mips_LBX_NM:
429
0
  case Mips_LBUX_NM:
430
0
  case Mips_LHX_NM:
431
0
  case Mips_LHUX_NM:
432
0
  case Mips_LHXS_NM:
433
0
  case Mips_LHUXS_NM:
434
0
  case Mips_SWX_NM:
435
0
  case Mips_SWXS_NM:
436
0
  case Mips_SBX_NM:
437
0
  case Mips_SHX_NM:
438
0
  case Mips_SHXS_NM:
439
0
    if (!MCOperand_isReg(MCInst_getOperand(MI, (opNum + 1)))) {
440
0
      Mips_add_cs_detail_0(MI, Mips_OP_GROUP_MemOperand,
441
0
               (opNum + 1));
442
0
      printRegName(MI, O,
443
0
             MCOperand_getImm(MCInst_getOperand(
444
0
               MI, (opNum + 1))));
445
0
      break;
446
0
    }
447
    // Fall through
448
33.4k
  default:
449
33.4k
    printOperand((MCInst *)MI, opNum + 1, O);
450
33.4k
    break;
451
33.4k
  }
452
33.4k
  SStream_concat0(O, "(");
453
33.4k
  printOperand((MCInst *)MI, opNum, O);
454
33.4k
  SStream_concat0(O, ")");
455
33.4k
  set_mem_access(MI, false);
456
33.4k
}
457
458
static void printMemOperandEA(MCInst *MI, int opNum, SStream *O)
459
0
{
460
  // when using stack locations for not load/store instructions
461
  // print the same way as all normal 3 operand instructions.
462
0
  printOperand((MCInst *)MI, opNum, O);
463
0
  SStream_concat0(O, ", ");
464
0
  printOperand((MCInst *)MI, opNum + 1, O);
465
0
}
466
467
static void printFCCOperand(MCInst *MI, int opNum, SStream *O)
468
0
{
469
0
  MCOperand *MO = MCInst_getOperand(MI, (opNum));
470
0
  SStream_concat0(O,
471
0
      MipsFCCToString((Mips_CondCode)MCOperand_getImm(MO)));
472
0
}
473
474
static bool printAlias(const char *Str, const MCInst *MI, uint64_t Address,
475
           unsigned OpNo, SStream *OS, bool IsBranch)
476
1.78k
{
477
1.78k
  SStream_concat(OS, "%s%s", "\t", Str);
478
1.78k
  SStream_concat0(OS, "\t");
479
1.78k
  if (IsBranch)
480
852
    printBranchOperand((MCInst *)MI, Address, OpNo, OS);
481
931
  else
482
931
    printOperand((MCInst *)MI, OpNo, OS);
483
1.78k
  return true;
484
1.78k
}
485
486
static bool printAlias2(const char *Str, const MCInst *MI, uint64_t Address,
487
      unsigned OpNo0, unsigned OpNo1, SStream *OS,
488
      bool IsBranch)
489
1.23k
{
490
1.23k
  printAlias(Str, MI, Address, OpNo0, OS, IsBranch);
491
1.23k
  SStream_concat0(OS, ", ");
492
1.23k
  if (IsBranch)
493
575
    printBranchOperand((MCInst *)MI, Address, OpNo1, OS);
494
660
  else
495
660
    printOperand((MCInst *)MI, OpNo1, OS);
496
1.23k
  return true;
497
1.23k
}
498
499
static bool printAlias3(const char *Str, const MCInst *MI, uint64_t Address,
500
      unsigned OpNo0, unsigned OpNo1, unsigned OpNo2,
501
      SStream *OS)
502
0
{
503
0
  printAlias(Str, MI, Address, OpNo0, OS, false);
504
0
  SStream_concat0(OS, ", ");
505
0
  printOperand((MCInst *)MI, OpNo1, OS);
506
0
  SStream_concat0(OS, ", ");
507
0
  printOperand((MCInst *)MI, OpNo2, OS);
508
0
  return true;
509
0
}
510
511
static bool printAlias4(const MCInst *MI, uint64_t Address, SStream *OS)
512
136k
{
513
136k
  switch (MCInst_getOpcode(MI)) {
514
1.52k
  case Mips_BEQ:
515
1.72k
  case Mips_BEQ_MM:
516
    // beq $zero, $zero, $L2 => b $L2
517
    // beq $r0, $zero, $L2 => beqz $r0, $L2
518
1.72k
    return (isReg(MI, 0, Mips_ZERO) && isReg(MI, 1, Mips_ZERO) &&
519
277
      printAlias("b", MI, Address, 2, OS, true)) ||
520
1.45k
           (isReg(MI, 1, Mips_ZERO) &&
521
220
      printAlias2("beqz", MI, Address, 0, 2, OS, true));
522
0
  case Mips_BEQ64:
523
    // beq $r0, $zero, $L2 => beqz $r0, $L2
524
0
    return isReg(MI, 1, Mips_ZERO_64) &&
525
0
           printAlias2("beqz", MI, Address, 0, 2, OS, true);
526
801
  case Mips_BNE:
527
1.03k
  case Mips_BNE_MM:
528
    // bne $r0, $zero, $L2 => bnez $r0, $L2
529
1.03k
    return isReg(MI, 1, Mips_ZERO) &&
530
355
           printAlias2("bnez", MI, Address, 0, 2, OS, true);
531
0
  case Mips_BNE64:
532
    // bne $r0, $zero, $L2 => bnez $r0, $L2
533
0
    return isReg(MI, 1, Mips_ZERO_64) &&
534
0
           printAlias2("bnez", MI, Address, 0, 2, OS, true);
535
204
  case Mips_BGEZAL:
536
    // bgezal $zero, $L1 => bal $L1
537
204
    return isReg(MI, 0, Mips_ZERO) &&
538
0
           printAlias("bal", MI, Address, 1, OS, true);
539
204
  case Mips_BC1T:
540
    // bc1t $fcc0, $L1 => bc1t $L1
541
204
    return isReg(MI, 0, Mips_FCC0) &&
542
0
           printAlias("bc1t", MI, Address, 1, OS, true);
543
206
  case Mips_BC1F:
544
    // bc1f $fcc0, $L1 => bc1f $L1
545
206
    return isReg(MI, 0, Mips_FCC0) &&
546
0
           printAlias("bc1f", MI, Address, 1, OS, true);
547
364
  case Mips_JALR:
548
    // jalr $zero, $r1 => jr $r1
549
    // jalr $ra, $r1 => jalr $r1
550
364
    return (isReg(MI, 0, Mips_ZERO) &&
551
74
      printAlias("jr", MI, Address, 1, OS, false)) ||
552
290
           (isReg(MI, 0, Mips_RA) &&
553
197
      printAlias("jalr", MI, Address, 1, OS, false));
554
0
  case Mips_JALR64:
555
    // jalr $zero, $r1 => jr $r1
556
    // jalr $ra, $r1 => jalr $r1
557
0
    return (isReg(MI, 0, Mips_ZERO_64) &&
558
0
      printAlias("jr", MI, Address, 1, OS, false)) ||
559
0
           (isReg(MI, 0, Mips_RA_64) &&
560
0
      printAlias("jalr", MI, Address, 1, OS, false));
561
143
  case Mips_NOR:
562
522
  case Mips_NOR_MM:
563
730
  case Mips_NOR_MMR6:
564
    // nor $r0, $r1, $zero => not $r0, $r1
565
730
    return isReg(MI, 2, Mips_ZERO) &&
566
590
           printAlias2("not", MI, Address, 0, 1, OS, false);
567
0
  case Mips_NOR64:
568
    // nor $r0, $r1, $zero => not $r0, $r1
569
0
    return isReg(MI, 2, Mips_ZERO_64) &&
570
0
           printAlias2("not", MI, Address, 0, 1, OS, false);
571
80
  case Mips_OR:
572
148
  case Mips_ADDu:
573
    // or $r0, $r1, $zero => move $r0, $r1
574
    // addu $r0, $r1, $zero => move $r0, $r1
575
148
    return isReg(MI, 2, Mips_ZERO) &&
576
70
           printAlias2("move", MI, Address, 0, 1, OS, false);
577
0
  case Mips_LI48_NM:
578
0
  case Mips_LI16_NM:
579
    // li[16/48] $r0, imm => li $r0, imm
580
0
    return printAlias2("li", MI, Address, 0, 1, OS, false);
581
0
  case Mips_ADDIU_NM:
582
0
  case Mips_ADDIUNEG_NM:
583
0
    if (isReg(MI, 1, Mips_ZERO_NM))
584
0
      return printAlias2("li", MI, Address, 0, 2, OS, false);
585
0
    else
586
0
      return printAlias3("addiu", MI, Address, 0, 1, 2, OS);
587
0
  case Mips_ADDIU48_NM:
588
0
  case Mips_ADDIURS5_NM:
589
0
  case Mips_ADDIUR1SP_NM:
590
0
  case Mips_ADDIUR2_NM:
591
0
  case Mips_ADDIUGPB_NM:
592
0
  case Mips_ADDIUGPW_NM:
593
0
    return printAlias3("addiu", MI, Address, 0, 1, 2, OS);
594
0
  case Mips_ANDI16_NM:
595
0
  case Mips_ANDI_NM:
596
    // andi[16/32] $r0, $r1, imm => andi $r0, $r1, imm
597
0
    return printAlias3("andi", MI, Address, 0, 1, 2, OS);
598
131k
  default:
599
131k
    return false;
600
136k
  }
601
136k
}
602
603
static void printRegisterList(MCInst *MI, int opNum, SStream *O)
604
1.63k
{
605
  // - 2 because register List is always first operand of instruction and it is
606
  // always followed by memory operand (base + offset).
607
1.63k
  Mips_add_cs_detail_0(MI, Mips_OP_GROUP_RegisterList, opNum);
608
6.21k
  for (int i = opNum, e = MCInst_getNumOperands(MI) - 2; i != e; ++i) {
609
4.57k
    if (i != opNum)
610
2.94k
      SStream_concat0(O, ", ");
611
4.57k
    printRegName(MI, O,
612
4.57k
           MCOperand_getReg(MCInst_getOperand(MI, (i))));
613
4.57k
  }
614
1.63k
}
615
616
static void printNanoMipsRegisterList(MCInst *MI, int OpNum, SStream *O)
617
0
{
618
0
  Mips_add_cs_detail_0(MI, Mips_OP_GROUP_NanoMipsRegisterList, OpNum);
619
0
  for (unsigned I = OpNum; I < MCInst_getNumOperands(MI); I++) {
620
0
    SStream_concat0(O, ", ");
621
0
    printRegName(MI, O,
622
0
           MCOperand_getReg(MCInst_getOperand(MI, (I))));
623
0
  }
624
0
}
625
626
static void printHi20(MCInst *MI, int OpNum, SStream *O)
627
0
{
628
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
629
0
  if (MCOperand_isImm(MO)) {
630
0
    Mips_add_cs_detail_0(MI, Mips_OP_GROUP_Hi20, OpNum);
631
0
    SStream_concat0(O, "%hi(");
632
0
    printUInt64(O, MCOperand_getImm(MO));
633
0
    SStream_concat0(O, ")");
634
0
  } else
635
0
    printOperand(MI, OpNum, O);
636
0
}
637
638
static void printHi20PCRel(MCInst *MI, uint64_t Address, int OpNum, SStream *O)
639
0
{
640
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
641
0
  if (MCOperand_isImm(MO)) {
642
0
    Mips_add_cs_detail_0(MI, Mips_OP_GROUP_Hi20PCRel, OpNum);
643
0
    SStream_concat0(O, "%pcrel_hi(");
644
0
    printUInt64(O, MCOperand_getImm(MO) + Address);
645
0
    SStream_concat0(O, ")");
646
0
  } else
647
0
    printOperand(MI, OpNum, O);
648
0
}
649
650
static void printPCRel(MCInst *MI, uint64_t Address, int OpNum, SStream *O)
651
0
{
652
0
  MCOperand *MO = MCInst_getOperand(MI, (OpNum));
653
0
  if (MCOperand_isImm(MO)) {
654
0
    Mips_add_cs_detail_0(MI, Mips_OP_GROUP_PCRel, OpNum);
655
0
    printUInt64(O, MCOperand_getImm(MO) + Address);
656
0
  } else
657
0
    printOperand(MI, OpNum, O);
658
0
}
659
660
const char *Mips_LLVM_getRegisterName(unsigned RegNo, bool noRegName)
661
291k
{
662
291k
  if (!RegNo || RegNo >= MIPS_REG_ENDING) {
663
0
    return NULL;
664
0
  }
665
291k
  if (noRegName) {
666
0
    return getRegisterName(RegNo);
667
0
  }
668
291k
  switch (RegNo) {
669
28.1k
  case MIPS_REG_AT:
670
29.0k
  case MIPS_REG_AT_64:
671
29.0k
    return "at";
672
7.06k
  case MIPS_REG_A0:
673
7.56k
  case MIPS_REG_A0_64:
674
7.56k
    return "a0";
675
5.94k
  case MIPS_REG_A1:
676
6.25k
  case MIPS_REG_A1_64:
677
6.25k
    return "a1";
678
6.58k
  case MIPS_REG_A2:
679
7.20k
  case MIPS_REG_A2_64:
680
7.20k
    return "a2";
681
5.92k
  case MIPS_REG_A3:
682
6.26k
  case MIPS_REG_A3_64:
683
6.26k
    return "a3";
684
2.61k
  case MIPS_REG_K0:
685
2.83k
  case MIPS_REG_K0_64:
686
2.83k
    return "k0";
687
3.09k
  case MIPS_REG_K1:
688
3.47k
  case MIPS_REG_K1_64:
689
3.47k
    return "k1";
690
13.7k
  case MIPS_REG_S0:
691
14.3k
  case MIPS_REG_S0_64:
692
14.3k
    return "s0";
693
6.29k
  case MIPS_REG_S1:
694
6.75k
  case MIPS_REG_S1_64:
695
6.75k
    return "s1";
696
2.48k
  case MIPS_REG_S2:
697
2.71k
  case MIPS_REG_S2_64:
698
2.71k
    return "s2";
699
2.99k
  case MIPS_REG_S3:
700
3.45k
  case MIPS_REG_S3_64:
701
3.45k
    return "s3";
702
3.42k
  case MIPS_REG_S4:
703
3.72k
  case MIPS_REG_S4_64:
704
3.72k
    return "s4";
705
2.86k
  case MIPS_REG_S5:
706
3.12k
  case MIPS_REG_S5_64:
707
3.12k
    return "s5";
708
3.76k
  case MIPS_REG_S6:
709
4.05k
  case MIPS_REG_S6_64:
710
4.05k
    return "s6";
711
3.47k
  case MIPS_REG_S7:
712
3.94k
  case MIPS_REG_S7_64:
713
3.94k
    return "s7";
714
5.33k
  case MIPS_REG_T0:
715
5.56k
  case MIPS_REG_T0_64:
716
5.56k
    return "t0";
717
2.70k
  case MIPS_REG_T1:
718
2.93k
  case MIPS_REG_T1_64:
719
2.93k
    return "t1";
720
2.77k
  case MIPS_REG_T2:
721
2.99k
  case MIPS_REG_T2_64:
722
2.99k
    return "t2";
723
2.90k
  case MIPS_REG_T3:
724
3.63k
  case MIPS_REG_T3_64:
725
3.63k
    return "t3";
726
2.34k
  case MIPS_REG_T4:
727
2.63k
  case MIPS_REG_T4_64:
728
2.63k
    return "t4";
729
2.27k
  case MIPS_REG_T5:
730
2.56k
  case MIPS_REG_T5_64:
731
2.56k
    return "t5";
732
2.33k
  case MIPS_REG_T6:
733
2.58k
  case MIPS_REG_T6_64:
734
2.58k
    return "t6";
735
3.93k
  case MIPS_REG_T7:
736
4.78k
  case MIPS_REG_T7_64:
737
4.78k
    return "t7";
738
5.19k
  case MIPS_REG_T8:
739
5.42k
  case MIPS_REG_T8_64:
740
5.42k
    return "t8";
741
3.92k
  case MIPS_REG_T9:
742
4.57k
  case MIPS_REG_T9_64:
743
4.57k
    return "t9";
744
11.6k
  case MIPS_REG_V0:
745
12.1k
  case MIPS_REG_V0_64:
746
12.1k
    return "v0";
747
6.35k
  case MIPS_REG_V1:
748
7.03k
  case MIPS_REG_V1_64:
749
7.03k
    return "v1";
750
129k
  default:
751
129k
    return getRegisterName(RegNo);
752
291k
  }
753
291k
}