summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp13
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp11
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoC.td25
-rw-r--r--llvm/test/MC/RISCV/rv32c-invalid.s8
-rw-r--r--llvm/test/MC/RISCV/rv32c-valid.s10
5 files changed, 52 insertions, 15 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 6a772bba71e..035c1ef6ac7 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -273,12 +273,13 @@ public:
(VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
}
- bool isUImm6NonZero() const {
+ bool isCLUIImm() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
- return IsConstantImm && isUInt<6>(Imm) && (Imm != 0) &&
- VK == RISCVMCExpr::VK_RISCV_None;
+ return IsConstantImm && (Imm != 0) &&
+ (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
+ VK == RISCVMCExpr::VK_RISCV_None;
}
bool isUImm7Lsb00() const {
@@ -631,8 +632,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
(1 << 5) - 1,
"immediate must be non-zero in the range");
- case Match_InvalidUImm6NonZero:
- return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
+ case Match_InvalidCLUIImm:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, 1, (1 << 5) - 1,
+ "immediate must be in [0xfffe0, 0xfffff] or");
case Match_InvalidUImm7Lsb00:
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 7) - 4,
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 563edc9e29d..91c72aa191d 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -232,6 +232,17 @@ static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
return MCDisassembler::Success;
}
+static DecodeStatus decodeCLUIImmOperand(MCInst &Inst, uint64_t Imm,
+ int64_t Address,
+ const void *Decoder) {
+ assert(isUInt<6>(Imm) && "Invalid immediate");
+ if (Imm > 31) {
+ Imm = (SignExtend64<6>(Imm) & 0xfffff);
+ }
+ Inst.addOperand(MCOperand::createImm(Imm));
+ return MCDisassembler::Success;
+}
+
#include "RISCVGenDisassemblerTables.inc"
DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index fc9c1dea5a8..b3566878e97 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -42,10 +42,25 @@ def simm6nonzero : Operand<XLenVT>,
let DecoderMethod = "decodeSImmOperand<6>";
}
-def uimm6nonzero : Operand<XLenVT>,
- ImmLeaf<XLenVT, [{return isUInt<6>(Imm) && (Imm != 0);}]> {
- let ParserMatchClass = UImmAsmOperand<6, "NonZero">;
- let DecoderMethod = "decodeUImmOperand<6>";
+def CLUIImmAsmOperand : AsmOperandClass {
+ let Name = "CLUIImm";
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = !strconcat("Invalid", Name);
+}
+
+
+// c_lui_imm checks the immediate range is in [1, 31] or [0xfffe0, 0xfffff].
+// The RISC-V ISA describes the constraint as [1, 63], with that value being
+// loaded in to bits 17-12 of the destination register and sign extended from
+// bit 17. Therefore, this 6-bit immediate can represent values in the ranges
+// [1, 31] and [0xfffe0, 0xfffff].
+def c_lui_imm : Operand<XLenVT>,
+ ImmLeaf<XLenVT, [{return (Imm != 0) &&
+ (isUInt<5>(Imm) ||
+ (Imm >= 0xfffe0 && Imm <= 0xfffff));}]> {
+ let ParserMatchClass = CLUIImmAsmOperand;
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeCLUIImmOperand";
}
// A 7-bit unsigned immediate where the least significant two bits are zero.
@@ -303,7 +318,7 @@ def C_ADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb),
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
def C_LUI : RVInst16CI<0b011, 0b01, (outs GPRNoX0X2:$rd),
- (ins uimm6nonzero:$imm),
+ (ins c_lui_imm:$imm),
"c.lui", "$rd, $imm"> {
let Inst{6-2} = imm{4-0};
}
diff --git a/llvm/test/MC/RISCV/rv32c-invalid.s b/llvm/test/MC/RISCV/rv32c-invalid.s
index 7c4380708df..8ee7c961237 100644
--- a/llvm/test/MC/RISCV/rv32c-invalid.s
+++ b/llvm/test/MC/RISCV/rv32c-invalid.s
@@ -52,9 +52,11 @@ c.addi t0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the ra
c.addi t0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31]
c.addi t0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be non-zero in the range [-32, 31]
-## uimm6nonzero
-c.lui t0, 64 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [1, 63]
-c.lui t0, 0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [1, 63]
+## c_lui_imm
+c.lui t0, 0 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31]
+c.lui t0, 32 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31]
+c.lui t0, 0xffffdf # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31]
+c.lui t0, 0x1000000 # CHECK: :[[@LINE]]:11: error: immediate must be in [0xfffe0, 0xfffff] or [1, 31]
## uimm8_lsb00
c.lwsp ra, 256(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 252]
diff --git a/llvm/test/MC/RISCV/rv32c-valid.s b/llvm/test/MC/RISCV/rv32c-valid.s
index 029dbdeaaae..449e3be51a7 100644
--- a/llvm/test/MC/RISCV/rv32c-valid.s
+++ b/llvm/test/MC/RISCV/rv32c-valid.s
@@ -94,6 +94,12 @@ c.ebreak
# CHECK-INST: c.lui s0, 1
# CHECK: encoding: [0x05,0x64]
c.lui s0, 1
-# CHECK-INST: c.lui s0, 63
+# CHECK-INST: c.lui s0, 31
+# CHECK: encoding: [0x7d,0x64]
+c.lui s0, 31
+# CHECK-INST: c.lui s0, 1048544
+# CHECK: encoding: [0x01,0x74]
+c.lui s0, 0xfffe0
+# CHECK-INST: c.lui s0, 1048575
# CHECK: encoding: [0x7d,0x74]
-c.lui s0, 63
+c.lui s0, 0xfffff
OpenPOWER on IntegriCloud