[RISCV] MC layer support for the standard RV64I instructions

llvm-svn: 320024
This commit is contained in:
Alex Bradbury 2017-12-07 10:53:48 +00:00
parent e4dd444e6f
commit f0d4f4bb55
7 changed files with 231 additions and 20 deletions

View File

@ -31,6 +31,7 @@ struct RISCVOperand;
class RISCVAsmParser : public MCTargetAsmParser {
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
@ -91,6 +92,8 @@ struct RISCVOperand : public MCParsedAsmOperand {
Immediate,
} Kind;
bool IsRV64;
struct RegOp {
unsigned RegNum;
};
@ -111,6 +114,7 @@ struct RISCVOperand : public MCParsedAsmOperand {
public:
RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
Kind = o.Kind;
IsRV64 = o.IsRV64;
StartLoc = o.StartLoc;
EndLoc = o.EndLoc;
switch (Kind) {
@ -202,6 +206,16 @@ public:
return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
}
bool isUImmLog2XLen() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
if (!isImm())
return false;
if (!evaluateConstantImm(Imm, VK) || VK != RISCVMCExpr::VK_RISCV_None)
return false;
return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
}
bool isUImm5() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
@ -259,6 +273,8 @@ public:
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
SMLoc getEndLoc() const override { return EndLoc; }
/// True if this operand is for an RV64 instruction
bool isRV64() const { return IsRV64; }
unsigned getReg() const override {
assert(Kind == Register && "Invalid type access!");
@ -290,29 +306,33 @@ public:
}
}
static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
bool IsRV64) {
auto Op = make_unique<RISCVOperand>(Token);
Op->Tok = Str;
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsRV64 = IsRV64;
return Op;
}
static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
SMLoc E) {
SMLoc E, bool IsRV64) {
auto Op = make_unique<RISCVOperand>(Register);
Op->Reg.RegNum = RegNo;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsRV64 = IsRV64;
return Op;
}
static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
SMLoc E) {
SMLoc E, bool IsRV64) {
auto Op = make_unique<RISCVOperand>(Immediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsRV64 = IsRV64;
return Op;
}
@ -482,6 +502,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
}
return Error(ErrorLoc, "invalid operand for instruction");
}
case Match_InvalidUImmLog2XLen:
if (isRV64())
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm5:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidSImm12:
@ -562,16 +586,16 @@ OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
}
}
if (HadParens)
Operands.push_back(RISCVOperand::createToken("(", FirstS));
Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
getLexer().Lex();
Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
}
if (HadParens) {
getParser().Lex(); // Eat ')'
Operands.push_back(RISCVOperand::createToken(")", getLoc()));
Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
}
return MatchOperand_Success;
@ -605,7 +629,7 @@ OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
return parseOperandWithModifier(Operands);
}
Operands.push_back(RISCVOperand::createImm(Res, S, E));
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
return MatchOperand_Success;
}
@ -645,7 +669,7 @@ RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
}
const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
Operands.push_back(RISCVOperand::createImm(ModExpr, S, E));
Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
return MatchOperand_Success;
}
@ -657,7 +681,7 @@ RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
}
getParser().Lex(); // Eat '('
Operands.push_back(RISCVOperand::createToken("(", getLoc()));
Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
if (parseRegister(Operands) != MatchOperand_Success) {
Error(getLoc(), "expected register");
@ -670,7 +694,7 @@ RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
}
getParser().Lex(); // Eat ')'
Operands.push_back(RISCVOperand::createToken(")", getLoc()));
Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
return MatchOperand_Success;
}
@ -700,7 +724,7 @@ bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
// First operand is token for instruction
Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
// If there are no more operands, then finish
if (getLexer().is(AsmToken::EndOfStatement))

View File

@ -40,6 +40,8 @@ def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
def Feature64Bit
: SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
def IsRV64 : Predicate<"Subtarget->is64Bit()">,
AssemblerPredicate<"Feature64Bit">;
def RV64 : HwMode<"+64bit">;
def RV32 : HwMode<"-64bit">;

View File

@ -188,6 +188,23 @@ class RVInstI<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
class RVInstIShift<bit arithshift, bits<3> funct3, RISCVOpcode opcode,
dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<6> shamt;
bits<5> rs1;
bits<5> rd;
let Inst{31} = 0;
let Inst{30} = arithshift;
let Inst{29-26} = 0;
let Inst{25-20} = shamt;
let Inst{19-15} = rs1;
let Inst{14-12} = funct3;
let Inst{11-7} = rd;
let Opcode = opcode.Value;
}
class RVInstIShiftW<bit arithshift, bits<3> funct3, RISCVOpcode opcode,
dag outs, dag ins, string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
bits<5> shamt;
bits<5> rs1;
bits<5> rd;

View File

