//===-- 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 // DEBUG #include #include #include #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(&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(MI->getOperand(OpNo).getImm()); O << RISCVFPRndMode::roundingModeToString(FRMArg); #endif SStream_concat0(O, roundingModeToString(FRMArg)); } #endif // CAPSTONE_HAS_RISCV