1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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;

mod encodings;
mod recipes;

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.build()
}

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.build()
}

pub(crate) fn define(shared_defs: &mut SharedDefinitions) -> TargetIsa {
    let settings = define_settings(&shared_defs.settings);
    let regs = define_registers();

    let inst_group = InstructionGroupBuilder::new(&mut shared_defs.all_instructions).build();

    // 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_no_flags = shared_defs.transform_groups.by_name("narrow_no_flags");

    rv_32.legalize_monomorphic(expand);
    rv_32.legalize_default(narrow_no_flags);
    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_no_flags);
    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 recipes = recipes::define(shared_defs, &regs);

    let encodings = encodings::define(shared_defs, &settings, &recipes);
    rv_32.set_encodings(encodings.enc32);
    rv_64.set_encodings(encodings.enc64);
    let encodings_predicates = encodings.inst_pred_reg.extract();

    let recipes = recipes.collect();

    let cpu_modes = vec![rv_32, rv_64];

    TargetIsa::new(
        "riscv",
        inst_group,
        settings,
        regs,
        recipes,
        cpu_modes,
        encodings_predicates,
    )
}