Coverage Report

Created: 2025-12-05 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/RISCV/RISCVInstPrinter.c
Line
Count
Source
1
//===-- RISCVInstPrinter.cpp - Convert RISCV MCInst to asm syntax ---------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This class prints an RISCV MCInst to a .s file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifdef CAPSTONE_HAS_RISCV
15
16
#include <stdio.h>    // DEBUG
17
#include <stdlib.h>
18
#include <string.h>
19
#include <capstone/platform.h>
20
21
#include "RISCVInstPrinter.h"
22
#include "RISCVBaseInfo.h"
23
#include "../../MCInst.h"
24
#include "../../SStream.h"
25
#include "../../MCRegisterInfo.h"
26
#include "../../utils.h"
27
#include "RISCVMapping.h"
28
29
//#include "RISCVDisassembler.h"
30
31
#define GET_REGINFO_ENUM
32
#define GET_REGINFO_MC_DESC
33
#include "RISCVGenRegisterInfo.inc"
34
#define GET_INSTRINFO_ENUM
35
#include "RISCVGenInstrInfo.inc"
36
37
// Autogenerated by tblgen.
38
static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
39
static bool printAliasInstr(MCInst *MI, SStream *OS, void *info);
40
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
41
static void printFenceArg(MCInst *MI, unsigned OpNo, SStream *O);
42
static void printCSRSystemRegister(MCInst*, unsigned, SStream *);
43
static void printFRMArg(MCInst *MI, unsigned OpNo, SStream *O);
44
static void printCustomAliasOperand( MCInst *, unsigned, unsigned, SStream *);
45
/// getRegisterName - This method is automatically generated by tblgen
46
/// from the register set description.  This returns the assembler name
47
/// for the specified register.
48
static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
49
50
// Include the auto-generated portion of the assembly writer.
51
#define PRINT_ALIAS_INSTR
52
#include "RISCVGenAsmWriter.inc"
53
54
55
static void fixDetailOfEffectiveAddr(MCInst *MI)
56
1.55k
{
57
1.55k
  unsigned reg = 0;
58
1.55k
  int64_t imm = 0;
59
60
1.55k
  CS_ASSERT(3 == MI->flat_insn->detail->riscv.op_count);
61
1.55k
  CS_ASSERT(RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[0].type);
62
63
1.55k
  if (RISCV_OP_IMM == MI->flat_insn->detail->riscv.operands[1].type) {
64
1.55k
    CS_ASSERT(RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[2].type);
65
1.55k
    imm = MI->flat_insn->detail->riscv.operands[1].imm;
66
1.55k
    reg = MI->flat_insn->detail->riscv.operands[2].reg;
67
1.55k
  } else if (RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[1].type) {
68
0
    CS_ASSERT(RISCV_OP_IMM == MI->flat_insn->detail->riscv.operands[2].type);
69
0
    reg = MI->flat_insn->detail->riscv.operands[1].reg;
70
0
    imm = MI->flat_insn->detail->riscv.operands[2].imm;
71
0
  }
72
73
  // set up effective address.
74
1.55k
  MI->flat_insn->detail->riscv.operands[1].type = RISCV_OP_MEM;
75
1.55k
  MI->flat_insn->detail->riscv.op_count--;
76
1.55k
      MI->flat_insn->detail->riscv.operands[1].mem.base = reg;
77
1.55k
      MI->flat_insn->detail->riscv.operands[1].mem.disp = imm;
78
79
1.55k
  return;
80
1.55k
}
81
82
83
//void RISCVInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
84
//                                 StringRef Annot, const MCSubtargetInfo &STI) 
85
void RISCV_printInst(MCInst *MI, SStream *O, void *info) 
86
247k
{
87
247k
    MCRegisterInfo *MRI = (MCRegisterInfo *) info;
88
    //bool Res = false;
89
    //MCInst *NewMI = MI;
90
    // TODO: RISCV compressd instructions.
91
    //MCInst UncompressedMI;
92
    //if (!NoAliases)
93
      //Res = uncompressInst(UncompressedMI, *MI, MRI, STI);
94
    //if (Res)
95
      //NewMI = const_cast<MCInst *>(&UncompressedMI);
96
247k
    if (/*NoAliases ||*/ !printAliasInstr(MI, O, info))
97
182k
        printInstruction(MI, O, MRI);
98
      //printAnnotation(O, Annot);
99
  // fix load/store type insttuction
100
247k
      if (MI->csh->detail && 
101
247k
      MI->flat_insn->detail->riscv.need_effective_addr)
102
15.6k
    fixDetailOfEffectiveAddr(MI);
103
  
104
247k
  return;
105
247k
}
106
107
static void printRegName(SStream *OS, unsigned RegNo) 
108
420k
{
109
420k
    SStream_concat0(OS, getRegisterName(RegNo, RISCV_ABIRegAltName));
110
420k
}
111
112
/**
113
void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
114
                                    raw_ostream &O, const char *Modifier) 
115
*/
116
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) 
117
274k
{
118
274k
    unsigned reg;
119
274k
    int64_t Imm = 0;
120
121
274k
    MCOperand *MO = MCInst_getOperand(MI, OpNo);
122
  
123
274k
    if (MCOperand_isReg(MO)) {
124
228k
        reg = MCOperand_getReg(MO);
125
228k
        printRegName(O, reg);
126
228k
        if (MI->csh->detail) {
127
228k
            MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].type = RISCV_OP_REG;
128
228k
            MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].reg = reg;
129
228k
            MI->flat_insn->detail->riscv.op_count++;
130
228k
        }
