diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/arch/RISCV/RISCVInstPrinter.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/arch/RISCV/RISCVInstPrinter.c')
-rw-r--r-- | capstone/arch/RISCV/RISCVInstPrinter.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/capstone/arch/RISCV/RISCVInstPrinter.c b/capstone/arch/RISCV/RISCVInstPrinter.c new file mode 100644 index 000000000..51d7b574b --- /dev/null +++ b/capstone/arch/RISCV/RISCVInstPrinter.c @@ -0,0 +1,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 |