Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -216,6 +216,18 @@ return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); } + bool isUImmLog2XLenNonZero() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + if (!isImm()) + return false; + if (!evaluateConstantImm(Imm, VK) || VK != RISCVMCExpr::VK_RISCV_None) + return false; + if (Imm == 0) + return false; + return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); + } + bool isUImm5() const { int64_t Imm; RISCVMCExpr::VariantKind VK; @@ -592,10 +604,12 @@ if (isRV64()) return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); + case Match_InvalidUImmLog2XLenNonZero: + if (isRV64()) + return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); + return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); case Match_InvalidUImm5: return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); - case Match_InvalidUImm5NonZero: - return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); case Match_InvalidSImm6: return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1); Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -13,12 +13,6 @@ // Operand definitions. //===----------------------------------------------------------------------===// -def uimm5nonzero : Operand, - ImmLeaf(Imm) && (Imm != 0);}]> { - let ParserMatchClass = UImmAsmOperand<5, "NonZero">; - let DecoderMethod = "decodeUImmOperand<5>"; -} - def simm6 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<6>; let EncoderMethod = "getImmOpValue"; @@ -95,6 +89,22 @@ let DecoderMethod = "decodeSImmOperandAndLsl1<12>"; } +def UImmLog2XLenNonZeroAsmOperand : AsmOperandClass { + let Name = "UImmLog2XLenNonZero"; + let RenderMethod = "addImmOperands"; + let DiagnosticType = "InvalidUImmLog2XLenNonZero"; +} + +def uimmlog2xlennonzero : Operand, ImmLeafis64Bit()) + return isUInt<6>(Imm) && (Imm != 0); + return isUInt<5>(Imm) && (Imm != 0); +}]> { + let ParserMatchClass = UImmLog2XLenNonZeroAsmOperand; + // TODO: should ensure invalid shamt is rejected when decoding. + let DecoderMethod = "decodeUImmOperand<6>"; +} + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -290,8 +300,8 @@ let Inst{6-2} = imm{4-0}; } -def C_SRLI : Shift_right<0b00, "c.srli", GPRC, uimm5nonzero>; -def C_SRAI : Shift_right<0b01, "c.srai", GPRC, uimm5nonzero>; +def C_SRLI : Shift_right<0b00, "c.srli", GPRC, uimmlog2xlennonzero>; +def C_SRAI : Shift_right<0b01, "c.srai", GPRC, uimmlog2xlennonzero>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ANDI : RVInst16CB<0b100, 0b01, (outs GPRC:$rs1_wb), (ins GPRC:$rs1, simm6:$imm), @@ -323,7 +333,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_SLLI : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb), - (ins GPRNoX0:$rd, uimm5nonzero:$imm), + (ins GPRNoX0:$rd, uimmlog2xlennonzero:$imm), "c.slli" ,"$rd, $imm"> { let Constraints = "$rd = $rd_wb"; 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 @@ -38,7 +38,7 @@ # Out of range immediates -## uimm5nonzero +## uimmlog2xlennonzero c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] c.srli a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 31] Index: test/MC/RISCV/rv64c-invalid.s =================================================================== --- test/MC/RISCV/rv64c-invalid.s +++ test/MC/RISCV/rv64c-invalid.s @@ -12,6 +12,11 @@ # Out of range immediates +## uimmlog2xlennonzero +c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] +c.srli a0, -1 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] +c.srai a0, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [1, 63] + ## simm6 c.addiw t0, -33 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] c.addiw t0, 32 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-32, 31] Index: test/MC/RISCV/rv64c-valid.s =================================================================== --- test/MC/RISCV/rv64c-valid.s +++ test/MC/RISCV/rv64c-valid.s @@ -31,3 +31,13 @@ # CHECK-INST: c.addiw a3, 31 # CHECK: encoding: [0xfd,0x26] c.addiw a3, 31 + +# CHECK-INST: c.slli s0, 1 +# CHECK: encoding: [0x06,0x04] +c.slli s0, 1 +# CHECK-INST: c.srli a3, 63 +# CHECK: encoding: [0xfd,0x92] +c.srli a3, 63 +# CHECK-INST: c.srai a2, 63 +# CHECK: encoding: [0x7d,0x96] +c.srai a2, 63