diff options
-rw-r--r-- | llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoC.td | 25 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/rv32c-invalid.s | 8 | ||||
-rw-r--r-- | llvm/test/MC/RISCV/rv32c-valid.s | 10 |
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 |