capstone/arch/RISCV/RISCVInstPrinter.c

205 lines
6.7 KiB
C

//===-- 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