aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 19:15:07 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 19:15:07 +0800
commitb1c08d57f1637f5ee813d1409dacdfa88c1509a0 (patch)
treed1c8d3f9ba3da70628e356dcd97f878ea7124b62
parentf89d528efc0228c049c2867dcba886a56bac8619 (diff)
downloadrcc-project-b1c08d57f1637f5ee813d1409dacdfa88c1509a0.tar.gz
rcc-project-b1c08d57f1637f5ee813d1409dacdfa88c1509a0.tar.xz
[RISCV] Generate complete Zcmp instruction definitions
-rw-r--r--backend/lib/Target/RISCV/CMakeLists.txt1
-rw-r--r--backend/lib/Target/RISCV/RISCVInstPrinter.cpp51
-rw-r--r--backend/lib/Target/RISCV/RISCVInstrInfoBase.rccdesc7
-rw-r--r--backend/lib/Target/RISCV/RISCVInstrInfoC.rccdesc30
-rw-r--r--backend/lib/Target/RISCV/RISCVInstrInfoZcmp.rccdesc101
-rw-r--r--backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp71
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;
}