802798ce3c
git-subtree-dir: external/capstone git-subtree-split: e46f64fadb351e9ecd05264fab26f2772feb0994
754 lines
24 KiB
C
754 lines
24 KiB
C
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
|
|
/* Rot127 <unisono@quyllur.org> 2022-2023 */
|
|
/* Automatically translated source file from LLVM. */
|
|
|
|
/* LLVM-commit: <commit> */
|
|
/* LLVM-tag: <tag> */
|
|
|
|
/* Only small edits allowed. */
|
|
/* For multiple similar edits, please create a Patch for the translator. */
|
|
|
|
/* Capstone's C++ file translator: */
|
|
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
|
|
|
|
//===-- RISCVDisassembler.cpp - Disassembler for RISC-V -------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the RISCVDisassembler class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <capstone/platform.h>
|
|
|
|
#include "../../MCInst.h"
|
|
#include "../../MathExtras.h"
|
|
#include "../../MCInstPrinter.h"
|
|
#include "../../MCDisassembler.h"
|
|
#include "../../MCFixedLenDisassembler.h"
|
|
#include "../../cs_priv.h"
|
|
#include "../../utils.h"
|
|
#include "RISCVDisassemblerExtension.h"
|
|
#include "RISCVBaseInfo.h"
|
|
#include "RISCVMapping.h"
|
|
|
|
#define GET_SUBTARGETINFO_ENUM
|
|
#include "RISCVGenSubtargetInfo.inc"
|
|
|
|
#define GET_REGINFO_ENUM
|
|
#include "RISCVGenRegisterInfo.inc"
|
|
|
|
#define GET_INSTRINFO_ENUM
|
|
#define GET_INSTRINFO_MC_DESC
|
|
#include "RISCVGenInstrInfo.inc"
|
|
|
|
#define CONCAT(a, b) CONCAT_(a, b)
|
|
#define CONCAT_(a, b) a##_##b
|
|
|
|
#define DEBUG_TYPE "riscv-disassembler"
|
|
|
|
DecodeStatus RISCV_getInstruction(MCInst *Instr, uint16_t *Size,
|
|
const uint8_t *Bytes, size_t BytesLen,
|
|
uint64_t Address, SStream *CStream);
|
|
void addSPOperands(MCInst *MI);
|
|
;
|
|
// end anonymous namespace
|
|
|
|
static DecodeStatus DecodeGPRRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
bool IsRVE = RISCV_getFeatureBits(Inst->csh->mode, RISCV_FeatureRVE);
|
|
|
|
if (RegNo >= 32 || (IsRVE && RegNo >= 16))
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_X0 + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeGPRX1X5RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
MCRegister Reg = RISCV_X0 + RegNo;
|
|
if (Reg != RISCV_X1 && Reg != RISCV_X5)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_F0_H + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_F0_F + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeFPR32CRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 8) {
|
|
return MCDisassembler_Fail;
|
|
}
|
|
MCRegister Reg = RISCV_F8_F + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_F0_D + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeFPR64CRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 8) {
|
|
return MCDisassembler_Fail;
|
|
}
|
|
MCRegister Reg = RISCV_F8_D + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo == 0) {
|
|
return MCDisassembler_Fail;
|
|
}
|
|
|
|
return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
|
|
}
|
|
|
|
static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst *Inst, uint64_t RegNo,
|
|
uint32_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo == 2) {
|
|
return MCDisassembler_Fail;
|
|
}
|
|
|
|
return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
|
|
}
|
|
|
|
static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 8)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_X8 + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeGPRPairRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32 || RegNo & 1)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_X0 + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeSR07RegisterClass(MCInst *Inst, uint64_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 8)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = (RegNo < 2) ? (RegNo + RISCV_X8) :
|
|
(RegNo - 2 + RISCV_X18);
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeVRRegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
if (RegNo >= 32)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = RISCV_V0 + RegNo;
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeVRM2RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32 || RegNo % 2)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = MCRegisterInfo_getMatchingSuperReg(
|
|
Inst->MRI, RISCV_V0 + RegNo, RISCV_sub_vrm1_0,
|
|
MCRegisterInfo_getRegClass(Inst->MRI, RISCV_VRM2RegClassID));
|
|
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeVRM4RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32 || RegNo % 4)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = MCRegisterInfo_getMatchingSuperReg(
|
|
Inst->MRI, RISCV_V0 + RegNo, RISCV_sub_vrm1_0,
|
|
MCRegisterInfo_getRegClass(Inst->MRI, RISCV_VRM4RegClassID));
|
|
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus DecodeVRM8RegisterClass(MCInst *Inst, uint32_t RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (RegNo >= 32 || RegNo % 8)
|
|
return MCDisassembler_Fail;
|
|
|
|
MCRegister Reg = MCRegisterInfo_getMatchingSuperReg(
|
|
Inst->MRI, RISCV_V0 + RegNo, RISCV_sub_vrm1_0,
|
|
MCRegisterInfo_getRegClass(Inst->MRI, RISCV_VRM8RegClassID));
|
|
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeVMaskReg(MCInst *Inst, uint64_t RegNo,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
if (RegNo > 2) {
|
|
return MCDisassembler_Fail;
|
|
}
|
|
MCRegister Reg = (RegNo == 0) ? RISCV_V0 : RISCV_NoRegister;
|
|
|
|
MCOperand_CreateReg0(Inst, (Reg));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
#define DEFINE_decodeUImmOperand(N) \
|
|
static DecodeStatus CONCAT(decodeUImmOperand, \
|
|
N)(MCInst * Inst, uint32_t Imm, \
|
|
int64_t Address, const void *Decoder) \
|
|
{ \
|
|
CS_ASSERT(isUIntN(N, Imm) && "Invalid immediate"); \
|
|
MCOperand_CreateImm0(Inst, (Imm)); \
|
|
return MCDisassembler_Success; \
|
|
}
|
|
DEFINE_decodeUImmOperand(6);
|
|
DEFINE_decodeUImmOperand(2);
|
|
DEFINE_decodeUImmOperand(8);
|
|
DEFINE_decodeUImmOperand(9);
|
|
DEFINE_decodeUImmOperand(7);
|
|
DEFINE_decodeUImmOperand(4);
|
|
DEFINE_decodeUImmOperand(20);
|
|
DEFINE_decodeUImmOperand(5);
|
|
DEFINE_decodeUImmOperand(11);
|
|
DEFINE_decodeUImmOperand(10);
|
|
DEFINE_decodeUImmOperand(12);
|
|
DEFINE_decodeUImmOperand(3);
|
|
DEFINE_decodeUImmOperand(1);
|
|
|
|
#define DEFINE_decodeUImmNonZeroOperand(N) \
|
|
static DecodeStatus CONCAT(decodeUImmNonZeroOperand, \
|
|
N)(MCInst * Inst, uint32_t Imm, \
|
|
int64_t Address, const void *Decoder) \
|
|
{ \
|
|
if (Imm == 0) \
|
|
return MCDisassembler_Fail; \
|
|
return CONCAT(decodeUImmOperand, N)(Inst, Imm, Address, \
|
|
Decoder); \
|
|
}
|
|
DEFINE_decodeUImmNonZeroOperand(10);
|
|
|
|
#define DEFINE_decodeSImmOperand(N) \
|
|
static DecodeStatus CONCAT(decodeSImmOperand, \
|
|
N)(MCInst * Inst, uint32_t Imm, \
|
|
int64_t Address, const void *Decoder) \
|
|
{ \
|
|
CS_ASSERT(isUIntN(N, Imm) && "Invalid immediate"); \
|
|
\
|
|
MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \
|
|
return MCDisassembler_Success; \
|
|
}
|
|
DEFINE_decodeSImmOperand(6);
|
|
DEFINE_decodeSImmOperand(12);
|
|
DEFINE_decodeSImmOperand(5);
|
|
DEFINE_decodeSImmOperand(10);
|
|
|
|
#define DEFINE_decodeSImmNonZeroOperand(N) \
|
|
static DecodeStatus CONCAT(decodeSImmNonZeroOperand, \
|
|
N)(MCInst * Inst, uint32_t Imm, \
|
|
int64_t Address, const void *Decoder) \
|
|
{ \
|
|
if (Imm == 0) \
|
|
return MCDisassembler_Fail; \
|
|
return CONCAT(decodeSImmOperand, N)(Inst, Imm, Address, \
|
|
Decoder); \
|
|
}
|
|
DEFINE_decodeSImmNonZeroOperand(6);
|
|
DEFINE_decodeSImmNonZeroOperand(10);
|
|
|
|
#define DEFINE_decodeSImmOperandAndLsl1(N) \
|
|
static DecodeStatus CONCAT(decodeSImmOperandAndLsl1, \
|
|
N)(MCInst * Inst, uint32_t Imm, \
|
|
int64_t Address, const void *Decoder) \
|
|
{ \
|
|
CS_ASSERT(isUIntN(N, Imm) && "Invalid immediate"); \
|
|
\
|
|
MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 1), N))); \
|
|
return MCDisassembler_Success; \
|
|
}
|
|
DEFINE_decodeSImmOperandAndLsl1(12);
|
|
DEFINE_decodeSImmOperandAndLsl1(9);
|
|
DEFINE_decodeSImmOperandAndLsl1(13);
|
|
DEFINE_decodeSImmOperandAndLsl1(21);
|
|
|
|
static DecodeStatus decodeCLUIImmOperand(MCInst *Inst, uint32_t Imm,
|
|
int64_t Address, const void *Decoder)
|
|
{
|
|
CS_ASSERT(isUIntN(6, Imm) && "Invalid immediate");
|
|
if (Imm > 31) {
|
|
Imm = (SignExtend64((Imm), 6) & 0xfffff);
|
|
}
|
|
MCOperand_CreateImm0(Inst, (Imm));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeFRMArg(MCInst *Inst, uint32_t Imm, int64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
CS_ASSERT(isUIntN(3, Imm) && "Invalid immediate");
|
|
if (!RISCVFPRndMode_isValidRoundingMode(Imm))
|
|
return MCDisassembler_Fail;
|
|
|
|
MCOperand_CreateImm0(Inst, (Imm));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
|
|
static DecodeStatus decodeRVCInstrRdSImm(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs2(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
|
|
static DecodeStatus decodeXTHeadMemPair(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeZcmpRlist(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeRegReg(MCInst *Inst, uint32_t Insn, uint64_t Address,
|
|
const void *Decoder);
|
|
|
|
static DecodeStatus decodeZcmpSpimm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeCSSPushPopchk(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus decodeUImmLog2XLenOperand(MCInst *Inst, uint32_t Imm,
|
|
int64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
CS_ASSERT(isUIntN(6, Imm) && "Invalid immediate");
|
|
|
|
if (!RISCV_getFeatureBits(Inst->csh->mode, RISCV_Feature64Bit) &&
|
|
!isUIntN(5, Imm))
|
|
return MCDisassembler_Fail;
|
|
|
|
MCOperand_CreateImm0(Inst, (Imm));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeUImmLog2XLenNonZeroOperand(MCInst *Inst, uint32_t Imm,
|
|
int64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
if (Imm == 0)
|
|
return MCDisassembler_Fail;
|
|
return decodeUImmLog2XLenOperand(Inst, Imm, Address, Decoder);
|
|
}
|
|
|
|
#include "RISCVGenDisassemblerTables.inc"
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1ImmZero(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
uint32_t Rd = fieldFromInstruction_4(Insn, 7, 5);
|
|
DecodeStatus Result =
|
|
DecodeGPRNoX0RegisterClass(Inst, Rd, Address, Decoder);
|
|
(void)Result;
|
|
CS_ASSERT(Result == MCDisassembler_Success && "Invalid register");
|
|
MCInst_addOperand2(Inst, (MCInst_getOperand(Inst, (0))));
|
|
MCOperand_CreateImm0(Inst, (0));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeCSSPushPopchk(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
uint32_t Rs1 = fieldFromInstruction_4(Insn, 7, 5);
|
|
DecodeStatus Result =
|
|
DecodeGPRX1X5RegisterClass(Inst, Rs1, Address, Decoder);
|
|
(void)Result;
|
|
CS_ASSERT(Result == MCDisassembler_Success && "Invalid register");
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRVCInstrRdSImm(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
MCOperand_CreateReg0(Inst, (RISCV_X0));
|
|
uint32_t SImm6 = fieldFromInstruction_4(Insn, 12, 1) << 5 |
|
|
fieldFromInstruction_4(Insn, 2, 5);
|
|
DecodeStatus Result =
|
|
CONCAT(decodeSImmOperand, 6)(Inst, SImm6, Address, Decoder);
|
|
(void)Result;
|
|
CS_ASSERT(Result == MCDisassembler_Success && "Invalid immediate");
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
MCOperand_CreateReg0(Inst, (RISCV_X0));
|
|
MCInst_addOperand2(Inst, (MCInst_getOperand(Inst, (0))));
|
|
uint32_t UImm6 = fieldFromInstruction_4(Insn, 12, 1) << 5 |
|
|
fieldFromInstruction_4(Insn, 2, 5);
|
|
DecodeStatus Result =
|
|
CONCAT(decodeUImmOperand, 6)(Inst, UImm6, Address, Decoder);
|
|
(void)Result;
|
|
CS_ASSERT(Result == MCDisassembler_Success && "Invalid immediate");
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs2(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
uint32_t Rd = fieldFromInstruction_4(Insn, 7, 5);
|
|
uint32_t Rs2 = fieldFromInstruction_4(Insn, 2, 5);
|
|
DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
|
|
DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
uint32_t Rd = fieldFromInstruction_4(Insn, 7, 5);
|
|
uint32_t Rs2 = fieldFromInstruction_4(Insn, 2, 5);
|
|
DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
|
|
MCInst_addOperand2(Inst, (MCInst_getOperand(Inst, (0))));
|
|
DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeXTHeadMemPair(MCInst *Inst, uint32_t Insn,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
uint32_t Rd1 = fieldFromInstruction_4(Insn, 7, 5);
|
|
uint32_t Rs1 = fieldFromInstruction_4(Insn, 15, 5);
|
|
uint32_t Rd2 = fieldFromInstruction_4(Insn, 20, 5);
|
|
uint32_t UImm2 = fieldFromInstruction_4(Insn, 25, 2);
|
|
DecodeGPRRegisterClass(Inst, Rd1, Address, Decoder);
|
|
DecodeGPRRegisterClass(Inst, Rd2, Address, Decoder);
|
|
DecodeGPRRegisterClass(Inst, Rs1, Address, Decoder);
|
|
DecodeStatus Result =
|
|
CONCAT(decodeUImmOperand, 2)(Inst, UImm2, Address, Decoder);
|
|
(void)Result;
|
|
CS_ASSERT(Result == MCDisassembler_Success && "Invalid immediate");
|
|
|
|
// Disassemble the final operand which is implicit.
|
|
unsigned Opcode = MCInst_getOpcode(Inst);
|
|
bool IsWordOp = (Opcode == RISCV_TH_LWD || Opcode == RISCV_TH_LWUD ||
|
|
Opcode == RISCV_TH_SWD);
|
|
if (IsWordOp)
|
|
MCOperand_CreateImm0(Inst, (3));
|
|
else
|
|
MCOperand_CreateImm0(Inst, (4));
|
|
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeZcmpRlist(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
if (Imm <= 3)
|
|
return MCDisassembler_Fail;
|
|
MCOperand_CreateImm0(Inst, (Imm));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeRegReg(MCInst *Inst, uint32_t Insn, uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
uint32_t Rs1 = fieldFromInstruction_4(Insn, 0, 5);
|
|
uint32_t Rs2 = fieldFromInstruction_4(Insn, 5, 5);
|
|
DecodeGPRRegisterClass(Inst, Rs1, Address, Decoder);
|
|
DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
static DecodeStatus decodeZcmpSpimm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder)
|
|
{
|
|
MCOperand_CreateImm0(Inst, (Imm));
|
|
return MCDisassembler_Success;
|
|
}
|
|
|
|
// Add implied SP operand for C.*SP compressed instructions. The SP operand
|
|
// isn't explicitly encoded in the instruction.
|
|
void addSPOperands(MCInst *MI)
|
|
{
|
|
const MCInstrDesc *MCID = MCInstrDesc_get(MCInst_getOpcode(MI),
|
|
RISCVDescs.Insts,
|
|
ARR_SIZE(RISCVDescs.Insts));
|
|
MCOperand SPReg;
|
|
SPReg.MachineOperandType = kRegister;
|
|
SPReg.Kind = kRegister;
|
|
SPReg.RegVal = RISCV_X2;
|
|
for (unsigned i = 0; i < MCID->NumOperands; i++)
|
|
if (MCID->OpInfo[i].RegClass == RISCV_SPRegClassID)
|
|
MCInst_insert0(MI, i, &SPReg);
|
|
}
|
|
|
|
DecodeStatus RISCV_getInstruction(MCInst *MI, uint16_t *Size,
|
|
const uint8_t *Bytes, size_t BytesLen,
|
|
uint64_t Address, SStream *CS)
|
|
{
|
|
// TODO: This will need modification when supporting instruction set
|
|
// extensions with instructions > 32-bits (up to 176 bits wide).
|
|
uint32_t Insn;
|
|
DecodeStatus Result;
|
|
|
|
#define TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION( \
|
|
width, FEATURE_CHECKS, DECODER_TABLE, DESC, ADDITIONAL_OPERATION) \
|
|
do { \
|
|
if (FEATURE_CHECKS) { \
|
|
Result = decodeInstruction_##width( \
|
|
DECODER_TABLE, MI, Insn, Address, NULL); \
|
|
if (Result != MCDisassembler_Fail) { \
|
|
ADDITIONAL_OPERATION; \
|
|
return Result; \
|
|
} \
|
|
} \
|
|
} while (false)
|
|
#define TRY_TO_DECODE_AND_ADD_SP(width, FEATURE_CHECKS, DECODER_TABLE, DESC) \
|
|
TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION( \
|
|
width, FEATURE_CHECKS, DECODER_TABLE, DESC, addSPOperands(MI))
|
|
#define TRY_TO_DECODE(width, FEATURE_CHECKS, DECODER_TABLE, DESC) \
|
|
TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION( \
|
|
width, FEATURE_CHECKS, DECODER_TABLE, DESC, (void)NULL)
|
|
#define TRY_TO_DECODE_FEATURE(width, FEATURE, DECODER_TABLE, DESC) \
|
|
TRY_TO_DECODE(width, RISCV_getFeatureBits(MI->csh->mode, FEATURE), \
|
|
DECODER_TABLE, DESC)
|
|
|
|
// It's a 32 bit instruction if bit 0 and 1 are 1.
|
|
if ((Bytes[0] & 0x3) == 0x3) {
|
|
if (BytesLen < 4) {
|
|
*Size = 0;
|
|
return MCDisassembler_Fail;
|
|
}
|
|
*Size = 4;
|
|
|
|
Insn = readBytes32(MI, Bytes);
|
|
|
|
TRY_TO_DECODE(4,
|
|
RISCV_getFeatureBits(MI->csh->mode,
|
|
RISCV_FeatureStdExtZdinx) &&
|
|
!RISCV_getFeatureBits(MI->csh->mode,
|
|
RISCV_Feature64Bit),
|
|
DecoderTableRV32Zdinx32,
|
|
"RV32Zdinx table (Double in Integer and rv32)");
|
|
TRY_TO_DECODE(4,
|
|
RISCV_getFeatureBits(MI->csh->mode,
|
|
RISCV_FeatureStdExtZacas) &&
|
|
!RISCV_getFeatureBits(MI->csh->mode,
|
|
RISCV_Feature64Bit),
|
|
DecoderTableRV32Zacas32,
|
|
"RV32Zacas table (Compare-And-Swap and rv32)");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureStdExtZfinx,
|
|
DecoderTableRVZfinx32,
|
|
"RVZfinx table (Float in Integer)");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXVentanaCondOps,
|
|
DecoderTableXVentana32,
|
|
"Ventana custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadBa,
|
|
DecoderTableXTHeadBa32,
|
|
"XTHeadBa custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadBb,
|
|
DecoderTableXTHeadBb32,
|
|
"XTHeadBb custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadBs,
|
|
DecoderTableXTHeadBs32,
|
|
"XTHeadBs custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadCondMov,
|
|
DecoderTableXTHeadCondMov32,
|
|
"XTHeadCondMov custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadCmo,
|
|
DecoderTableXTHeadCmo32,
|
|
"XTHeadCmo custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadFMemIdx,
|
|
DecoderTableXTHeadFMemIdx32,
|
|
"XTHeadFMemIdx custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadMac,
|
|
DecoderTableXTHeadMac32,
|
|
"XTHeadMac custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadMemIdx,
|
|
DecoderTableXTHeadMemIdx32,
|
|
"XTHeadMemIdx custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadMemPair,
|
|
DecoderTableXTHeadMemPair32,
|
|
"XTHeadMemPair custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadSync,
|
|
DecoderTableXTHeadSync32,
|
|
"XTHeadSync custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXTHeadVdot,
|
|
DecoderTableXTHeadVdot32,
|
|
"XTHeadVdot custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXSfvcp,
|
|
DecoderTableXSfvcp32,
|
|
"SiFive VCIX custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXSfvqmaccdod,
|
|
DecoderTableXSfvqmaccdod32,
|
|
"SiFive Matrix Multiplication (2x8 and 8x2) Instruction opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXSfvqmaccqoq,
|
|
DecoderTableXSfvqmaccqoq32,
|
|
"SiFive Matrix Multiplication (4x8 and 8x4) Instruction opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXSfvfwmaccqqq,
|
|
DecoderTableXSfvfwmaccqqq32,
|
|
"SiFive Matrix Multiplication Instruction opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXSfvfnrclipxfqf,
|
|
DecoderTableXSfvfnrclipxfqf32,
|
|
"SiFive FP32-to-int8 Ranged Clip Instructions opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXCVbitmanip,
|
|
DecoderTableXCVbitmanip32,
|
|
"CORE-V Bit Manipulation custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXCVelw,
|
|
DecoderTableXCVelw32,
|
|
"CORE-V Event load custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXCVmac,
|
|
DecoderTableXCVmac32,
|
|
"CORE-V MAC custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXCVmem,
|
|
DecoderTableXCVmem32,
|
|
"CORE-V MEM custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(4, RISCV_FeatureVendorXCValu,
|
|
DecoderTableXCValu32,
|
|
"CORE-V ALU custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXCVsimd, DecoderTableXCVsimd32,
|
|
"CORE-V SIMD extensions custom opcode table");
|
|
TRY_TO_DECODE_FEATURE(
|
|
4, RISCV_FeatureVendorXCVbi, DecoderTableXCVbi32,
|
|
"CORE-V Immediate Branching custom opcode table");
|
|
TRY_TO_DECODE(4, true, DecoderTable32, "RISCV32 table");
|
|
|
|
return MCDisassembler_Fail;
|
|
}
|
|
|
|
if (BytesLen < 2) {
|
|
*Size = 0;
|
|
return MCDisassembler_Fail;
|
|
}
|
|
*Size = 2;
|
|
|
|
Insn = readBytes16(MI, Bytes);
|
|
TRY_TO_DECODE_AND_ADD_SP(
|
|
2, !RISCV_getFeatureBits(MI->csh->mode, RISCV_Feature64Bit),
|
|
DecoderTableRISCV32Only_16,
|
|
"RISCV32Only_16 table (16-bit Instruction)");
|
|
TRY_TO_DECODE_FEATURE(2, RISCV_FeatureStdExtZicfiss,
|
|
DecoderTableZicfiss16,
|
|
"RVZicfiss table (Shadow Stack)");
|
|
TRY_TO_DECODE_FEATURE(2, RISCV_FeatureStdExtZcmt, DecoderTableRVZcmt16,
|
|
"Zcmt table (16-bit Table Jump Instructions)");
|
|
TRY_TO_DECODE_FEATURE(
|
|
2, RISCV_FeatureStdExtZcmp, DecoderTableRVZcmp16,
|
|
"Zcmp table (16-bit Push/Pop & Double Move Instructions)");
|
|
TRY_TO_DECODE_AND_ADD_SP(2, true, DecoderTable16,
|
|
"RISCV_C table (16-bit Instruction)");
|
|
|
|
return MCDisassembler_Fail;
|
|
}
|
|
|
|
bool RISCV_LLVM_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen,
|
|
MCInst *MI, uint16_t *Size, uint64_t Address,
|
|
void *Info)
|
|
{
|
|
RISCV_init_cs_detail(MI);
|
|
MI->MRI = (MCRegisterInfo *)Info;
|
|
return RISCV_getInstruction(MI, Size, Bytes, ByteLen, Address, NULL) !=
|
|
MCDisassembler_Fail;
|
|
}
|