diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -564,7 +564,8 @@ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); - return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; + return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) && + VK == RISCVMCExpr::VK_RISCV_None; } bool isSImm6() const { @@ -573,7 +574,8 @@ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); - return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; + return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) && + VK == RISCVMCExpr::VK_RISCV_None; } bool isSImm6NonZero() const { @@ -582,7 +584,8 @@ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); - return IsConstantImm && isInt<6>(Imm) && (Imm != 0) && + return IsConstantImm && Imm != 0 && + isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) && VK == RISCVMCExpr::VK_RISCV_None; } @@ -659,6 +662,14 @@ VK == RISCVMCExpr::VK_RISCV_None; } + // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits. + // This allows writing 'addi a0, a0, 0xffffffff'. + static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) { + if (IsRV64Imm || !isUInt<32>(Imm)) + return Imm; + return SignExtend64<32>(Imm); + } + bool isSImm12() const { RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; int64_t Imm; @@ -669,7 +680,7 @@ if (!IsConstantImm) IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK); else - IsValid = isInt<12>(Imm); + IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm())); return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) || VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO || @@ -757,7 +768,8 @@ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); - return IsConstantImm && isInt<5>(Imm - 1) && + return IsConstantImm && + isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) && VK == RISCVMCExpr::VK_RISCV_None; } @@ -909,14 +921,15 @@ return Op; } - static void addExpr(MCInst &Inst, const MCExpr *Expr) { + static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) { assert(Expr && "Expr shouldn't be null!"); int64_t Imm = 0; RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; bool IsConstant = evaluateConstantImm(Expr, Imm, VK); if (IsConstant) - Inst.addOperand(MCOperand::createImm(Imm)); + Inst.addOperand( + MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm))); else Inst.addOperand(MCOperand::createExpr(Expr)); } @@ -929,7 +942,7 @@ void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - addExpr(Inst, getImm()); + addExpr(Inst, getImm(), isRV64Imm()); } void addFenceArgOperands(MCInst &Inst, unsigned N) const { diff --git a/llvm/test/MC/RISCV/rv32c-only-valid.s b/llvm/test/MC/RISCV/rv32c-only-valid.s --- a/llvm/test/MC/RISCV/rv32c-only-valid.s +++ b/llvm/test/MC/RISCV/rv32c-only-valid.s @@ -21,3 +21,8 @@ # CHECK-NO-RV32: error: instruction requires the following: RV32I Base Instruction Set{{$}} # CHECK-NO-RV32-AND-EXT: error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores), RV32I Base Instruction Set{{$}} c.jal 2046 + +# CHECK-OBJ: c.addi a1, -1 +# CHECK-ASM: c.addi a1, -1 +# CHECK-ASM: encoding: [0xfd,0x15] +c.addi a1, 0xffffffff diff --git a/llvm/test/MC/RISCV/rv32i-only-valid.s b/llvm/test/MC/RISCV/rv32i-only-valid.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32i-only-valid.s @@ -0,0 +1,12 @@ +# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 < %s \ +# RUN: | llvm-objdump -M no-aliases -d -r - \ +# RUN: | FileCheck -check-prefixes=CHECK-ASM-AND-OBJ %s + +# CHECK-ASM-AND-OBJ: addi a0, a1, -1 +# CHECK-ASM: encoding: [0x13,0x85,0xf5,0xff] +addi a0, a1, 4294967295 # 0xffffffff +# CHECK-ASM-AND-OBJ: ori a2, a3, -2048 +# CHECK-ASM: encoding: [0x13,0xe6,0x06,0x80] +ori a2, a3, 0xfffff800 diff --git a/llvm/test/MC/RISCV/rvv/rv32-immediate.s b/llvm/test/MC/RISCV/rvv/rv32-immediate.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/rv32-immediate.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -triple=riscv32 -show-encoding --mattr=+v %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +# RUN: llvm-mc -triple=riscv32 -filetype=obj --mattr=+v %s \ +# RUN: | llvm-objdump -d --mattr=+v - \ +# RUN: | FileCheck %s --check-prefix=CHECK-INST + +# For rv32, allow 32 bit constants that contains a simm5 value. + +vadd.vi v8, v4, 0xfffffff0 +# CHECK-INST: vadd.vi v8, v4, -16 +# CHECK-ENCODING: [0x57,0x34,0x48,0x02] + +vmsltu.vi v8, v4, 0xfffffff1 +# CHECK-INST: vmsleu.vi v8, v4, -16 +# CHECK-ENCODING: [0x57,0x34,0x48,0x72]