@ -69,6 +69,22 @@ def fencearg : Operand<XLenVT> {
let DecoderMethod = "decodeUImmOperand<4>";
}
def UImmLog2XLenAsmOperand : AsmOperandClass {
let Name = "UImmLog2XLen";
let RenderMethod = "addImmOperands";
let DiagnosticType = "InvalidUImmLog2XLen";
}
def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
if (Subtarget->is64Bit())
return isUInt<6>(Imm);
return isUInt<5>(Imm);
}]> {
let ParserMatchClass = UImmLog2XLenAsmOperand;
// TODO: should ensure invalid shamt is rejected when decoding.
let DecoderMethod = "decodeUImmOperand<6>";
}
def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5>;
let DecoderMethod = "decodeUImmOperand<5>";
@ -161,7 +177,7 @@ class ALU_ri<bits<3> funct3, string opcodestr>
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class Shift_ri<bit arithshift, bits<3> funct3, string opcodestr>
: RVInstIShift<arithshift, funct3, OPC_OP_IMM, (outs GPR:$rd),
(ins GPR:$rs1, uimm5:$shamt), opcodestr,
(ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
"$rd, $rs1, $shamt">;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
@ -180,6 +196,17 @@ class CSR_ii<bits<3> funct3, string opcodestr> :
(ins uimm12:$imm12, uimm5:$rs1),
opcodestr, "$rd, $imm12, $rs1">;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class ShiftW_ri<bit arithshift, bits<3> funct3, string opcodestr>
: RVInstIShiftW<arithshift, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
(ins GPR:$rs1, uimm5:$shamt), opcodestr,
"$rd, $rs1, $shamt">;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
: RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
(ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">;
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@ -279,6 +306,29 @@ def CSRRWI : CSR_ii<0b101, "csrrwi">;
def CSRRSI : CSR_ii<0b110, "csrrsi">;
def CSRRCI : CSR_ii<0b111, "csrrci">;
/// RV64I instructions
let Predicates = [IsRV64] in {
def LWU : Load_ri<0b110, "lwu">;
def LD : Load_ri<0b011, "ld">;
def SD : Store_rri<0b011, "sd">;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
(ins GPR:$rs1, simm12:$imm12),
"addiw", "$rd, $rs1, $imm12">;
def SLLIW : ShiftW_ri<0, 0b001, "slliw">;
def SRLIW : ShiftW_ri<0, 0b101, "srliw">;
def SRAIW : ShiftW_ri<1, 0b101, "sraiw">;
def ADDW : ALUW_rr<0b0000000, 0b000, "addw">;
def SUBW : ALUW_rr<0b0100000, 0b000, "subw">;
def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">;
def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">;
def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">;
} // Predicates = [IsRV64]
//===----------------------------------------------------------------------===//
// Pseudo-instructions and codegen patterns
//
@ -293,9 +343,9 @@ class PatGprGpr<SDPatternOperator OpNode, RVInstR Inst>
: Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
: Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
class PatGprUimm5<SDPatternOperator OpNode, RVInstIShift Inst>
: Pat<(OpNode GPR:$rs1, uimm5:$shamt),
(Inst GPR:$rs1, uimm5:$shamt)>;
class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
: Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
(Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
/// Immediates
@ -315,11 +365,11 @@ def : PatGprSimm12<and, ANDI>;
def : PatGprGpr<xor, XOR>;
def : PatGprSimm12<xor, XORI>;
def : PatGprGpr<shl, SLL>;
def : PatGprUimm5<shl, SLLI>;
def : PatGprUimmLog2XLen<shl, SLLI>;
def : PatGprGpr<srl, SRL>;
def : PatGprUimm5<srl, SRLI>;
def : PatGprUimmLog2XLen<srl, SRLI>;
def : PatGprGpr<sra, SRA>;
def : PatGprUimm5<sra, SRAI>;
def : PatGprUimmLog2XLen<sra, SRAI>;
/// Setcc

View File

@ -111,8 +111,8 @@ slti a10, a2, 0x20 # CHECK: :[[@LINE]]:6: error: invalid operand for instruction
slt x32, s0, s0 # CHECK: :[[@LINE]]:5: error: invalid operand for instruction
# RV64I mnemonics
addiw a0, sp, 100 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
sraw t0, s2, zero # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic
addiw a0, sp, 100 # CHECK: :[[@LINE]]:1: error: instruction use requires an option to be enabled
sraw t0, s2, zero # CHECK: :[[@LINE]]:1: error: instruction use requires an option to be enabled
# Invalid operand types
xori sp, 22, 220 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction

View File

@ -0,0 +1,20 @@
# RUN: not llvm-mc -triple riscv64 < %s 2>&1 | FileCheck %s
# Out of range immediates
## uimm5
slliw a0, a0, 32 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
srliw a0, a0, -1 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
sraiw a0, a0, -19 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
## simm12
addiw a0, a1, -2049 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [-2048, 2047]
ld ra, 2048(sp) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-2048, 2047]
# Illegal operand modifier
## uimm5
slliw a0, a0, %lo(1) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
srliw a0, a0, %lo(a) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
sraiw a0, a0, %hi(2) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 31]
## simm12
addiw a0, a1, %hi(foo) # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [-2048, 2047]

View File

@ -0,0 +1,98 @@
# RUN: llvm-mc %s -triple=riscv64 -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s
# CHECK-INST: lwu zero, 4(ra)
# CHECK: encoding: [0x03,0xe0,0x40,0x00]
lwu x0, 4(x1)
# CHECK-INST: lwu sp, 4(gp)
# CHECK: encoding: [0x03,0xe1,0x41,0x00]
lwu x2, +4(x3)
# CHECK-INST: lwu tp, -2048(t0)
# CHECK: encoding: [0x03,0xe2,0x02,0x80]
lwu x4, -2048(x5)
# CHECK-INST: lwu t1, -2048(t2)
# CHECK: encoding: [0x03,0xe3,0x03,0x80]
lwu x6, %lo(2048)(x7)
# CHECK-INST: lwu s0, 2047(s1)
# CHECK: encoding: [0x03,0xe4,0xf4,0x7f]
lwu x8, 2047(x9)
# CHECK-INST: ld a0, -2048(a1)
# CHECK: encoding: [0x03,0xb5,0x05,0x80]
ld x10, -2048(x11)
# CHECK-INST: ld a2, -2048(a3)
# CHECK: encoding: [0x03,0xb6,0x06,0x80]
ld x12, %lo(2048)(x13)
# CHECK-INST: ld a4, 2047(a5)
# CHECK: encoding: [0x03,0xb7,0xf7,0x7f]
ld x14, 2047(x15)
# CHECK-INST: sd a6, -2048(a7)
# CHECK: encoding: [0x23,0xb0,0x08,0x81]
sd x16, -2048(x17)
# CHECK-INST: sd s2, -2048(s3)
# CHECK: encoding: [0x23,0xb0,0x29,0x81]
sd x18, %lo(2048)(x19)
# CHECK-INST: sd s4, 2047(s5)
# CHECK: encoding: [0xa3,0xbf,0x4a,0x7f]
sd x20, 2047(x21)
# CHECK-INST: slli s6, s7, 45
# CHECK: encoding: [0x13,0x9b,0xdb,0x02]
slli x22, x23, 45
# CHECK-INST: srli s8, s9, 0
# CHECK: encoding: [0x13,0xdc,0x0c,0x00]
srli x24, x25, 0
# CHECK-INST: srai s10, s11, 31
# CHECK: encoding: [0x13,0xdd,0xfd,0x41]
srai x26, x27, 31
# CHECK-INST: addiw t3, t4, -2048
# CHECK: encoding: [0x1b,0x8e,0x0e,0x80]
addiw x28, x29, -2048
# CHECK-INST: addiw t5, t6, 2047
# CHECK: encoding: [0x1b,0x8f,0xff,0x7f]
addiw x30, x31, 2047
# CHECK-INST: slliw zero, ra, 0
# CHECK: encoding: [0x1b,0x90,0x00,0x00]
slliw zero, ra, 0
# CHECK-INST: slliw sp, gp, 31
# CHECK: encoding: [0x1b,0x91,0xf1,0x01]
slliw sp, gp, 31
# CHECK-INST: srliw tp, t0, 0
# CHECK: encoding: [0x1b,0xd2,0x02,0x00]
srliw tp, t0, 0
# CHECK-INST: srliw t1, t2, 31
# CHECK: encoding: [0x1b,0xd3,0xf3,0x01]
srliw t1, t2, 31
# CHECK-INST: sraiw s0, s1, 0
# CHECK: encoding: [0x1b,0xd4,0x04,0x40]
sraiw s0, s1, 0
# CHECK-INST: sraiw a0, a1, 31
# CHECK: encoding: [0x1b,0xd5,0xf5,0x41]
sraiw a0, a1, 31
# CHECK-INST: addw a2, a3, a4
# CHECK: encoding: [0x3b,0x86,0xe6,0x00]
addw a2, a3, a4
# CHECK-INST: addw a5, a6, a7
# CHECK: encoding: [0xbb,0x07,0x18,0x01]
addw a5, a6, a7
# CHECK-INST: subw s2, s3, s4
# CHECK: encoding: [0x3b,0x89,0x49,0x41]
subw s2, s3, s4
# CHECK-INST: subw s5, s6, s7
# CHECK: encoding: [0xbb,0x0a,0x7b,0x41]
subw s5, s6, s7
# CHECK-INST: sllw s8, s9, s10
# CHECK: encoding: [0x3b,0x9c,0xac,0x01]
sllw s8, s9, s10
# CHECK-INST: srlw s11, t3, t4
# CHECK: encoding: [0xbb,0x5d,0xde,0x01]
srlw s11, t3, t4
# CHECK-INST: sraw t5, t6, zero
# CHECK: encoding: [0x3b,0xdf,0x0f,0x40]
sraw t5, t6, zero