205 lines
6.7 KiB
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
|