aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/arch/RISCV/RISCVInstPrinter.c
diff options
context:
space:
mode:
Diffstat (limited to 'capstone/arch/RISCV/RISCVInstPrinter.c')
-rw-r--r--capstone/arch/RISCV/RISCVInstPrinter.c204
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