Skip to content

Commit

Permalink
[RISCV] MC layer support for the remaining RVC instructions
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D40003

Patch by Shiva Chen.

llvm-svn: 320558
  • Loading branch information
asb committed Dec 13, 2017
1 parent 6090c14 commit 60714f9
Show file tree
Hide file tree
Showing 14 changed files with 581 additions and 23 deletions.
69 changes: 67 additions & 2 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,24 @@ struct RISCVOperand : public MCParsedAsmOperand {
return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm5NonZero() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm6NonZero() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
return IsConstantImm && isUInt<6>(Imm) && (Imm != 0) &&
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm7Lsb00() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
Expand Down Expand Up @@ -259,6 +277,27 @@ struct RISCVOperand : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm10Lsb00NonZero() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isSImm6() const {
RISCVMCExpr::VariantKind VK;
int64_t Imm;
bool IsValid;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
if (!IsConstantImm)
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
else
IsValid = isInt<6>(Imm);
return IsValid &&
(VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
}

bool isSImm12() const {
RISCVMCExpr::VariantKind VK;
int64_t Imm;
Expand Down Expand Up @@ -287,6 +326,14 @@ struct RISCVOperand : public MCParsedAsmOperand {

bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }

bool isSImm10Lsb0000() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
return IsConstantImm && isShiftedInt<6, 4>(Imm) &&
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isUImm20() const {
RISCVMCExpr::VariantKind VK;
int64_t Imm;
Expand Down Expand Up @@ -491,10 +538,13 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
unsigned Reg = Op.getReg();
bool IsRegFPR32 =
RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
bool IsRegFPR32C =
RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg);

// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
// register from FPR32 to FPR64 if necessary.
if (IsRegFPR32 && Kind == MCK_FPR64) {
// register from FPR32 to FPR64 or FPR32C to FPR64C if necessary.
if ((IsRegFPR32 && Kind == MCK_FPR64) ||
(IsRegFPR32C && Kind == MCK_FPR64C)) {
Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
return Match_Success;
}
Expand Down Expand Up @@ -544,6 +594,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm5:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm5NonZero:
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
case Match_InvalidUImm6NonZero:
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
case Match_InvalidUImm7Lsb00:
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 7) - 4,
Expand All @@ -564,6 +618,17 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 9) - 8,
"immediate must be a multiple of 8 bytes in the range");
case Match_InvalidUImm10Lsb00NonZero:
return generateImmOutOfRangeError(
Operands, ErrorInfo, 4, (1 << 10) - 4,
"immediate must be a multiple of 4 bytes in the range");
case Match_InvalidSImm6:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
(1 << 5) - 1);
case Match_InvalidSImm10Lsb0000:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
"immediate must be a multiple of 16 bytes in the range");
case Match_InvalidSImm12:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
(1 << 11) - 1);
Expand Down
80 changes: 66 additions & 14 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ static const unsigned GPRDecoderTable[] = {
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > sizeof(GPRDecoderTable))
return MCDisassembler::Fail;

// We must define our own mapping from RegNo to register identifier.
// Accessing index RegNo in the register class will work in the case that
// registers were added in ascending order, but not in general.
unsigned Reg = GPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
if (RegNo > sizeof(GPRDecoderTable))
return MCDisassembler::Fail;

// We must define our own mapping from RegNo to register identifier.
// Accessing index RegNo in the register class will work in the case that
// registers were added in ascending order, but not in general.
unsigned Reg = GPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

static const unsigned FPR32DecoderTable[] = {
Expand Down Expand Up @@ -105,6 +105,17 @@ static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}

static DecodeStatus DecodeFPR32CRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 8) {
return MCDisassembler::Fail;
}
unsigned Reg = FPR32DecoderTable[RegNo + 8];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

static const unsigned FPR64DecoderTable[] = {
RISCV::F0_64, RISCV::F1_64, RISCV::F2_64, RISCV::F3_64,
RISCV::F4_64, RISCV::F5_64, RISCV::F6_64, RISCV::F7_64,
Expand All @@ -130,14 +141,35 @@ static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}

static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 8) {
return MCDisassembler::Fail;
}
unsigned Reg = FPR64DecoderTable[RegNo + 8];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}

static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo == 0) {
return MCDisassembler::Fail;
}
if (RegNo == 0) {
return MCDisassembler::Fail;
}

return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
}

static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo == 2) {
return MCDisassembler::Fail;
}

return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
}

static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
Expand All @@ -155,7 +187,14 @@ static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
// operand isn't explicitly encoded in the instruction.
static void addImplySP(MCInst &Inst, int64_t Address, const void *Decoder) {
if (Inst.getOpcode() == RISCV::CLWSP || Inst.getOpcode() == RISCV::CSWSP ||
Inst.getOpcode() == RISCV::CLDSP || Inst.getOpcode() == RISCV::CSDSP) {
Inst.getOpcode() == RISCV::CLDSP || Inst.getOpcode() == RISCV::CSDSP ||
Inst.getOpcode() == RISCV::CFLWSP || Inst.getOpcode() == RISCV::CFSWSP ||
Inst.getOpcode() == RISCV::CFLDSP || Inst.getOpcode() == RISCV::CFSDSP ||
Inst.getOpcode() == RISCV::CADDI4SPN) {
DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
}
if (Inst.getOpcode() == RISCV::CADDI16SP) {
DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
}
}
Expand All @@ -173,6 +212,7 @@ template <unsigned N>
static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
int64_t Address, const void *Decoder) {
assert(isUInt<N>(Imm) && "Invalid immediate");
addImplySP(Inst, Address, Decoder);
// Sign-extend the number in the bottom N bits of Imm
Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
return MCDisassembler::Success;
Expand Down Expand Up @@ -210,6 +250,18 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
Size = 4;
} else {
Insn = support::endian::read16le(Bytes.data());

if (!STI.getFeatureBits()[RISCV::Feature64Bit]) {
DEBUG(dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n");
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTableRISCV32Only_16, MI, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail) {
Size = 2;
return Result;
}
}

DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n");
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrFormatsC.td
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ class RVInst16CSS<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
let Inst{1-0} = opcode;
}

class RVInst16CIW<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
string opcodestr, string argstr>
: RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCIW> {
bits<10> imm;
bits<3> rd;

let Inst{15-13} = funct3;
let Inst{4-2} = rd;
let Inst{1-0} = opcode;
}

// The immediate value encoding differs for each instruction, so each subclass
// is responsible for setting the appropriate bits in the Inst field.
// The bits Inst{12-10} and Inst{6-5} must be set for each instruction.
Expand Down
Loading

0 comments on commit 60714f9

Please sign in to comment.