This follows the rest of the code base data structures, where we have a mutable data structure builder; once the data structure is constructed, it's immutable. This also makes the definition of instructions easier, and it paves the way for defining immediate variants.
119 lines
3.7 KiB
Rust
119 lines
3.7 KiB
Rust
use crate::cdsl::cpu_modes::CpuMode;
|
|
use crate::cdsl::instructions::InstructionGroupBuilder;
|
|
use crate::cdsl::isa::TargetIsa;
|
|
use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder};
|
|
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};
|
|
|
|
use crate::shared::types::Float::{F32, F64};
|
|
use crate::shared::types::Int::{I32, I64};
|
|
use crate::shared::Definitions as SharedDefinitions;
|
|
|
|
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
|
let mut setting = SettingGroupBuilder::new("riscv");
|
|
|
|
let supports_m = setting.add_bool(
|
|
"supports_m",
|
|
"CPU supports the 'M' extension (mul/div)",
|
|
false,
|
|
);
|
|
let supports_a = setting.add_bool(
|
|
"supports_a",
|
|
"CPU supports the 'A' extension (atomics)",
|
|
false,
|
|
);
|
|
let supports_f = setting.add_bool(
|
|
"supports_f",
|
|
"CPU supports the 'F' extension (float)",
|
|
false,
|
|
);
|
|
let supports_d = setting.add_bool(
|
|
"supports_d",
|
|
"CPU supports the 'D' extension (double)",
|
|
false,
|
|
);
|
|
|
|
let enable_m = setting.add_bool(
|
|
"enable_m",
|
|
"Enable the use of 'M' instructions if available",
|
|
true,
|
|
);
|
|
|
|
setting.add_bool(
|
|
"enable_e",
|
|
"Enable the 'RV32E' instruction set with only 16 registers",
|
|
false,
|
|
);
|
|
|
|
let shared_enable_atomics = shared.get_bool("enable_atomics");
|
|
let shared_enable_float = shared.get_bool("enable_float");
|
|
let shared_enable_simd = shared.get_bool("enable_simd");
|
|
|
|
setting.add_predicate("use_m", predicate!(supports_m && enable_m));
|
|
setting.add_predicate("use_a", predicate!(supports_a && shared_enable_atomics));
|
|
setting.add_predicate("use_f", predicate!(supports_f && shared_enable_float));
|
|
setting.add_predicate("use_d", predicate!(supports_d && shared_enable_float));
|
|
setting.add_predicate(
|
|
"full_float",
|
|
predicate!(shared_enable_simd && supports_f && supports_d),
|
|
);
|
|
|
|
setting.finish()
|
|
}
|
|
|
|
fn define_registers() -> IsaRegs {
|
|
let mut regs = IsaRegsBuilder::new();
|
|
|
|
let builder = RegBankBuilder::new("IntRegs", "x")
|
|
.units(32)
|
|
.track_pressure(true);
|
|
let int_regs = regs.add_bank(builder);
|
|
|
|
let builder = RegBankBuilder::new("FloatRegs", "f")
|
|
.units(32)
|
|
.track_pressure(true);
|
|
let float_regs = regs.add_bank(builder);
|
|
|
|
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
|
regs.add_class(builder);
|
|
|
|
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
|
regs.add_class(builder);
|
|
|
|
regs.finish()
|
|
}
|
|
|
|
pub fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
|
|
let settings = define_settings(&shared_defs.settings);
|
|
let regs = define_registers();
|
|
|
|
let inst_group = InstructionGroupBuilder::new(
|
|
"riscv",
|
|
"riscv specific instruction set",
|
|
&shared_defs.format_registry,
|
|
)
|
|
.finish();
|
|
|
|
// CPU modes for 32-bit and 64-bit operation.
|
|
let mut rv_32 = CpuMode::new("RV32");
|
|
let mut rv_64 = CpuMode::new("RV64");
|
|
|
|
let expand = shared_defs.transform_groups.by_name("expand");
|
|
let narrow = shared_defs.transform_groups.by_name("narrow");
|
|
rv_32.legalize_monomorphic(expand);
|
|
rv_32.legalize_default(narrow);
|
|
rv_32.legalize_type(I32, expand);
|
|
rv_32.legalize_type(F32, expand);
|
|
rv_32.legalize_type(F64, expand);
|
|
|
|
rv_64.legalize_monomorphic(expand);
|
|
rv_64.legalize_default(narrow);
|
|
rv_64.legalize_type(I32, expand);
|
|
rv_64.legalize_type(I64, expand);
|
|
rv_64.legalize_type(F32, expand);
|
|
rv_64.legalize_type(F64, expand);
|
|
|
|
let cpu_modes = vec![rv_32, rv_64];
|
|
|
|
TargetIsa::new("riscv", inst_group, settings, regs, cpu_modes)
|
|
}
|