131
228k
    } else {
132
45.7k
    CS_ASSERT(MCOperand_isImm(MO) && "Unknown operand kind in printOperand");
133
45.7k
        Imm = MCOperand_getImm(MO);
134
45.7k
        if (Imm >= 0) {
135
43.1k
            if (Imm > HEX_THRESHOLD)
136
29.4k
              SStream_concat(O, "0x%" PRIx64, Imm);
137
13.7k
            else
138
13.7k
        SStream_concat(O, "%" PRIu64, Imm);
139
43.1k
        } else {
140
2.55k
            if (Imm < -HEX_THRESHOLD)
141
2.17k
        SStream_concat(O, "-0x%" PRIx64, -Imm);
142
381
            else
143
381
        SStream_concat(O, "-%" PRIu64, -Imm);
144
2.55k
        }
145
146
45.7k
        if (MI->csh->detail) {
147
45.7k
            MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].type = RISCV_OP_IMM;
148
45.7k
            MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].imm = Imm;
149
45.7k
            MI->flat_insn->detail->riscv.op_count++;
150
45.7k
    }
151
45.7k
      }
152
153
    //CS_ASSERT(MO.isExpr() && "Unknown operand kind in printOperand");
154
  
155
274k
  return;
156
274k
}
157
158
static const char *getCSRSystemRegisterName(unsigned CsrNo)
159
143k
{
160
143k
  switch (CsrNo) {
161
  /*
162
   * From RISC-V Privileged Architecture Version 1.10.
163
   * In the same order as Table 2.5.
164
   */
165
324
  case 0x0000: return "ustatus";
166
792
  case 0x0004: return "uie";
167
201
  case 0x0005: return "utvec";
168
169
188
  case 0x0040: return "uscratch";
170
313
  case 0x0041: return "uepc";
171
1.02k
  case 0x0042: return "ucause";
172
240
  case 0x0043: return "utval";
173
101
  case 0x0044: return "uip";
174
175
1.00k
  case 0x0001: return "fflags";
176
988
  case 0x0002: return "frm";
177
948
  case 0x0003: return "fcsr";
178
179
1.22k
  case 0x0c00: return "cycle";
180
2.26k
  case 0x0c01: return "time";
181
721
  case 0x0c02: return "instret";
182
240
  case 0x0c03: return "hpmcounter3";
183
788
  case 0x0c04: return "hpmcounter4";
184
303
  case 0x0c05: return "hpmcounter5";
185
447
  case 0x0c06: return "hpmcounter6";
186
608
  case 0x0c07: return "hpmcounter7";
187
645
  case 0x0c08: return "hpmcounter8";
188
928
  case 0x0c09: return "hpmcounter9";
189
502
  case 0x0c0a: return "hpmcounter10";
190
634
  case 0x0c0b: return "hpmcounter11";
191
472
  case 0x0c0c: return "hpmcounter12";
192
667
  case 0x0c0d: return "hpmcounter13";
193
351
  case 0x0c0e: return "hpmcounter14";
194
928
  case 0x0c0f: return "hpmcounter15";
195
494
  case 0x0c10: return "hpmcounter16";
196
591
  case 0x0c11: return "hpmcounter17";
197
331
  case 0x0c12: return "hpmcounter18";
198
166
  case 0x0c13: return "hpmcounter19";
199
1.58k
  case 0x0c14: return "hpmcounter20";
200
197
  case 0x0c15: return "hpmcounter21";
201
321
  case 0x0c16: return "hpmcounter22";
202
1.67k
  case 0x0c17: return "hpmcounter23";
203
291
  case 0x0c18: return "hpmcounter24";
204
509
  case 0x0c19: return "hpmcounter25";
205
405
  case 0x0c1a: return "hpmcounter26";
206
1.12k
  case 0x0c1b: return "hpmcounter27";
207
503
  case 0x0c1c: return "hpmcounter28";
208
128
  case 0x0c1d: return "hpmcounter29";
209
1.88k
  case 0x0c1e: return "hpmcounter30";
210
971
  case 0x0c1f: return "hpmcounter31";
211
372
  case 0x0c80: return "cycleh";
212
361
  case 0x0c81: return "timeh";
213
1.71k
  case 0x0c82: return "instreth";
214
798
  case 0x0c83: return "hpmcounter3h";
215
140
  case 0x0c84: return "hpmcounter4h";
216
578
  case 0x0c85: return "hpmcounter5h";
217
1.12k
  case 0x0c86: return "hpmcounter6h";
218
824
  case 0x0c87: return "hpmcounter7h";
219
250
  case 0x0c88: return "hpmcounter8h";
220
112
  case 0x0c89: return "hpmcounter9h";
221
675
  case 0x0c8a: return "hpmcounter10h";
222
211
  case 0x0c8b: return "hpmcounter11h";
223
598
  case 0x0c8c: return "hpmcounter12h";
224
650
  case 0x0c8d: return "hpmcounter13h";
225
272
  case 0x0c8e: return "hpmcounter14h";
226
465
  case 0x0c8f: return "hpmcounter15h";
227
1.00k
  case 0x0c90: return "hpmcounter16h";
228
463
  case 0x0c91: return "hpmcounter17h";
229
1.13k
  case 0x0c92: return "hpmcounter18h";
230
313
  case 0x0c93: return "hpmcounter19h";
231
209
  case 0x0c94: return "hpmcounter20h";
232
547
  case 0x0c95: return "hpmcounter21h";
233
237
  case 0x0c96: return "hpmcounter22h";
234
195
  case 0x0c97: return "hpmcounter23h";
235
207
  case 0x0c98: return "hpmcounter24h";
236
784
  case 0x0c99: return "hpmcounter25h";
237
334
  case 0x0c9a: return "hpmcounter26h";
238
1.01k
  case 0x0c9b: return "hpmcounter27h";
239
852
  case 0x0c9c: return "hpmcounter28h";
240
1.36k
  case 0x0c9d: return "hpmcounter29h";
241
260
  case 0x0c9e: return "hpmcounter30h";
242
990
  case 0x0c9f: return "hpmcounter31h";
243
244
588
  case 0x0100: return "sstatus";
245
973
  case 0x0102: return "sedeleg";
246
441
  case 0x0103: return "sideleg";
247
468
  case 0x0104: return "sie";
248
1.45k
  case 0x0105: return "stvec";
249
729
  case 0x0106: return "scounteren";
250
251
171
  case 0x0140: return "sscratch";
252
958
  case 0x0141: return "sepc";
253
327
  case 0x0142: return "scause";
254
252
  case 0x0143: return "stval";
255
804
  case 0x0144: return "sip";
256
257
264
  case 0x0180: return "satp";
258
259
150
  case 0x0f11: return "mvendorid";
260
152
  case 0x0f12: return "marchid";
261
490
  case 0x0f13: return "mimpid";
262
77
  case 0x0f14: return "mhartid";
263
264
123
  case 0x0300: return "mstatus";
265
174
  case 0x0301: return "misa";
266
1.30k
  case 0x0302: return "medeleg";
267
569
  case 0x0303: return "mideleg";
268
325
  case 0x0304: return "mie";
269
718
  case 0x0305: return "mtvec";
270
155
  case 0x0306: return "mcounteren";
271
272
237
  case 0x0340: return "mscratch";
273
777
  case 0x0341: return "mepc";
274
753
  case 0x0342: return "mcause";
275
174
  case 0x0343: return "mtval";
276
979
  case 0x0344: return "mip";
277
278
156
  case 0x03a0: return "pmpcfg0";
279
341
  case 0x03a1: return "pmpcfg1";
280
495
  case 0x03a2: return "pmpcfg2";
281
160
  case 0x03a3: return "pmpcfg3";
282
814
  case 0x03b0: return "pmpaddr0";
283
226
  case 0x03b1: return "pmpaddr1";
284
659
  case 0x03b2: return "pmpaddr2";
285
584
  case 0x03b3: return "pmpaddr3";
286
126
  case 0x03b4: return "pmpaddr4";
287
945
  case 0x03b5: return "pmpaddr5";
288
284
  case 0x03b6: return "pmpaddr6";
289
489
  case 0x03b7: return "pmpaddr7";
290
143
  case 0x03b8: return "pmpaddr8";
291
619
  case 0x03b9: return "pmpaddr9";
292
100
  case 0x03ba: return "pmpaddr10";
293
846
  case 0x03bb: return "pmpaddr11";
294
1.01k
  case 0x03bc: return "pmpaddr12";
295
405
  case 0x03bd: return "pmpaddr14";
296
483
  case 0x03be: return "pmpaddr13";
297
765
  case 0x03bf: return "pmpaddr15";
298
299
622
  case 0x0b00: return "mcycle";
300
626
  case 0x0b02: return "minstret";
301
1.00k
  case 0x0b03: return "mhpmcounter3";
302
284
  case 0x0b04: return "mhpmcounter4";
303
547
  case 0x0b05: return "mhpmcounter5";
304
225
  case 0x0b06: return "mhpmcounter6";
305
859
  case 0x0b07: return "mhpmcounter7";
306
129
  case 0x0b08: return "mhpmcounter8";
307
103
  case 0x0b09: return "mhpmcounter9";
308
109
  case 0x0b0a: return "mhpmcounter10";
309
574
  case 0x0b0b: return "mhpmcounter11";
310
157
  case 0x0b0c: return "mhpmcounter12";
311
210
  case 0x0b0d: return "mhpmcounter13";
312
152
  case 0x0b0e: return "mhpmcounter14";
313
211
  case 0x0b0f: return "mhpmcounter15";
314
446
  case 0x0b10: return "mhpmcounter16";
315
555
  case 0x0b11: return "mhpmcounter17";
316
679
  case 0x0b12: return "mhpmcounter18";
317
344
  case 0x0b13: return "mhpmcounter19";
318
644
  case 0x0b14: return "mhpmcounter20";
319
819
  case 0x0b15: return "mhpmcounter21";
320
464
  case 0x0b16: return "mhpmcounter22";
321
160
  case 0x0b17: return "mhpmcounter23";
322
333
  case 0x0b18: return "mhpmcounter24";
323
245
  case 0x0b19: return "mhpmcounter25";
324
407
  case 0x0b1a: return "mhpmcounter26";
325
308
  case 0x0b1b: return "mhpmcounter27";
326
562
  case 0x0b1c: return "mhpmcounter28";
327
653
  case 0x0b1d: return "mhpmcounter29";
328
234
  case 0x0b1e: return "mhpmcounter30";
329
429
  case 0x0b1f: return "mhpmcounter31";
330
1.82k
  case 0x0b80: return "mcycleh";
331
221
  case 0x0b82: return "minstreth";
332
102
  case 0x0b83: return "mhpmcounter3h";
333
179
  case 0x0b84: return "mhpmcounter4h";
334
132
  case 0x0b85: return "mhpmcounter5h";
335
133
  case 0x0b86: return "mhpmcounter6h";
336
286
  case 0x0b87: return "mhpmcounter7h";
337
84
  case 0x0b88: return "mhpmcounter8h";
338
156
  case 0x0b89: return "mhpmcounter9h";
339
331
  case 0x0b8a: return "mhpmcounter10h";
340
1.90k
  case 0x0b8b: return "mhpmcounter11h";
341
104
  case 0x0b8c: return "mhpmcounter12h";
342
140
  case 0x0b8d: return "mhpmcounter13h";
343
621
  case 0x0b8e: return "mhpmcounter14h";
344
925
  case 0x0b8f: return "mhpmcounter15h";
345
534
  case 0x0b90: return "mhpmcounter16h";
346
185
  case 0x0b91: return "mhpmcounter17h";
347
217
  case 0x0b92: return "mhpmcounter18h";
348
165
  case 0x0b93: return "mhpmcounter19h";
349
182
  case 0x0b94: return "mhpmcounter20h";
350
326
  case 0x0b95: return "mhpmcounter21h";
351
160
  case 0x0b96: return "mhpmcounter22h";
352
307
  case 0x0b97: return "mhpmcounter23h";
353
207
  case 0x0b98: return "mhpmcounter24h";
354
257
  case 0x0b99: return "mhpmcounter25h";
355
177
  case 0x0b9a: return "mhpmcounter26h";
356
1.12k
  case 0x0b9b: return "mhpmcounter27h";
357
1.09k
  case 0x0b9c: return "mhpmcounter28h";
358
484
  case 0x0b9d: return "mhpmcounter29h";
359
543
  case 0x0b9e: return "mhpmcounter30h";
360
226
  case 0x0b9f: return "mhpmcounter31h";
361
362
141
  case 0x0323: return "mhpmevent3";
363
183
  case 0x0324: return "mhpmevent4";
364
447
  case 0x0325: return "mhpmevent5";
365
131
  case 0x0326: return "mhpmevent6";
366
277
  case 0x0327: return "mhpmevent7";
367
1.06k
  case 0x0328: return "mhpmevent8";
368
226
  case 0x0329: return "mhpmevent9";
369
272
  case 0x032a: return "mhpmevent10";
370
551
  case 0x032b: return "mhpmevent11";
371
118
  case 0x032c: return "mhpmevent12";
372
492
  case 0x032d: return "mhpmevent13";
373
210
  case 0x032e: return "mhpmevent14";
374
77
  case 0x032f: return "mhpmevent15";
375
275
  case 0x0330: return "mhpmevent16";
376
521
  case 0x0331: return "mhpmevent17";
377
1.56k
  case 0x0332: return "mhpmevent18";
378
427
  case 0x0333: return "mhpmevent19";
379
1.10k
  case 0x0334: return "mhpmevent20";
380
642
  case 0x0335: return "mhpmevent21";
381
798
  case 0x0336: return "mhpmevent22";
382
162
  case 0x0337: return "mhpmevent23";
383
111
  case 0x0338: return "mhpmevent24";
384
933
  case 0x0339: return "mhpmevent25";
385
240
  case 0x033a: return "mhpmevent26";
386
764
  case 0x033b: return "mhpmevent27";
387
1.04k
  case 0x033c: return "mhpmevent28";
388
1.06k
  case 0x033d: return "mhpmevent29";
389
628
  case 0x033e: return "mhpmevent30";
390
782
  case 0x033f: return "mhpmevent31";
391
392
229
  case 0x07a0: return "tselect";
393
165
  case 0x07a1: return "tdata1";
394
1.65k
  case 0x07a2: return "tdata2";
395
424
  case 0x07a3: return "tdata3";
396
397
377
  case 0x07b0: return "dcsr";
398
173
  case 0x07b1: return "dpc";
399
156
  case 0x07b2: return "dscratch";
400
143k
  }
401
26.2k
  return NULL;
402
143k
}
403
404
static void printCSRSystemRegister(MCInst *MI, unsigned OpNo,
405
                                   //const MCSubtargetInfo &STI,
406
                                   SStream *O) 
