Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -273,11 +273,12 @@ (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) && + return IsConstantImm && (Imm != 0) && + (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) && VK == RISCVMCExpr::VK_RISCV_None; } @@ -630,8 +631,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: lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp =================================================================== --- lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ 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: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -71,6 +71,10 @@ unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getCLUIImmOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -121,6 +125,25 @@ } unsigned +RISCVMCCodeEmitter::getCLUIImmOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) { + unsigned Res = MO.getImm(); + assert((isUInt<5>(Res) || (Res >= 0xfffe0 && Res <= 0xfffff)) && + "Not in c.lui immediate range!"); + if (isUInt<5>(Res)) + return Res; + + return Res & 0x3f; + } + + return getImmOpValue(MI, OpNo, Fixups, STI); +} + +unsigned RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -42,10 +42,23 @@ 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 in [1, 31] or [0xfffe0, 0xfffff]. +// The RISCV ISA describes the constraint as [1, 63] with signed extension +// highest bit. Eventually, the upper value could represent will be [1, 31] +// or [0xfffe0, 0xfffff], the value will encoded as [1, 63]. +def c_lui_imm : Operand, + ImmLeaf(Imm) || + (Imm >= 0xfffe0 && Imm <= 0xfffff));}]> { + let ParserMatchClass = CLUIImmAsmOperand; + let EncoderMethod = "getCLUIImmOpValue"; + let DecoderMethod = "decodeCLUIImmOperand"; } // A 7-bit unsigned immediate where the least significant two bits are zero. @@ -303,7 +316,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: test/MC/RISCV/rv32c-invalid.s =================================================================== --- test/MC/RISCV/rv32c-invalid.s +++ 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] +## uimm6_c_lui +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: test/MC/RISCV/rv32c-valid.s =================================================================== --- test/MC/RISCV/rv32c-valid.s +++ 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