Index: llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -273,12 +273,13 @@ (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 @@ 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, Index: llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ llvm/trunk/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -232,6 +232,17 @@ 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, Index: llvm/trunk/lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- llvm/trunk/lib/Target/RISCV/RISCVInstrInfoC.td +++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfoC.td @@ -42,10 +42,25 @@ let DecoderMethod = "decodeSImmOperand<6>"; } -def uimm6nonzero : Operand, - ImmLeaf(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, + ImmLeaf(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 @@ 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}; } Index: llvm/trunk/test/MC/RISCV/rv32c-invalid.s =================================================================== --- llvm/trunk/test/MC/RISCV/rv32c-invalid.s +++ llvm/trunk/test/MC/RISCV/rv32c-invalid.s @@ -52,9 +52,11 @@ 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] Index: llvm/trunk/test/MC/RISCV/rv32c-valid.s =================================================================== --- llvm/trunk/test/MC/RISCV/rv32c-valid.s +++ llvm/trunk/test/MC/RISCV/rv32c-valid.s @@ -94,6 +94,12 @@ # 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