aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'backend/lib/Target')
-rw-r--r--backend/lib/Target/Description/TargetDescriptionGenerator.cpp30
-rw-r--r--backend/lib/Target/RISCV/CMakeLists.txt18
-rw-r--r--backend/lib/Target/RISCV/RISCV.rccdesc195
-rw-r--r--backend/lib/Target/RISCV/RISCVAsmBackend.cpp382
-rw-r--r--backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp984
-rw-r--r--backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp112
-rw-r--r--backend/lib/Target/RISCV/RISCVObjectFile.cpp148
-rw-r--r--backend/lib/Target/RISCV/RISCVTargetConstant.cpp169
8 files changed, 2004 insertions, 34 deletions
diff --git a/backend/lib/Target/Description/TargetDescriptionGenerator.cpp b/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
index cd5ba97..dd3545b 100644
--- a/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
+++ b/backend/lib/Target/Description/TargetDescriptionGenerator.cpp
@@ -198,6 +198,7 @@ struct SourceInstruction final {
std::string Symbol;
std::string Name;
std::string AssemblyMnemonic;
+ std::optional<std::uint32_t> BinaryEncoding;
std::vector<SourceOperand> Operands;
std::uint32_t NumExplicitDefs = 0;
bool Variadic = false;
@@ -360,6 +361,7 @@ struct NormalizedInstruction final {
std::string Symbol;
std::string Name;
std::string AssemblyMnemonic;
+ std::uint32_t BinaryEncoding = 0;
std::vector<NormalizedOperand> Operands;
std::uint32_t NumExplicitDefs = 0;
bool Variadic = false;
@@ -1476,10 +1478,11 @@ private:
if (!requireMapping(Element, "instruction"))
return false;
if (!checkKeys(*Element,
- {"id", "symbol", "name", "assembly_mnemonic", "operands", "num_explicit_defs",
- "variadic", "implicit_defs", "implicit_uses", "allow_extra_implicit_operands",
- "flags", "scheduling_class", "encoding_category", "assembly_format",
- "requires_memory_operands", "owner", "deadline"},
+ {"id", "symbol", "name", "assembly_mnemonic", "encoding", "operands",
+ "num_explicit_defs", "variadic", "implicit_defs", "implicit_uses",
+ "allow_extra_implicit_operands", "flags", "scheduling_class",
+ "encoding_category", "assembly_format", "requires_memory_operands", "owner",
+ "deadline"},
"instruction")) {
return false;
}
@@ -1513,6 +1516,12 @@ private:
return false;
Instruction.AssemblyMnemonic = *Value;
}
+ if (const yaml::Node *Encoding = optionalNode(*Element, "encoding")) {
+ const auto Value = unsignedInteger32(*Encoding, "instruction encoding");
+ if (!Value)
+ return false;
+ Instruction.BinaryEncoding = Value;
+ }
if (const yaml::Node *SchedulingClass = optionalNode(*Element, "scheduling_class")) {
const auto Value = scalar(*SchedulingClass, "instruction scheduling_class");
if (!Value)
@@ -2386,13 +2395,14 @@ private:
std::unordered_set<std::string> Names;
for (const SourceInstruction &Instruction : Input.Instructions) {
const bool HasMnemonic = !Instruction.AssemblyMnemonic.empty();
+ const bool HasBinaryEncoding = Instruction.BinaryEncoding.has_value();
const bool HasSchedulingClass = !Instruction.SchedulingClassSymbol.empty();
const bool HasEncodingCategory = !Instruction.EncodingCategorySymbol.empty();
const bool HasAssemblyFormat = !Instruction.AssemblyFormatSymbol.empty();
- const bool HasAllMachineFacts =
- HasMnemonic && HasSchedulingClass && HasEncodingCategory && HasAssemblyFormat;
- const bool HasAnyMachineFact =
- HasMnemonic || HasSchedulingClass || HasEncodingCategory || HasAssemblyFormat;
+ const bool HasAllMachineFacts = HasMnemonic && HasBinaryEncoding && HasSchedulingClass &&
+ HasEncodingCategory && HasAssemblyFormat;
+ const bool HasAnyMachineFact = HasMnemonic || HasBinaryEncoding || HasSchedulingClass ||
+ HasEncodingCategory || HasAssemblyFormat;
const bool IsPseudoSource =
std::ranges::find(Instruction.Flags, "pseudo") != Instruction.Flags.end();
const bool IsTerminalEmissionSource =
@@ -2432,6 +2442,7 @@ private:
.Symbol = Instruction.Symbol,
.Name = Instruction.Name,
.AssemblyMnemonic = Instruction.AssemblyMnemonic,
+ .BinaryEncoding = Instruction.BinaryEncoding.value_or(0),
.Operands = {},
.NumExplicitDefs = Instruction.NumExplicitDefs,
.Variadic = Instruction.Variadic,
@@ -2970,7 +2981,8 @@ void emitImmediatePredicate(std::ostream &Output, const NormalizedImmediatePredi
continue;
Output << " {Opcode::fromValue(" << Instruction.ID << "), ";
appendQuoted(Output, Instruction.AssemblyMnemonic);
- Output << ", AssemblyFormatID::fromValue(" << Instruction.AssemblyFormat << ")},\n";
+ Output << ", AssemblyFormatID::fromValue(" << Instruction.AssemblyFormat << "), "
+ << Instruction.BinaryEncoding << "},\n";
}
Output << "}};\n\n";
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt
index 646e856..55578a2 100644
--- a/backend/lib/Target/RISCV/CMakeLists.txt
+++ b/backend/lib/Target/RISCV/CMakeLists.txt
@@ -53,6 +53,9 @@ add_library(
RISCVAssemblyPrinter.cpp
RISCVFrameLowering.cpp
RISCVInstPrinter.cpp
+ RISCVAsmBackend.cpp
+ RISCVMCCodeEmitter.cpp
+ RISCVObjectFile.cpp
RISCVMCTargetLowering.cpp
RISCVMachineCombiner.cpp
RISCVMachineMemoryFolding.cpp
@@ -61,6 +64,7 @@ add_library(
RISCVRegisterAllocation.cpp
RISCVScheduling.cpp
RISCVTarget.cpp
+ RISCVTargetConstant.cpp
"${RCCBackendRISCVGeneratedRegisterHeader}"
"${RCCBackendRISCVGeneratedInstructionHeader}"
"${RCCBackendRISCVGeneratedTables}"
@@ -114,6 +118,9 @@ rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVFrameLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstPrinter.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVAsmBackend.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCCodeEmitter.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVObjectFile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCTargetLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineCombiner.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineMemoryFolding.cpp"
@@ -122,12 +129,19 @@ rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVRegisterAllocation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVScheduling.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVTarget.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTargetConstant.cpp"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCodeGen.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVCallLowering.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVInstPrinter.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVAsmBackend.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVFixupKinds.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVMCCodeEmitter.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVObjectFile.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVMCTargetLowering.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTarget.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTargetConstant.h"
+ "${RCC_BACKEND_SOURCE_DIR}/include/rcc/Target/RISCV/RISCVTargetRelocationKinds.h"
)
rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVBranchInfo.cpp"
@@ -136,6 +150,9 @@ rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVCallLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVFrameLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstPrinter.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVAsmBackend.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCCodeEmitter.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVObjectFile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCTargetLowering.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineCombiner.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVMachineMemoryFolding.cpp"
@@ -144,4 +161,5 @@ rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVRegisterAllocation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVScheduling.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVTarget.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVTargetConstant.cpp"
)
diff --git a/backend/lib/Target/RISCV/RISCV.rccdesc b/backend/lib/Target/RISCV/RISCV.rccdesc
index dce984c..237e294 100644
--- a/backend/lib/Target/RISCV/RISCV.rccdesc
+++ b/backend/lib/Target/RISCV/RISCV.rccdesc
@@ -375,6 +375,7 @@ instructions:
symbol: LUI
name: LUI
assembly_mnemonic: lui
+ encoding: 5175
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: SIMM20, name: IMM }
@@ -388,6 +389,7 @@ instructions:
symbol: AUIPC
name: AUIPC
assembly_mnemonic: auipc
+ encoding: 5143
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate, basic_block, global_symbol, external_symbol, mc_symbol], immediate_predicate: SIMM20, allowed_target_flags: 3, name: IMM }
@@ -401,6 +403,7 @@ instructions:
symbol: ADDI
name: ADDI
assembly_mnemonic: addi
+ encoding: 1344531
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -415,6 +418,7 @@ instructions:
symbol: SRLI
name: SRLI
assembly_mnemonic: srli
+ encoding: 1365011
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -429,6 +433,7 @@ instructions:
symbol: SRAI
name: SRAI
assembly_mnemonic: srai
+ encoding: 1075106835
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -443,6 +448,7 @@ instructions:
symbol: ADDIW
name: ADDIW
assembly_mnemonic: addiw
+ encoding: 1344539
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -457,6 +463,7 @@ instructions:
symbol: SLLIW
name: SLLIW
assembly_mnemonic: slliw
+ encoding: 1348635
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -471,6 +478,7 @@ instructions:
symbol: SRLIW
name: SRLIW
assembly_mnemonic: srliw
+ encoding: 1365019
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -485,6 +493,7 @@ instructions:
symbol: SRAIW
name: SRAIW
assembly_mnemonic: sraiw
+ encoding: 1075106843
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -499,6 +508,7 @@ instructions:
symbol: SLL
name: SLL
assembly_mnemonic: sll
+ encoding: 10785843
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -513,6 +523,7 @@ instructions:
symbol: SLT
name: SLT
assembly_mnemonic: slt
+ encoding: 10789939
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -527,6 +538,7 @@ instructions:
symbol: SLTU
name: SLTU
assembly_mnemonic: sltu
+ encoding: 10794035
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -541,6 +553,7 @@ instructions:
symbol: XOR
name: XOR
assembly_mnemonic: xor
+ encoding: 10798131
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -555,6 +568,7 @@ instructions:
symbol: SRL
name: SRL
assembly_mnemonic: srl
+ encoding: 10802227
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -569,6 +583,7 @@ instructions:
symbol: SRA
name: SRA
assembly_mnemonic: sra
+ encoding: 1084544051
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -583,6 +598,7 @@ instructions:
symbol: OR
name: OR
assembly_mnemonic: or
+ encoding: 10806323
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -597,6 +613,7 @@ instructions:
symbol: AND
name: AND
assembly_mnemonic: and
+ encoding: 10810419
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -611,6 +628,7 @@ instructions:
symbol: ADDW
name: ADDW
assembly_mnemonic: addw
+ encoding: 10781755
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -625,6 +643,7 @@ instructions:
symbol: SUBW
name: SUBW
assembly_mnemonic: subw
+ encoding: 1084523579
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -639,6 +658,7 @@ instructions:
symbol: SLLW
name: SLLW
assembly_mnemonic: sllw
+ encoding: 10785851
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -653,6 +673,7 @@ instructions:
symbol: SRLW
name: SRLW
assembly_mnemonic: srlw
+ encoding: 10802235
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -667,6 +688,7 @@ instructions:
symbol: SRAW
name: SRAW
assembly_mnemonic: sraw
+ encoding: 1084544059
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -681,6 +703,7 @@ instructions:
symbol: LB
name: LB
assembly_mnemonic: lb
+ encoding: 8684547
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -696,6 +719,7 @@ instructions:
symbol: LH
name: LH
assembly_mnemonic: lh
+ encoding: 8688643
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -711,6 +735,7 @@ instructions:
symbol: LW
name: LW
assembly_mnemonic: lw
+ encoding: 8692739
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -726,6 +751,7 @@ instructions:
symbol: LBU
name: LBU
assembly_mnemonic: lbu
+ encoding: 8700931
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -741,6 +767,7 @@ instructions:
symbol: LHU
name: LHU
assembly_mnemonic: lhu
+ encoding: 8705027
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -756,6 +783,7 @@ instructions:
symbol: LWU
name: LWU
assembly_mnemonic: lwu
+ encoding: 8709123
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -771,6 +799,7 @@ instructions:
symbol: SB
name: SB
assembly_mnemonic: sb
+ encoding: 10781731
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -786,6 +815,7 @@ instructions:
symbol: SH
name: SH
assembly_mnemonic: sh
+ encoding: 10785827
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -801,6 +831,7 @@ instructions:
symbol: SW
name: SW
assembly_mnemonic: sw
+ encoding: 10789923
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -816,6 +847,7 @@ instructions:
symbol: BLT
name: BLT
assembly_mnemonic: blt
+ encoding: 9715811
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -830,6 +862,7 @@ instructions:
symbol: BGE
name: BGE
assembly_mnemonic: bge
+ encoding: 9719907
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -844,6 +877,7 @@ instructions:
symbol: BLTU
name: BLTU
assembly_mnemonic: bltu
+ encoding: 9724003
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -858,6 +892,7 @@ instructions:
symbol: BGEU
name: BGEU
assembly_mnemonic: bgeu
+ encoding: 9728099
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -872,6 +907,7 @@ instructions:
symbol: JALR
name: JALR
assembly_mnemonic: jalr
+ encoding: 1344615
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -886,6 +922,7 @@ instructions:
symbol: FENCE
name: FENCE
assembly_mnemonic: fence
+ encoding: 15
operands:
- { kinds: [immediate], immediate_predicate: UIMM4, name: PRED }
- { kinds: [immediate], immediate_predicate: UIMM4, name: SUCC }
@@ -899,6 +936,7 @@ instructions:
symbol: FENCE_I
name: FENCE_I
assembly_mnemonic: fence.i
+ encoding: 4111
operands: []
num_explicit_defs: 0
flags: [has_side_effects, produces_code]
@@ -910,6 +948,7 @@ instructions:
symbol: CSRRW
name: CSRRW
assembly_mnemonic: csrrw
+ encoding: 1348723
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -924,6 +963,7 @@ instructions:
symbol: CSRRS
name: CSRRS
assembly_mnemonic: csrrs
+ encoding: 1352819
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -938,6 +978,7 @@ instructions:
symbol: CSRRC
name: CSRRC
assembly_mnemonic: csrrc
+ encoding: 1356915
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -952,6 +993,7 @@ instructions:
symbol: CSRRWI
name: CSRRWI
assembly_mnemonic: csrrwi
+ encoding: 1102963
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -966,6 +1008,7 @@ instructions:
symbol: MUL
name: MUL
assembly_mnemonic: mul
+ encoding: 44336179
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -980,6 +1023,7 @@ instructions:
symbol: MULH
name: MULH
assembly_mnemonic: mulh
+ encoding: 44340275
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -994,6 +1038,7 @@ instructions:
symbol: MULHSU
name: MULHSU
assembly_mnemonic: mulhsu
+ encoding: 44344371
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1008,6 +1053,7 @@ instructions:
symbol: MULHU
name: MULHU
assembly_mnemonic: mulhu
+ encoding: 44348467
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1022,6 +1068,7 @@ instructions:
symbol: DIV
name: DIV
assembly_mnemonic: div
+ encoding: 44352563
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1036,6 +1083,7 @@ instructions:
symbol: DIVU
name: DIVU
assembly_mnemonic: divu
+ encoding: 44356659
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1050,6 +1098,7 @@ instructions:
symbol: REM
name: REM
assembly_mnemonic: rem
+ encoding: 44360755
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1064,6 +1113,7 @@ instructions:
symbol: REMU
name: REMU
assembly_mnemonic: remu
+ encoding: 44364851
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1078,6 +1128,7 @@ instructions:
symbol: MULW
name: MULW
assembly_mnemonic: mulw
+ encoding: 44336187
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1092,6 +1143,7 @@ instructions:
symbol: DIVW
name: DIVW
assembly_mnemonic: divw
+ encoding: 44352571
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1106,6 +1158,7 @@ instructions:
symbol: DIVUW
name: DIVUW
assembly_mnemonic: divuw
+ encoding: 44356667
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1120,6 +1173,7 @@ instructions:
symbol: REMW
name: REMW
assembly_mnemonic: remw
+ encoding: 44360763
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1134,6 +1188,7 @@ instructions:
symbol: REMUW
name: REMUW
assembly_mnemonic: remuw
+ encoding: 44364859
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1148,6 +1203,7 @@ instructions:
symbol: CSRRSI
name: CSRRSI
assembly_mnemonic: csrrsi
+ encoding: 1107059
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -1162,6 +1218,7 @@ instructions:
symbol: CSRRCI
name: CSRRCI
assembly_mnemonic: csrrci
+ encoding: 1111155
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM12, name: CSR }
@@ -1176,6 +1233,7 @@ instructions:
symbol: ADD
name: ADD
assembly_mnemonic: add
+ encoding: 10781747
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1190,6 +1248,7 @@ instructions:
symbol: SUB
name: SUB
assembly_mnemonic: sub
+ encoding: 1084523571
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1204,6 +1263,7 @@ instructions:
symbol: LD
name: LD
assembly_mnemonic: ld
+ encoding: 8696835
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1219,6 +1279,7 @@ instructions:
symbol: SD
name: SD
assembly_mnemonic: sd
+ encoding: 10794019
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1234,6 +1295,7 @@ instructions:
symbol: BEQ
name: BEQ
assembly_mnemonic: beq
+ encoding: 9699427
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -1248,6 +1310,7 @@ instructions:
symbol: BNE
name: BNE
assembly_mnemonic: bne
+ encoding: 9703523
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 }
@@ -1262,6 +1325,7 @@ instructions:
symbol: JAL
name: JAL
assembly_mnemonic: jal
+ encoding: 1135
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [basic_block], name: TARGET }
@@ -1275,6 +1339,7 @@ instructions:
symbol: ECALL
name: ECALL
assembly_mnemonic: ecall
+ encoding: 115
operands: []
num_explicit_defs: 0
flags: [has_side_effects, produces_code]
@@ -1286,6 +1351,7 @@ instructions:
symbol: EBREAK
name: EBREAK
assembly_mnemonic: ebreak
+ encoding: 1048691
operands: []
num_explicit_defs: 0
flags: [has_side_effects, produces_code]
@@ -1297,6 +1363,7 @@ instructions:
symbol: SLTI
name: SLTI
assembly_mnemonic: slti
+ encoding: 1352723
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1311,6 +1378,7 @@ instructions:
symbol: SLTIU
name: SLTIU
assembly_mnemonic: sltiu
+ encoding: 1356819
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1325,6 +1393,7 @@ instructions:
symbol: XORI
name: XORI
assembly_mnemonic: xori
+ encoding: 1360915
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1339,6 +1408,7 @@ instructions:
symbol: ORI
name: ORI
assembly_mnemonic: ori
+ encoding: 1369107
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1353,6 +1423,7 @@ instructions:
symbol: ANDI
name: ANDI
assembly_mnemonic: andi
+ encoding: 1373203
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1367,6 +1438,7 @@ instructions:
symbol: SLLI
name: SLLI
assembly_mnemonic: slli
+ encoding: 1348627
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1381,6 +1453,7 @@ instructions:
symbol: LR_W
name: LR_W
assembly_mnemonic: lr.w
+ encoding: 268739631
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1395,6 +1468,7 @@ instructions:
symbol: SC_W
name: SC_W
assembly_mnemonic: sc.w
+ encoding: 413443119
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -1410,6 +1484,7 @@ instructions:
symbol: AMOSWAP_W
name: AMOSWAP_W
assembly_mnemonic: amoswap.w
+ encoding: 145007663
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -1425,6 +1500,7 @@ instructions:
symbol: FLW
name: FLW
assembly_mnemonic: flw
+ encoding: 8692743
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, memory_role: value, name: FRD }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1440,6 +1516,7 @@ instructions:
symbol: FSW
name: FSW
assembly_mnemonic: fsw
+ encoding: 10789927
operands:
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, memory_role: value, name: FRS2 }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1455,6 +1532,7 @@ instructions:
symbol: FMADD_S
name: FMADD_S
assembly_mnemonic: fmadd.s
+ encoding: 1487176771
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1471,6 +1549,7 @@ instructions:
symbol: FMSUB_S
name: FMSUB_S
assembly_mnemonic: fmsub.s
+ encoding: 1487176775
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1487,6 +1566,7 @@ instructions:
symbol: FNMSUB_S
name: FNMSUB_S
assembly_mnemonic: fnmsub.s
+ encoding: 1487176779
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1503,6 +1583,7 @@ instructions:
symbol: FNMADD_S
name: FNMADD_S
assembly_mnemonic: fnmadd.s
+ encoding: 1487176783
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1519,6 +1600,7 @@ instructions:
symbol: FADD_S
name: FADD_S
assembly_mnemonic: fadd.s
+ encoding: 10781779
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1534,6 +1616,7 @@ instructions:
symbol: FSUB_S
name: FSUB_S
assembly_mnemonic: fsub.s
+ encoding: 144999507
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1549,6 +1632,7 @@ instructions:
symbol: FMUL_S
name: FMUL_S
assembly_mnemonic: fmul.s
+ encoding: 279217235
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1564,6 +1648,7 @@ instructions:
symbol: FDIV_S
name: FDIV_S
assembly_mnemonic: fdiv.s
+ encoding: 413434963
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1579,6 +1664,7 @@ instructions:
symbol: FSQRT_S
name: FSQRT_S
assembly_mnemonic: fsqrt.s
+ encoding: 1476691027
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1593,6 +1679,7 @@ instructions:
symbol: FSGNJ_S
name: FSGNJ_S
assembly_mnemonic: fsgnj.s
+ encoding: 547652691
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1607,6 +1694,7 @@ instructions:
symbol: FSGNJN_S
name: FSGNJN_S
assembly_mnemonic: fsgnjn.s
+ encoding: 547656787
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1621,6 +1709,7 @@ instructions:
symbol: FSGNJX_S
name: FSGNJX_S
assembly_mnemonic: fsgnjx.s
+ encoding: 547660883
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1635,6 +1724,7 @@ instructions:
symbol: FMIN_S
name: FMIN_S
assembly_mnemonic: fmin.s
+ encoding: 681870419
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1649,6 +1739,7 @@ instructions:
symbol: FMAX_S
name: FMAX_S
assembly_mnemonic: fmax.s
+ encoding: 681874515
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1663,6 +1754,7 @@ instructions:
symbol: FCVT_W_S
name: FCVT_W_S
assembly_mnemonic: fcvt.w.s
+ encoding: 3221521491
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1677,6 +1769,7 @@ instructions:
symbol: FCVT_WU_S
name: FCVT_WU_S
assembly_mnemonic: fcvt.wu.s
+ encoding: 3222570067
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1691,6 +1784,7 @@ instructions:
symbol: FCVT_L_S
name: FCVT_L_S
assembly_mnemonic: fcvt.l.s
+ encoding: 3223618643
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1705,6 +1799,7 @@ instructions:
symbol: FCVT_LU_S
name: FCVT_LU_S
assembly_mnemonic: fcvt.lu.s
+ encoding: 3224667219
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1719,6 +1814,7 @@ instructions:
symbol: FMV_X_W
name: FMV_X_W
assembly_mnemonic: fmv.x.w
+ encoding: 3758392403
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1732,6 +1828,7 @@ instructions:
symbol: FEQ_S
name: FEQ_S
assembly_mnemonic: feq.s
+ encoding: 2695144531
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1746,6 +1843,7 @@ instructions:
symbol: FLT_S
name: FLT_S
assembly_mnemonic: flt.s
+ encoding: 2695140435
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1760,6 +1858,7 @@ instructions:
symbol: FLE_S
name: FLE_S
assembly_mnemonic: fle.s
+ encoding: 2695136339
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1774,6 +1873,7 @@ instructions:
symbol: FCLASS_S
name: FCLASS_S
assembly_mnemonic: fclass.s
+ encoding: 3758396499
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -1787,6 +1887,7 @@ instructions:
symbol: FCVT_S_W
name: FCVT_S_W
assembly_mnemonic: fcvt.s.w
+ encoding: 3489956947
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1801,6 +1902,7 @@ instructions:
symbol: FCVT_S_WU
name: FCVT_S_WU
assembly_mnemonic: fcvt.s.wu
+ encoding: 3491005523
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1815,6 +1917,7 @@ instructions:
symbol: FCVT_S_L
name: FCVT_S_L
assembly_mnemonic: fcvt.s.l
+ encoding: 3492054099
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1829,6 +1932,7 @@ instructions:
symbol: FCVT_S_LU
name: FCVT_S_LU
assembly_mnemonic: fcvt.s.lu
+ encoding: 3493102675
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1843,6 +1947,7 @@ instructions:
symbol: FMV_W_X
name: FMV_W_X
assembly_mnemonic: fmv.w.x
+ encoding: 4026827859
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -1856,6 +1961,7 @@ instructions:
symbol: FLD
name: FLD
assembly_mnemonic: fld
+ encoding: 8696839
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRD }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1871,6 +1977,7 @@ instructions:
symbol: FSD
name: FSD
assembly_mnemonic: fsd
+ encoding: 10794023
operands:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRS2 }
- { kinds: [register, frame_index], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -1886,6 +1993,7 @@ instructions:
symbol: FMADD_D
name: FMADD_D
assembly_mnemonic: fmadd.d
+ encoding: 1520731203
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1902,6 +2010,7 @@ instructions:
symbol: FMSUB_D
name: FMSUB_D
assembly_mnemonic: fmsub.d
+ encoding: 1520731207
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1918,6 +2027,7 @@ instructions:
symbol: FNMSUB_D
name: FNMSUB_D
assembly_mnemonic: fnmsub.d
+ encoding: 1520731211
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1934,6 +2044,7 @@ instructions:
symbol: FNMADD_D
name: FNMADD_D
assembly_mnemonic: fnmadd.d
+ encoding: 1520731215
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1950,6 +2061,7 @@ instructions:
symbol: FADD_D
name: FADD_D
assembly_mnemonic: fadd.d
+ encoding: 44336211
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1965,6 +2077,7 @@ instructions:
symbol: FSUB_D
name: FSUB_D
assembly_mnemonic: fsub.d
+ encoding: 178553939
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1980,6 +2093,7 @@ instructions:
symbol: FMUL_D
name: FMUL_D
assembly_mnemonic: fmul.d
+ encoding: 312771667
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -1995,6 +2109,7 @@ instructions:
symbol: FDIV_D
name: FDIV_D
assembly_mnemonic: fdiv.d
+ encoding: 446989395
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2010,6 +2125,7 @@ instructions:
symbol: FSQRT_D
name: FSQRT_D
assembly_mnemonic: fsqrt.d
+ encoding: 1510245459
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2024,6 +2140,7 @@ instructions:
symbol: FSGNJ_D
name: FSGNJ_D
assembly_mnemonic: fsgnj.d
+ encoding: 581207123
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2038,6 +2155,7 @@ instructions:
symbol: FSGNJN_D
name: FSGNJN_D
assembly_mnemonic: fsgnjn.d
+ encoding: 581211219
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2052,6 +2170,7 @@ instructions:
symbol: FSGNJX_D
name: FSGNJX_D
assembly_mnemonic: fsgnjx.d
+ encoding: 581215315
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2066,6 +2185,7 @@ instructions:
symbol: FMIN_D
name: FMIN_D
assembly_mnemonic: fmin.d
+ encoding: 715424851
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2080,6 +2200,7 @@ instructions:
symbol: FMAX_D
name: FMAX_D
assembly_mnemonic: fmax.d
+ encoding: 715428947
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2094,6 +2215,7 @@ instructions:
symbol: FCVT_W_D
name: FCVT_W_D
assembly_mnemonic: fcvt.w.d
+ encoding: 3255075923
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2108,6 +2230,7 @@ instructions:
symbol: FCVT_WU_D
name: FCVT_WU_D
assembly_mnemonic: fcvt.wu.d
+ encoding: 3256124499
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2122,6 +2245,7 @@ instructions:
symbol: FCVT_L_D
name: FCVT_L_D
assembly_mnemonic: fcvt.l.d
+ encoding: 3257173075
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2136,6 +2260,7 @@ instructions:
symbol: FCVT_LU_D
name: FCVT_LU_D
assembly_mnemonic: fcvt.lu.d
+ encoding: 3258221651
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2150,6 +2275,7 @@ instructions:
symbol: FMV_X_D
name: FMV_X_D
assembly_mnemonic: fmv.x.d
+ encoding: 3791946835
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2163,6 +2289,7 @@ instructions:
symbol: FEQ_D
name: FEQ_D
assembly_mnemonic: feq.d
+ encoding: 2728698963
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2177,6 +2304,7 @@ instructions:
symbol: FLT_D
name: FLT_D
assembly_mnemonic: flt.d
+ encoding: 2728694867
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2191,6 +2319,7 @@ instructions:
symbol: FLE_D
name: FLE_D
assembly_mnemonic: fle.d
+ encoding: 2728690771
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2205,6 +2334,7 @@ instructions:
symbol: FCLASS_D
name: FCLASS_D
assembly_mnemonic: fclass.d
+ encoding: 3791950931
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2218,6 +2348,7 @@ instructions:
symbol: FCVT_D_W
name: FCVT_D_W
assembly_mnemonic: fcvt.d.w
+ encoding: 3523511379
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -2232,6 +2363,7 @@ instructions:
symbol: FCVT_D_WU
name: FCVT_D_WU
assembly_mnemonic: fcvt.d.wu
+ encoding: 3524559955
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -2246,6 +2378,7 @@ instructions:
symbol: FCVT_D_L
name: FCVT_D_L
assembly_mnemonic: fcvt.d.l
+ encoding: 3525608531
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -2260,6 +2393,7 @@ instructions:
symbol: FCVT_D_LU
name: FCVT_D_LU
assembly_mnemonic: fcvt.d.lu
+ encoding: 3526657107
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -2274,6 +2408,7 @@ instructions:
symbol: FMV_D_X
name: FMV_D_X
assembly_mnemonic: fmv.d.x
+ encoding: 4060382291
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -2287,6 +2422,7 @@ instructions:
symbol: FCVT_S_D
name: FCVT_S_D
assembly_mnemonic: fcvt.s.d
+ encoding: 1075086419
operands:
- { kinds: [register], role: def, register_class: FPR32, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, name: FRS1 }
@@ -2301,6 +2437,7 @@ instructions:
symbol: C_ADDI4SPN
name: C_ADDI4SPN
assembly_mnemonic: c.addi4spn
+ encoding: 2048
operands:
- { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_UIMM10_NZ_A4, name: IMM }
@@ -2315,6 +2452,7 @@ instructions:
symbol: C_FLD
name: C_FLD
assembly_mnemonic: c.fld
+ encoding: 9344
operands:
- { kinds: [register], role: def, register_class: FPR64C, register_bank: FPR, memory_role: value, name: FRD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2330,6 +2468,7 @@ instructions:
symbol: C_LW
name: C_LW
assembly_mnemonic: c.lw
+ encoding: 17536
operands:
- { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2345,6 +2484,7 @@ instructions:
symbol: C_LD
name: C_LD
assembly_mnemonic: c.ld
+ encoding: 25728
operands:
- { kinds: [register], role: def, register_class: GPRC, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2360,6 +2500,7 @@ instructions:
symbol: C_FSD
name: C_FSD
assembly_mnemonic: c.fsd
+ encoding: 42120
operands:
- { kinds: [register], role: use, register_class: FPR64C, register_bank: FPR, memory_role: value, name: FRS2 }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2375,6 +2516,7 @@ instructions:
symbol: C_SW
name: C_SW
assembly_mnemonic: c.sw
+ encoding: 50312
operands:
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2390,6 +2532,7 @@ instructions:
symbol: C_SD
name: C_SD
assembly_mnemonic: c.sd
+ encoding: 58504
operands:
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2405,6 +2548,7 @@ instructions:
symbol: C_ADDI
name: C_ADDI
assembly_mnemonic: c.addi
+ encoding: 1029
operands:
- { kinds: [register], role: def_use, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM }
@@ -2418,6 +2562,7 @@ instructions:
symbol: C_ADDIW
name: C_ADDIW
assembly_mnemonic: c.addiw
+ encoding: 9221
operands:
- { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM }
@@ -2431,6 +2576,7 @@ instructions:
symbol: C_LI
name: C_LI
assembly_mnemonic: c.li
+ encoding: 17413
operands:
- { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM }
@@ -2444,6 +2590,7 @@ instructions:
symbol: C_ADDI16SP
name: C_ADDI16SP
assembly_mnemonic: c.addi16sp
+ encoding: 24897
operands:
- { kinds: [immediate], immediate_predicate: C_SIMM10_A16_NZ, name: IMM }
num_explicit_defs: 0
@@ -2458,6 +2605,7 @@ instructions:
symbol: C_LUI
name: C_LUI
assembly_mnemonic: c.lui
+ encoding: 25605
operands:
- { kinds: [register], role: def, register_class: GPR_NX0_NX2, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_SIMM6_NZ, name: IMM }
@@ -2471,6 +2619,7 @@ instructions:
symbol: C_SRLI
name: C_SRLI
assembly_mnemonic: c.srli
+ encoding: 32773
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM6, name: IMM }
@@ -2484,6 +2633,7 @@ instructions:
symbol: C_SRAI
name: C_SRAI
assembly_mnemonic: c.srai
+ encoding: 33797
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM6, name: IMM }
@@ -2497,6 +2647,7 @@ instructions:
symbol: C_ANDI
name: C_ANDI
assembly_mnemonic: c.andi
+ encoding: 34821
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: C_SIMM6, name: IMM }
@@ -2510,6 +2661,7 @@ instructions:
symbol: C_SUB
name: C_SUB
assembly_mnemonic: c.sub
+ encoding: 35845
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2523,6 +2675,7 @@ instructions:
symbol: C_XOR
name: C_XOR
assembly_mnemonic: c.xor
+ encoding: 35877
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2536,6 +2689,7 @@ instructions:
symbol: C_OR
name: C_OR
assembly_mnemonic: c.or
+ encoding: 35909
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2549,6 +2703,7 @@ instructions:
symbol: C_AND
name: C_AND
assembly_mnemonic: c.and
+ encoding: 35941
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2562,6 +2717,7 @@ instructions:
symbol: C_SUBW
name: C_SUBW
assembly_mnemonic: c.subw
+ encoding: 39941
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2575,6 +2731,7 @@ instructions:
symbol: C_ADDW
name: C_ADDW
assembly_mnemonic: c.addw
+ encoding: 39973
operands:
- { kinds: [register], role: def_use, register_class: GPRC, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS2 }
@@ -2588,6 +2745,7 @@ instructions:
symbol: C_J
name: C_J
assembly_mnemonic: c.j
+ encoding: 40961
operands:
- { kinds: [basic_block], name: TARGET }
num_explicit_defs: 0
@@ -2600,6 +2758,7 @@ instructions:
symbol: C_BEQZ
name: C_BEQZ
assembly_mnemonic: c.beqz
+ encoding: 49153
operands:
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS1 }
- { kinds: [basic_block], name: TARGET }
@@ -2613,6 +2772,7 @@ instructions:
symbol: C_BNEZ
name: C_BNEZ
assembly_mnemonic: c.bnez
+ encoding: 57345
operands:
- { kinds: [register], role: use, register_class: GPRC, register_bank: GPR, name: RS1 }
- { kinds: [basic_block], name: TARGET }
@@ -2626,6 +2786,7 @@ instructions:
symbol: C_SLLI
name: C_SLLI
assembly_mnemonic: c.slli
+ encoding: 1030
operands:
- { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD }
- { kinds: [immediate], immediate_predicate: UIMM6, name: IMM }
@@ -2639,6 +2800,7 @@ instructions:
symbol: C_FLDSP
name: C_FLDSP
assembly_mnemonic: c.fldsp
+ encoding: 9250
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRD }
- { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM }
@@ -2654,6 +2816,7 @@ instructions:
symbol: C_LWSP
name: C_LWSP
assembly_mnemonic: c.lwsp
+ encoding: 17442
operands:
- { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [immediate], immediate_predicate: C_UIMM8_A4, name: IMM }
@@ -2669,6 +2832,7 @@ instructions:
symbol: C_LDSP
name: C_LDSP
assembly_mnemonic: c.ldsp
+ encoding: 25634
operands:
- { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM }
@@ -2684,6 +2848,7 @@ instructions:
symbol: C_JR
name: C_JR
assembly_mnemonic: c.jr
+ encoding: 33794
operands:
- { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS1 }
num_explicit_defs: 0
@@ -2696,6 +2861,7 @@ instructions:
symbol: C_MV
name: C_MV
assembly_mnemonic: c.mv
+ encoding: 33830
operands:
- { kinds: [register], role: def, register_class: GPR_NX0, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS2 }
@@ -2709,6 +2875,7 @@ instructions:
symbol: C_EBREAK
name: C_EBREAK
assembly_mnemonic: c.ebreak
+ encoding: 36866
operands: []
num_explicit_defs: 0
flags: [has_side_effects, produces_code]
@@ -2720,6 +2887,7 @@ instructions:
symbol: C_JALR
name: C_JALR
assembly_mnemonic: c.jalr
+ encoding: 37890
operands:
- { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS1 }
num_explicit_defs: 0
@@ -2733,6 +2901,7 @@ instructions:
symbol: C_ADD
name: C_ADD
assembly_mnemonic: c.add
+ encoding: 37926
operands:
- { kinds: [register], role: def_use, register_class: GPR_NX0, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR_NX0, register_bank: GPR, name: RS2 }
@@ -2746,6 +2915,7 @@ instructions:
symbol: C_FSDSP
name: C_FSDSP
assembly_mnemonic: c.fsdsp
+ encoding: 42018
operands:
- { kinds: [register], role: use, register_class: FPR64, register_bank: FPR, memory_role: value, name: FRS2 }
- { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM }
@@ -2761,6 +2931,7 @@ instructions:
symbol: C_SWSP
name: C_SWSP
assembly_mnemonic: c.swsp
+ encoding: 50210
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [immediate], immediate_predicate: C_UIMM8_A4, name: IMM }
@@ -2776,6 +2947,7 @@ instructions:
symbol: C_SDSP
name: C_SDSP
assembly_mnemonic: c.sdsp
+ encoding: 58402
operands:
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
- { kinds: [immediate], immediate_predicate: C_UIMM9_A8, name: IMM }
@@ -2791,6 +2963,7 @@ instructions:
symbol: FCVT_D_S
name: FCVT_D_S
assembly_mnemonic: fcvt.d.s
+ encoding: 1107592275
operands:
- { kinds: [register], role: def, register_class: FPR64, register_bank: FPR, name: FRD }
- { kinds: [register], role: use, register_class: FPR32, register_bank: FPR, name: FRS1 }
@@ -2805,6 +2978,7 @@ instructions:
symbol: AMOADD_W
name: AMOADD_W
assembly_mnemonic: amoadd.w
+ encoding: 10789935
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2820,6 +2994,7 @@ instructions:
symbol: AMOXOR_W
name: AMOXOR_W
assembly_mnemonic: amoxor.w
+ encoding: 547660847
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2835,6 +3010,7 @@ instructions:
symbol: AMOAND_W
name: AMOAND_W
assembly_mnemonic: amoand.w
+ encoding: 1621402671
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2850,6 +3026,7 @@ instructions:
symbol: AMOOR_W
name: AMOOR_W
assembly_mnemonic: amoor.w
+ encoding: 1084531759
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2865,6 +3042,7 @@ instructions:
symbol: AMOMIN_W
name: AMOMIN_W
assembly_mnemonic: amomin.w
+ encoding: 2158273583
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2880,6 +3058,7 @@ instructions:
symbol: AMOMAX_W
name: AMOMAX_W
assembly_mnemonic: amomax.w
+ encoding: 2695144495
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2895,6 +3074,7 @@ instructions:
symbol: AMOMINU_W
name: AMOMINU_W
assembly_mnemonic: amominu.w
+ encoding: 3232015407
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2910,6 +3090,7 @@ instructions:
symbol: AMOMAXU_W
name: AMOMAXU_W
assembly_mnemonic: amomaxu.w
+ encoding: 3768886319
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2925,6 +3106,7 @@ instructions:
symbol: LR_D
name: LR_D
assembly_mnemonic: lr.d
+ encoding: 268743727
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: address, name: RS1 }
@@ -2939,6 +3121,7 @@ instructions:
symbol: SC_D
name: SC_D
assembly_mnemonic: sc.d
+ encoding: 413447215
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2954,6 +3137,7 @@ instructions:
symbol: AMOSWAP_D
name: AMOSWAP_D
assembly_mnemonic: amoswap.d
+ encoding: 145011759
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2969,6 +3153,7 @@ instructions:
symbol: AMOADD_D
name: AMOADD_D
assembly_mnemonic: amoadd.d
+ encoding: 10794031
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2984,6 +3169,7 @@ instructions:
symbol: AMOXOR_D
name: AMOXOR_D
assembly_mnemonic: amoxor.d
+ encoding: 547664943
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -2999,6 +3185,7 @@ instructions:
symbol: AMOAND_D
name: AMOAND_D
assembly_mnemonic: amoand.d
+ encoding: 1621406767
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3014,6 +3201,7 @@ instructions:
symbol: AMOOR_D
name: AMOOR_D
assembly_mnemonic: amoor.d
+ encoding: 1084535855
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3029,6 +3217,7 @@ instructions:
symbol: AMOMIN_D
name: AMOMIN_D
assembly_mnemonic: amomin.d
+ encoding: 2158277679
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3044,6 +3233,7 @@ instructions:
symbol: AMOMAX_D
name: AMOMAX_D
assembly_mnemonic: amomax.d
+ encoding: 2695148591
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3059,6 +3249,7 @@ instructions:
symbol: AMOMINU_D
name: AMOMINU_D
assembly_mnemonic: amominu.d
+ encoding: 3232019503
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3074,6 +3265,7 @@ instructions:
symbol: AMOMAXU_D
name: AMOMAXU_D
assembly_mnemonic: amomaxu.d
+ encoding: 3768890415
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, memory_role: value, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, memory_role: value, name: RS2 }
@@ -3204,6 +3396,7 @@ instructions:
symbol: JALR_CALL
name: JALR_CALL
assembly_mnemonic: jalr
+ encoding: 1344615
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -3221,6 +3414,7 @@ instructions:
symbol: JALR_TAIL
name: JALR_TAIL
assembly_mnemonic: jalr
+ encoding: 1344615
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
@@ -3238,6 +3432,7 @@ instructions:
symbol: JALR_RET
name: JALR_RET
assembly_mnemonic: jalr
+ encoding: 1344615
operands:
- { kinds: [register], role: def, register_class: GPR, register_bank: GPR, name: RD }
- { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 }
diff --git a/backend/lib/Target/RISCV/RISCVAsmBackend.cpp b/backend/lib/Target/RISCV/RISCVAsmBackend.cpp
new file mode 100644
index 0000000..4e07933
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVAsmBackend.cpp
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVAsmBackend.h"
+
+#include "rcc/Target/RISCV/RISCVFixupKinds.h"
+#include "rcc/Target/RISCV/RISCVInstPrinter.h"
+#include "rcc/Target/RISCV/RISCVInstructions.h"
+#include "rcc/Target/RISCV/RISCVRegisters.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <string>
+
+namespace rcc::riscv {
+namespace {
+
+enum class RISCVRelocation : std::uint32_t {
+ Relocation32 = 1,
+ Relocation64 = 2,
+ Branch = 16,
+ JAL = 17,
+ CallPLT = 19,
+ PCRelativeHigh20 = 23,
+ PCRelativeLow12I = 24,
+ PCRelativeLow12S = 25,
+ High20 = 26,
+ Low12I = 27,
+ Low12S = 28,
+ Add8 = 33,
+ Add16 = 34,
+ Add32 = 35,
+ Add64 = 36,
+ Subtract8 = 37,
+ Subtract16 = 38,
+ Subtract32 = 39,
+ Subtract64 = 40,
+ RVCBranch = 44,
+ RVCJump = 45,
+ PCRelative32 = 57,
+};
+
+[[nodiscard]] bool isTargetKind(mc::MCFixupKind Kind, RISCVFixupKind TargetKind) noexcept {
+ return Kind == fixupKind(TargetKind);
+}
+
+[[nodiscard]] Expected<void> requireStorage(std::span<std::uint8_t> Data, std::uint64_t Offset,
+ std::uint8_t Size) {
+ if (Offset > Data.size() || Size > Data.size() - static_cast<std::size_t>(Offset)) {
+ return makeUnexpected(ErrorCode::FixupApplicationFailed,
+ "RISC-V fixup exceeds its encoded fragment");
+ }
+ return {};
+}
+
+void writeLittleEndian(std::span<std::uint8_t> Data, std::uint64_t Offset, std::uint64_t Value,
+ std::uint8_t Size) noexcept {
+ for (std::uint8_t Index = 0; Index < Size; ++Index)
+ Data[static_cast<std::size_t>(Offset) + Index] =
+ static_cast<std::uint8_t>(Value >> (Index * 8U));
+}
+
+[[nodiscard]] std::uint32_t readWord(std::span<const std::uint8_t> Data,
+ std::uint64_t Offset) noexcept {
+ std::uint32_t Result = 0;
+ for (std::uint8_t Index = 0; Index < 4; ++Index)
+ Result |= static_cast<std::uint32_t>(Data[static_cast<std::size_t>(Offset) + Index])
+ << (Index * 8U);
+ return Result;
+}
+
+[[nodiscard]] std::uint16_t readHalf(std::span<const std::uint8_t> Data,
+ std::uint64_t Offset) noexcept {
+ return static_cast<std::uint16_t>(Data[static_cast<std::size_t>(Offset)]) |
+ static_cast<std::uint16_t>(Data[static_cast<std::size_t>(Offset) + 1U] << 8U);
+}
+
+[[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;
+ return Value >= Minimum && Value <= Maximum;
+}
+
+[[nodiscard]] Expected<void> requireDisplacement(std::int64_t Value, unsigned Bits,
+ std::string_view Name) {
+ if ((Value & 1) != 0 || !fitsSigned(Value, Bits)) {
+ return makeUnexpected(ErrorCode::FixupApplicationFailed,
+ std::string(Name) + " displacement is out of range or unaligned");
+ }
+ return {};
+}
+
+[[nodiscard]] std::uint32_t encodeBranchImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint32_t>(Value);
+ return ((Bits >> 12U) & 0x1U) << 31U | ((Bits >> 5U) & 0x3fU) << 25U |
+ ((Bits >> 1U) & 0xfU) << 8U | ((Bits >> 11U) & 0x1U) << 7U;
+}
+
+[[nodiscard]] std::uint32_t encodeJALImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint32_t>(Value);
+ return ((Bits >> 20U) & 0x1U) << 31U | ((Bits >> 1U) & 0x3ffU) << 21U |
+ ((Bits >> 11U) & 0x1U) << 20U | ((Bits >> 12U) & 0xffU) << 12U;
+}
+
+[[nodiscard]] std::uint16_t encodeRVCJumpImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint16_t>(Value);
+ return static_cast<std::uint16_t>(((Bits >> 11U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 11U |
+ ((Bits >> 8U) & 3U) << 9U | ((Bits >> 10U) & 1U) << 8U |
+ ((Bits >> 6U) & 1U) << 7U | ((Bits >> 7U) & 1U) << 6U |
+ ((Bits >> 1U) & 7U) << 3U | ((Bits >> 5U) & 1U) << 2U);
+}
+
+[[nodiscard]] std::uint16_t encodeRVCBranchImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint16_t>(Value);
+ return static_cast<std::uint16_t>(((Bits >> 8U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 10U |
+ ((Bits >> 6U) & 3U) << 5U | ((Bits >> 1U) & 3U) << 3U |
+ ((Bits >> 5U) & 1U) << 2U);
+}
+
+[[nodiscard]] Expected<void> requireRelocationTargetKind(const mc::MCValue &Value,
+ std::uint32_t Expected,
+ std::string_view Name) {
+ if (Value.TargetKind != Expected) {
+ return makeUnexpected(ErrorCode::RelocationFailed,
+ std::string(Name) + " has an incompatible target expression");
+ }
+ return {};
+}
+
+} // namespace
+
+Expected<mc::MCFixupKindInfo> RISCVAsmBackend::fixupKindInfo(mc::MCFixupKind Kind) const {
+ switch (Kind) {
+ case mc::fixup_kind::Data1:
+ return mc::MCFixupKindInfo{.StorageSize = 1, .PCRelative = false};
+ case mc::fixup_kind::Data2:
+ return mc::MCFixupKindInfo{.StorageSize = 2, .PCRelative = false};
+ case mc::fixup_kind::Data4:
+ return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = false};
+ case mc::fixup_kind::Data8:
+ return mc::MCFixupKindInfo{.StorageSize = 8, .PCRelative = false};
+ case mc::fixup_kind::PCRelative4:
+ return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = true};
+ default:
+ break;
+ }
+ if (isTargetKind(Kind, RISCVFixupKind::RVCJump) ||
+ isTargetKind(Kind, RISCVFixupKind::RVCBranch)) {
+ return mc::MCFixupKindInfo{.StorageSize = 2, .PCRelative = true};
+ }
+ if (Kind >= fixupKind(RISCVFixupKind::High20) && Kind <= fixupKind(RISCVFixupKind::CallPLT)) {
+ const bool PCRelative = Kind >= fixupKind(RISCVFixupKind::PCRelativeHigh20);
+ return mc::MCFixupKindInfo{.StorageSize = 4, .PCRelative = PCRelative};
+ }
+ return makeUnexpected(ErrorCode::InvalidArgument, "unknown RISC-V fixup kind");
+}
+
+Expected<void> RISCVAsmBackend::applyFixup(mc::MCFixupKind Kind, std::span<std::uint8_t> Data,
+ std::uint64_t Offset, std::int64_t Value) const {
+ auto Info = fixupKindInfo(Kind);
+ if (!Info)
+ return std::unexpected(Info.error());
+ auto Storage = requireStorage(Data, Offset, Info->StorageSize);
+ if (!Storage)
+ return std::unexpected(Storage.error());
+
+ if (Kind == mc::fixup_kind::Data1 || Kind == mc::fixup_kind::Data2 ||
+ Kind == mc::fixup_kind::Data4 || Kind == mc::fixup_kind::Data8 ||
+ Kind == mc::fixup_kind::PCRelative4) {
+ writeLittleEndian(Data, Offset, static_cast<std::uint64_t>(Value), Info->StorageSize);
+ return {};
+ }
+
+ if (Info->StorageSize == 2) {
+ std::uint16_t Instruction = readHalf(Data, Offset);
+ if (isTargetKind(Kind, RISCVFixupKind::RVCJump)) {
+ auto Range = requireDisplacement(Value, 12, "RISC-V compressed jump");
+ if (!Range)
+ return std::unexpected(Range.error());
+ Instruction = static_cast<std::uint16_t>((Instruction & ~std::uint16_t{0x1ffc}) |
+ encodeRVCJumpImmediate(Value));
+ } else {
+ auto Range = requireDisplacement(Value, 9, "RISC-V compressed branch");
+ if (!Range)
+ return std::unexpected(Range.error());
+ Instruction = static_cast<std::uint16_t>((Instruction & ~std::uint16_t{0x1c7c}) |
+ encodeRVCBranchImmediate(Value));
+ }
+ writeLittleEndian(Data, Offset, Instruction, 2);
+ return {};
+ }
+
+ std::uint32_t Instruction = readWord(Data, Offset);
+ if (isTargetKind(Kind, RISCVFixupKind::High20) ||
+ isTargetKind(Kind, RISCVFixupKind::PCRelativeHigh20) ||
+ isTargetKind(Kind, RISCVFixupKind::CallPLT)) {
+ const std::uint64_t Adjusted = static_cast<std::uint64_t>(Value) + 0x800U;
+ const std::uint32_t High = static_cast<std::uint32_t>(Adjusted >> 12U);
+ Instruction = (Instruction & 0xfffU) | (High << 12U);
+ } else if (isTargetKind(Kind, RISCVFixupKind::Low12I) ||
+ isTargetKind(Kind, RISCVFixupKind::PCRelativeLow12I)) {
+ Instruction = (Instruction & 0x000fffffU) | (static_cast<std::uint32_t>(Value) & 0xfffU) << 20U;
+ } else if (isTargetKind(Kind, RISCVFixupKind::Low12S) ||
+ isTargetKind(Kind, RISCVFixupKind::PCRelativeLow12S)) {
+ const std::uint32_t Low = static_cast<std::uint32_t>(Value) & 0xfffU;
+ Instruction = (Instruction & ~std::uint32_t{0xfe000f80}) | ((Low >> 5U) & 0x7fU) << 25U |
+ (Low & 0x1fU) << 7U;
+ } else if (isTargetKind(Kind, RISCVFixupKind::JAL)) {
+ auto Range = requireDisplacement(Value, 21, "RISC-V JAL");
+ if (!Range)
+ return std::unexpected(Range.error());
+ Instruction = (Instruction & 0xfffU) | encodeJALImmediate(Value);
+ } else if (isTargetKind(Kind, RISCVFixupKind::Branch)) {
+ auto Range = requireDisplacement(Value, 13, "RISC-V branch");
+ if (!Range)
+ return std::unexpected(Range.error());
+ Instruction = (Instruction & ~std::uint32_t{0xfe000f80}) | encodeBranchImmediate(Value);
+ } else {
+ return makeUnexpected(ErrorCode::FixupApplicationFailed,
+ "RISC-V fixup cannot be applied to an instruction");
+ }
+ writeLittleEndian(Data, Offset, Instruction, 4);
+ return {};
+}
+
+Expected<std::uint32_t> RISCVAsmBackend::relocationType(const mc::MCFixup &Fixup,
+ const mc::MCValue &Value) const {
+ const auto Relocation = [](RISCVRelocation Type) { return static_cast<std::uint32_t>(Type); };
+ switch (Fixup.Kind) {
+ case mc::fixup_kind::Data4:
+ return Relocation(RISCVRelocation::Relocation32);
+ case mc::fixup_kind::Data8:
+ return Relocation(RISCVRelocation::Relocation64);
+ case mc::fixup_kind::PCRelative4:
+ return Relocation(RISCVRelocation::PCRelative32);
+ default:
+ break;
+ }
+
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeHigh20)) {
+ auto Kind = requireRelocationTargetKind(
+ Value, static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeHigh), "R_RISCV_PCREL_HI20");
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ return Relocation(RISCVRelocation::PCRelativeHigh20);
+ }
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12I) ||
+ isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12S)) {
+ auto Kind = requireRelocationTargetKind(
+ Value, static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeLow), "R_RISCV_PCREL_LO12");
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ return Relocation(isTargetKind(Fixup.Kind, RISCVFixupKind::PCRelativeLow12I)
+ ? RISCVRelocation::PCRelativeLow12I
+ : RISCVRelocation::PCRelativeLow12S);
+ }
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::CallPLT)) {
+ auto Kind = requireRelocationTargetKind(
+ Value, static_cast<std::uint32_t>(RISCVMCExprKind::CallPLT), "R_RISCV_CALL_PLT");
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ return Relocation(RISCVRelocation::CallPLT);
+ }
+ if (Value.TargetKind != 0) {
+ return makeUnexpected(ErrorCode::RelocationFailed,
+ "RISC-V relocation has an unsupported target expression");
+ }
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::High20))
+ return Relocation(RISCVRelocation::High20);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::Low12I))
+ return Relocation(RISCVRelocation::Low12I);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::Low12S))
+ return Relocation(RISCVRelocation::Low12S);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::JAL))
+ return Relocation(RISCVRelocation::JAL);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::Branch))
+ return Relocation(RISCVRelocation::Branch);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCJump))
+ return Relocation(RISCVRelocation::RVCJump);
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCBranch))
+ return Relocation(RISCVRelocation::RVCBranch);
+ return makeUnexpected(ErrorCode::RelocationFailed, "RISC-V fixup has no ELF relocation type");
+}
+
+Expected<std::vector<mc::MCFixupRelocation>>
+RISCVAsmBackend::relocationsForFixup(const mc::MCFixup &Fixup, const mc::MCValue &Value) const {
+ if (!Value.SubtractSymbol)
+ return mc::MCAsmBackend::relocationsForFixup(Fixup, Value);
+ if (!Value.AddSymbol || Value.TargetKind != 0) {
+ return makeUnexpected(ErrorCode::RelocationFailed,
+ "RISC-V symbol difference has an invalid relocation expression");
+ }
+
+ RISCVRelocation AddType;
+ RISCVRelocation SubtractType;
+ switch (Fixup.Kind) {
+ case mc::fixup_kind::Data1:
+ AddType = RISCVRelocation::Add8;
+ SubtractType = RISCVRelocation::Subtract8;
+ break;
+ case mc::fixup_kind::Data2:
+ AddType = RISCVRelocation::Add16;
+ SubtractType = RISCVRelocation::Subtract16;
+ break;
+ case mc::fixup_kind::Data4:
+ AddType = RISCVRelocation::Add32;
+ SubtractType = RISCVRelocation::Subtract32;
+ break;
+ case mc::fixup_kind::Data8:
+ AddType = RISCVRelocation::Add64;
+ SubtractType = RISCVRelocation::Subtract64;
+ break;
+ default:
+ return makeUnexpected(ErrorCode::RelocationFailed,
+ "RISC-V fixup cannot encode a symbol difference");
+ }
+ return std::vector<mc::MCFixupRelocation>{
+ {.Type = static_cast<std::uint32_t>(AddType),
+ .Symbol = Value.AddSymbol,
+ .Addend = Value.Addend},
+ {.Type = static_cast<std::uint32_t>(SubtractType),
+ .Symbol = Value.SubtractSymbol,
+ .Addend = 0},
+ };
+}
+
+bool RISCVAsmBackend::mayNeedRelaxation(const mc::MCInst &Instruction) const noexcept {
+ const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value());
+ return Opcode == InstructionOpcode::C_J || Opcode == InstructionOpcode::C_BEQZ ||
+ Opcode == InstructionOpcode::C_BNEZ;
+}
+
+Expected<bool> RISCVAsmBackend::fixupNeedsRelaxation(const mc::MCFixup &Fixup,
+ std::int64_t Value) const {
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCJump))
+ return !fitsSigned(Value, 12) || (Value & 1) != 0;
+ if (isTargetKind(Fixup.Kind, RISCVFixupKind::RVCBranch))
+ return !fitsSigned(Value, 9) || (Value & 1) != 0;
+ return false;
+}
+
+Expected<mc::MCInst> RISCVAsmBackend::relaxInstruction(const mc::MCInst &Instruction) const {
+ const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value());
+ const bool IsJump = Opcode == InstructionOpcode::C_J;
+ const bool IsBranch = Opcode == InstructionOpcode::C_BEQZ || Opcode == InstructionOpcode::C_BNEZ;
+ const std::size_t ExpectedOperands = IsJump ? 1U : 2U;
+ if ((!IsJump && !IsBranch) || Instruction.operands().size() != ExpectedOperands) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V MC relaxation received an unsupported instruction");
+ }
+
+ const mc::MCOperand &Target = Instruction.operands().back();
+ if (Target.expressionValue() == nullptr) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V MC relaxation requires a symbolic target");
+ }
+ const InstructionOpcode RelaxedOpcode =
+ IsJump
+ ? InstructionOpcode::JAL
+ : (Opcode == InstructionOpcode::C_BEQZ ? InstructionOpcode::BEQ : InstructionOpcode::BNE);
+ mc::MCInst Result(mc::MCOpcode::fromValue(static_cast<std::uint32_t>(RelaxedOpcode)));
+ Result.setFlags(Instruction.flags());
+ Result.setSourceIdentity(Instruction.sourceIdentity());
+ if (IsJump) {
+ Result.addOperand(mc::MCOperand::registerOperand(
+ mc::MCRegister::fromValue(static_cast<std::uint32_t>(PhysicalRegisterID::X0))));
+ } else {
+ Result.addOperand(Instruction.operands().front());
+ Result.addOperand(mc::MCOperand::registerOperand(
+ mc::MCRegister::fromValue(static_cast<std::uint32_t>(PhysicalRegisterID::X0))));
+ }
+ Result.addOperand(Target);
+ return Result;
+}
+
+std::uint32_t RISCVAsmBackend::objectFlags() const noexcept {
+ constexpr std::uint32_t RVC = 1;
+ constexpr std::uint32_t FloatABIDouble = 4;
+ return RVC | FloatABIDouble;
+}
+
+} // namespace rcc::riscv
diff --git a/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp
new file mode 100644
index 0000000..5f98887
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVMCCodeEmitter.cpp
@@ -0,0 +1,984 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVMCCodeEmitter.h"
+
+#include "rcc/CodeGen/Register.h"
+#include "rcc/MC/MCExpr.h"
+#include "rcc/Target/RISCV/RISCVFixupKinds.h"
+#include "rcc/Target/RISCV/RISCVInstPrinter.h"
+#include "rcc/Target/RISCV/RISCVTarget.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+namespace rcc::riscv {
+namespace {
+
+[[nodiscard]] Expected<void> requireOperandCount(const mc::MCInst &Instruction, std::size_t Count) {
+ if (Instruction.operands().size() != Count) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V instruction has an unexpected encoding operand count");
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<std::uint32_t> registerEncoding(const mc::MCInst &Instruction,
+ std::size_t Index,
+ const TargetDescription &Target) {
+ if (Index >= Instruction.operands().size()) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V encoding references an absent register operand");
+ }
+ const mc::MCRegister *Register = Instruction.operands()[Index].registerValue();
+ if (Register == nullptr) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V encoding requires a register operand");
+ }
+ auto Physical = PhysicalRegister::create(Register->value());
+ if (!Physical)
+ return std::unexpected(Physical.error());
+ const PhysicalRegisterDesc *Description = Target.registers().physicalRegister(*Physical);
+ if (Description == nullptr || Description->Encoding >= 32) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V encoding references an unknown physical register");
+ }
+ return Description->Encoding;
+}
+
+[[nodiscard]] Expected<void> validateRegisterOperands(const mc::MCInst &Instruction,
+ const InstructionDescriptor &Descriptor,
+ const TargetDescription &Target) {
+ for (std::size_t Index = 0; Index < Instruction.operands().size(); ++Index) {
+ const mc::MCRegister *Register = Instruction.operands()[Index].registerValue();
+ if (Register == nullptr)
+ continue;
+ if (Index >= Descriptor.Operands.size()) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V register operand has no target descriptor");
+ }
+ auto Physical = PhysicalRegister::create(Register->value());
+ if (!Physical)
+ return std::unexpected(Physical.error());
+ const OperandDescriptor &Operand = Descriptor.Operands[Index];
+ if (Operand.RegClass &&
+ !Target.registers().registerClassContains(*Operand.RegClass, *Physical)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V register is outside its required register class");
+ }
+ if (Operand.RegBank && !Target.registers().bankContainsRegister(*Operand.RegBank, *Physical)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V register is outside its required register bank");
+ }
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<std::uint32_t> compactRegisterEncoding(const mc::MCInst &Instruction,
+ std::size_t Index,
+ const TargetDescription &Target) {
+ auto Encoding = registerEncoding(Instruction, Index, Target);
+ if (!Encoding)
+ return std::unexpected(Encoding.error());
+ if (*Encoding < 8 || *Encoding > 15) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "compressed RISC-V instruction requires an x8-x15 register");
+ }
+ return *Encoding - 8U;
+}
+
+[[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;
+ return Value >= Minimum && Value <= Maximum;
+}
+
+[[nodiscard]] bool fitsUnsigned(std::int64_t Value, unsigned Bits) noexcept {
+ return Value >= 0 && static_cast<std::uint64_t>(Value) < (std::uint64_t{1} << Bits);
+}
+
+[[nodiscard]] Expected<void> requireSigned(std::int64_t Value, unsigned Bits,
+ std::string_view Name) {
+ if (!fitsSigned(Value, Bits)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ std::string(Name) + " immediate is out of range");
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<void> requireUnsigned(std::int64_t Value, unsigned Bits,
+ std::string_view Name) {
+ if (!fitsUnsigned(Value, Bits)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ std::string(Name) + " immediate is out of range");
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<void> requireRoundingMode(std::int64_t Value) {
+ if ((Value >= 0 && Value <= 4) || Value == 7)
+ return {};
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V rounding mode is not an ISA-defined value");
+}
+
+[[nodiscard]] Expected<void> requireAligned(std::int64_t Value, std::uint64_t Alignment,
+ std::string_view Name) {
+ if (Value % static_cast<std::int64_t>(Alignment) != 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ std::string(Name) + " immediate is not aligned");
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<std::uint32_t> expressionTargetKind(const mc::MCOperand &Operand) {
+ const mc::MCExprRef *Expression = Operand.expressionValue();
+ if (Expression == nullptr)
+ return 0U;
+ if (!*Expression) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V instruction has a null expression operand");
+ }
+ auto Value = mc::evaluateAsRelocatable(**Expression);
+ if (!Value)
+ return std::unexpected(Value.error());
+ return Value->TargetKind;
+}
+
+[[nodiscard]] Expected<std::int64_t> immediateOrFixup(const mc::MCInst &Instruction,
+ std::size_t Index, mc::MCFixupKind Kind,
+ bool PCRelative,
+ mc::MCEncodedInstruction &Result) {
+ if (Index >= Instruction.operands().size()) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V encoding references an absent immediate operand");
+ }
+ const mc::MCOperand &Operand = Instruction.operands()[Index];
+ if (const std::int64_t *Immediate = Operand.immediateValue(); Immediate != nullptr)
+ return *Immediate;
+ const mc::MCExprRef *Expression = Operand.expressionValue();
+ if (Expression == nullptr || !*Expression) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V encoding requires an immediate or expression operand");
+ }
+ if (const auto Absolute = (*Expression)->evaluateAbsolute())
+ return *Absolute;
+ if (Kind == mc::fixup_kind::None) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V instruction does not permit a symbolic immediate here");
+ }
+ Result.Fixups.push_back(mc::MCFixup{.Offset = 0,
+ .Value = *Expression,
+ .Kind = Kind,
+ .PCRelative = PCRelative,
+ .LinkerRelaxable = false});
+ return 0;
+}
+
+[[nodiscard]] Expected<mc::MCFixupKind> uFixupKind(const mc::MCOperand &Operand) {
+ auto Kind = expressionTargetKind(Operand);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ if (*Kind == 0)
+ return fixupKind(RISCVFixupKind::High20);
+ if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeHigh))
+ return fixupKind(RISCVFixupKind::PCRelativeHigh20);
+ if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::CallPLT))
+ return fixupKind(RISCVFixupKind::CallPLT);
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V U-type operand has an incompatible target expression");
+}
+
+[[nodiscard]] Expected<mc::MCFixupKind> lowFixupKind(const mc::MCOperand &Operand, bool Store) {
+ auto Kind = expressionTargetKind(Operand);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ if (*Kind == 0)
+ return fixupKind(Store ? RISCVFixupKind::Low12S : RISCVFixupKind::Low12I);
+ if (*Kind == static_cast<std::uint32_t>(RISCVMCExprKind::PCRelativeLow)) {
+ return fixupKind(Store ? RISCVFixupKind::PCRelativeLow12S : RISCVFixupKind::PCRelativeLow12I);
+ }
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V low immediate has an incompatible target expression");
+}
+
+[[nodiscard]] Expected<void> requirePlainExpression(const mc::MCOperand &Operand,
+ std::string_view Name) {
+ auto Kind = expressionTargetKind(Operand);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ if (*Kind != 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ std::string(Name) + " does not accept a target expression modifier");
+ }
+ return {};
+}
+
+[[nodiscard]] std::uint32_t encodeBranchImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint32_t>(Value);
+ return ((Bits >> 12U) & 1U) << 31U | ((Bits >> 5U) & 0x3fU) << 25U | ((Bits >> 1U) & 0xfU) << 8U |
+ ((Bits >> 11U) & 1U) << 7U;
+}
+
+[[nodiscard]] std::uint32_t encodeJALImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint32_t>(Value);
+ return ((Bits >> 20U) & 1U) << 31U | ((Bits >> 1U) & 0x3ffU) << 21U |
+ ((Bits >> 11U) & 1U) << 20U | ((Bits >> 12U) & 0xffU) << 12U;
+}
+
+[[nodiscard]] std::uint16_t encodeRVCJumpImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint16_t>(Value);
+ return static_cast<std::uint16_t>(((Bits >> 11U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 11U |
+ ((Bits >> 8U) & 3U) << 9U | ((Bits >> 10U) & 1U) << 8U |
+ ((Bits >> 6U) & 1U) << 7U | ((Bits >> 7U) & 1U) << 6U |
+ ((Bits >> 1U) & 7U) << 3U | ((Bits >> 5U) & 1U) << 2U);
+}
+
+[[nodiscard]] std::uint16_t encodeRVCBranchImmediate(std::int64_t Value) noexcept {
+ const auto Bits = static_cast<std::uint16_t>(Value);
+ return static_cast<std::uint16_t>(((Bits >> 8U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 10U |
+ ((Bits >> 6U) & 3U) << 5U | ((Bits >> 1U) & 3U) << 3U |
+ ((Bits >> 5U) & 1U) << 2U);
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeRType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly) {
+ const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value());
+ std::size_t RegisterCount = 0;
+ bool HasRoundingMode = false;
+ switch (Format) {
+ case AssemblyFormat::RD_RS1_RS2:
+ case AssemblyFormat::FRD_FRS1_FRS2:
+ case AssemblyFormat::RD_FRS1_FRS2:
+ RegisterCount = 3;
+ break;
+ case AssemblyFormat::FRD_FRS1_FRS2_RM:
+ RegisterCount = 3;
+ HasRoundingMode = true;
+ break;
+ case AssemblyFormat::FRD_FRS1_RM:
+ case AssemblyFormat::RD_FRS1_RM:
+ case AssemblyFormat::FRD_RS1_RM:
+ RegisterCount = 2;
+ HasRoundingMode = true;
+ break;
+ case AssemblyFormat::RD_FRS1:
+ case AssemblyFormat::FRD_RS1:
+ RegisterCount = 2;
+ break;
+ default:
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "unsupported RISC-V R-type assembly format");
+ }
+ auto Count = requireOperandCount(Instruction, RegisterCount + (HasRoundingMode ? 1U : 0U));
+ if (!Count)
+ return std::unexpected(Count.error());
+
+ std::uint32_t Encoding = Assembly.Encoding & ~std::uint32_t{0x000f8f80};
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ auto Source1 = registerEncoding(Instruction, 1, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Source1)
+ return std::unexpected(Source1.error());
+ Encoding |= *Destination << 7U | *Source1 << 15U;
+ if (RegisterCount == 3) {
+ auto Source2 = registerEncoding(Instruction, 2, Target);
+ if (!Source2)
+ return std::unexpected(Source2.error());
+ Encoding = (Encoding & ~std::uint32_t{0x01f00000}) | *Source2 << 20U;
+ }
+ return Encoding;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeRTypeWithResult(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Encoding = encodeRType(Instruction, Target, Assembly);
+ if (!Encoding)
+ return std::unexpected(Encoding.error());
+ const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value());
+ std::size_t ModeIndex = 0;
+ switch (Format) {
+ case AssemblyFormat::FRD_FRS1_FRS2_RM:
+ ModeIndex = 3;
+ break;
+ case AssemblyFormat::FRD_FRS1_RM:
+ case AssemblyFormat::RD_FRS1_RM:
+ case AssemblyFormat::FRD_RS1_RM:
+ ModeIndex = 2;
+ break;
+ default:
+ return *Encoding;
+ }
+ auto Mode = immediateOrFixup(Instruction, ModeIndex, mc::fixup_kind::None, false, Result);
+ if (!Mode)
+ return std::unexpected(Mode.error());
+ auto Range = requireRoundingMode(*Mode);
+ if (!Range)
+ return std::unexpected(Range.error());
+ return (*Encoding & ~std::uint32_t{0x7000}) | static_cast<std::uint32_t>(*Mode) << 12U;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeIType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value());
+ if (Format == AssemblyFormat::NONE) {
+ auto Count = requireOperandCount(Instruction, 0);
+ if (!Count)
+ return std::unexpected(Count.error());
+ return Assembly.Encoding;
+ }
+ if (Format == AssemblyFormat::IMM_IMM) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Predecessor = immediateOrFixup(Instruction, 0, mc::fixup_kind::None, false, Result);
+ auto Successor = immediateOrFixup(Instruction, 1, mc::fixup_kind::None, false, Result);
+ if (!Predecessor)
+ return std::unexpected(Predecessor.error());
+ if (!Successor)
+ return std::unexpected(Successor.error());
+ auto PredRange = requireUnsigned(*Predecessor, 4, "RISC-V fence predecessor");
+ auto SuccRange = requireUnsigned(*Successor, 4, "RISC-V fence successor");
+ if (!PredRange)
+ return std::unexpected(PredRange.error());
+ if (!SuccRange)
+ return std::unexpected(SuccRange.error());
+ return (Assembly.Encoding & ~std::uint32_t{0x0ff00000}) |
+ static_cast<std::uint32_t>(*Predecessor) << 24U |
+ static_cast<std::uint32_t>(*Successor) << 20U;
+ }
+ if (Format != AssemblyFormat::RD_RS1_IMM && Format != AssemblyFormat::RD_OFFSET_RS1 &&
+ Format != AssemblyFormat::FRD_OFFSET_RS1) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "unsupported RISC-V I-type assembly format");
+ }
+ auto Count = requireOperandCount(Instruction, 3);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ auto Source = registerEncoding(Instruction, 1, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Source)
+ return std::unexpected(Source.error());
+ std::uint32_t Encoding =
+ (Assembly.Encoding & ~std::uint32_t{0x000f8f80}) | *Destination << 7U | *Source << 15U;
+
+ const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value());
+ const bool Shift64 = Opcode == InstructionOpcode::SLLI || Opcode == InstructionOpcode::SRLI ||
+ Opcode == InstructionOpcode::SRAI;
+ const bool Shift32 = Opcode == InstructionOpcode::SLLIW || Opcode == InstructionOpcode::SRLIW ||
+ Opcode == InstructionOpcode::SRAIW;
+ if (Shift64 || Shift32) {
+ auto Immediate = immediateOrFixup(Instruction, 2, mc::fixup_kind::None, false, Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ auto Range = requireUnsigned(*Immediate, Shift64 ? 6U : 5U, "RISC-V shift");
+ if (!Range)
+ return std::unexpected(Range.error());
+ const std::uint32_t Mask = Shift64 ? 0x03f00000U : 0x01f00000U;
+ return (Encoding & ~Mask) | static_cast<std::uint32_t>(*Immediate) << 20U;
+ }
+
+ auto Kind = lowFixupKind(Instruction.operands()[2], false);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ auto Immediate = immediateOrFixup(Instruction, 2, *Kind,
+ *Kind == fixupKind(RISCVFixupKind::PCRelativeLow12I), Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ if (Instruction.operands()[2].expressionValue() == nullptr) {
+ auto Range = requireSigned(*Immediate, 12, "RISC-V I-type");
+ if (!Range)
+ return std::unexpected(Range.error());
+ }
+ return (Encoding & ~std::uint32_t{0xfff00000}) | (static_cast<std::uint32_t>(*Immediate) & 0xfffU)
+ << 20U;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeSType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Count = requireOperandCount(Instruction, 3);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Source2 = registerEncoding(Instruction, 0, Target);
+ auto Source1 = registerEncoding(Instruction, 1, Target);
+ if (!Source2)
+ return std::unexpected(Source2.error());
+ if (!Source1)
+ return std::unexpected(Source1.error());
+ auto Kind = lowFixupKind(Instruction.operands()[2], true);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ auto Immediate = immediateOrFixup(Instruction, 2, *Kind,
+ *Kind == fixupKind(RISCVFixupKind::PCRelativeLow12S), Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ if (Instruction.operands()[2].expressionValue() == nullptr) {
+ auto Range = requireSigned(*Immediate, 12, "RISC-V S-type");
+ if (!Range)
+ return std::unexpected(Range.error());
+ }
+ const std::uint32_t Bits = static_cast<std::uint32_t>(*Immediate) & 0xfffU;
+ return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Source1 << 15U | *Source2 << 20U |
+ ((Bits >> 5U) & 0x7fU) << 25U | (Bits & 0x1fU) << 7U;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeBType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Count = requireOperandCount(Instruction, 3);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Source1 = registerEncoding(Instruction, 0, Target);
+ auto Source2 = registerEncoding(Instruction, 1, Target);
+ if (!Source1)
+ return std::unexpected(Source1.error());
+ if (!Source2)
+ return std::unexpected(Source2.error());
+ auto Plain = requirePlainExpression(Instruction.operands()[2], "RISC-V branch");
+ if (!Plain)
+ return std::unexpected(Plain.error());
+ auto Immediate =
+ immediateOrFixup(Instruction, 2, fixupKind(RISCVFixupKind::Branch), true, Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ if (Instruction.operands()[2].expressionValue() == nullptr &&
+ (!fitsSigned(*Immediate, 13) || (*Immediate & 1) != 0)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V branch displacement is out of range or unaligned");
+ }
+ return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Source1 << 15U | *Source2 << 20U |
+ encodeBranchImmediate(*Immediate);
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeUType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ auto Kind = uFixupKind(Instruction.operands()[1]);
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ const bool PCRelative = *Kind == fixupKind(RISCVFixupKind::PCRelativeHigh20) ||
+ *Kind == fixupKind(RISCVFixupKind::CallPLT);
+ auto Immediate = immediateOrFixup(Instruction, 1, *Kind, PCRelative, Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ if (Instruction.operands()[1].expressionValue() == nullptr) {
+ auto Range = requireSigned(*Immediate, 20, "RISC-V U-type");
+ if (!Range)
+ return std::unexpected(Range.error());
+ }
+ return (Assembly.Encoding & 0x7fU) | *Destination << 7U |
+ (static_cast<std::uint32_t>(*Immediate) & 0xfffffU) << 12U;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeJType(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ auto Plain = requirePlainExpression(Instruction.operands()[1], "RISC-V JAL");
+ if (!Plain)
+ return std::unexpected(Plain.error());
+ auto Immediate = immediateOrFixup(Instruction, 1, fixupKind(RISCVFixupKind::JAL), true, Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ if (Instruction.operands()[1].expressionValue() == nullptr &&
+ (!fitsSigned(*Immediate, 21) || (*Immediate & 1) != 0)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V JAL displacement is out of range or unaligned");
+ }
+ return (Assembly.Encoding & 0x7fU) | *Destination << 7U | encodeJALImmediate(*Immediate);
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeSystem(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value());
+ if (Format == AssemblyFormat::NONE) {
+ auto Count = requireOperandCount(Instruction, 0);
+ if (!Count)
+ return std::unexpected(Count.error());
+ return Assembly.Encoding;
+ }
+ if (Format != AssemblyFormat::RD_CSR_RS1 && Format != AssemblyFormat::RD_CSR_IMM) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "unsupported RISC-V system assembly format");
+ }
+ auto Count = requireOperandCount(Instruction, 3);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ auto CSR = immediateOrFixup(Instruction, 1, mc::fixup_kind::None, false, Result);
+ if (!CSR)
+ return std::unexpected(CSR.error());
+ auto CSRRange = requireUnsigned(*CSR, 12, "RISC-V CSR");
+ if (!CSRRange)
+ return std::unexpected(CSRRange.error());
+ std::uint32_t Source = 0;
+ if (Format == AssemblyFormat::RD_CSR_RS1) {
+ auto Register = registerEncoding(Instruction, 2, Target);
+ if (!Register)
+ return std::unexpected(Register.error());
+ Source = *Register;
+ } else {
+ auto Immediate = immediateOrFixup(Instruction, 2, mc::fixup_kind::None, false, Result);
+ if (!Immediate)
+ return std::unexpected(Immediate.error());
+ auto Range = requireUnsigned(*Immediate, 5, "RISC-V CSR immediate");
+ if (!Range)
+ return std::unexpected(Range.error());
+ Source = static_cast<std::uint32_t>(*Immediate);
+ }
+ return (Assembly.Encoding & ~std::uint32_t{0xffff8f80}) | *Destination << 7U | Source << 15U |
+ static_cast<std::uint32_t>(*CSR) << 20U;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeAMO(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly) {
+ const auto Format = static_cast<AssemblyFormat>(Assembly.Format.value());
+ const bool IsLoadReserved = Format == AssemblyFormat::RD_PAREN_RS1;
+ if (!IsLoadReserved && Format != AssemblyFormat::RD_RS2_PAREN_RS1) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "unsupported RISC-V atomic assembly format");
+ }
+ auto Count = requireOperandCount(Instruction, IsLoadReserved ? 2U : 3U);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ auto Source1 = registerEncoding(Instruction, IsLoadReserved ? 1U : 2U, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Source1)
+ return std::unexpected(Source1.error());
+ std::uint32_t Encoding =
+ (Assembly.Encoding & ~std::uint32_t{0x000f8f80}) | *Destination << 7U | *Source1 << 15U;
+ if (!IsLoadReserved) {
+ auto Source2 = registerEncoding(Instruction, 1, Target);
+ if (!Source2)
+ return std::unexpected(Source2.error());
+ Encoding = (Encoding & ~std::uint32_t{0x01f00000}) | *Source2 << 20U;
+ }
+ return Encoding;
+}
+
+[[nodiscard]] Expected<std::uint32_t> encodeR4(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ auto Count = requireOperandCount(Instruction, 5);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ auto Source1 = registerEncoding(Instruction, 1, Target);
+ auto Source2 = registerEncoding(Instruction, 2, Target);
+ auto Source3 = registerEncoding(Instruction, 3, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Source1)
+ return std::unexpected(Source1.error());
+ if (!Source2)
+ return std::unexpected(Source2.error());
+ if (!Source3)
+ return std::unexpected(Source3.error());
+ auto Mode = immediateOrFixup(Instruction, 4, mc::fixup_kind::None, false, Result);
+ if (!Mode)
+ return std::unexpected(Mode.error());
+ auto Range = requireRoundingMode(*Mode);
+ if (!Range)
+ return std::unexpected(Range.error());
+ return (Assembly.Encoding & ~std::uint32_t{0xf9ffff80}) | *Destination << 7U |
+ static_cast<std::uint32_t>(*Mode) << 12U | *Source1 << 15U | *Source2 << 20U |
+ *Source3 << 27U;
+}
+
+[[nodiscard]] Expected<std::uint16_t> encodeCompressed(const mc::MCInst &Instruction,
+ const TargetDescription &Target,
+ const AssemblyInstructionInfo &Assembly,
+ mc::MCEncodedInstruction &Result) {
+ const auto Opcode = static_cast<InstructionOpcode>(Instruction.opcode().value());
+ std::uint16_t Encoding = static_cast<std::uint16_t>(Assembly.Encoding);
+ const auto Immediate = [&](std::size_t Index, mc::MCFixupKind Kind = mc::fixup_kind::None,
+ bool PCRelative = false) {
+ return immediateOrFixup(Instruction, Index, Kind, PCRelative, Result);
+ };
+
+ if (Opcode == InstructionOpcode::C_ADDI4SPN) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = compactRegisterEncoding(Instruction, 0, Target);
+ auto Value = Immediate(1);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (!fitsUnsigned(*Value, 10) || *Value == 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "C.ADDI4SPN immediate is out of range or zero");
+ }
+ auto Alignment = requireAligned(*Value, 4, "C.ADDI4SPN");
+ if (!Alignment)
+ return std::unexpected(Alignment.error());
+ const auto Bits = static_cast<std::uint16_t>(*Value);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) |
+ ((Bits >> 4U) & 3U) << 11U | ((Bits >> 6U) & 0xfU) << 7U |
+ ((Bits >> 2U) & 1U) << 6U | ((Bits >> 3U) & 1U) << 5U |
+ *Destination << 2U);
+ }
+
+ const bool CompactDoubleLoad =
+ Opcode == InstructionOpcode::C_FLD || Opcode == InstructionOpcode::C_LD;
+ const bool CompactWordLoad = Opcode == InstructionOpcode::C_LW;
+ const bool CompactDoubleStore =
+ Opcode == InstructionOpcode::C_FSD || Opcode == InstructionOpcode::C_SD;
+ const bool CompactWordStore = Opcode == InstructionOpcode::C_SW;
+ if (CompactDoubleLoad || CompactWordLoad || CompactDoubleStore || CompactWordStore) {
+ auto Count = requireOperandCount(Instruction, 3);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto ValueRegister = compactRegisterEncoding(Instruction, 0, Target);
+ auto Base = compactRegisterEncoding(Instruction, 1, Target);
+ auto Offset = Immediate(2);
+ if (!ValueRegister)
+ return std::unexpected(ValueRegister.error());
+ if (!Base)
+ return std::unexpected(Base.error());
+ if (!Offset)
+ return std::unexpected(Offset.error());
+ const bool IsDouble = CompactDoubleLoad || CompactDoubleStore;
+ auto Range = requireUnsigned(*Offset, IsDouble ? 8U : 7U, "compressed load/store");
+ if (!Range)
+ return std::unexpected(Range.error());
+ auto Alignment = requireAligned(*Offset, IsDouble ? 8U : 4U, "compressed load/store");
+ if (!Alignment)
+ return std::unexpected(Alignment.error());
+ const auto Bits = static_cast<std::uint16_t>(*Offset);
+ std::uint16_t ImmediateBits = static_cast<std::uint16_t>(((Bits >> 3U) & 7U) << 10U);
+ ImmediateBits |=
+ IsDouble
+ ? static_cast<std::uint16_t>(((Bits >> 6U) & 3U) << 5U)
+ : static_cast<std::uint16_t>(((Bits >> 2U) & 1U) << 6U | ((Bits >> 6U) & 1U) << 5U);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits |
+ *Base << 7U | *ValueRegister << 2U);
+ }
+
+ const bool CI = Opcode == InstructionOpcode::C_ADDI || Opcode == InstructionOpcode::C_ADDIW ||
+ Opcode == InstructionOpcode::C_LI || Opcode == InstructionOpcode::C_LUI ||
+ Opcode == InstructionOpcode::C_SLLI;
+ if (CI) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Register = registerEncoding(Instruction, 0, Target);
+ auto Value = Immediate(1);
+ if (!Register)
+ return std::unexpected(Register.error());
+ if (!Value)
+ return std::unexpected(Value.error());
+ const bool IsShift = Opcode == InstructionOpcode::C_SLLI;
+ auto Range =
+ IsShift ? requireUnsigned(*Value, 6, "C.SLLI") : requireSigned(*Value, 6, "compressed CI");
+ if (!Range)
+ return std::unexpected(Range.error());
+ if (Opcode == InstructionOpcode::C_LUI && *Value == 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "C.LUI immediate must be nonzero");
+ }
+ const auto Bits = static_cast<std::uint16_t>(*Value);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) |
+ ((Bits >> 5U) & 1U) << 12U | *Register << 7U |
+ (Bits & 0x1fU) << 2U);
+ }
+
+ if (Opcode == InstructionOpcode::C_ADDI16SP) {
+ auto Count = requireOperandCount(Instruction, 1);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Value = Immediate(0);
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (!fitsSigned(*Value, 10) || *Value == 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "C.ADDI16SP immediate is out of range or zero");
+ }
+ auto Alignment = requireAligned(*Value, 16, "C.ADDI16SP");
+ if (!Alignment)
+ return std::unexpected(Alignment.error());
+ const auto Bits = static_cast<std::uint16_t>(*Value);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x107c}) |
+ ((Bits >> 9U) & 1U) << 12U | ((Bits >> 4U) & 1U) << 6U |
+ ((Bits >> 6U) & 1U) << 5U | ((Bits >> 7U) & 3U) << 3U |
+ ((Bits >> 5U) & 1U) << 2U);
+ }
+
+ const bool CompactShift =
+ Opcode == InstructionOpcode::C_SRLI || Opcode == InstructionOpcode::C_SRAI;
+ if (CompactShift || Opcode == InstructionOpcode::C_ANDI) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Register = compactRegisterEncoding(Instruction, 0, Target);
+ auto Value = Immediate(1);
+ if (!Register)
+ return std::unexpected(Register.error());
+ if (!Value)
+ return std::unexpected(Value.error());
+ auto Range = CompactShift ? requireUnsigned(*Value, 6, "compressed shift")
+ : requireSigned(*Value, 6, "C.ANDI");
+ if (!Range)
+ return std::unexpected(Range.error());
+ const auto Bits = static_cast<std::uint16_t>(*Value);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x13fc}) |
+ ((Bits >> 5U) & 1U) << 12U | *Register << 7U |
+ (Bits & 0x1fU) << 2U);
+ }
+
+ const bool CompactALU =
+ Opcode == InstructionOpcode::C_SUB || Opcode == InstructionOpcode::C_XOR ||
+ Opcode == InstructionOpcode::C_OR || Opcode == InstructionOpcode::C_AND ||
+ Opcode == InstructionOpcode::C_SUBW || Opcode == InstructionOpcode::C_ADDW;
+ if (CompactALU) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = compactRegisterEncoding(Instruction, 0, Target);
+ auto Source = compactRegisterEncoding(Instruction, 1, Target);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Source)
+ return std::unexpected(Source.error());
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x039c}) | *Destination << 7U |
+ *Source << 2U);
+ }
+
+ if (Opcode == InstructionOpcode::C_J) {
+ auto Count = requireOperandCount(Instruction, 1);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Plain = requirePlainExpression(Instruction.operands()[0], "C.J");
+ if (!Plain)
+ return std::unexpected(Plain.error());
+ auto Value = Immediate(0, fixupKind(RISCVFixupKind::RVCJump), true);
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (Instruction.operands()[0].expressionValue() == nullptr &&
+ (!fitsSigned(*Value, 12) || (*Value & 1) != 0)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "C.J displacement is out of range or unaligned");
+ }
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) |
+ encodeRVCJumpImmediate(*Value));
+ }
+
+ if (Opcode == InstructionOpcode::C_BEQZ || Opcode == InstructionOpcode::C_BNEZ) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Source = compactRegisterEncoding(Instruction, 0, Target);
+ if (!Source)
+ return std::unexpected(Source.error());
+ auto Plain = requirePlainExpression(Instruction.operands()[1], "compressed branch");
+ if (!Plain)
+ return std::unexpected(Plain.error());
+ auto Value = Immediate(1, fixupKind(RISCVFixupKind::RVCBranch), true);
+ if (!Value)
+ return std::unexpected(Value.error());
+ if (Instruction.operands()[1].expressionValue() == nullptr &&
+ (!fitsSigned(*Value, 9) || (*Value & 1) != 0)) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "compressed branch displacement is out of range or unaligned");
+ }
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | *Source << 7U |
+ encodeRVCBranchImmediate(*Value));
+ }
+
+ const bool StackDoubleLoad =
+ Opcode == InstructionOpcode::C_FLDSP || Opcode == InstructionOpcode::C_LDSP;
+ const bool StackWordLoad = Opcode == InstructionOpcode::C_LWSP;
+ if (StackDoubleLoad || StackWordLoad) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Destination = registerEncoding(Instruction, 0, Target);
+ auto Offset = Immediate(1);
+ if (!Destination)
+ return std::unexpected(Destination.error());
+ if (!Offset)
+ return std::unexpected(Offset.error());
+ auto Range = requireUnsigned(*Offset, StackDoubleLoad ? 9U : 8U, "stack load");
+ if (!Range)
+ return std::unexpected(Range.error());
+ auto Alignment = requireAligned(*Offset, StackDoubleLoad ? 8U : 4U, "stack load");
+ if (!Alignment)
+ return std::unexpected(Alignment.error());
+ const auto Bits = static_cast<std::uint16_t>(*Offset);
+ const std::uint16_t ImmediateBits =
+ StackDoubleLoad
+ ? static_cast<std::uint16_t>(((Bits >> 5U) & 1U) << 12U | ((Bits >> 3U) & 3U) << 5U |
+ ((Bits >> 6U) & 7U) << 2U)
+ : static_cast<std::uint16_t>(((Bits >> 5U) & 1U) << 12U | ((Bits >> 2U) & 7U) << 4U |
+ ((Bits >> 6U) & 3U) << 2U);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits |
+ *Destination << 7U);
+ }
+
+ const bool CRSingle = Opcode == InstructionOpcode::C_JR || Opcode == InstructionOpcode::C_JALR;
+ const bool CRDouble = Opcode == InstructionOpcode::C_MV || Opcode == InstructionOpcode::C_ADD;
+ if (CRSingle || CRDouble) {
+ auto Count = requireOperandCount(Instruction, CRSingle ? 1U : 2U);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto First = registerEncoding(Instruction, 0, Target);
+ if (!First)
+ return std::unexpected(First.error());
+ Encoding = static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x0f80}) | *First << 7U);
+ if (CRDouble) {
+ auto Second = registerEncoding(Instruction, 1, Target);
+ if (!Second)
+ return std::unexpected(Second.error());
+ Encoding = static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x007c}) | *Second << 2U);
+ }
+ return Encoding;
+ }
+
+ if (Opcode == InstructionOpcode::C_EBREAK) {
+ auto Count = requireOperandCount(Instruction, 0);
+ if (!Count)
+ return std::unexpected(Count.error());
+ return Encoding;
+ }
+
+ const bool StackDoubleStore =
+ Opcode == InstructionOpcode::C_FSDSP || Opcode == InstructionOpcode::C_SDSP;
+ const bool StackWordStore = Opcode == InstructionOpcode::C_SWSP;
+ if (StackDoubleStore || StackWordStore) {
+ auto Count = requireOperandCount(Instruction, 2);
+ if (!Count)
+ return std::unexpected(Count.error());
+ auto Source = registerEncoding(Instruction, 0, Target);
+ auto Offset = Immediate(1);
+ if (!Source)
+ return std::unexpected(Source.error());
+ if (!Offset)
+ return std::unexpected(Offset.error());
+ auto Range = requireUnsigned(*Offset, StackDoubleStore ? 9U : 8U, "stack store");
+ if (!Range)
+ return std::unexpected(Range.error());
+ auto Alignment = requireAligned(*Offset, StackDoubleStore ? 8U : 4U, "stack store");
+ if (!Alignment)
+ return std::unexpected(Alignment.error());
+ const auto Bits = static_cast<std::uint16_t>(*Offset);
+ const std::uint16_t ImmediateBits =
+ StackDoubleStore
+ ? static_cast<std::uint16_t>(((Bits >> 3U) & 7U) << 10U | ((Bits >> 6U) & 7U) << 7U)
+ : static_cast<std::uint16_t>(((Bits >> 2U) & 0xfU) << 9U | ((Bits >> 6U) & 3U) << 7U);
+ return static_cast<std::uint16_t>((Encoding & ~std::uint16_t{0x1ffc}) | ImmediateBits |
+ *Source << 2U);
+ }
+
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "unsupported compressed RISC-V instruction");
+}
+
+void appendLittleEndian(mc::MCEncodedInstruction &Result, std::uint32_t Encoding,
+ std::uint8_t Size) {
+ Result.Bytes.reserve(Size);
+ for (std::uint8_t Index = 0; Index < Size; ++Index)
+ Result.Bytes.push_back(static_cast<std::uint8_t>(Encoding >> (Index * 8U)));
+}
+
+} // namespace
+
+Expected<mc::MCEncodedInstruction>
+RISCVMCCodeEmitter::encodeInstruction(const mc::MCInst &Instruction) const {
+ if (!Instruction.opcode().isValid()) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "cannot encode an invalid RISC-V MC opcode");
+ }
+ const Opcode OpcodeValue = Opcode::fromValue(Instruction.opcode().value());
+ const InstructionDescriptor *Descriptor = Target->instructionDescriptor(OpcodeValue);
+ const AssemblyInstructionInfo *Assembly = assemblyInstruction(OpcodeValue);
+ if (Descriptor == nullptr || Assembly == nullptr || Assembly->Encoding == 0) {
+ return makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V instruction has no binary encoding description");
+ }
+ auto Registers = validateRegisterOperands(Instruction, *Descriptor, *Target);
+ if (!Registers)
+ return std::unexpected(Registers.error());
+
+ mc::MCEncodedInstruction Result;
+ const auto Category = static_cast<EncodingCategory>(Descriptor->EncodingCategory.value());
+ Expected<std::uint32_t> Encoding = makeUnexpected(ErrorCode::InstructionEncodingFailed,
+ "RISC-V instruction has no encoding category");
+ switch (Category) {
+ case EncodingCategory::R:
+ Encoding = encodeRTypeWithResult(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::I:
+ Encoding = encodeIType(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::S:
+ Encoding = encodeSType(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::B:
+ Encoding = encodeBType(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::U:
+ Encoding = encodeUType(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::J:
+ Encoding = encodeJType(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::SYSTEM:
+ Encoding = encodeSystem(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::AMO:
+ Encoding = encodeAMO(Instruction, *Target, *Assembly);
+ break;
+ case EncodingCategory::R4:
+ Encoding = encodeR4(Instruction, *Target, *Assembly, Result);
+ break;
+ case EncodingCategory::C: {
+ auto Compressed = encodeCompressed(Instruction, *Target, *Assembly, Result);
+ if (!Compressed)
+ return std::unexpected(Compressed.error());
+ appendLittleEndian(Result, *Compressed, 2);
+ return Result;
+ }
+ case EncodingCategory::None:
+ break;
+ }
+ if (!Encoding)
+ return std::unexpected(Encoding.error());
+ appendLittleEndian(Result, *Encoding, 4);
+ return Result;
+}
+
+} // namespace rcc::riscv
diff --git a/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp b/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp
index 4e8d5ec..19b1b11 100644
--- a/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp
+++ b/backend/lib/Target/RISCV/RISCVMCTargetLowering.cpp
@@ -22,6 +22,7 @@
#include "rcc/MC/MCStreamer.h"
#include "rcc/MC/MCSymbol.h"
#include "rcc/Target/RISCV/RISCVTarget.h"
+#include "rcc/Target/RISCV/RISCVTargetRelocationKinds.h"
#include <algorithm>
#include <bit>
@@ -53,6 +54,15 @@ struct TypeLayout final {
std::uint64_t Alignment = 1;
};
+[[nodiscard]] Expected<std::uint8_t> targetRelocationSize(TargetRelocationKindID Kind) {
+ if (Kind == targetRelocationKind(RISCVTargetRelocationKind::Absolute32))
+ return 4;
+ if (Kind == targetRelocationKind(RISCVTargetRelocationKind::Absolute64))
+ return 8;
+ return makeUnexpected(ErrorCode::Unsupported,
+ "RV64GC target constant has an unknown relocation kind");
+}
+
[[nodiscard]] Expected<std::uint64_t> checkedAdd(std::uint64_t Left, std::uint64_t Right) {
std::uint64_t Result = 0;
if (__builtin_add_overflow(Left, Right, &Result))
@@ -612,6 +622,80 @@ struct TypeLayout final {
return {};
}
+[[nodiscard]] Expected<void> emitTargetBytes(std::span<const std::byte> Bytes,
+ mc::MCStreamer &Streamer) {
+ if (Bytes.empty())
+ return {};
+ std::vector<std::uint8_t> Storage;
+ Storage.reserve(Bytes.size());
+ for (const std::byte Byte : Bytes)
+ Storage.push_back(std::to_integer<std::uint8_t>(Byte));
+ return Streamer.emitBytes(Storage);
+}
+
+[[nodiscard]] Expected<void> emitTargetConstantImpl(const TargetConstant &Constant,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) {
+ auto Emission = Constant.emit();
+ if (!Emission)
+ return std::unexpected(Emission.error());
+ auto DeclaredKind = Constant.relocationKind();
+ if (!DeclaredKind)
+ return std::unexpected(DeclaredKind.error());
+ if (Emission->Fixups.empty() != !DeclaredKind->has_value()) {
+ return makeUnexpected(ErrorCode::AssemblyLoweringFailed,
+ "RV64GC target constant relocation declaration is inconsistent");
+ }
+ if (Emission->Fixups.empty())
+ return emitTargetBytes(Emission->Bytes, Streamer);
+
+ std::vector<const TargetConstantFixup *> Fixups;
+ Fixups.reserve(Emission->Fixups.size());
+ for (const TargetConstantFixup &Fixup : Emission->Fixups) {
+ if (Fixup.Kind != **DeclaredKind) {
+ return makeUnexpected(ErrorCode::AssemblyLoweringFailed,
+ "RV64GC target constant contains mixed relocation kinds");
+ }
+ Fixups.push_back(&Fixup);
+ }
+ std::ranges::sort(Fixups, {}, [](const TargetConstantFixup *Fixup) { return Fixup->Offset; });
+
+ std::uint64_t Cursor = 0;
+ for (const TargetConstantFixup *Fixup : Fixups) {
+ auto Size = targetRelocationSize(Fixup->Kind);
+ if (!Size)
+ return std::unexpected(Size.error());
+ if (Fixup->Offset < Cursor || Fixup->Offset > Emission->Bytes.size() ||
+ *Size > Emission->Bytes.size() - static_cast<std::size_t>(Fixup->Offset)) {
+ return makeUnexpected(ErrorCode::AssemblyLoweringFailed,
+ "RV64GC target constant relocation storage is invalid");
+ }
+ auto RawBytes = emitTargetBytes(std::span<const std::byte>(Emission->Bytes)
+ .subspan(static_cast<std::size_t>(Cursor),
+ static_cast<std::size_t>(Fixup->Offset - Cursor)),
+ Streamer);
+ if (!RawBytes)
+ return std::unexpected(RawBytes.error());
+
+ auto Symbol = Context.symbol(Fixup->Symbol);
+ if (!Symbol)
+ return std::unexpected(Symbol.error());
+ auto Expression = mc::MCExpr::symbol(std::move(*Symbol));
+ if (!Expression)
+ return std::unexpected(Expression.error());
+ auto WithAddend = addOffset(std::move(*Expression), Fixup->Addend);
+ if (!WithAddend)
+ return std::unexpected(WithAddend.error());
+ auto Value = Streamer.emitValue(std::move(*WithAddend), *Size);
+ if (!Value)
+ return std::unexpected(Value.error());
+ Cursor = Fixup->Offset + *Size;
+ }
+ return emitTargetBytes(
+ std::span<const std::byte>(Emission->Bytes).subspan(static_cast<std::size_t>(Cursor)),
+ Streamer);
+}
+
[[nodiscard]] Expected<void> emitGlobalInitializerImpl(const GlobalInitializer &Initializer,
MachineMCContext &Context,
mc::MCStreamer &Streamer,
@@ -722,18 +806,7 @@ struct TypeLayout final {
const auto *Value = Initializer.getIf<TargetConstant>();
if (Value == nullptr)
return makeUnexpected(ErrorCode::InternalError, "target initializer has no value");
- auto Emission = Value->emit();
- if (!Emission)
- return std::unexpected(Emission.error());
- if (!Emission->Fixups.empty()) {
- return makeUnexpected(ErrorCode::Unsupported,
- "RV64GC target initializer fixups require native object emission");
- }
- std::vector<std::uint8_t> Bytes;
- Bytes.reserve(Emission->Bytes.size());
- for (const std::byte Byte : Emission->Bytes)
- Bytes.push_back(std::to_integer<std::uint8_t>(Byte));
- return Streamer.emitBytes(Bytes);
+ return emitTargetConstantImpl(*Value, Context, Streamer);
}
case GlobalInitializer::Kind::AlignmentPadding: {
const auto *Value = Initializer.getIf<GlobalAlignmentPadding>();
@@ -1090,20 +1163,9 @@ Expected<void> RISCVMCTargetLowering::emitGlobalInitializer(const GlobalInitiali
}
Expected<void> RISCVMCTargetLowering::emitTargetConstant(const TargetConstant &Constant,
- MachineMCContext &,
+ MachineMCContext &Context,
mc::MCStreamer &Streamer) const {
- auto Emission = Constant.emit();
- if (!Emission)
- return std::unexpected(Emission.error());
- if (!Emission->Fixups.empty()) {
- return makeUnexpected(ErrorCode::Unsupported,
- "RV64GC target-constant fixups require the native object stage");
- }
- std::vector<std::uint8_t> Bytes;
- Bytes.reserve(Emission->Bytes.size());
- for (const std::byte Byte : Emission->Bytes)
- Bytes.push_back(std::to_integer<std::uint8_t>(Byte));
- return Streamer.emitBytes(Bytes);
+ return emitTargetConstantImpl(Constant, Context, Streamer);
}
Expected<void> RISCVMCTargetLowering::emitTargetJumpTable(const MachineFunction &Function,
diff --git a/backend/lib/Target/RISCV/RISCVObjectFile.cpp b/backend/lib/Target/RISCV/RISCVObjectFile.cpp
new file mode 100644
index 0000000..15d4980
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVObjectFile.cpp
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVObjectFile.h"
+
+#include "rcc/CodeGen/AsmPrinter.h"
+#include "rcc/CodeGen/CompilationUnit.h"
+#include "rcc/CodeGen/MachineFunction.h"
+#include "rcc/CodeGen/MachineMCContext.h"
+#include "rcc/MC/ELFObjectWriter.h"
+#include "rcc/MC/MCContext.h"
+#include "rcc/MC/MCObjectStreamer.h"
+#include "rcc/Target/RISCV/RISCVAsmBackend.h"
+#include "rcc/Target/RISCV/RISCVMCCodeEmitter.h"
+#include "rcc/Target/RISCV/RISCVMCTargetLowering.h"
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+namespace rcc::riscv {
+namespace {
+
+constexpr std::uint16_t EMRISCV = 243;
+constexpr std::uint32_t SHTRISCVAttributes = 0x70000003;
+
+[[nodiscard]] AsmPrinterOptions printerOptions(ObjectEmissionOptions Options) noexcept {
+ return AsmPrinterOptions{
+ .EmitFunctionDirectives = Options.EmitFunctionDirectives,
+ .EmitCFI = Options.EmitCFI,
+ .EmitBlockLabels = Options.EmitBlockLabels,
+ .EmitInstructionSymbols = true,
+ .VerifyInput = Options.VerifyInput,
+ };
+}
+
+[[nodiscard]] std::vector<std::uint8_t> attributesSection() {
+ constexpr char Architecture[] = "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_"
+ "zmmul1p0_zaamo1p0_zalrsc1p0";
+ const std::uint32_t FilePayloadSize = 1U + sizeof(Architecture) + 2U;
+ const std::uint32_t VendorSize = 4U + 6U + 1U + 4U + FilePayloadSize;
+ std::vector<std::uint8_t> Bytes;
+ Bytes.reserve(1U + VendorSize);
+ const auto AppendU32 = [&Bytes](std::uint32_t Value) {
+ for (std::uint8_t Shift = 0; Shift < 32; Shift += 8)
+ Bytes.push_back(static_cast<std::uint8_t>(Value >> Shift));
+ };
+ Bytes.push_back('A');
+ AppendU32(VendorSize);
+ Bytes.insert(Bytes.end(), {'r', 'i', 's', 'c', 'v', 0});
+ Bytes.push_back(1);
+ AppendU32(5U + FilePayloadSize);
+ Bytes.push_back(5);
+ Bytes.insert(Bytes.end(), Architecture, Architecture + sizeof(Architecture));
+ Bytes.push_back(4);
+ Bytes.push_back(16);
+ return Bytes;
+}
+
+[[nodiscard]] mc::ELFObjectTargetInfo objectTargetInfo() {
+ mc::ELFObjectTargetInfo Info;
+ Info.Machine = EMRISCV;
+ Info.ExtraSections.push_back(mc::ELFExtraSection{
+ .Name = ".riscv.attributes",
+ .Type = SHTRISCVAttributes,
+ .Flags = 0,
+ .Alignment = 1,
+ .EntrySize = 0,
+ .Contents = attributesSection(),
+ });
+ return Info;
+}
+
+struct ObjectEmissionContext final {
+ explicit ObjectEmissionContext(const TargetDescription &Target)
+ : MachineContext(Context), Lowering(Target), Emitter(Target), Writer(objectTargetInfo()),
+ Streamer(Emitter, Backend, Writer) {
+ mc::MCSectionDesc EHFrameDescription{
+ .Name = ".eh_frame",
+ .Kind = mc::MCSectionKind::EHFrame,
+ .Flags = {mc::MCSectionFlag::Alloc},
+ .Alignment = 8,
+ .EntrySize = 0,
+ .Group = {},
+ .UniqueID = std::nullopt,
+ };
+ auto EHFrame = Context.getOrCreateSection(std::move(EHFrameDescription));
+ if (!EHFrame) {
+ Initialization = std::unexpected(EHFrame.error());
+ return;
+ }
+ Initialization = Streamer.configureDwarfFrame(std::move(*EHFrame),
+ mc::MCDwarfFrameInfo{.CodeAlignment = 1,
+ .DataAlignment = -8,
+ .ReturnAddressRegister = 1,
+ .InitialCFARegister = 2,
+ .InitialCFAOffset = 0});
+ }
+
+ mc::MCContext Context;
+ MachineMCContext MachineContext;
+ RISCVMCTargetLowering Lowering;
+ RISCVMCCodeEmitter Emitter;
+ RISCVAsmBackend Backend;
+ mc::ELF64LEObjectWriter Writer;
+ mc::ELFObjectStreamer Streamer;
+ Expected<void> Initialization;
+};
+
+} // namespace
+
+Expected<std::vector<std::uint8_t>> emitObject(const CompilationUnit &Unit,
+ const TargetDescription &Target,
+ ObjectEmissionOptions Options) {
+ ObjectEmissionContext Context(Target);
+ if (!Context.Initialization)
+ return std::unexpected(Context.Initialization.error());
+ AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer,
+ printerOptions(Options));
+ auto Emitted = Printer.emitCompilationUnit(Unit);
+ if (!Emitted)
+ return std::unexpected(Emitted.error());
+ return Context.Streamer.takeOutput();
+}
+
+Expected<std::vector<std::uint8_t>> emitObject(const MachineFunction &Function,
+ const TargetDescription &Target,
+ ObjectEmissionOptions Options) {
+ ObjectEmissionContext Context(Target);
+ if (!Context.Initialization)
+ return std::unexpected(Context.Initialization.error());
+ AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer,
+ printerOptions(Options));
+ auto Header = Context.Lowering.emitFileHeader(Context.MachineContext, Context.Streamer);
+ if (!Header)
+ return std::unexpected(Header.error());
+ auto Emitted = Printer.emitFunction(Function);
+ if (!Emitted)
+ return std::unexpected(Emitted.error());
+ auto Trailer = Context.Lowering.emitFileTrailer(Context.MachineContext, Context.Streamer);
+ if (!Trailer)
+ return std::unexpected(Trailer.error());
+ auto Finished = Context.Streamer.finish();
+ if (!Finished)
+ return std::unexpected(Finished.error());
+ return Context.Streamer.takeOutput();
+}
+
+} // namespace rcc::riscv
diff --git a/backend/lib/Target/RISCV/RISCVTargetConstant.cpp b/backend/lib/Target/RISCV/RISCVTargetConstant.cpp
new file mode 100644
index 0000000..6fda900
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVTargetConstant.cpp
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVTargetConstant.h"
+
+#include "rcc/Target/RISCV/RISCVTargetRelocationKinds.h"
+
+#include <bit>
+#include <charconv>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <string_view>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+namespace rcc::riscv {
+namespace {
+
+[[nodiscard]] std::string_view kindSpelling(RISCVSymbolConstantKind Kind) noexcept {
+ switch (Kind) {
+ case RISCVSymbolConstantKind::GlobalValue:
+ return "global";
+ case RISCVSymbolConstantKind::ExternalSymbol:
+ return "external";
+ }
+ return {};
+}
+
+[[nodiscard]] Expected<RISCVSymbolConstantKind> parseKind(std::string_view Text) {
+ if (Text == "global")
+ return RISCVSymbolConstantKind::GlobalValue;
+ if (Text == "external")
+ return RISCVSymbolConstantKind::ExternalSymbol;
+ return makeUnexpected(ErrorCode::ParseError, "unknown RV64GC symbol constant kind");
+}
+
+void appendU64(std::vector<std::byte> &Bytes, std::uint64_t Value) {
+ for (std::uint8_t Shift = 0; Shift < 64; Shift += 8)
+ Bytes.push_back(static_cast<std::byte>(Value >> Shift));
+}
+
+[[nodiscard]] std::uint64_t readU64(std::span<const std::byte> Bytes) noexcept {
+ std::uint64_t Result = 0;
+ for (std::uint8_t Shift = 0; Shift < 64; Shift += 8)
+ Result |= std::to_integer<std::uint64_t>(Bytes[Shift / 8U]) << Shift;
+ return Result;
+}
+
+} // namespace
+
+Expected<void> RISCVSymbolConstant::verify() const {
+ if (kindSpelling(ConstantKind).empty())
+ return makeUnexpected(ErrorCode::VerificationError, "RV64GC symbol constant kind is invalid");
+ if (SymbolName.empty() || SymbolName.find('\0') != std::string::npos) {
+ return makeUnexpected(ErrorCode::VerificationError,
+ "RV64GC symbol constant requires a valid symbol name");
+ }
+ return {};
+}
+
+Expected<RISCVSymbolConstant> RISCVSymbolConstant::clone() const {
+ return RISCVSymbolConstant(ConstantKind, SymbolName, SymbolAddend);
+}
+
+std::uint64_t RISCVSymbolConstant::stableHash() const noexcept {
+ constexpr std::uint64_t OffsetBasis = 14695981039346656037ULL;
+ constexpr std::uint64_t Prime = 1099511628211ULL;
+ std::uint64_t Hash = OffsetBasis;
+ const auto Mix = [&Hash](std::uint8_t Byte) {
+ Hash ^= Byte;
+ Hash *= Prime;
+ };
+ Mix(static_cast<std::uint8_t>(ConstantKind));
+ const std::uint64_t AddendBits = std::bit_cast<std::uint64_t>(SymbolAddend);
+ for (std::uint8_t Shift = 0; Shift < 64; Shift += 8)
+ Mix(static_cast<std::uint8_t>(AddendBits >> Shift));
+ for (const char Character : SymbolName)
+ Mix(static_cast<unsigned char>(Character));
+ return Hash;
+}
+
+std::string RISCVSymbolConstant::print() const {
+ return std::string(kindSpelling(ConstantKind)) + "," + std::to_string(SymbolAddend) + "," +
+ SymbolName;
+}
+
+Expected<std::vector<std::byte>> RISCVSymbolConstant::encode() const {
+ auto Verification = verify();
+ if (!Verification)
+ return std::unexpected(Verification.error());
+ std::vector<std::byte> Payload;
+ Payload.reserve(9U + SymbolName.size());
+ Payload.push_back(static_cast<std::byte>(static_cast<std::uint8_t>(ConstantKind)));
+ appendU64(Payload, std::bit_cast<std::uint64_t>(SymbolAddend));
+ for (const char Character : SymbolName)
+ Payload.push_back(static_cast<std::byte>(static_cast<unsigned char>(Character)));
+ return Payload;
+}
+
+Expected<TargetConstantEmission> RISCVSymbolConstant::emit() const {
+ auto Verification = verify();
+ if (!Verification)
+ return std::unexpected(Verification.error());
+ TargetConstantEmission Emission;
+ Emission.Bytes.resize(8);
+ Emission.Fixups.push_back(TargetConstantFixup{
+ .Offset = 0,
+ .Kind = targetRelocationKind(RISCVTargetRelocationKind::Absolute64),
+ .Symbol = SymbolName,
+ .Addend = SymbolAddend,
+ });
+ return Emission;
+}
+
+Alignment RISCVSymbolConstant::requiredAlignment() const noexcept {
+ return *Alignment::create(8);
+}
+
+std::optional<TargetRelocationKindID> RISCVSymbolConstant::relocationKind() const noexcept {
+ return targetRelocationKind(RISCVTargetRelocationKind::Absolute64);
+}
+
+Expected<RISCVSymbolConstant> RISCVSymbolConstant::parse(std::string_view Text) {
+ const std::size_t KindEnd = Text.find(',');
+ const std::size_t AddendEnd =
+ KindEnd == std::string_view::npos ? std::string_view::npos : Text.find(',', KindEnd + 1U);
+ if (KindEnd == std::string_view::npos || AddendEnd == std::string_view::npos) {
+ return makeUnexpected(ErrorCode::ParseError,
+ "RV64GC symbol constant must be 'kind,addend,symbol'");
+ }
+ auto Kind = parseKind(Text.substr(0, KindEnd));
+ if (!Kind)
+ return std::unexpected(Kind.error());
+ std::int64_t Addend = 0;
+ const std::string_view AddendText = Text.substr(KindEnd + 1U, AddendEnd - KindEnd - 1U);
+ const auto [End, Error] =
+ std::from_chars(AddendText.data(), AddendText.data() + AddendText.size(), Addend);
+ if (Error != std::errc{} || End != AddendText.data() + AddendText.size())
+ return makeUnexpected(ErrorCode::ParseError, "RV64GC symbol constant addend is invalid");
+ RISCVSymbolConstant Result(*Kind, std::string(Text.substr(AddendEnd + 1U)), Addend);
+ auto Verification = Result.verify();
+ if (!Verification)
+ return std::unexpected(Verification.error());
+ return Result;
+}
+
+Expected<RISCVSymbolConstant> RISCVSymbolConstant::decode(std::uint32_t Version,
+ std::span<const std::byte> Payload) {
+ if (Version != schemaVersion() || Payload.size() < 10) {
+ return makeUnexpected(ErrorCode::ParseError,
+ "encoded RV64GC symbol constant has an invalid version or size");
+ }
+ const auto KindValue = std::to_integer<std::uint8_t>(Payload.front());
+ if (KindValue > static_cast<std::uint8_t>(RISCVSymbolConstantKind::ExternalSymbol))
+ return makeUnexpected(ErrorCode::ParseError, "encoded RV64GC symbol constant kind is invalid");
+ std::string Symbol;
+ Symbol.reserve(Payload.size() - 9U);
+ for (const std::byte Character : Payload.subspan(9))
+ Symbol.push_back(static_cast<char>(std::to_integer<unsigned char>(Character)));
+ RISCVSymbolConstant Result(static_cast<RISCVSymbolConstantKind>(KindValue), std::move(Symbol),
+ std::bit_cast<std::int64_t>(readU64(Payload.subspan(1, 8))));
+ auto Verification = Result.verify();
+ if (!Verification)
+ return std::unexpected(Verification.error());
+ return Result;
+}
+
+} // namespace rcc::riscv