1 use crate::cdsl::isa::TargetIsa; 2 use crate::cdsl::settings::{PredicateNode, 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 28 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 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 } 196