407
143k
{
408
143k
  unsigned Imm = MCOperand_getImm(MCInst_getOperand(MI, OpNo));
409
143k
  const char *Name = getCSRSystemRegisterName(Imm);
410
411
143k
  if (Name) {
412
117k
    SStream_concat0(O, Name);
413
117k
  } else {
414
26.2k
    SStream_concat(O, "%u", Imm);
415
26.2k
  }
416
143k
}
417
418
static void printFenceArg(MCInst *MI, unsigned OpNo, SStream *O) 
419
4.89k
{
420
4.89k
    unsigned FenceArg = MCOperand_getImm(MCInst_getOperand(MI, OpNo));
421
    //CS_ASSERT (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg");
422
423
4.89k
    if ((FenceArg & RISCVFenceField_I) != 0)
424
2.47k
        SStream_concat0(O, "i");
425
4.89k
    if ((FenceArg & RISCVFenceField_O) != 0)
426
2.04k
        SStream_concat0(O, "o");
427
4.89k
  if ((FenceArg & RISCVFenceField_R) != 0)
428
2.37k
        SStream_concat0(O, "r");
429
4.89k
    if ((FenceArg & RISCVFenceField_W) != 0)
430
2.28k
        SStream_concat0(O, "w");
431
4.89k
    if (FenceArg == 0)
432
1.22k
        SStream_concat0(O, "unknown");
433
4.89k
}
434
435
static void printFRMArg(MCInst *MI, unsigned OpNo, SStream *O) 
436
24.2k
{
437
24.2k
    enum RoundingMode FRMArg = 
438
24.2k
        (enum RoundingMode)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
439
#if 0
440
  auto FRMArg =
441
      static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());
442
  O << RISCVFPRndMode::roundingModeToString(FRMArg);
443
#endif
444
24.2k
    SStream_concat0(O, roundingModeToString(FRMArg));
445
24.2k
}
446
  
447
#endif        // CAPSTONE_HAS_RISCV