cranelift_codegen_meta/isa/
riscv64.rs

1use crate::cdsl::isa::TargetIsa;
2use crate::cdsl::settings::{PredicateNode, SettingGroupBuilder};
3
4macro_rules! define_zvl_ext {
5    (DEF: $settings:expr, $size:expr) => {{
6        let name = concat!("has_zvl", $size, "b");
7        let desc = concat!("has extension Zvl", $size, "b?");
8        let comment = concat!(
9            "Zvl",
10            $size,
11            "b: Vector register has a minimum of ",
12            $size,
13            " bits"
14        );
15        $settings.add_bool(&name, &desc, &comment, false)
16    }};
17    ($settings:expr, $size:expr $(, $implies:expr)*) => {{
18        let has_feature = define_zvl_ext!(DEF: $settings, $size);
19
20        let name = concat!("zvl", $size, "b");
21        let desc = concat!("Has a vector register size of at least ", $size, " bits");
22
23        let preset = $settings.add_preset(&name, &desc, preset!(has_feature $( && $implies )*));
24        (has_feature, preset)
25    }};
26}
27
28pub(crate) fn define() -> TargetIsa {
29    let mut setting = SettingGroupBuilder::new("riscv64");
30
31    // We target a minimum of riscv64g. That means that we have the following extensions by default:
32    //
33    // * M (integer multiplication and division)
34    // * A (atomic instructions)
35    // * F (single-precision floating point)
36    // * D (double-precision floating point)
37    // * Zicsr (control and status register instructions)
38    // * Zifencei (instruction-fetch fence)
39
40    let has_m = setting.add_bool(
41        "has_m",
42        "has extension M?",
43        "Integer multiplication and division",
44        true,
45    );
46    let has_a = setting.add_bool("has_a", "has extension A?", "Atomic instructions", true);
47    let has_f = setting.add_bool(
48        "has_f",
49        "has extension F?",
50        "Single-precision floating point",
51        true,
52    );
53    let has_d = setting.add_bool(
54        "has_d",
55        "has extension D?",
56        "Double-precision floating point",
57        true,
58    );
59
60    let _has_zfa = setting.add_bool(
61        "has_zfa",
62        "has extension Zfa?",
63        "Zfa: Extension for Additional Floating-Point Instructions",
64        false,
65    );
66
67    let _has_zfhmin = setting.add_bool(
68        "has_zfhmin",
69        "has extension Zfhmin?",
70        "Zfhmin: Minimal Half-Precision Floating-Point",
71        false,
72    );
73
74    let _has_zfh = setting.add_bool(
75        "has_zfh",
76        "has extension Zfh?",
77        "Zfh: Half-Precision Floating-Point Instructions",
78        false,
79    );
80
81    let _has_v = setting.add_bool(
82        "has_v",
83        "has extension V?",
84        "Vector instruction support",
85        false,
86    );
87
88    let _has_zvfh = setting.add_bool(
89        "has_zvfh",
90        "has extension Zvfh?",
91        "Zvfh: Vector Extension for Half-Precision Floating-Point",
92        false,
93    );
94
95    let has_zca = setting.add_bool(
96        "has_zca",
97        "has extension Zca?",
98        "Zca is the C extension without floating point loads",
99        false,
100    );
101    let has_zcd = setting.add_bool(
102        "has_zcd",
103        "has extension Zcd?",
104        "Zcd contains only the double precision floating point loads from the C extension",
105        false,
106    );
107    setting.add_preset(
108        "has_c",
109        "Support for compressed instructions",
110        preset!(has_zca && has_zcd),
111    );
112
113    let _has_zcb = setting.add_bool(
114        "has_zcb",
115        "has extension Zcb?",
116        "Zcb: Extra compressed instructions",
117        false,
118    );
119
120    let _has_zbkb = setting.add_bool(
121        "has_zbkb",
122        "has extension zbkb?",
123        "Zbkb: Bit-manipulation for Cryptography",
124        false,
125    );
126    let _has_zba = setting.add_bool(
127        "has_zba",
128        "has extension zba?",
129        "Zba: Address Generation",
130        false,
131    );
132    let _has_zbb = setting.add_bool(
133        "has_zbb",
134        "has extension zbb?",
135        "Zbb: Basic bit-manipulation",
136        false,
137    );
138    let _has_zbc = setting.add_bool(
139        "has_zbc",
140        "has extension zbc?",
141        "Zbc: Carry-less multiplication",
142        false,
143    );
144    let _has_zbs = setting.add_bool(
145        "has_zbs",
146        "has extension zbs?",
147        "Zbs: Single-bit instructions",
148        false,
149    );
150    let _has_zicond = setting.add_bool(
151        "has_zicond",
152        "has extension zicond?",
153        "ZiCond: Integer Conditional Operations",
154        false,
155    );
156
157    let has_zicsr = setting.add_bool(
158        "has_zicsr",
159        "has extension zicsr?",
160        "Zicsr: Control and Status Register (CSR) Instructions",
161        true,
162    );
163    let has_zifencei = setting.add_bool(
164        "has_zifencei",
165        "has extension zifencei?",
166        "Zifencei: Instruction-Fetch Fence",
167        true,
168    );
169
170    // Zvl*: Minimum Vector Length Standard Extensions
171    // These extension specify the minimum number of bits in a vector register.
172    // Since it is a minimum, Zvl64b implies Zvl32b, Zvl128b implies Zvl64b, etc.
173    // The V extension supports a maximum of 64K bits in a single register.
174    //
175    // See: https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#181-zvl-minimum-vector-length-standard-extensions
176    let (_, zvl32b) = define_zvl_ext!(setting, 32);
177    let (_, zvl64b) = define_zvl_ext!(setting, 64, zvl32b);
178    let (_, zvl128b) = define_zvl_ext!(setting, 128, zvl64b);
179    let (_, zvl256b) = define_zvl_ext!(setting, 256, zvl128b);
180    let (_, zvl512b) = define_zvl_ext!(setting, 512, zvl256b);
181    let (_, zvl1024b) = define_zvl_ext!(setting, 1024, zvl512b);
182    let (_, zvl2048b) = define_zvl_ext!(setting, 2048, zvl1024b);
183    let (_, zvl4096b) = define_zvl_ext!(setting, 4096, zvl2048b);
184    let (_, zvl8192b) = define_zvl_ext!(setting, 8192, zvl4096b);
185    let (_, zvl16384b) = define_zvl_ext!(setting, 16384, zvl8192b);
186    let (_, zvl32768b) = define_zvl_ext!(setting, 32768, zvl16384b);
187    let (_, _zvl65536b) = define_zvl_ext!(setting, 65536, zvl32768b);
188
189    setting.add_predicate(
190        "has_g",
191        predicate!(has_m && has_a && has_f && has_d && has_zicsr && has_zifencei),
192    );
193
194    TargetIsa::new("riscv64", setting.build())
195}