Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -225,6 +225,24 @@ return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; } + bool isUImm5NonZero() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + if (!isImm()) + return false; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) && + VK == RISCVMCExpr::VK_RISCV_None; + } + + bool isUImm6NonZero() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isUInt<6>(Imm) && (Imm != 0) && + VK == RISCVMCExpr::VK_RISCV_None; + } + bool isUImm7Lsb00() const { int64_t Imm; RISCVMCExpr::VariantKind VK; @@ -259,6 +277,27 @@ VK == RISCVMCExpr::VK_RISCV_None; } + bool isUImm10Lsb00NonZero() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + bool IsConstantImm = evaluateConstantImm(Imm, VK); + return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) && + 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; @@ -287,6 +326,14 @@ bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } + 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 isUImm20() const { RISCVMCExpr::VariantKind VK; int64_t Imm; @@ -491,10 +538,12 @@ unsigned Reg = Op.getReg(); bool IsRegFPR32 = RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg); + bool IsRegFPR32C = + RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg); // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the - // register from FPR32 to FPR64 if necessary. - if (IsRegFPR32 && Kind == MCK_FPR64) { + // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary. + if ((IsRegFPR32 && Kind == MCK_FPR64) || (IsRegFPR32C && Kind == MCK_FPR64C)){ Op.Reg.RegNum = convertFPR32ToFPR64(Reg); return Match_Success; } @@ -544,6 +593,10 @@ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (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_InvalidUImm6NonZero: + return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); case Match_InvalidUImm7Lsb00: return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 7) - 4, @@ -564,6 +617,17 @@ return generateImmOutOfRangeError( Operands, ErrorInfo, 0, (1 << 9) - 8, "immediate must be a multiple of 8 bytes in the range"); + case Match_InvalidUImm10Lsb00NonZero: + return generateImmOutOfRangeError( + Operands, ErrorInfo, 4, (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_InvalidSImm10Lsb0000: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16, + "immediate must be a multiple of 16 bytes in the range"); case Match_InvalidSImm12: return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1); Index: lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp =================================================================== --- lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -69,15 +69,15 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { - if (RegNo > sizeof(GPRDecoderTable)) - return MCDisassembler::Fail; - - // We must define our own mapping from RegNo to register identifier. - // Accessing index RegNo in the register class will work in the case that - // registers were added in ascending order, but not in general. - unsigned Reg = GPRDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; + if (RegNo > sizeof(GPRDecoderTable)) + return MCDisassembler::Fail; + + // We must define our own mapping from RegNo to register identifier. + // Accessing index RegNo in the register class will work in the case that + // registers were added in ascending order, but not in general. + unsigned Reg = GPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; } static const unsigned FPR32DecoderTable[] = { @@ -105,6 +105,17 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeFPR32CRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 8) { + return MCDisassembler::Fail; + } + unsigned Reg = FPR32DecoderTable[RegNo + 8]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static const unsigned FPR64DecoderTable[] = { RISCV::F0_64, RISCV::F1_64, RISCV::F2_64, RISCV::F3_64, RISCV::F4_64, RISCV::F5_64, RISCV::F6_64, RISCV::F7_64, @@ -130,14 +141,35 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 8) { + return MCDisassembler::Fail; + } + unsigned Reg = FPR64DecoderTable[RegNo + 8]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { - if (RegNo == 0) { - return MCDisassembler::Fail; - } + if (RegNo == 0) { + return MCDisassembler::Fail; + } + + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo == 2) { + return MCDisassembler::Fail; + } - return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); + return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo, @@ -155,7 +187,14 @@ // operand isn't explicitly encoded in the instruction. 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::CFLWSP || Inst.getOpcode() == RISCV::CFSWSP || + Inst.getOpcode() == RISCV::CFLDSP || Inst.getOpcode() == RISCV::CFSDSP || + Inst.getOpcode() == RISCV::CADDI4SPN) { + DecodeGPRRegisterClass(Inst, 2, Address, Decoder); + } + if (Inst.getOpcode() == RISCV::CADDI16SP) { + DecodeGPRRegisterClass(Inst, 2, Address, Decoder); DecodeGPRRegisterClass(Inst, 2, Address, Decoder); } } @@ -173,6 +212,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; @@ -210,6 +250,18 @@ Size = 4; } else { Insn = support::endian::read16le(Bytes.data()); + + if (!STI.getFeatureBits()[RISCV::Feature64Bit]) { + DEBUG(dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableRISCV32Only_16, MI, Insn, Address, + this, STI); + if (Result != MCDisassembler::Fail) { + Size = 2; + return Result; + } + } + DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI); Index: lib/Target/RISCV/RISCV.td =================================================================== --- lib/Target/RISCV/RISCV.td +++ lib/Target/RISCV/RISCV.td @@ -50,6 +50,9 @@ def IsRV64 : Predicate<"Subtarget->is64Bit()">, AssemblerPredicate<"Feature64Bit">; +def IsRV32 : Predicate<"!Subtarget->is64Bit()">, + AssemblerPredicate<"!Feature64Bit">; + def RV64 : HwMode<"+64bit">; def RV32 : HwMode<"-64bit">; Index: lib/Target/RISCV/RISCVInstrFormatsC.td =================================================================== --- lib/Target/RISCV/RISCVInstrFormatsC.td +++ lib/Target/RISCV/RISCVInstrFormatsC.td @@ -77,6 +77,17 @@ let Inst{1-0} = opcode; } +class RVInst16CIW funct3, bits<2> opcode, dag outs, dag ins, + string opcodestr, string argstr> + : RVInst16 { + bits<10> imm; + bits<3> rd; + + let Inst{15-13} = funct3; + let Inst{4-2} = rd; + let Inst{1-0} = opcode; +} + // The immediate value encoding differs for each instruction, so each subclass // is responsible for setting the appropriate bits in the Inst field. // The bits Inst{12-10} and Inst{6-5} must be set for each instruction. Index: lib/Target/RISCV/RISCVInstrInfoC.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfoC.td +++ lib/Target/RISCV/RISCVInstrInfoC.td @@ -13,6 +13,24 @@ // Operand definitions. //===----------------------------------------------------------------------===// +def simm6 : Operand, ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<6>; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<6>"; +} + +def uimm5nonzero : Operand, + ImmLeaf(Imm) && (Imm != 0);}]> { + let ParserMatchClass = UImmAsmOperand<5, "NonZero">; + let DecoderMethod = "decodeUImmOperand<5>"; +} + +def uimm6nonzero : Operand, + ImmLeaf(Imm) && (Imm != 0);}]> { + let ParserMatchClass = UImmAsmOperand<6, "NonZero">; + let DecoderMethod = "decodeUImmOperand<6>"; +} + // A 7-bit unsigned immediate where the least significant two bits are zero. def uimm7_lsb00 : Operand, ImmLeaf(Imm);}]> { @@ -52,6 +70,24 @@ let DecoderMethod = "decodeUImmOperand<9>"; } +// A 10-bit unsigned immediate where the least significant two bits are zero +// and the immediate can't be zero. +def uimm10_lsb00nonzero : Operand, + ImmLeaf(Imm) && (Imm != 0);}]> { + let ParserMatchClass = UImmAsmOperand<10, "Lsb00NonZero">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeUImmOperand<10>"; +} + +// A 10-bit signed immediate where the least significant four bits are zero. +def simm10_lsb0000 : Operand, + ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<10, "Lsb0000">; + let EncoderMethod = "getImmOpValue"; + let DecoderMethod = "decodeSImmOperand<10>"; +} + // A 12-bit signed immediate where the least significant bit is zero. def simm12_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<12, "Lsb0">; @@ -78,13 +114,13 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class CLoad_ri funct3, string OpcodeStr, RegisterClass cls, DAGOperand opnd> : - RVInst16CL; let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in class CStore_rri funct3, string OpcodeStr, RegisterClass cls, DAGOperand opnd> : - RVInst16CS; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in @@ -101,12 +137,54 @@ let Inst{2} = imm{4}; } +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +class Shift_right funct2, string OpcodeStr, RegisterClass cls, + Operand ImmOpnd> : + RVInst16CB<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 CS_ALU funct2, string OpcodeStr, RegisterClass cls, + bit RV64only> : + RVInst16CS<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 //===----------------------------------------------------------------------===// let Predicates = [HasStdExtC] in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CADDI4SPN : RVInst16CIW<0b000, 0b00, (outs GPRC:$rd), + (ins SP:$rs1, uimm10_lsb00nonzero:$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}; +} + +def CFLD : CLoad_ri<0b001, "c.fld", FPR64C, uimm8_lsb000>, + Requires<[HasStdExtD]> { + bits<8> imm; + let Inst{12-10} = imm{5-3}; + let Inst{6-5} = imm{7-6}; +} + def CLW : CLoad_ri<0b010, "c.lw", GPRC, uimm7_lsb00> { bits<7> imm; let Inst{12-10} = imm{5-3}; @@ -114,6 +192,15 @@ let Inst{5} = imm{6}; } +let DecoderNamespace = "RISCV32Only_" in +def CFLW : CLoad_ri<0b011, "c.flw", FPR32C, uimm7_lsb00>, + Requires<[HasStdExtF, IsRV32]> { + bits<7> imm; + let Inst{12-10} = imm{5-3}; + let Inst{6} = imm{2}; + let Inst{5} = imm{6}; +} + def CLD : CLoad_ri<0b011, "c.ld", GPRC, uimm8_lsb000>, Requires<[IsRV64]> { bits<8> imm; @@ -121,6 +208,13 @@ let Inst{6-5} = imm{7-6}; } +def CFSD : CStore_rri<0b101, "c.fsd", FPR64C, uimm8_lsb000>, + Requires<[HasStdExtD]> { + bits<8> imm; + let Inst{12-10} = imm{5-3}; + let Inst{6-5} = imm{7-6}; +} + def CSW : CStore_rri<0b110, "c.sw", GPRC, uimm7_lsb00> { bits<7> imm; let Inst{12-10} = imm{5-3}; @@ -128,6 +222,15 @@ let Inst{5} = imm{6}; } +let DecoderNamespace = "RISCV32Only_" in +def CFSW : CStore_rri<0b111, "c.fsw", FPR32C, uimm7_lsb00>, + Requires<[HasStdExtF, IsRV32]> { + bits<7> imm; + let Inst{12-10} = imm{5-3}; + let Inst{6} = imm{2}; + let Inst{5} = imm{6}; +} + def CSD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000>, Requires<[IsRV64]> { bits<8> imm; @@ -135,9 +238,77 @@ let Inst{6-5} = imm{7-6}; } -let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1 in +let rd = 0, imm = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CNOP : RVInst16CI<0b000, 0b01, (outs), (ins), "c.nop", "">; + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CADDI : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb), + (ins GPRNoX0:$rd, simm6:$imm), + "c.addi", "$rd, $imm"> { + let Constraints = "$rd = $rd_wb"; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, +DecoderNamespace = "RISCV32Only_" in def CJAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset), - "c.jal", "$offset">; + "c.jal", "$offset">, + Requires<[IsRV32]>; + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CADDIW : RVInst16CI<0b001, 0b01, (outs GPRNoX0:$rd_wb), + (ins GPRNoX0:$rd, simm6:$imm), + "c.addiw", "$rd, $imm">, + Requires<[IsRV64]> { + let Constraints = "$rd = $rd_wb"; + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CLI : RVInst16CI<0b010, 0b01, (outs GPRNoX0:$rd), (ins simm6:$imm), + "c.li", "$rd, $imm"> { + let Inst{6-2} = imm{4-0}; +} + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb), + (ins SP:$rd, simm10_lsb0000:$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 +def CLUI : RVInst16CI<0b011, 0b01, (outs GPRNoX0X2:$rd), + (ins uimm6nonzero:$imm), + "c.lui", "$rd, $imm"> { + let Inst{6-2} = imm{4-0}; +} + +def CSRLI : Shift_right<0b00, "c.srli", GPRC, uimm5nonzero>; +def CSRAI : Shift_right<0b01, "c.srai", GPRC, uimm5nonzero>; + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CANDI : RVInst16CB<0b100, 0b01, (outs GPRC:$rs1_wb), (ins GPRC:$rs1, simm6:$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}; +} + +def CSUB : CS_ALU<0b00, "c.sub", GPRC, 0>; +def CXOR : CS_ALU<0b01, "c.xor", GPRC, 0>; +def COR : CS_ALU<0b10, "c.or" , GPRC, 0>; +def CAND : CS_ALU<0b11, "c.and", GPRC, 0>; + +def CSUBW : CS_ALU<0b00, "c.subw", GPRC, 1>, Requires<[IsRV64]>; +def CADDW : CS_ALU<0b01, "c.addw", GPRC, 1>, Requires<[IsRV64]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def CJ : RVInst16CJ<0b101, 0b01, (outs), (ins simm12_lsb0:$offset), @@ -150,11 +321,32 @@ def CBEQZ : Bcz<0b110, "c.beqz", seteq, GPRC>; def CBNEZ : Bcz<0b111, "c.bnez", setne, GPRC>; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CSLLI : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb), + (ins GPRNoX0:$rd, uimm5nonzero:$imm), + "c.slli" ,"$rd, $imm"> { + let Constraints = "$rd = $rd_wb"; + let Inst{6-2} = imm{4-0}; +} + +def CFLDSP : CStackLoad<0b001, "c.fldsp", FPR64, uimm9_lsb000>, + Requires<[HasStdExtD]> { + let Inst{6-5} = imm{4-3}; + let Inst{4-2} = imm{8-6}; +} + def CLWSP : CStackLoad<0b010, "c.lwsp", GPRNoX0, uimm8_lsb00> { let Inst{6-4} = imm{4-2}; let Inst{3-2} = imm{7-6}; } +let DecoderNamespace = "RISCV32Only_" in +def CFLWSP : CStackLoad<0b011, "c.flwsp", FPR32, uimm8_lsb00>, + Requires<[HasStdExtF, IsRV32]> { + let Inst{6-4} = imm{4-2}; + let Inst{3-2} = imm{7-6}; +} + def CLDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000>, Requires<[IsRV64]> { let Inst{6-5} = imm{4-3}; @@ -171,16 +363,43 @@ let rs2 = 0; } +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CMV : RVInst16CR<0b1000, 0b10, (outs GPRNoX0:$rs1), (ins GPRNoX0:$rs2), + "c.mv", "$rs1, $rs2">; + +let rs1 = 0, rs2 = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CEBREAK : RVInst16CR<0b1001, 0b10, (outs), (ins), "c.ebreak", "">; + let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall=1, Defs=[X1], rs2 = 0 in def CJALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPRNoX0:$rs1), "c.jalr", "$rs1">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in +def CADD : RVInst16CR<0b1001, 0b10, (outs GPRNoX0:$rs1_wb), + (ins GPRNoX0:$rs1, GPRNoX0:$rs2), + "c.add", "$rs1, $rs2"> { + let Constraints = "$rs1 = $rs1_wb"; +} + +def CFSDSP : CStackStore<0b101, "c.fsdsp", FPR64, uimm9_lsb000>, + Requires<[HasStdExtD]> { + let Inst{12-10} = imm{5-3}; + let Inst{9-7} = imm{8-6}; +} + def CSWSP : CStackStore<0b110, "c.swsp", GPR, uimm8_lsb00> { let Inst{12-9} = imm{5-2}; let Inst{8-7} = imm{7-6}; } +let DecoderNamespace = "RISCV32Only_" in +def CFSWSP : CStackStore<0b111, "c.fswsp", FPR32, uimm8_lsb00>, + Requires<[HasStdExtF, IsRV32]> { + let Inst{12-9} = imm{5-2}; + let Inst{8-7} = imm{7-6}; +} + def CSDSP : CStackStore<0b111, "c.sdsp", GPR, uimm9_lsb000>, Requires<[IsRV64]> { let Inst{12-10} = imm{5-3}; Index: lib/Target/RISCV/RISCVRegisterInfo.td =================================================================== --- lib/Target/RISCV/RISCVRegisterInfo.td +++ lib/Target/RISCV/RISCVRegisterInfo.td @@ -106,6 +106,19 @@ [RegInfo<32,32,32>, RegInfo<64,64,64>, RegInfo<32,32,32>]>; } +def GPRNoX0X2 : RegisterClass<"RISCV", [XLenVT], 32, (add + (sequence "X%u", 10, 17), + (sequence "X%u", 5, 7), + (sequence "X%u", 28, 31), + (sequence "X%u", 8, 9), + (sequence "X%u", 18, 27), + X1, X3, X4 + )> { + let RegInfos = RegInfoByHwMode< + [RV32, RV64, DefaultMode], + [RegInfo<32,32,32>, RegInfo<64,64,64>, RegInfo<32,32,32>]>; +} + def GPRC : RegisterClass<"RISCV", [XLenVT], 32, (add (sequence "X%u", 10, 15), (sequence "X%u", 8, 9) @@ -172,6 +185,11 @@ (sequence "F%u_32", 18, 27) )>; +def FPR32C : RegisterClass<"RISCV", [f32], 32, (add + (sequence "F%u_32", 10, 15), + (sequence "F%u_32", 8, 9) +)>; + // The order of registers represents the preferred allocation sequence, // meaning caller-save regs are listed before callee-save. def FPR64 : RegisterClass<"RISCV", [f64], 64, (add @@ -181,3 +199,8 @@ (sequence "F%u_64", 8, 9), (sequence "F%u_64", 18, 27) )>; + +def FPR64C : RegisterClass<"RISCV", [f64], 64, (add + (sequence "F%u_64", 10, 15), + (sequence "F%u_64", 8, 9) +)>; 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 -triple riscv32 -mattr=+c -show-encoding \ # RUN: | FileCheck -check-prefix=CHECK-FIXUP %s # RUN: llvm-mc -triple riscv32 -filetype=obj -mattr=+c < %s \ -# RUN: | llvm-objdump -mattr=+c -d - | FileCheck -check-prefix=CHECK-INSTR %s +# RUN: | llvm-objdump -mattr=+32bit,+c -d - | FileCheck -check-prefix=CHECK-INSTR %s .LBB0_2: # CHECK-FIXUP: fixup A - offset: 0, value: .LBB0_2, kind: fixup_riscv_rvc_jump Index: test/MC/RISCV/rv32c-invalid.s =================================================================== --- test/MC/RISCV/rv32c-invalid.s +++ test/MC/RISCV/rv32c-invalid.s @@ -6,15 +6,52 @@ 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 ## GPRNoX0 c.lwsp x0, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction c.lwsp zero, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction c.jr x0 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction c.jalr zero # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.addi x0, x0, 1 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.li zero, 2 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.slli zero, zero, 4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +c.mv zero, s0 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.mv ra, x0 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction +c.add ra, ra, x0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction +c.add zero, zero, sp # CHECK: :[[@LINE]]:8: error: invalid operand for instruction + +## GPRNoX0X2 +c.lui x0, 4 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction +c.lui x2, 4 # CHECK: :[[@LINE]]:7: 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 +## uimm5nonzero +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] + +## simm6 +c.li t0, 128 # CHECK: :[[@LINE]]:10: error: immediate must be an integer in the range [-32, 31] +c.addi t0, 32 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-32, 31] +c.andi a0, -33 # CHECK: :[[@LINE]]:12: error: immediate must be an integer 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] + ## uimm8_lsb00 c.lwsp ra, 256(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 252] c.swsp ra, -4(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 252] @@ -29,3 +66,11 @@ ## simm12_lsb0 c.j 2048 # CHECK: :[[@LINE]]:5: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] c.jal -2050 # CHECK: :[[@LINE]]:7: error: immediate must be a multiple of 2 bytes in the range [-2048, 2046] + +## uimm10_lsb00nonzero +c.addi4spn a0, sp, 0 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] +c.addi4spn a0, sp, 1024 # CHECK: :[[@LINE]]:21: error: immediate must be a multiple of 4 bytes in the range [4, 1020] + +## simm10_lsb0000 +c.addi16sp sp, -528 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-512, 496] +c.addi16sp sp, 512 # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 16 bytes in the range [-512, 496] Index: test/MC/RISCV/rv32c-only-valid.s =================================================================== --- /dev/null +++ test/MC/RISCV/rv32c-only-valid.s @@ -0,0 +1,8 @@ +# RUN: llvm-mc -triple=riscv32 -mattr=+c -show-encoding < %s \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c < %s \ +# RUN: | llvm-objdump -mattr=+32bit,+c -d - | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: c.jal 2046 +# CHECK: encoding: [0xfd,0x2f] +c.jal 2046 Index: test/MC/RISCV/rv32c-valid.s =================================================================== --- test/MC/RISCV/rv32c-valid.s +++ test/MC/RISCV/rv32c-valid.s @@ -25,9 +25,6 @@ # CHECK-INST: c.j -2048 # CHECK: encoding: [0x01,0xb0] c.j -2048 -# CHECK-INST: c.jal 2046 -# CHECK: encoding: [0xfd,0x2f] -c.jal 2046 # CHECK-INST: c.jr a7 # CHECK: encoding: [0x82,0x88] c.jr a7 @@ -40,3 +37,61 @@ # CHECK-INST: c.bnez a5, 254 # CHECK: encoding: [0xfd,0xef] c.bnez a5, 254 + +# CHECK-INST: c.li a7, 31 +# CHECK: encoding: [0xfd,0x48] +c.li a7, 31 +# CHECK-INST: c.addi a3, -32 +# CHECK: encoding: [0x81,0x16] +c.addi a3, -32 +# CHECK-INST: c.addi16sp sp, -512 +# CHECK: encoding: [0x01,0x71] +c.addi16sp sp, -512 +# CHECK-INST: c.addi16sp sp, 496 +# CHECK: encoding: [0x7d,0x61] +c.addi16sp sp, 496 +# CHECK-INST: c.addi4spn a3, sp, 1020 +# CHECK: encoding: [0xf4,0x1f] +c.addi4spn a3, sp, 1020 +# CHECK-INST: c.addi4spn a3, sp, 4 +# CHECK: encoding: [0x54,0x00] +c.addi4spn a3, sp, 4 +# CHECK-INST: c.slli a1, 1 +# CHECK: encoding: [0x86,0x05] +c.slli a1, 1 +# CHECK-INST: c.srli a3, 31 +# CHECK: encoding: [0xfd,0x82] +c.srli a3, 31 +# 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.lui s0, 1 +# CHECK: encoding: [0x05,0x64] +c.lui s0, 1 +# CHECK-INST: c.lui s0, 63 +# CHECK: encoding: [0x7d,0x74] +c.lui s0, 63 Index: test/MC/RISCV/rv32dc-invalid.s =================================================================== --- /dev/null +++ test/MC/RISCV/rv32dc-invalid.s @@ -0,0 +1,12 @@ +# RUN: not llvm-mc -triple=riscv32 -mattr=+c,+d < %s 2>&1 | FileCheck %s + +## FPRC +c.fld ft3, 8(a5) # CHECK: :[[@LINE]]:8: error: invalid operand for instruction + +## uimm9_lsb000 +c.fldsp fs1, 512(sp) # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 8 bytes in the range [0, 504] +c.fsdsp fs2, -8(sp) # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 8 bytes in the range [0, 504] + +## uimm8_lsb000 +c.fld fs0, -8(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 248] +c.fsd fs1, 256(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 248] Index: test/MC/RISCV/rv32dc-valid.s =================================================================== --- /dev/null +++ test/MC/RISCV/rv32dc-valid.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+c,+d -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+c,+d < %s \ +# RUN: | llvm-objdump -mattr=+c,+d -d - | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: c.fldsp fs0, 504(sp) +# CHECK: encoding: [0x7e,0x34] +c.fldsp fs0, 504(sp) +# CHECK-INST: c.fsdsp fa7, 504(sp) +# CHECK: encoding: [0xc6,0xbf] +c.fsdsp fa7, 504(sp) + +# CHECK-INST: c.fld fa3, 248(a5) +# CHECK: encoding: [0xf4,0x3f] +c.fld fa3, 248(a5) +# CHECK-INST: c.fsd fa2, 248(a1) +# CHECK: encoding: [0xf0,0xbd] +c.fsd fa2, 248(a1) Index: test/MC/RISCV/rv32fc-invalid.s =================================================================== --- /dev/null +++ test/MC/RISCV/rv32fc-invalid.s @@ -0,0 +1,12 @@ +# RUN: not llvm-mc -triple=riscv32 -mattr=+c,+f < %s 2>&1 | FileCheck %s + +## FPRC +c.flw ft3, 8(a5) # CHECK: :[[@LINE]]:8: error: invalid operand for instruction + +## uimm8_lsb00 +c.flwsp fs1, 256(sp) # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [0, 252] +c.fswsp fs2, -4(sp) # CHECK: :[[@LINE]]:15: error: immediate must be a multiple of 4 bytes in the range [0, 252] + +## uimm7_lsb00 +c.flw fs0, -4(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 124] +c.fsw fs1, 128(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 4 bytes in the range [0, 124] Index: test/MC/RISCV/rv32fc-valid.s =================================================================== --- /dev/null +++ test/MC/RISCV/rv32fc-valid.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+c,+f -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+c,+f < %s \ +# RUN: | llvm-objdump -mattr=+c,+f,+32bit -d - | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: c.flwsp fs0, 252(sp) +# CHECK: encoding: [0x7e,0x74] +c.flwsp fs0, 252(sp) +# CHECK-INST: c.fswsp fa7, 252(sp) +# CHECK: encoding: [0xc6,0xff] +c.fswsp fa7, 252(sp) + +# CHECK-INST: c.flw fa3, 124(a5) +# CHECK: encoding: [0xf4,0x7f] +c.flw fa3, 124(a5) +# CHECK-INST: c.fsw fa2, 124(a1) +# CHECK: encoding: [0xf0,0xfd] +c.fsw fa2, 124(a1) Index: test/MC/RISCV/rv64c-invalid.s =================================================================== --- test/MC/RISCV/rv64c-invalid.s +++ test/MC/RISCV/rv64c-invalid.s @@ -3,6 +3,8 @@ ## GPRC c.ld ra, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction c.sd sp, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction +c.addw a0, a7 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction +c.subw a0, a6 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction ## GPRNoX0 c.ldsp x0, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction @@ -10,6 +12,10 @@ # Out of range immediates +## 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] + ## uimm9_lsb000 c.ldsp ra, 512(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 504] c.sdsp ra, -8(sp) # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 8 bytes in the range [0, 504] Index: test/MC/RISCV/rv64c-valid.s =================================================================== --- test/MC/RISCV/rv64c-valid.s +++ test/MC/RISCV/rv64c-valid.s @@ -17,3 +17,17 @@ # CHECK-INST: c.sd a5, 248(a3) # CHECK: encoding: [0xfc,0xfe] c.sd a5, 248(a3) + +# CHECK-INST: c.subw a3, a4 +# CHECK: encoding: [0x99,0x9e] +c.subw a3, a4 +# CHECK-INST: c.addw a0, a2 +# CHECK: encoding: [0x31,0x9d] +c.addw a0, a2 + +# CHECK-INST: c.addiw a3, -32 +# CHECK: encoding: [0x81,0x36] +c.addiw a3, -32 +# CHECK-INST: c.addiw a3, 31 +# CHECK: encoding: [0xfd,0x26] +c.addiw a3, 31