aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/arch/RISCV/RISCVInstPrinter.c
blob: 51d7b574be10c71f94a9240719aaa013a4b03243 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//===-- RISCVInstPrinter.cpp - Convert RISCV MCInst to asm syntax ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an RISCV MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#ifdef CAPSTONE_HAS_RISCV

#include <stdio.h>		// DEBUG
#include <stdlib.h>
#include <string.h>
#include <capstone/platform.h>

#include "RISCVInstPrinter.h"
#include "RISCVBaseInfo.h"
#include "../../MCInst.h"
#include "../../SStream.h"
#include "../../MCRegisterInfo.h"
#include "../../utils.h"
#include "RISCVMapping.h"

//#include "RISCVDisassembler.h"

#define GET_REGINFO_ENUM
#define GET_REGINFO_MC_DESC
#include "RISCVGenRegisterInfo.inc"
#define GET_INSTRINFO_ENUM
#include "RISCVGenInstrInfo.inc"

// Autogenerated by tblgen.
static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
static bool printAliasInstr(MCInst *MI, SStream *OS, void *info);
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
static void printFenceArg(MCInst *MI, unsigned OpNo, SStream *O);
static void printCSRSystemRegister(const MCInst*, unsigned, SStream *);
static void printFRMArg(MCInst *MI, unsigned OpNo, SStream *O);
static void printCustomAliasOperand( MCInst *, unsigned, unsigned, SStream *);
/// getRegisterName - This method is automatically generated by tblgen
/// from the register set description.  This returns the assembler name
/// for the specified register.
static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);

// Include the auto-generated portion of the assembly writer.
#define PRINT_ALIAS_INSTR
#include "RISCVGenAsmWriter.inc"


static void fixDetailOfEffectiveAddr(MCInst *MI)
{
	unsigned reg = 0;
	int64_t imm = 0;

	CS_ASSERT(3 == MI->flat_insn->detail->riscv.op_count);
	CS_ASSERT(RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[0].type);

	if (RISCV_OP_IMM == MI->flat_insn->detail->riscv.operands[1].type) {
		CS_ASSERT(RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[2].type);
		imm = MI->flat_insn->detail->riscv.operands[1].imm;
		reg = MI->flat_insn->detail->riscv.operands[2].reg;
	} else if (RISCV_OP_REG == MI->flat_insn->detail->riscv.operands[1].type) {
		CS_ASSERT(RISCV_OP_IMM == MI->flat_insn->detail->riscv.operands[2].type);
		reg = MI->flat_insn->detail->riscv.operands[1].reg;
		imm = MI->flat_insn->detail->riscv.operands[2].imm;
	}

	// set up effective address.
	MI->flat_insn->detail->riscv.operands[1].type = RISCV_OP_MEM;
	MI->flat_insn->detail->riscv.op_count--;
     	MI->flat_insn->detail->riscv.operands[1].mem.base = reg;
     	MI->flat_insn->detail->riscv.operands[1].mem.disp = imm;

	return;
}


//void RISCVInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
//                                 StringRef Annot, const MCSubtargetInfo &STI) 
void RISCV_printInst(MCInst *MI, SStream *O, void *info) 
{
  	MCRegisterInfo *MRI = (MCRegisterInfo *) info;
  	//bool Res = false;
  	//MCInst *NewMI = MI;
  	// TODO: RISCV compressd instructions.
  	//MCInst UncompressedMI;
  	//if (!NoAliases)
    	//Res = uncompressInst(UncompressedMI, *MI, MRI, STI);
  	//if (Res)
    	//NewMI = const_cast<MCInst *>(&UncompressedMI);
  	if (/*NoAliases ||*/ !printAliasInstr(MI, O, info))
    		printInstruction(MI, O, MRI);
  		//printAnnotation(O, Annot);
	// fix load/store type insttuction
    	if (MI->csh->detail && 
	    MI->flat_insn->detail->riscv.need_effective_addr)
		fixDetailOfEffectiveAddr(MI);
	
	return;
}

static void printRegName(SStream *OS, unsigned RegNo) 
{
  	SStream_concat0(OS, getRegisterName(RegNo, RISCV_ABIRegAltName));
}

/**
void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O, const char *Modifier) 
*/
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) 
{
  	unsigned reg;
  	int64_t Imm = 0;

  	MCOperand *MO = MCInst_getOperand(MI, OpNo);
  
  	if (MCOperand_isReg(MO)) {
    		reg = MCOperand_getReg(MO);
    		printRegName(O, reg);
    		if (MI->csh->detail) {
      			MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].type = RISCV_OP_REG;
      			MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].reg = reg;
      			MI->flat_insn->detail->riscv.op_count++;
    		}
  	} else {
		CS_ASSERT(MCOperand_isImm(MO) && "Unknown operand kind in printOperand");
    		Imm = MCOperand_getImm(MO);
    		if (Imm >= 0) {
      			if (Imm > HEX_THRESHOLD)
        			SStream_concat(O, "0x%" PRIx64, Imm);
      			else
				SStream_concat(O, "%" PRIu64, Imm);
    		} else {
      			if (Imm < -HEX_THRESHOLD)
				SStream_concat(O, "-0x%" PRIx64, -Imm);
      			else
				SStream_concat(O, "-%" PRIu64, -Imm);
    		}

    		if (MI->csh->detail) {
      			MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].type = RISCV_OP_IMM;
      			MI->flat_insn->detail->riscv.operands[MI->flat_insn->detail->riscv.op_count].imm = Imm;
      			MI->flat_insn->detail->riscv.op_count++;
		}
    	}

  	//CS_ASSERT(MO.isExpr() && "Unknown operand kind in printOperand");
	
	return;
}

static void printCSRSystemRegister(const MCInst *MI, unsigned OpNo,
                                   //const MCSubtargetInfo &STI,
                                   SStream *O) 
{
	// TODO: Not yeat implementated.
	return;
  	//CS_ASSERT (0 && "CSR system register hav't support.");
#if 0
  unsigned Imm = MI->getOperand(OpNo).getImm();
  auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
  if (SysReg && SysReg->haveRequiredFeatures(STI.getFeatureBits()))
    O << SysReg->Name;
  else
    O << Imm;
#endif
}

static void printFenceArg(MCInst *MI, unsigned OpNo, SStream *O) 
{
  	unsigned FenceArg = MCOperand_getImm(MCInst_getOperand(MI, OpNo));
  	//CS_ASSERT (((FenceArg >> 4) == 0) && "Invalid immediate in printFenceArg");

  	if ((FenceArg & RISCVFenceField_I) != 0)
    		SStream_concat0(O, "i");
  	if ((FenceArg & RISCVFenceField_O) != 0)
    		SStream_concat0(O, "o");
 	if ((FenceArg & RISCVFenceField_R) != 0)
    		SStream_concat0(O, "r");
  	if ((FenceArg & RISCVFenceField_W) != 0)
    		SStream_concat0(O, "w");
  	if (FenceArg == 0)
    		SStream_concat0(O, "unknown");
}

static void printFRMArg(MCInst *MI, unsigned OpNo, SStream *O) 
{
  	enum RoundingMode FRMArg = 
    	  (enum RoundingMode)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
#if 0
  auto FRMArg =
      static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());
  O << RISCVFPRndMode::roundingModeToString(FRMArg);
#endif
  	SStream_concat0(O, roundingModeToString(FRMArg));
}
  
#endif				// CAPSTONE_HAS_RISCV