1 use crate::cdsl::isa::TargetIsa;
2 use crate::cdsl::settings::SettingGroupBuilder;
3 
4 macro_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 
define() -> TargetIsa28 pub(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     TargetIsa::new("riscv64", setting.build())
190 }
191