Coverage Report

Created: 2025-07-04 06:11

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