Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -194,6 +194,13 @@ return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; } + bool isUImm6() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isUInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; + } + bool isUImm7Lsb00() const { int64_t Imm; RISCVMCExpr::VariantKind VK; @@ -210,6 +217,14 @@ VK == RISCVMCExpr::VK_RISCV_None; } + bool isUImm10Lsb00() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isShiftedUInt<8, 2>(Imm) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isUImm8Lsb000() const { int64_t Imm; RISCVMCExpr::VariantKind VK; @@ -226,6 +241,19 @@ VK == RISCVMCExpr::VK_RISCV_None; } + bool isSImm6() const { + RISCVMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (!IsConstantImm) + IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); + else + IsValid = isInt<6>(Imm); + return IsValid && + (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO); + } + bool isSImm12() const { RISCVMCExpr::VariantKind VK; int64_t Imm; @@ -250,6 +278,14 @@ return IsConstantImm && isUInt<12>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; } + bool isSImm10Lsb0000() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isShiftedInt<6, 4>(Imm) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); } bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } @@ -426,6 +462,8 @@ } case Match_InvalidUImm5: return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); + case Match_InvalidUImm6: + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); case Match_InvalidUImm7Lsb00: return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 7) - 4, @@ -442,6 +480,13 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 9) - 8, "immediate must be a multiple of 8 bytes in the range"); + case Match_InvalidUImm10Lsb00: + return generateImmOutOfRangeError( + Operands, ErrorInfo, 0, (1 << 10) - 4, + "immediate must be a multiple of 4 bytes in the range"); + case Match_InvalidSImm6: + return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), + (1 << 5) - 1); case Match_InvalidSImm12: return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1); @@ -451,6 +496,10 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2, "immediate must be a multiple of 2 bytes in the range"); + case Match_InvalidSImm10Lsb0000: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 10), (1 << 10) - 16, + "immediate must be a multiple of 16 bytes in the range"); case Match_InvalidSImm12Lsb0: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, Index: lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp =================================================================== --- lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -96,7 +96,12 @@ // in bit field). static void addImplySP(MCInst &Inst, int64_t Address, const void *Decoder) { if (Inst.getOpcode() == RISCV::CLWSP || Inst.getOpcode() == RISCV::CSWSP || - Inst.getOpcode() == RISCV::CLDSP || Inst.getOpcode() == RISCV::CSDSP) { + Inst.getOpcode() == RISCV::CLDSP || Inst.getOpcode() == RISCV::CSDSP || + Inst.getOpcode() == RISCV::CADDI4SPN) { + DecodeGPRRegisterClass(Inst, 2, Address, Decoder); + } + if (Inst.getOpcode() == RISCV::CADDI16SP) { + DecodeGPRRegisterClass(Inst, 2, Address, Decoder); DecodeGPRRegisterClass(Inst, 2, Address, Decoder); } } @@ -114,6 +119,7 @@ static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, const void *Decoder) { assert(isUInt(Imm) && "Invalid immediate"); + addImplySP(Inst, Address, Decoder); // Sign-extend the number in the bottom N bits of Imm Inst.addOperand(MCOperand::createImm(SignExtend64(Imm))); return MCDisassembler::Success; Index: lib/Target/RISCV/RISCVInstrFormatsC.td =================================================================== --- lib/Target/RISCV/RISCVInstrFormatsC.td +++ lib/Target/RISCV/RISCVInstrFormatsC.td @@ -71,6 +71,17 @@ let Inst{1-0} = opcode; } +class CIW funct3, bits<2> opcode, dag outs, dag ins, + string opcodestr, string argstr> + : RV16Inst { + bits<10> imm; + bits<3> rd; + + let Inst{15-13} = funct3; + let Inst{4-2} = rd; + let Inst{1-0} = opcode; +} + class CL funct3, bits<2> opcode, dag outs, dag ins, string opcodestr, string argstr> : RV16Inst { Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -13,6 +13,17 @@ // Operand definitions. //===----------------------------------------------------------------------===// +def uimm6 : Operand, ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<6>; + let DecoderMethod = "decodeUImmOperand<6>"; +} + +def simm6 : Operand, ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<6>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<6>"; +} + // A 9-bit signed immediate where the least significant bit is zero. def simm9_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<9, "Lsb0">; @@ -59,6 +70,20 @@ let DecoderMethod = "decodeUImmOperand<9>"; } +def uimm10_2lsb0 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<10, "Lsb00">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmOperand<10>"; +} + +def simm10_4lsb0 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<10, "Lsb0000">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<10>"; +} + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -130,6 +155,109 @@ let Inst{2} = imm{5}; } +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Move_Imm : + CI<0b010, 0b01, (outs cls:$rd), (ins ImmOpnd:$imm), + "c.li", "$rd, $imm"> { + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Move_High : + CI<0b011, 0b01, (outs cls:$rd), (ins ImmOpnd:$imm), + "c.lui", "$rd, $imm"> { + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Add_Imm : + CI<0b000, 0b01, (outs cls:$rd_wb), (ins cls:$rd, ImmOpnd:$imm), + "c.addi", "$rd, $imm"> { + let Constraints = "$rd = $rd_wb"; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class ADDI_16SP : + CI<0b011, 0b01, (outs cls:$rd_wb), + (ins cls:$rd, simm10_4lsb0:$imm), + "c.addi16sp", "$rd, $imm"> { + let Constraints = "$rd = $rd_wb"; + let Inst{12} = imm{9}; + let Inst{11-7} = 2; + let Inst{6} = imm{4}; + let Inst{5} = imm{6}; + let Inst{4-3} = imm{8-7}; + let Inst{2} = imm{5}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class ADDI_4SPN : + CIW<0b000, 0b00, (outs cls:$rd), + (ins spcls:$rs1, uimm10_2lsb0:$imm), + "c.addi4spn", "$rd, $rs1, $imm"> { + bits<5> rs1; + let Inst{12-11} = imm{5-4}; + let Inst{10-7} = imm{9-6}; + let Inst{6} = imm{2}; + let Inst{5} = imm{3}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Shift_left : + CI<0b000, 0b10, (outs cls:$rd_wb), + (ins cls:$rd, ImmOpnd:$imm), + "c.slli" ,"$rd, $imm"> { + let Constraints = "$rd = $rd_wb"; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Shift_right funct2, string OpcodeStr, SDPatternOperator OpNode, + RegisterClass cls, Operand ImmOpnd> : + CB<0b100, 0b01, (outs cls:$rs1_wb), (ins cls:$rs1, ImmOpnd:$imm), + OpcodeStr, "$rs1, $imm"> { + let Constraints = "$rs1 = $rs1_wb"; + let Inst{12} = imm{5}; + let Inst{11-10} = funct2; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class And_Imm : + CB<0b100, 0b01, (outs cls:$rs1_wb), (ins cls:$rs1, ImmOpnd:$imm), + "c.andi", "$rs1, $imm"> { + let Constraints = "$rs1 = $rs1_wb"; + let Inst{12} = imm{5}; + let Inst{11-10} = 0b10; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Move_Reg : + CR<0b1000, 0b10, (outs cls:$rs1), (ins cls:$rs2), + "c.mv", "$rs1, $rs2">; + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Add_Reg : + CR<0b1001, 0b10, (outs cls:$rs1_wb), (ins cls:$rs1, cls:$rs2), + "c.add", "$rs1, $rs2"> { + let Constraints = "$rs1 = $rs1_wb"; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class CS_ALU funct2, string OpcodeStr, SDPatternOperator OpNode, + RegisterClass cls, bit RV64only> : + CS<0b100, 0b01, (outs cls:$rd_wb), (ins cls:$rd, cls:$rs2), + OpcodeStr, "$rd, $rs2"> { + bits<3> rd; + let Constraints = "$rd = $rd_wb"; + let Inst{12} = RV64only; + let Inst{11-10} = 0b11; + let Inst{9-7} = rd; + let Inst{6-5} = funct2; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -198,3 +326,38 @@ def CBEQZ : Bcz<0b110, "c.beqz", seteq, GPRC>, Requires<[HasStdExtC]>; def CBNEZ : Bcz<0b111, "c.bnez", setne, GPRC>, Requires<[HasStdExtC]>; + +def CLI : Move_Imm, Requires<[HasStdExtC]>; + +def CLUI : Move_High, Requires<[HasStdExtC]>; + +def CADDI : Add_Imm, Requires<[HasStdExtC]>; + +def CADDI16SP : ADDI_16SP, Requires<[HasStdExtC]>; + +def CADDI4SPN : ADDI_4SPN, Requires<[HasStdExtC]>; + +def CSLLI : Shift_left, Requires<[HasStdExtC]>; + +def CSRLI : Shift_right<0b00, "c.srli", srl, GPRC, uimm5>, + Requires<[HasStdExtC]>; +def CSRAI : Shift_right<0b01, "c.srai", sra, GPRC, uimm5>, + Requires<[HasStdExtC]>; + +def CANDI : And_Imm, Requires<[HasStdExtC]>; + +def CMV : Move_Reg, Requires<[HasStdExtC]>; + +def CADD : Add_Reg, Requires<[HasStdExtC]>; + +def CAND : CS_ALU<0b11, "c.and", and, GPRC, 0>, Requires<[HasStdExtC]>; +def COR : CS_ALU<0b10, "c.or" , or, GPRC, 0>, Requires<[HasStdExtC]>; +def CXOR : CS_ALU<0b01, "c.xor", xor, GPRC, 0>, Requires<[HasStdExtC]>; +def CSUB : CS_ALU<0b00, "c.sub", sub, GPRC, 0>, Requires<[HasStdExtC]>; + +let rd = 0, imm = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CNOP : CI<0b000, 0b01, (outs), (ins), "c.nop", "">, Requires<[HasStdExtC]>; + +let rs1 = 0, rs2 = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CEBREAK : CR<0b1001, 0b10, (outs), (ins), "c.ebreak", "">, + Requires<[HasStdExtC]>; Index: test/MC/RISCV/fixups-compressed.s =================================================================== --- test/MC/RISCV/fixups-compressed.s +++ test/MC/RISCV/fixups-compressed.s @@ -1,7 +1,7 @@ -# RUN: llvm-mc %s -mattr=+c -show-encoding \ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+c -show-encoding \ # RUN: | FileCheck -check-prefix=CHECK-FIXUP %s -# RUN: llvm-mc -filetype=obj -mattr=+c < %s \ -# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INSTR %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+c < %s \ +# RUN: | llvm-objdump -mattr=+c -d - | FileCheck -check-prefix=CHECK-INSTR %s .LBB0_2: # CHECK-FIXUP: encoding: [0bAAAAAA01,0b101AAAAA] @@ -16,3 +16,7 @@ # CHECK-FIXUP: fixup A - offset: 0, value: .LBB0_2, kind: fixup_riscv_rvc_branch # CHECK-INSTR: c.bnez a5, -8 c.bnez a5, .LBB0_2 + +# CHECK: encoding: [0bAAAAAA01,0b001AAAAA] +# CHECK: fixup A - offset: 0, value: func1, kind: fixup_riscv_rvc_jump +c.jal func1 Index: test/MC/RISCV/rv32c-invalid.s =================================================================== --- test/MC/RISCV/rv32c-invalid.s +++ test/MC/RISCV/rv32c-invalid.s @@ -6,6 +6,18 @@ c.sw sp, 4(sp) # CHECK: :[[@LINE]]:7: error: invalid operand for instruction c.beqz t0, .LBB # CHECK: :[[@LINE]]:9: error: invalid operand for instruction c.bnez s8, .LBB # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.addi4spn s4, sp, 12 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction +c.srli s7, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.srai t0, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.andi t1, 12 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.and t1, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction +c.or a0, s8 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction +c.xor t2, a0 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction +c.sub a0, s8 # CHECK: :[[@LINE]]:12: error: invalid operand for instruction + +## SP +c.addi4spn a0, a0, 12 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction +c.addi16sp t0, 16 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction # Out of range immediates @@ -23,3 +35,26 @@ ## simm12_lsb0 c.j 4096 # CHECK: :[[@LINE]]:5: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] c.jal -3000 # CHECK: :[[@LINE]]:7: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] + +## simm6 +c.li t0, 128 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.addi t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +c.andi a0, -64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] + +## uimm6 +c.lui t0, 128 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 63] + +## uimm10_2lsb0 +c.addi4spn a0, sp, 2048 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [0, 1020] +c.addi4spn a0, sp, -4 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [0, 1020] +c.addi4spn a0, sp, 2 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [0, 1020] + +## simm10_4lsb0 +c.addi16sp sp, 2048 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-1024, 1008] +c.addi16sp sp, -2048 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-1024, 1008] +c.addi16sp sp, 8 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-1024, 1008] + +## uimm5 +c.slli t0, 64 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 31] +c.srli a0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 31] +c.srai a0, -1 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 31] Index: test/MC/RISCV/rv32c-valid.s =================================================================== --- test/MC/RISCV/rv32c-valid.s +++ test/MC/RISCV/rv32c-valid.s @@ -36,3 +36,55 @@ # CHECK-INST: c.bnez a5, -12 # CHECK: encoding: [0xed,0xff] c.bnez a5, -12 + +# CHECK-INST: c.li a7, 31 +# CHECK: encoding: [0xfd,0x48] +c.li a7, 31 +# CHECK-INST: c.addi a3, 15 +# CHECK: encoding: [0xbd,0x06] +c.addi a3, 15 +# CHECK-INST: c.addi16sp sp, -16 +# CHECK: encoding: [0x7d,0x71] +c.addi16sp sp, -16 +# CHECK-INST: c.addi4spn a3, sp, 16 +# CHECK: encoding: [0x14,0x08] +c.addi4spn a3, sp, 16 +# CHECK-INST: c.slli a1, 2 +# CHECK: encoding: [0x8a,0x05] +c.slli a1, 2 +# CHECK-INST: c.srli a3, 3 +# CHECK: encoding: [0x8d,0x82] +c.srli a3, 3 +# CHECK-INST: c.srai a4, 2 +# CHECK: encoding: [0x09,0x87] +c.srai a4, 2 +# CHECK-INST: c.andi a5, 15 +# CHECK: encoding: [0xbd,0x8b] +c.andi a5, 15 +# CHECK-INST: c.mv a7, s0 +# CHECK: encoding: [0xa2,0x88] +c.mv a7, s0 +# CHECK-INST: c.and a1, a2 +# CHECK: encoding: [0xf1,0x8d] +c.and a1, a2 +# CHECK-INST: c.or a2, a3 +# CHECK: encoding: [0x55,0x8e] +c.or a2, a3 +# CHECK-INST: c.xor a3, a4 +# CHECK: encoding: [0xb9,0x8e] +c.xor a3, a4 +# CHECK-INST: c.sub a4, a5 +# CHECK: encoding: [0x1d,0x8f] +c.sub a4, a5 +# CHECK-INST: c.nop +# CHECK: encoding: [0x01,0x00] +c.nop +# CHECK-INST: c.ebreak +# CHECK: encoding: [0x02,0x90] +c.ebreak +# CHECK-INST: c.jal 256 +# CHECK: encoding: [0x41,0x20] +c.jal 256 +# CHECK-INST: c.lui s0, 30 +# CHECK: encoding: [0x79,0x64] +c.lui s0, 30