blob: c09efd564d0aa183d1e3093da0606ecb5c8585ed [file]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the ISA description for the RiscV64G architecture.
includes {
#include "riscv/riscv_vector_fp_compare_instructions.h"
#include "riscv/riscv_vector_fp_instructions.h"
#include "riscv/riscv_vector_fp_reduction_instructions.h"
#include "riscv/riscv_vector_fp_unary_instructions.h"
#include "riscv/riscv_vector_memory_instructions.h"
#include "riscv/riscv_vector_opi_instructions.h"
#include "riscv/riscv_vector_opm_instructions.h"
#include "riscv/riscv_vector_permute_instructions.h"
#include "riscv/riscv_vector_reduction_instructions.h"
#include "riscv/riscv_vector_unary_instructions.h"
#include "absl/functional/bind_front.h"
}
// First disasm field is 18 char wide and left justified.
disasm widths = {-18};
int global_latency = 1;
isa RiscV64G {
namespace mpact::sim::riscv::isa64;
slots { riscv64g; }
}
// This should be the RiscV64G set, where G stands for IMAFDZicsr_Zifencei.
slot riscv64g : riscv64i, riscv64c, riscv64chints, riscv64m, riscv64_hints, riscv64_amo_arithmetic, riscv64f, riscv64d, zicsr, zfencei, privileged {
default size = 4;
default opcode =
disasm: "Illegal instruction at %(@:08x)",
semfunc: "&RiscVIllegalInstruction";
}
// Basic integer ALU instructions, part of the RiscV 64i subset.
slot riscv64i {
includes {
#include "riscv/riscv_i_instructions.h"
}
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
addi{: rs1, %reloc(I_imm12) : rd},
resources: TwoOp,
disasm: "addi", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVIAdd";
nop{},
resources: { next_pc },
disasm: "nop",
semfunc: "&RiscVINop";
addiw{: rs1, %reloc(I_imm12) : rd},
resources: TwoOp,
disasm: "addiw", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVIAddw";
slti{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "slti", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVISlt";
sltiu{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "sltiu", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVISltu";
andi{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "andi", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVIAnd";
ori{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "ori", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVIOr";
xori{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "xori", "%rd, %rs1, %I_imm12",
semfunc: "&RV64::RiscVIXor";
slli{: rs1, I_uimm6 : rd},
resources: TwoOp,
disasm: "slli", "%rd, %rs1, %(I_uimm6:x)",
semfunc: "&RV64::RiscVISll";
srli{: rs1, I_uimm6 : rd},
resources: TwoOp,
disasm: "srli", "%rd %rs1, %(I_uimm6:x)",
semfunc: "&RV64::RiscVISrl";
srai{: rs1, I_uimm6 : rd},
resources: TwoOp,
disasm: "srai", "%rd, %rs1, %(I_uimm6:x)",
semfunc: "&RV64::RiscVISra";
slliw{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "slliw", "%rd, %rs1, %(I_uimm5:x)",
semfunc: "&RV64::RiscVISllw";
srliw{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "srliw", "%rd %rs1, %(I_uimm5:x)",
semfunc: "&RV64::RiscVISrlw";
sraiw{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "sraiw", "%rd, %rs1, %(I_uimm5:x)",
semfunc: "&RV64::RiscVISraw";
lui{: %reloc(U_imm20) : rd},
resources: { next_pc : rd[0..]},
disasm: "lui", "%rd, %(U_imm20:08x)",
semfunc: "&RV64::RiscVILui";
auipc{: %reloc(U_imm20) : rd},
resources: { next_pc : rd[0..]},
disasm: "auipc", "%rd, %(U_imm20:08x)",
semfunc: "&RV64::RiscVIAuipc";
add{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "add", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVIAdd";
addw{: rs1, rs2 : rd},
disasm: "addw", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVIAddw";
slt{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "slt", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISlt";
sltu{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sltu", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISltu";
and{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "and", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVIAnd";
or{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "or", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVIOr";
xor{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "xor", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVIXor";
sll{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sll", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISll";
srl{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "srl", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISrl";
sub{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sub", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISub";
sra{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sra", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISra";
sllw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sll", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISllw";
srlw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "srl", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISrlw";
subw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "subw", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISubw";
sraw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sra", "%rd, %rs1, %rs2",
semfunc: "&RV64::RiscVISraw";
hint{},
disasm: "hint",
semfunc: "&RiscVINop";
jal{: %reloc(J_imm20) : next_pc, rd},
resources: { next_pc : next_pc[0..], rd[0..]},
disasm: "jal", "%rd, %(@+J_imm20:08x)",
semfunc: "&RV64::RiscVIJal";
jalr{: rs1, %reloc(J_imm12) : next_pc, rd},
resources: { next_pc, rs1 : next_pc[0..], rd[0..]},
disasm: "jalr", "%rd, %rs1, %J_imm12",
semfunc: "&RV64::RiscVIJalr";
j{: %reloc(J_imm20) : next_pc, rd},
resources: { next_pc : next_pc[0..], rd[0..]},
disasm: "j", "%(@+J_imm20:08x)",
semfunc: "&RV64::RiscVIJal";
jr{: rs1, %reloc(J_imm12) : next_pc, rd},
resources: { next_pc, rs1 : next_pc[0..], rd[0..]},
disasm: "jr", "%rs1, %(J_imm12:08x)",
semfunc: "&RV64::RiscVIJalr";
beq{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "beq", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBeq";
bne{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "bne", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBne";
blt{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "blt", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBlt";
bltu{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "bltu", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBltu";
bge{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "bge", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBge";
bgeu{: rs1, rs2, %reloc(B_imm12) : next_pc},
resources: { next_pc, rs1, rs2 : next_pc[0..]},
disasm: "bgeu", "%rs1, %rs2, %(@+B_imm12:08x)",
semfunc: "&RV64::RiscVIBgeu";
ld{(: rs1, %reloc(I_imm12)), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "ld", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild";
lw{(: rs1, %reloc(I_imm12)), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lw", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILw", "&RV64::RiscVILwChild";
lwu{(: rs1, %reloc(I_imm12)), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lwu", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILw", "&RV64::RiscVILwuChild";
lh{(: rs1, %reloc(I_imm12) :), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lh", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILh", "&RV64::RiscVILhChild";
lhu{(: rs1, %reloc(I_imm12) :), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lhu", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILhu", "&RV64::RiscVILhuChild";
lb{(: rs1, %reloc(I_imm12) :), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lb", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILb", "&RV64::RiscVILbChild";
lbu{(: rs1, %reloc(I_imm12) :), (: : rd)},
resources: { next_pc, rs1 : rd[0..]},
disasm: "lbu", "%rd, %I_imm12(%rs1)",
semfunc: "&RV64::RiscVILbu", "&RV64::RiscVILbuChild";
sd{: rs1, %reloc(S_imm12), rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sd", "%rs2, %S_imm12(%rs1)",
semfunc: "&RV64::RiscVISd";
sw{: rs1, %reloc(S_imm12), rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sw", "%rs2, %S_imm12(%rs1)",
semfunc: "&RV64::RiscVISw";
sh{: rs1, %reloc(S_imm12), rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sh", "%rs2, %S_imm12(%rs1)",
semfunc: "&RV64::RiscVISh";
sb{: rs1, %reloc(S_imm12), rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sb", "%rs2, %S_imm12(%rs1)",
semfunc: "&RV64::RiscVISb";
fence{: pred, succ : },
disasm: "fence",
semfunc: "&RiscVIFence";
fence_tso{},
disasm: "fence.tso",
semfunc: "&RiscVIFenceTso";
ecall{},
disasm: "ecall",
semfunc: "&RiscVIEcall";
ebreak{},
disasm: "ebreak",
semfunc: "&RiscVIEbreak";
unimp{},
disasm: "unimp",
semfunc: "&RiscVIUnimplemented";
}
}
// This slot contains the hint instructions. These execute as nops, but can be
// changed to provide performance hints to a simulated microarchitecture.
slot riscv64_hints {
includes {
#include "riscv/riscv_i_instructions.h"
}
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
addi_hint1{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "addi", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
addi_hint2{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "addi", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
slti_hint{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "slti", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
sltiu_hint{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "sltiu", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
andi_hint{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "andi", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
ori_hint{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "ori", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
xori_hint{: rs1, I_imm12 : rd},
resources: TwoOp,
disasm: "xori", "%rd, %rs1, %I_imm12",
semfunc: "&RiscVINop";
slli_semihost{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "slli", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
slli_hint1{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "slli", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
slli_hint2{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "slli", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
srli_hint{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "srli", "%rd %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
srai_semihost{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "srai", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
srai_hint1{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "srai", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
srai_hint2{: rs1, I_uimm5 : rd},
resources: TwoOp,
disasm: "srai", "%rd, %rs1, 0x%(I_uimm5:x)",
semfunc: "&RiscVINop";
lui_hint{: U_imm20 : rd},
resources: { next_pc : rd[0..]},
disasm: "lui", "%rd, 0x%(U_imm20:08x)",
semfunc: "&RiscVINop";
auipc_hint{: U_imm20 : rd},
resources: { next_pc : rd[0..]},
disasm: "auipc", "%rd, 0x%(U_imm20:08x)",
semfunc: "&RiscVINop";
add_hint1{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "add", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
add_hint2{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "add.hint", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
add_hint3{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "add", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
and_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "and", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
or_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "or", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
xor_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "xor", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
sll_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sll", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
srl_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "srl", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
sub_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sub", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
sra_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sra", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
slt_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "slt", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
sltu_hint{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "sltu", "%rd, %rs1, %rs2",
semfunc: "&RiscVINop";
fence_hint1{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint2{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint3{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint4{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint5{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint6{:pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
fence_hint7{: pred, succ :},
disasm: "fence",
semfunc: "&RiscVINop";
}
}
// Privileged instructions.
slot privileged {
includes {
#include "riscv/riscv_priv_instructions.h"
}
default size = 4;
default latency = global_latency;
opcodes {
uret{: : next_pc(0)},
disasm: "uret",
semfunc: "&RV64::RiscVPrivURet";
sret{: : next_pc(0)},
disasm: "sret",
semfunc: "&RV64::RiscVPrivSRet";
mret{: : next_pc(0)},
disasm: "mret",
semfunc: "&RV64::RiscVPrivMRet";
wfi{},
disasm: "wfi",
semfunc: "&RiscVPrivWfi";
// The sfence instruction has 4 behaviors depending on if rs1 and/or rs2
// are 0. These behaviors are split into 4 instructions.
sfence_vma_zz{: rs1, rs2},
resources: {},
disasm: "sfence.vma", "%rs1, %rs2",
semfunc: "&RiscVPrivSFenceVmaZZ";
sfence_vma_zn{: rs1, rs2},
resources: {rs2},
disasm: "sfence.vma", "%rs1, %rs2",
semfunc: "&RiscVPrivSFenceVmaZN";
sfence_vma_nz{: rs1, rs2},
resources: { rs1 },
disasm: "sfence.vma", "%rs1, %rs2",
semfunc: "&RiscVPrivSFenceVmaNZ";
sfence_vma_nn{: rs1, rs2},
resources: {rs1, rs2},
disasm: "sfence.vma", "%rs1, %rs2",
semfunc: "&RiscVPrivSFenceVmaNN";
// Skipping hypervisor memory management instructions for now.
}
}
// Instruction fence.
slot zfencei {
includes {
#include "riscv/riscv_zfencei_instructions.h"
}
default size = 4;
default latency = global_latency;
opcodes {
fencei{: I_imm12 : },
disasm: "fence.i",
semfunc: "&RiscVZFencei";
}
}
// RiscV64 multiply/divide instructions.
slot riscv64m {
includes {
#include "riscv/riscv_m_instructions.h"
}
default size = 4;
default latency = global_latency;
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
mul{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "mul", "%rd, %rs1, %rs2",
semfunc: "&RV64::MMul";
mulw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "mul", "%rd, %rs1, %rs2",
semfunc: "&RV64::MMulw";
mulh{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "mulh", "%rd, %rs1, %rs2",
semfunc: "&RV64::MMulh";
mulhu{: rs1, rs2: rd},
resources: ThreeOp,
disasm: "mulhu", "%rd, %rs1, %rs2",
semfunc: "&RV64::MMulhu";
mulhsu{: rs1, rs2: rd},
resources: ThreeOp,
disasm: "mulhsu", "%rd, %rs1, %rs2",
semfunc: "&RV64::MMulhsu";
div{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "div", "%rd, %rs1, %rs2",
semfunc: "&RV64::MDiv";
divu{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "divu", "%rd, %rs1, %rs2",
semfunc: "&RV64::MDivu";
rem{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "rem", "%rd, %rs1, %rs2",
semfunc: "&RV64::MRem";
remu{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "remu", "%rd, %rs1, %rs2",
semfunc: "&RV64::MRemu";
divw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "divw", "%rd, %rs1, %rs2",
semfunc: "&RV64::MDivw";
divuw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "divuw", "%rd, %rs1, %rs2",
semfunc: "&RV64::MDivuw";
remw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "remw", "%rd, %rs1, %rs2",
semfunc: "&RV64::MRemw";
remuw{: rs1, rs2 : rd},
resources: ThreeOp,
disasm: "remuw", "%rd, %rs1, %rs2",
semfunc: "&RV64::MRemuw";
}
}
// The RiscV architecture allows for different subsets of the AMO instructions
// to be implemented. The following slot definitions define these subsets.
// RiscV atomic memory instructions subset AMO None.
slot riscv64_amo_none {
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
lrw{(: rs1, A_aq, A_rl), (: : rd)},
resources: TwoOp,
disasm: "lr.w", "%rd, (%rs1)",
semfunc: "&ALrw", "&RV64::RiscVILwChild";
lrd{(: rs1, A_aq, A_rl), (: : rd)},
resources: TwoOp,
disasm: "lr.d", "%rd, (%rs1)",
semfunc: "&ALrd", "&RV64::RiscVILdChild";
scw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "sc.w", "%rd, %rs2, (%rs1)",
semfunc: "&AScw", "&RV64::RiscVILwChild";
scd{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "sc.d", "%rd, %rs2, (%rs1)",
semfunc: "&AScd", "&RV64::RiscVILdChild";
}
}
// RiscV atomic memory instructions subset AMO swap.
slot riscv64_amo_swap : riscv64_amo_none {
includes {
#include "riscv/riscv_a_instructions.h"
}
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
amoswapw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoswap.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoswapw", "&RV64::RiscVILwChild";
amoswapd{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoswap.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoswapd", "&RV64::RiscVILdChild";
}
}
// RiscV atomic memory instructions subset AMO logical.
slot riscv64_amo_logical : riscv64_amo_swap {
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
amoandw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoand.w%A_aq%A_rl", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoandw", "&RV64::RiscVILwChild";
amoandd{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoand.d%A_aq%A_rl", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoandd", "&RV64::RiscVILdChild";
amoorw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoor.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoorw", "&RV64::RiscVILwChild";
amoord{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoor.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoord", "&RV64::RiscVILdChild";
amoxorw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoxor.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoxorw", "&RV64::RiscVILwChild";
amoxord{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoxor.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoxord", "&RV64::RiscVILdChild";
}
}
// RiscV atomic memory instructions subset AMO arithmetic.
slot riscv64_amo_arithmetic : riscv64_amo_logical {
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, rs1 : rd[..rd]};
resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]};
opcodes {
amoaddw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoadd.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoaddw", "&RV64::RiscVILwChild";
amoaddd{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amoadd.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmoaddd", "&RV64::RiscVILdChild";
amomaxw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomax.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmomaxw", "&RV64::RiscVILwChild";
amomaxd{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomax.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmomaxd", "&RV64::RiscVILdChild";
amomaxuw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomaxu.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmomaxuw", "&RV64::RiscVILwChild";
amomaxud{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomaxu.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmomaxud", "&RV64::RiscVILdChild";
amominw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomin.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmominw", "&RV64::RiscVILwChild";
amomind{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amomin.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmomind", "&RV64::RiscVILdChild";
amominuw{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amominu.w", "%rd, %rs2, (%rs1)",
semfunc: "&AAmominuw", "&RV64::RiscVILwChild";
amominud{(: rs1, rs2, A_aq, A_rl), (: : rd)},
resources: ThreeOp,
disasm: "amominu.d", "%rd, %rs2, (%rs1)",
semfunc: "&AAmominud", "&RV64::RiscVILdChild";
}
}
// RiscV64 CSR manipulation instructions.
slot zicsr {
includes {
#include "riscv/riscv_zicsr_instructions.h"
}
default size = 4;
default latency = global_latency;
opcodes {
csrrw{: rs1, csr : rd, csr},
resources: { next_pc, rs1, csr : rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrw",
disasm: "csrw", "%rd, %csr, %rs1";
csrrs{: rs1, csr : rd, csr},
resources: { next_pc, rs1, csr : rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrs",
disasm: "csrs", "%rd, %csr, %rs1";
csrrc{: rs1, csr : rd, csr},
resources: { next_pc, rs1, csr : rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrc",
disasm: "csrc", "%rd, %csr, %rs1";
csrrs_nr{: rs1, csr : rd, csr},
resources: { next_pc, rs1, csr : rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrs",
disasm: "csrs", "%csr, %rs1";
csrrc_nr{: rs1, csr : rd, csr},
resources: { next_pc, rs1, csr : rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrc",
disasm: "csrc", "%csr, %rs1";
csrrw_nr{: rs1, csr : csr},
resources: { next_pc, rs1: csr[0..]},
semfunc: "&RV64::RiscVZiCsrrwNr", // rd == 0 (x0).
disasm: "csrw", "%csr, %rs1";
csrrs_nw{: csr : rd},
resources: { next_pc, csr: rd[0..]},
semfunc: "&RV64::RiscVZiCsrrNw", // rs1 == 0 (x0).
disasm: "csrr", "%rd, %csr";
csrrc_nw{: csr : rd},
resources: { next_pc, csr: rd[0..]},
semfunc: "&RV64::RiscVZiCsrrNw", // rs1 == 0 (x0).
disasm: "csrr", "%rd, %csr";
csrrwi{: CSR_uimm5, csr : rd, csr},
resources: { next_pc, csr: rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrw",
disasm: "csrwi", "%rd, %csr, %CSR_uimm5";
csrrsi{: CSR_uimm5, csr : rd, csr},
resources: { next_pc, csr: rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrs",
disasm: "csrsi", "%rd, %csr, %CSR_uimm5";
csrrci{: CSR_uimm5, csr : rd, csr},
resources: { next_pc, csr: rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrc",
disasm: "csrci", "%rd, %csr, %CSR_uimm5";
csrrsi_nr{: CSR_uimm5, csr : rd, csr},
resources: { next_pc, csr: rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrs",
disasm: "csrsi", "%csr, %CSR_uimm5";
csrrci_nr{: CSR_uimm5, csr : rd, csr},
resources: { next_pc, csr: rd[0..], csr[0..]},
semfunc: "&RV64::RiscVZiCsrrc",
disasm: "csrci", "%csr, %CSR_uimm5";
csrrwi_nr{: CSR_uimm5, csr : csr},
resources: { next_pc : csr[0..]},
semfunc: "&RV64::RiscVZiCsrrwNr", // rd == 0 (x0).
disasm: "csrrwi", "%csr, %CSR_uimm5";
csrrsi_nw{: csr : rd},
resources: { next_pc, csr : rd[0..]},
semfunc: "&RV64::RiscVZiCsrrNw", // uimm5 == 0.
disasm: "csrr", "%rd, %csr";
csrrci_nw{: csr : rd},
resources: { next_pc, csr : rd[0..]},
semfunc: "&RV64::RiscVZiCsrrNw", // uimm5 == 0.
disasm: "csrr", "%rd, %csr";
}
}
// RiscV64 F (single precision floating point) instructions.
slot riscv64f {
includes {
#include "riscv/riscv_f_instructions.h"
}
default size = 4;
default latency = global_latency;
resources TwoOp = { next_pc, frs1 : frd[0..]};
resources ThreeOp = { next_pc, frs1, frs2 : frd[0..]};
resources FourOp = { next_pc, frs1, frs2, frs3 : frd[0..]};
opcodes {
flw{(: rs1, %reloc(I_imm12) : ), (: : frd)},
resources: { next_pc, rs1 : frd[0..]},
semfunc: "&RV64::RiscVILw", "&RiscVIFlwChild",
disasm: "flw", "%frd, %I_imm12(%rs1)";
fsw{: rs1, %reloc(S_imm12), frs2},
resources: { next_pc, rs1, frs2},
semfunc: "&RV64::RiscVFSw",
disasm: "fsw", "%frs2, %S_imm12(%rs1)";
fadd_s{: frs1, frs2, rm : frd},
resources: ThreeOp,
semfunc: "&RiscVFAdd",
disasm: "fadd", "%frd, %frs1, %frs2";
fsub_s{: frs1, frs2, rm : frd},
resources: ThreeOp,
semfunc: "&RiscVFSub",
disasm: "fsub", "%frd, %frs1, %frs2";
fmul_s{: frs1, frs2, rm : frd},
resources: ThreeOp,
semfunc: "&RiscVFMul",
disasm: "fmul", "%frd, %frs1, %frs2";
fdiv_s{: frs1, frs2, rm : frd},
resources: ThreeOp,
semfunc: "&RiscVFDiv",
disasm: "fdiv", "%frd, %frs1, %frs2";
fsqrt_s{: frs1, rm : frd, fflags},
resources: TwoOp,
semfunc: "&RiscVFSqrt",
disasm: "fsqrt", "%frd, %frs1";
fmin_s{: frs1, frs2 : frd, fflags},
resources: ThreeOp,
semfunc: "&RiscVFMin",
disasm: "fmin", "%frd, %frs1, %frs2";
fmax_s{: frs1, frs2 : frd, fflags},
resources: ThreeOp,
semfunc: "&RiscVFMax",
disasm: "fmax", "%frd, %frs1, %frs2";
fmadd_s{: frs1, frs2, frs3, rm : frd, fflags},
resources: FourOp,
semfunc: "&RiscVFMadd",
disasm: "fmadd", "%frd, %frs1, %frs2, %frs3";
fmsub_s{: frs1, frs2, frs3, rm : frd, fflags},
resources: FourOp,
semfunc: "&RiscVFMsub",
disasm: "fmsub", "%frd, %frs1, %frs2, %frs3";
fnmadd_s{: frs1, frs2, frs3, rm : frd, fflags},
resources: FourOp,
semfunc: "&RiscVFNmadd",
disasm: "fnmadd", "%frd, %frs1, %frs2, %frs3";
fnmsub_s{: frs1, frs2, frs3, rm : frd, fflags},
resources: FourOp,
semfunc: "&RiscVFNmsub",
disasm: "fnmsub", "%frd, %frs1, %frs2, %frs3";
fcvt_ws{: frs1, rm : rd, fflags},
resources: TwoOp,
semfunc: "&RV64::RiscVFCvtWs",
disasm: "fcvt.w.s", "%rd, %frs1";
fcvt_ls{: frs1, rm : rd, fflags},
resources: TwoOp,
semfunc: "&RV64::RiscVFCvtLs",
disasm: "fcvt.l.s", "%rd, %frs1";
fcvt_sw{: rs1, rm : frd},
resources: TwoOp,
semfunc: "&RiscVFCvtSw",
disasm: "fcvt.s.w", "%frd, %rs1";
fcvt_sl{: rs1, rm : frd},
resources: TwoOp,
semfunc: "&RiscVFCvtSl",
disasm: "fcvt.s.l", "%frd, %rs1";
fcvt_wus{: frs1, rm : rd, fflags},
resources: TwoOp,
semfunc: "&RV64::RiscVFCvtWus",
disasm: "fcvt.wu.s", "%rd, %frs1";
fcvt_lus{: frs1, rm : rd, fflags},
resources: TwoOp,
semfunc: "&RV64::RiscVFCvtLus",
disasm: "fcvt.lu.s", "%rd, %frs1";
fcvt_swu{: rs1, rm : frd},
resources: TwoOp,
semfunc: "&RiscVFCvtSwu",
disasm: "fcvt.s.wu", "%frd, %rs1";
fcvt_slu{: rs1, rm : frd},
resources: TwoOp,
semfunc: "&RiscVFCvtSlu",
disasm: "fcvt.s.lu", "%frd, %rs1";
fsgnj_s{: frs1, frs2 : frd},
resources: ThreeOp,
semfunc: "&RiscVFSgnj",
disasm: "fsgnj.s", "%frd, %frs1, %frs2";
fsgnjn_s{: frs1, frs2 : frd},
resources: ThreeOp,
semfunc: "&RiscVFSgnjn",
disasm: "fsgnjn.s", "%frd, %frs1, %frs2";
fsgnjx_s{: frs1, frs2 : frd},
resources: ThreeOp,
semfunc: "&RiscVFSgnjx",
disasm: "fsgnjx.s", "%frd, %frs1, %frs2";
fmv_xw{: frs1 : rd},
resources: { next_pc, frs1 : rd[0..]},
disasm: "mv.x.w", "%rd, %frs1",
semfunc: "&RV64::RiscVFMvxw";
fmv_wx{: rs1 : frd},
resources: { next_pc, rs1 : frd[0..]},
disasm: "mv.w.x", "%frd, %rs1",
semfunc: "&RiscVFMvwx";
fcmpeq_s{: frs1, frs2 : rd, fflags},
resources: { next_pc, frs1, frs2 : rd[0..]},
semfunc: "&RV64::RiscVFCmpeq",
disasm: "fcmpeq", "%rd, %frs1, %frs2";
fcmplt_s{: frs1, frs2 : rd, fflags},
resources: { next_pc, frs1, frs2 : rd[0..]},
semfunc: "&RV64::RiscVFCmplt",
disasm: "fcmplt", "%rd, %frs1, %frs2";
fcmple_s{: frs1, frs2 : rd, fflags},
resources: { next_pc, frs1, frs2 : rd[0..]},
semfunc: "&RV64::RiscVFCmple",
disasm: "fcmple", "%rd, %frs1, %frs2";
fclass_s{: frs1 : rd},
resources: { next_pc, frs1 : rd[0..]},
semfunc: "&RV64::RiscVFClass",
disasm: "fclass", "%rd, %frs1";
}
}
// RiscV64 D (double precision floating point) instructions.
slot riscv64d {
includes {
#include "riscv/riscv_d_instructions.h"
}
default size = 4;
default latency = global_latency;
opcodes {
fld{(: rs1, %reloc(I_imm12) : ), (: : drd)},
resources: {next_pc, rs1 : drd[0..]},
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild",
disasm: "fld", "%drd, %I_imm12(%rs1)";
fsd{: rs1, %reloc(S_imm12), drs2},
resources: {next_pc, rs1, drs2},
semfunc: "&RV64::RiscVDSd",
disasm: "fsd", "%drs2, %S_imm12(%rs1)";
fadd_d{: drs1, drs2, rm : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDAdd",
disasm: "fadd.d", "%drd, %drs1, %drs2";
fsub_d{: drs1, drs2, rm : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDSub",
disasm: "fsub.d", "%drd, %drs1, %drs2";
fmul_d{: drs1, drs2, rm : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDMul",
disasm: "fmul.d", "%drd, %drs1, %drs2";
fdiv_d{: drs1, drs2, rm : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDDiv",
disasm: "fdiv.d", "%drd, %drs1, %drs2";
fsqrt_d{: drs1, rm : drd, fflags},
resources: {next_pc, drs1 : drd[0..]},
semfunc: "&RiscVDSqrt",
disasm: "fsqrt.d", "%drd, %drs1";
fmin_d{: drs1, drs2 : drd, fflags},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDMin",
disasm: "fmin.d", "%drd, %drs1, %drs2";
fmax_d{: drs1, drs2 : drd, fflags},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDMax",
disasm: "fmax.d", "%drd, %drs1, %drs2";
fmadd_d{: drs1, drs2, drs3, rm : drd, fflags},
resources: {next_pc, drs1, drs2, drs3 : drd[0..]},
semfunc: "&RiscVDMadd",
disasm: "fmadd.d", "%drd, %drs1, %drs2, %drs3";
fmsub_d{: drs1, drs2, drs3, rm : drd, fflags},
resources: {next_pc, drs1, drs2, drs3 : drd[0..]},
semfunc: "&RiscVDMsub",
disasm: "fmsub.d", "%drd, %drs1, %drs2, %drs3";
fnmadd_d{: drs1, drs2, drs3, rm : drd, fflags},
resources: {next_pc, drs1, drs2, drs3 : drd[0..]},
semfunc: "&RiscVDNmadd",
disasm: "fnmadd.d", "%drd, %drs1, %drs2, %drs3";
fnmsub_d{: drs1, drs2, drs3, rm : drd, fflags},
resources: {next_pc, drs1, drs2, drs3 : drd[0..]},
semfunc: "&RiscVDNmsub",
disasm: "fnmsub.d", "%drd, %drs1, %drs2, %drs3";
fcvt_wd{: drs1, rm : rd, fflags},
resources: {next_pc, drs1 : rd[0..]},
semfunc: "&RV64::RiscVDCvtWd",
disasm: "fcvt.w.d", "%rd, %drs1";
fcvt_ld{: drs1, rm : rd, fflags},
resources: {next_pc, drs1 : rd[0..]},
semfunc: "&RV64::RiscVDCvtLd",
disasm: "fcvt.l.d", "%rd, %drs1";
fcvt_dw{: rs1, rm : drd},
resources: {next_pc, rs1 : drd[0..]},
semfunc: "&RiscVDCvtDw",
disasm: "fcvt.d.w", "%drd, %rs1";
fcvt_dl{: rs1, rm : drd},
resources: {next_pc, rs1 : drd[0..]},
semfunc: "&RV64::RiscVDCvtDl",
disasm: "fcvt.d.l", "%drd, %rs1";
fcvt_wud{: drs1, rm : rd, fflags},
resources: {next_pc, drs1 : rd[0..]},
semfunc: "&RV64::RiscVDCvtWud",
disasm: "fcvt.wu.d", "%rd, %drs1";
fcvt_lud{: drs1, rm : rd, fflags},
resources: {next_pc, drs1 : rd[0..]},
semfunc: "&RV64::RiscVDCvtLud",
disasm: "fcvt.lu.d", "%rd, %drs1";
fcvt_dwu{: rs1, rm : drd},
resources: {next_pc, rs1 : drd[0..]},
semfunc: "&RiscVDCvtDwu",
disasm: "fcvt.d.wu", "%drd, %rs1";
fcvt_dlu{: rs1, rm : drd},
resources: {next_pc, rs1 : drd[0..]},
semfunc: "&RV64::RiscVDCvtDlu",
disasm: "fcvt.d.lu", "%drd, %rs1";
fcvt_sd{: drs1, rm : drd},
resources: {next_pc, drs1 : drd[0..]},
semfunc: "&RiscVDCvtSd",
disasm: "fcvt.s.d", "%drd, %drs1";
fcvt_ds{: drs1, rm : drd},
resources: {next_pc, drs1 : drd[0..]},
semfunc: "&RiscVDCvtDs",
disasm: "fcvt.d.s", "%drd, %drs1";
fsgnj_d{: drs1, drs2 : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDSgnj",
disasm: "fsgnj.d", "%drd, %drs1, %drs2";
fsgnjn_d{: drs1, drs2 : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDSgnjn",
disasm: "fsgnjn.d", "%drd, %drs1, %drs2";
fsgnjx_d{: drs1, drs2 : drd},
resources: {next_pc, drs1, drs2 : drd[0..]},
semfunc: "&RiscVDSgnjx",
disasm: "fsgnjx.d", "%drd, %drs1, %drs2";
fcmpeq_d{: drs1, drs2 : rd, fflags},
resources: {next_pc, drs1, drs2 : rd[0..]},
semfunc: "&RV64::RiscVDCmpeq",
disasm: "fcmpeq.d", "%rd, %drs1, %drs2";
fcmplt_d{: drs1, drs2 : rd, fflags},
resources: {next_pc, drs1, drs2 : rd[0..]},
semfunc: "&RV64::RiscVDCmplt",
disasm: "fcmplt.d", "%rd, %drs1, %drs2";
fcmple_d{: drs1, drs2 : rd, fflags},
resources: {next_pc, drs1, drs2 : rd[0..]},
semfunc: "&RV64::RiscVDCmple",
disasm: "fcmple.d", "%rd, %drs1, %drs2";
fclass_d{: drs1 : rd},
resources: {next_pc, drs1 : rd[0..]},
semfunc: "&RV64::RiscVDClass",
disasm: "fclass.d", "%rd, %drs1";
fmv_dx{: rs1 : frd},
resources: { next_pc, rs1 : frd[0..]},
disasm: "mv.d.x", "%frd, %rs1",
semfunc: "&RV64::RiscVDMvdx";
fmv_xd{: frs1 : rd},
resources: { next_pc, frs1 : rd[0..]},
disasm: "mv.x.d", "%rd, %frs1",
semfunc: "&RV64::RiscVDMvxd";
}
}
// RISCV64 C (compact instructions).
slot riscv64c {
default size = 2;
default latency = global_latency;
opcodes {
clwsp{(: x2, I_ci_uimm6x4 : ), (: : rd)},
resources:{next_pc,x2 : rd[0..]},
disasm: "c.lw", "%rd, %I_ci_uimm6x4(%x2)",
semfunc: "&RV64::RiscVILw", "&RV64::RiscVILwChild";
cldsp{(: x2, I_ci_uimm6x8 : ), (: : rd)},
resources:{next_pc,x2 : rd[0..]},
disasm: "c.ldsp", "%rd, %I_ci_uimm6x8(%x2)",
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild";
cfldsp{(: x2, I_ci_uimm6x8 : ), (: : drd)},
resources:{next_pc,x2 : drd[0..]},
disasm: "c.fld", "%drd, %I_ci_uimm6x8(%x2)",
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild";
cswsp{: x2, I_css_uimm6x4, crs2 : },
resources: {next_pc,x2, crs2},
disasm: "c.sw", "%crs2, %I_css_uimm6x4(%x2)",
semfunc: "&RV64::RiscVISw";
csdsp{: x2, I_css_uimm6x8, crs2 : },
resources: {next_pc,x2, crs2},
disasm: "c.sdsp", "%crs2, %I_css_uimm6x8(%x2)",
semfunc: "&RV64::RiscVISd";
cfsdsp{: x2, I_css_uimm6x8, cdrs2 : },
resources: {next_pc,x2, cdrs2},
disasm: "c.fsd", "%cdrs2, %I_css_uimm6x8(%x2)",
semfunc: "&RV64::RiscVISd";
clw{(: c3rs1, I_cl_uimm5x4 : ), (: : c3rd)},
resources: {next_pc,c3rs1 : c3rd[0..]},
disasm: "c.lw", "%c3rd, %I_cl_uimm5x4(%c3rs1)",
semfunc: "&RV64::RiscVILw", "&RV64::RiscVILwChild";
cld{(: c3rs1, I_cl_uimm5x8 : ), (: : c3rd)},
resources: {next_pc,c3rs1 : c3rd[0..]},
disasm: "c.ld", "%c3rd, %I_cl_uimm5x8(%c3rs1)",
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild";
cfld{(: c3rs1, I_cl_uimm5x8 : ), (: : c3drd)},
resources: {next_pc,c3rs1 : c3drd[0..]},
disasm: "c.fld", "%c3drd, %I_cl_uimm5x8(%c3rs1)",
semfunc: "&RV64::RiscVILd", "&RV64::RiscVILdChild";
csw{: c3rs1, I_cl_uimm5x4, c3rs2 : },
resources: {next_pc,c3rs1, c3rs2},
disasm: "c.sw", "%c3rs2, %I_cl_uimm5x4(%c3rs1)",
semfunc: "&RV64::RiscVISw";
csd{: c3rs1, I_cl_uimm5x8, c3rs2 : },
resources: {next_pc,c3rs1, c3rs2},
disasm: "c.sd", "%c3rs2, %I_cl_uimm5x8(%c3rs1)",
semfunc: "&RV64::RiscVISd";
cfsd{: c3rs1, I_cl_uimm5x8, c3drs2 : },
resources: {next_pc,c3rs1, c3drs2},
disasm: "c.fsd", "%c3drs2, %I_cl_uimm5x8(%c3rs1)",
semfunc: "&RV64::RiscVISd";
cj{: %reloc(I_cj_imm11), x0 : next_pc, x0},
resources: {next_pc,x0 : next_pc[0..], x0[0..]},
disasm: "c.j", "%(@+I_cj_imm11:08x)",
semfunc: "&RV64::RiscVIJal";
cjr{: crs1, x0 : next_pc, x0},
resources: {next_pc,crs1, x0 : next_pc[0..], x0[0..]},
disasm: "c.jr", "%crs1",
semfunc: "&RV64::RiscVIJalr";
cjalr{: crs1, x0 : next_pc, x1},
resources: {next_pc,crs1, x0 : next_pc[0..], x1[0..]},
disasm: "c.jalr", "%crs1",
semfunc: "&RV64::RiscVIJalr";
cbeqz{: c3rs1, x0, %reloc(I_cb_imm8) : next_pc},
resources: {next_pc,c3rs1, x0 : next_pc[0..]},
disasm: "c.beqz", "%c3rs1, %(@+I_cb_imm8:08x)",
semfunc: "&RV64::RiscVIBeq";
cbnez{: c3rs1, x0, %reloc(I_cb_imm8) : next_pc},
resources: {next_pc,c3rs1, x0 : next_pc[0..]},
disasm: "c.bnez", "%c3rs1, %(@+I_cb_imm8:08x)",
semfunc: "&RV64::RiscVIBne";
cli{: x0, I_ci_imm6 : rd},
resources: {next_pc,x0 : rd[0..]},
disasm: "c.li", "%rd, %I_ci_imm6",
semfunc: "&RV64::RiscVIAdd";
clui{: I_ci_imm6_12 : rd},
resources: {next_pc : rd[0..]},
disasm: "c.lui", "%rd, %(I_ci_imm6_12:x)",
semfunc: "&RV64::RiscVILui";
caddi{: rd, I_ci_imm6 : rd},
resources: {next_pc, rd : rd[0..]},
disasm: "c.addi", "%rd, %rd, %I_ci_imm6",
semfunc: "&RV64::RiscVIAdd";
caddiw{: rd, I_ci_imm6 : rd},
resources: {next_pc, rd : rd[0..]},
disasm: "c.addiw", "%rd, %rd, %I_ci_imm6",
semfunc: "&RV64::RiscVIAddw";
caddi16sp{: x2, I_ci_imm6x16 : x2},
resources: {next_pc, x2 : x2[0..]},
disasm: "c.addi", "%x2, %x2, %(I_ci_imm6x16:d)",
semfunc: "&RV64::RiscVIAdd";
caddi4spn{: x2, I_ciw_uimm8x4 : c3rd},
resources: {next_pc, x2 : c3rd[0..]},
disasm: "c.addi", "%c3rd, %x2, %I_ciw_uimm8x4",
semfunc: "&RV64::RiscVIAdd";
cslli{: rd, I_ci_uimm6 : rd},
resources: {next_pc, rd : rd[0..]},
disasm: "c.slli", "%rd, %rd, %(I_ci_uimm6:x)",
semfunc: "&RV64::RiscVISll";
csrli{: c3rs1, I_ci_uimm6 : c3rs1},
resources: {next_pc, c3rs1 : c3rs1[0..]},
disasm: "c.srli", "%c3rs1, %c3rs1, %(I_ci_uimm6:x)",
semfunc: "&RV64::RiscVISrl";
csrai{: c3rs1, I_ci_uimm6 : c3rs1},
resources: {next_pc, c3rs1 : c3rs1[0..]},
disasm: "c.srai", "%c3rs1, %c3rs1, %(I_ci_uimm6:x)",
semfunc: "&RV64::RiscVISra";
candi{: c3rs1, I_ci_imm6 : c3rs1},
resources: {next_pc, c3rs1 : c3rs1[0..]},
disasm: "c.andi", "%c3rs1, %c3rs1, %I_ci_imm6",
semfunc: "&RV64::RiscVIAnd";
cmv{: crs2 , x0: rd},
resources: {next_pc, crs2, x0 : rd[0..]},
disasm: "c.mv", "%rd, %crs2",
semfunc: "&RV64::RiscVIAdd";
cadd{: crs2, rd: rd},
resources: {next_pc, crs2, rd : rd[0..]},
disasm: "c.add", "%rd, %rd, %crs2",
semfunc: "&RV64::RiscVIAdd";
cand{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.and", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVIAnd";
cor{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.or", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVIOr";
cxor{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.xor", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVIXor";
csub{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.sub", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVISub";
caddw{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.addw", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVIAddw";
csubw{: c3rs1, c3rs2 : c3rs1},
resources: {next_pc, c3rs1, c3rs2 : c3rs1[0..]},
disasm: "c.subw", "%c3rs1, %c3rs1, %c3rs2",
semfunc: "&RV64::RiscVISubw";
cnop{},
disasm: "c.nop",
resources: {next_pc},
semfunc: "&RiscVINop";
cebreak{},
disasm: "c.ebreak",
resources: {next_pc},
semfunc: "&RiscVIEbreak";
cunimp{},
disasm: "c.unimp",
resources: {next_pc},
semfunc: "&RiscVIUnimplemented";
}
}
slot riscv64chints {
default size = 2;
default latency = global_latency;
opcodes {
cnop_hint{},
disasm: "cnop",
semfunc: "&RiscVINop";
cli_hint{: x0, I_ci_imm6 : rd},
disasm: "li", "%rd, %I_ci_imm6",
semfunc: "&RiscVINop";
clui_hint{: I_ci_imm6_12 : rd},
disasm: "lui", "%rd, 0x%(I_ci_imm6_12:x)",
semfunc: "&RiscVINop";
cmv_hint{: crs2 , x0: rd},
disasm: "mv", "%rd, %crs2",
semfunc: "&RiscVINop";
caddi_hint{: rd, I_ci_imm6 : rd},
disasm: "addi", "%rd, %rd, %I_ci_imm6",
semfunc: "&RiscVINop";
cslli_hint{: rd, I_ci_uimm6 : rd},
disasm: "slli", "%rd, %rd, 0x%(I_ci_uimm6:x)",
semfunc: "&RiscVINop";
cadd_hint{: crs2, rd: rd},
disasm: "add", "%rd, %rd, %crs2",
semfunc: "&RiscVINop";
}
}