diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-28 19:15:07 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-28 19:15:07 +0800 |
| commit | b1c08d57f1637f5ee813d1409dacdfa88c1509a0 (patch) | |
| tree | d1c8d3f9ba3da70628e356dcd97f878ea7124b62 | |
| parent | f89d528efc0228c049c2867dcba886a56bac8619 (diff) | |
| download | rcc-project-b1c08d57f1637f5ee813d1409dacdfa88c1509a0.tar.gz rcc-project-b1c08d57f1637f5ee813d1409dacdfa88c1509a0.tar.xz | |
[RISCV] Generate complete Zcmp instruction definitions
| -rw-r--r-- | backend/lib/Target/RISCV/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVInstPrinter.cpp | 51 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc | 7 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc | 30 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVInstrInfoZcmp.rccdesc | 101 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp | 71 |
6 files changed, 217 insertions, 44 deletions
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt index 2b9c023..6d44c06 100644 --- a/backend/lib/Target/RISCV/CMakeLists.txt +++ b/backend/lib/Target/RISCV/CMakeLists.txt @@ -12,6 +12,7 @@ set( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoF.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoD.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoC.rccdesc" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoZcmp.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoZb.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoPseudo.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelInteger.rccdesc" diff --git a/backend/lib/Target/RISCV/RISCVInstPrinter.cpp b/backend/lib/Target/RISCV/RISCVInstPrinter.cpp index 723628f..b66d909 100644 --- a/backend/lib/Target/RISCV/RISCVInstPrinter.cpp +++ b/backend/lib/Target/RISCV/RISCVInstPrinter.cpp @@ -165,6 +165,46 @@ constexpr std::array LinearFormats{ return Result; } +[[nodiscard]] Expected<std::string> formatZcmpRegisterList(const mc::MCOperand &Operand) { + const std::int64_t *Encoding = Operand.immediateValue(); + if (Encoding == nullptr || *Encoding < 4 || *Encoding > 15) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "Zcmp register list encoding is out of range"); + } + std::string Result = "{ra"; + if (*Encoding > 4) { + Result += ", s0"; + if (*Encoding == 15) + Result += "-s11"; + else if (*Encoding > 5) + Result += "-s" + std::to_string(*Encoding - 5); + } + Result += "}"; + return Result; +} + +[[nodiscard]] Expected<std::string> formatZcmpStackAdjustment(const mc::MCInst &Instruction, + bool Negate) { + if (Instruction.operands().size() != 2) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "Zcmp stack instruction requires two operands"); + } + const std::int64_t *RegisterList = Instruction.operands()[0].immediateValue(); + const std::int64_t *ExtraAdjustment = Instruction.operands()[1].immediateValue(); + if (RegisterList == nullptr || ExtraAdjustment == nullptr || *RegisterList < 4 || + *RegisterList > 15 || *ExtraAdjustment < 0 || *ExtraAdjustment > 48 || + *ExtraAdjustment % 16 != 0) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "Zcmp stack instruction has invalid encoded operands"); + } + std::int64_t RegisterCount = *RegisterList - 3; + if (*RegisterList == 15) + ++RegisterCount; + const std::int64_t BaseAdjustment = ((RegisterCount * 8 + 15) / 16) * 16; + const std::int64_t Adjustment = BaseAdjustment + *ExtraAdjustment; + return std::to_string(Negate ? -Adjustment : Adjustment); +} + } // namespace Expected<std::string> RISCVInstPrinter::printInstruction(const mc::MCInst &Instruction) const { @@ -254,6 +294,17 @@ Expected<std::string> RISCVInstPrinter::printInstruction(const mc::MCInst &Instr if (!Offset) return std::unexpected(Offset.error()); Operands = *First + ", " + *Offset + "(sp)"; + } else if (Format->Name == "rlist-stackadj") { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto RegisterList = formatZcmpRegisterList(Instruction.operands()[0]); + if (!RegisterList) + return std::unexpected(RegisterList.error()); + auto StackAdjustment = formatZcmpStackAdjustment(Instruction, Assembly->Mnemonic == "cm.push"); + if (!StackAdjustment) + return std::unexpected(StackAdjustment.error()); + Operands = *RegisterList + ", " + *StackAdjustment; } else { return makeUnexpected(ErrorCode::AssemblyLoweringFailed, "RISC-V assembly printer does not support generated format '" + diff --git a/backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc b/backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc index e1e84d0..c4c6bf4 100644 --- a/backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc +++ b/backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc @@ -13,6 +13,8 @@ named_operands: - { id: 12, symbol: FRS2, name: frs2 } - { id: 13, symbol: FRS3, name: frs3 } - { id: 14, symbol: RM, name: rm } + - { id: 15, symbol: RLIST, name: rlist } + - { id: 16, symbol: STACKADJ, name: stackadj } immediate_predicates: - { id: 1, symbol: SIMM12, name: simm12, kind: signed, bits: 12 } @@ -32,6 +34,8 @@ immediate_predicates: - { id: 15, symbol: C_SIMM9_A2, name: c-simm9-a2, kind: signed, bits: 9, alignment: 2 } - { id: 16, symbol: C_SIMM12_A2, name: c-simm12-a2, kind: signed, bits: 12, alignment: 2 } - { id: 17, symbol: C_SIMM10_A16_NZ, name: c-simm10-a16-nz, kind: signed, bits: 10, alignment: 16, nonzero: true } + - { id: 18, symbol: ZCMP_RLIST, name: zcmp-rlist, kind: unsigned, bits: 4, allowed_values: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] } + - { id: 19, symbol: ZCMP_STACKADJ, name: zcmp-stackadj, kind: unsigned, bits: 6, alignment: 16 } scheduling_classes: - { id: 1, symbol: ALU, name: alu, micro_ops: 1, latency: 1 } @@ -61,6 +65,8 @@ encoding_categories: - { id: 8, symbol: AMO, name: amo, size_bytes: 4 } - { id: 9, symbol: R4, name: r4, size_bytes: 4 } - { id: 10, symbol: C, name: c, size_bytes: 2 } + - { id: 11, symbol: ZCMP_MOVE, name: zcmp-move, size_bytes: 2 } + - { id: 12, symbol: ZCMP_STACK, name: zcmp-stack, size_bytes: 2 } assembly_formats: - { id: 1, symbol: RD_IMM, name: rd-imm } @@ -98,3 +104,4 @@ assembly_formats: - { id: 33, symbol: FRD_OFFSET_SP, name: frd-offset-sp } - { id: 34, symbol: FRS2_OFFSET_SP, name: frs2-offset-sp } - { id: 35, symbol: RD_RS1, name: rd-rs1 } + - { id: 36, symbol: RLIST_STACKADJ, name: rlist-stackadj } diff --git a/backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc b/backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc index 7f5c3c5..fa1b75a 100644 --- a/backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc +++ b/backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc @@ -513,33 +513,3 @@ instructions: scheduling_class: STORE encoding_category: C assembly_format: RS2_OFFSET_SP - - - id: 1270 - symbol: CM_MVA01S - name: CM_MVA01S - assembly_mnemonic: cm.mva01s - encoding: 44130 - operands: - - { kinds: [register], role: use, register_class: SR07, register_bank: GPR, name: RS1 } - - { kinds: [register], role: use, register_class: SR07, register_bank: GPR, name: RS2 } - num_explicit_defs: 0 - flags: [produces_code] - implicit_defs: [{ register: X10 }, { register: X11 }] - scheduling_class: COMPRESSED - encoding_category: C - assembly_format: RD_RS2 - - - id: 1271 - symbol: CM_MVSA01 - name: CM_MVSA01 - assembly_mnemonic: cm.mvsa01 - encoding: 44066 - operands: - - { kinds: [register], role: def, register_class: SR07, register_bank: GPR, name: RD } - - { kinds: [register], role: def, register_class: SR07, register_bank: GPR, name: RS2 } - num_explicit_defs: 2 - flags: [produces_code] - implicit_uses: [{ register: X10 }, { register: X11 }] - scheduling_class: COMPRESSED - encoding_category: C - assembly_format: RD_RS2 diff --git a/backend/lib/Target/RISCV/RISCVInstrInfoZcmp.rccdesc b/backend/lib/Target/RISCV/RISCVInstrInfoZcmp.rccdesc new file mode 100644 index 0000000..eb0f822 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVInstrInfoZcmp.rccdesc @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +instructions: + - + id: 1270 + symbol: CM_MVA01S + name: CM_MVA01S + assembly_mnemonic: cm.mva01s + encoding: 44130 + operands: + - { kinds: [register], role: use, register_class: SR07, register_bank: GPR, name: RS1 } + - { kinds: [register], role: use, register_class: SR07, register_bank: GPR, name: RS2 } + num_explicit_defs: 0 + flags: [produces_code] + implicit_defs: [{ register: X10 }, { register: X11 }] + scheduling_class: COMPRESSED + encoding_category: ZCMP_MOVE + assembly_format: RD_RS2 + - + id: 1271 + symbol: CM_MVSA01 + name: CM_MVSA01 + assembly_mnemonic: cm.mvsa01 + encoding: 44066 + operands: + - { kinds: [register], role: def, register_class: SR07, register_bank: GPR, name: RD } + - { kinds: [register], role: def, register_class: SR07, register_bank: GPR, name: RS2 } + num_explicit_defs: 2 + flags: [produces_code] + implicit_uses: [{ register: X10 }, { register: X11 }] + scheduling_class: COMPRESSED + encoding_category: ZCMP_MOVE + assembly_format: RD_RS2 + - + id: 1272 + symbol: CM_PUSH + name: CM_PUSH + assembly_mnemonic: cm.push + encoding: 47106 + operands: + - { kinds: [immediate], immediate_predicate: ZCMP_RLIST, name: RLIST } + - { kinds: [immediate], immediate_predicate: ZCMP_STACKADJ, name: STACKADJ } + num_explicit_defs: 0 + allow_extra_implicit_operands: true + flags: [may_store, produces_code] + implicit_defs: [{ register: X2 }] + implicit_uses: [{ register: X2 }] + scheduling_class: STORE + encoding_category: ZCMP_STACK + assembly_format: RLIST_STACKADJ + - + id: 1273 + symbol: CM_POPRET + name: CM_POPRET + assembly_mnemonic: cm.popret + encoding: 48642 + operands: + - { kinds: [immediate], immediate_predicate: ZCMP_RLIST, name: RLIST } + - { kinds: [immediate], immediate_predicate: ZCMP_STACKADJ, name: STACKADJ } + num_explicit_defs: 0 + allow_extra_implicit_operands: true + flags: [terminator, return, barrier, may_load, produces_code] + implicit_defs: [{ register: X2 }] + implicit_uses: [{ register: X2 }] + scheduling_class: LOAD + encoding_category: ZCMP_STACK + assembly_format: RLIST_STACKADJ + - + id: 1274 + symbol: CM_POPRETZ + name: CM_POPRETZ + assembly_mnemonic: cm.popretz + encoding: 48130 + operands: + - { kinds: [immediate], immediate_predicate: ZCMP_RLIST, name: RLIST } + - { kinds: [immediate], immediate_predicate: ZCMP_STACKADJ, name: STACKADJ } + num_explicit_defs: 0 + allow_extra_implicit_operands: true + flags: [terminator, return, barrier, may_load, produces_code] + implicit_defs: [{ register: X2 }, { register: X10 }] + implicit_uses: [{ register: X2 }] + scheduling_class: LOAD + encoding_category: ZCMP_STACK + assembly_format: RLIST_STACKADJ + - + id: 1275 + symbol: CM_POP + name: CM_POP + assembly_mnemonic: cm.pop + encoding: 47618 + operands: + - { kinds: [immediate], immediate_predicate: ZCMP_RLIST, name: RLIST } + - { kinds: [immediate], immediate_predicate: ZCMP_STACKADJ, name: STACKADJ } + num_explicit_defs: 0 + allow_extra_implicit_operands: true + flags: [may_load, produces_code] + implicit_defs: [{ register: X2 }] + implicit_uses: [{ register: X2 }] + scheduling_class: LOAD + encoding_category: ZCMP_STACK + assembly_format: RLIST_STACKADJ diff --git a/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp index 339d817..48de3e4 100644 --- a/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp +++ b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp @@ -102,6 +102,23 @@ namespace { "Zcmp move requires an s0-s7 register"); } +[[nodiscard]] Expected<std::uint16_t> encodeZcmpMove(const mc::MCInst &Instruction, + const TargetDescription &Target, + const AssemblyInstructionInfo &Assembly) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto First = savedRegisterEncoding(Instruction, 0, Target); + auto Second = savedRegisterEncoding(Instruction, 1, Target); + if (!First) + return std::unexpected(First.error()); + if (!Second) + return std::unexpected(Second.error()); + const auto Encoding = static_cast<std::uint16_t>(Assembly.Encoding); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x039c}) | *First << 7U | + *Second << 2U); +} + [[nodiscard]] bool fitsSigned(std::int64_t Value, unsigned Bits) noexcept { const std::int64_t Minimum = -(std::int64_t{1} << (Bits - 1U)); const std::int64_t Maximum = (std::int64_t{1} << (Bits - 1U)) - 1; @@ -190,6 +207,32 @@ namespace { return 0; } +[[nodiscard]] Expected<std::uint16_t> encodeZcmpStack(const mc::MCInst &Instruction, + const AssemblyInstructionInfo &Assembly, + mc::MCEncodedInstruction &Result) { + auto Count = requireOperandCount(Instruction, 2); + if (!Count) + return std::unexpected(Count.error()); + auto RegisterList = immediateOrFixup(Instruction, 0, mc::fixup_kind::None, false, Result); + auto StackAdjustment = immediateOrFixup(Instruction, 1, mc::fixup_kind::None, false, Result); + if (!RegisterList) + return std::unexpected(RegisterList.error()); + if (!StackAdjustment) + return std::unexpected(StackAdjustment.error()); + if (*RegisterList < 4 || *RegisterList > 15) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "Zcmp register list encoding is out of range"); + } + if (*StackAdjustment < 0 || *StackAdjustment > 48 || *StackAdjustment % 16 != 0) { + return makeUnexpected(ErrorCode::InstructionEncodingFailed, + "Zcmp stack adjustment must be 0, 16, 32, or 48"); + } + const auto Encoding = static_cast<std::uint16_t>(Assembly.Encoding); + return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x00fc}) | + static_cast<std::uint16_t>(*RegisterList) << 4U | + static_cast<std::uint16_t>(*StackAdjustment >> 4U) << 2U); +} + [[nodiscard]] Expected<mc::MCFixupKind> uFixupKind(const mc::MCOperand &Operand) { auto Kind = expressionTargetKind(Operand); if (!Kind) @@ -663,20 +706,6 @@ namespace { return immediateOrFixup(Instruction, Index, Kind, PCRelative, Result); }; - if (Opcode == InstructionOpcode::CM_MVA01S || Opcode == InstructionOpcode::CM_MVSA01) { - auto Count = requireOperandCount(Instruction, 2); - if (!Count) - return std::unexpected(Count.error()); - auto First = savedRegisterEncoding(Instruction, 0, Target); - auto Second = savedRegisterEncoding(Instruction, 1, Target); - if (!First) - return std::unexpected(First.error()); - if (!Second) - return std::unexpected(Second.error()); - return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x039c}) | *First << 7U | - *Second << 2U); - } - if (Opcode == InstructionOpcode::C_ADDI4SPN) { auto Count = requireOperandCount(Instruction, 2); if (!Count) @@ -1020,6 +1049,20 @@ RISCVMCCodeEmitter::encodeInstruction(const mc::MCInst &Instruction) const { appendLittleEndian(Result, *Compressed, 2); return Result; } + case EncodingCategory::ZCMP_MOVE: { + auto ZcmpMove = encodeZcmpMove(Instruction, *Target, *Assembly); + if (!ZcmpMove) + return std::unexpected(ZcmpMove.error()); + appendLittleEndian(Result, *ZcmpMove, 2); + return Result; + } + case EncodingCategory::ZCMP_STACK: { + auto ZcmpStack = encodeZcmpStack(Instruction, *Assembly, Result); + if (!ZcmpStack) + return std::unexpected(ZcmpStack.error()); + appendLittleEndian(Result, *ZcmpStack, 2); + return Result; + } case EncodingCategory::None: break; } |
