1use serde::{Deserialize, Serialize};
2
3macro_rules! opcodes {
5 (
6 $(#[$($attrss:meta)*])*
7 pub enum $name:ident<$t:ty> {}
8 ) => {
9 opcodes!(
10 $(#[$($attrss)*])*
11 pub enum $name<$t> {,}
12 );
13 };
14 (
15 $(#[$($attrss:meta)*])*
16 pub enum $name:ident<$t:ty> {
17 $(
18 $(#[$($a:meta)*])*
19 $foo:ident($($i:ty),*)
20 ),*
21 ,
22 }
23 ) => {
24 $(#[$($attrss)*])*
25 pub enum $name {
26 #[doc = "Writes an output variable by index"]
28 Output($t, u32),
29 #[doc = "Read an input variable by index"]
30 Input($t, u32),
31 #[doc = "Copies the given register"]
32 CopyReg($t, $t),
33 #[doc = "Copy an immediate to a register"]
34 CopyImm($t, f32),
35
36 #[doc = "Negate the given register"]
38 NegReg($t, $t),
39 #[doc = "Take the absolute value of the given register"]
40 AbsReg($t, $t),
41 #[doc = "Take the reciprocal of the given register (1.0 / value)"]
42 RecipReg($t, $t),
43 #[doc = "Take the square root of the given register"]
44 SqrtReg($t, $t),
45 #[doc = "Square the given register"]
46 SquareReg($t, $t),
47 #[doc = "Returns the largest integer less than or equal to `self`"]
48 FloorReg($t, $t),
49 #[doc = "Returns the smallest integer greater than or equal to `self`"]
50 CeilReg($t, $t),
51 #[doc = "Returns the nearest integer to `self`. If a value is half-way between two integers, round away from `0.0`."]
52 RoundReg($t, $t),
53 #[doc = "Computes the sine of the given register (in radians)"]
54 SinReg($t, $t),
55 #[doc = "Computes the cosine of the given register (in radians)"]
56 CosReg($t, $t),
57 #[doc = "Computes the tangent of the given register (in radians)"]
58 TanReg($t, $t),
59 #[doc = "Computes the arcsin of the given register (in radians)"]
60 AsinReg($t, $t),
61 #[doc = "Computes the arccos of the given register (in radians)"]
62 AcosReg($t, $t),
63 #[doc = "Computes the arctangent of the given register (in radians)"]
64 AtanReg($t, $t),
65 #[doc = "Computes the exponential function of the given register"]
66 ExpReg($t, $t),
67 #[doc = "Computes the natural log of the given register"]
68 LnReg($t, $t),
69 #[doc = "Computes the logical negation of the given register\n\nEquivalent to `if arg == 0 { 1 } else { 0 }`"]
70 NotReg($t, $t),
71
72 #[doc = "Add a register and an immediate"]
74 AddRegImm($t, $t, f32),
75 #[doc = "Multiply a register and an immediate"]
76 MulRegImm($t, $t, f32),
77 #[doc = "Divides a register and an immediate"]
78 DivRegImm($t, $t, f32),
79 #[doc = "Divides an immediate by a register"]
80 DivImmReg($t, $t, f32),
81 #[doc = "Subtract a register from an immediate"]
82 SubImmReg($t, $t, f32),
83 #[doc = "Subtract an immediate from a register"]
84 SubRegImm($t, $t, f32),
85 #[doc = "Take the module (least nonnegative remainder) of two registers"]
86 ModRegReg($t, $t, $t),
87 #[doc = "Take the module (least nonnegative remainder) of a register and an immediate"]
88 ModRegImm($t, $t, f32),
89 #[doc = "atan2 of a position `(y, x)` specified as register, immediate"]
90 AtanRegImm($t, $t, f32),
91 #[doc = "Compares a register with an immediate"]
92 CompareRegImm($t, $t, f32),
93
94 #[doc = "Compute the minimum of a register and an immediate"]
96 MinRegImm($t, $t, f32),
97 #[doc = "Compute the maximum of a register and an immediate"]
98 MaxRegImm($t, $t, f32),
99 #[doc = "Logical `AND` (short-circuiting)\n\nThis is equivalent to `if lhs == 0 { lhs } else { imm }`"]
100 AndRegImm($t, $t, f32),
101 #[doc = "Logical `OR` (short-circuiting)\n\nThis is equivalent to `if lhs != 0 { lhs } else { imm }`"]
102 OrRegImm($t, $t, f32),
103
104 #[doc = "Take the module (least nonnegative remainder) of an immediate and a register"]
106 ModImmReg($t, $t, f32),
107 #[doc = "atan2 of a position `(y, x)` specified as immediate, register"]
108 AtanImmReg($t, $t, f32),
109 #[doc = "Compares an immediate with a register"]
110 CompareImmReg($t, $t, f32),
111
112 #[doc = "Add two registers"]
114 AddRegReg($t, $t, $t),
115 #[doc = "Multiply two registers"]
116 MulRegReg($t, $t, $t),
117 #[doc = "Divides two registers"]
118 DivRegReg($t, $t, $t),
119 #[doc = "Subtract one register from another"]
120 SubRegReg($t, $t, $t),
121 #[doc = "Compares two registers"]
122 CompareRegReg($t, $t, $t),
123 #[doc = "atan2 of a position `(y, x)` specified as register, register"]
124 AtanRegReg($t, $t, $t),
125
126 #[doc = "Take the minimum of two registers"]
128 MinRegReg($t, $t, $t),
129 #[doc = "Take the maximum of two registers"]
130 MaxRegReg($t, $t, $t),
131 #[doc = "Logical `AND` (short-circuiting)\n\nThis is equivalent to `if lhs == 0 { lhs } else { rhs }`"]
132 AndRegReg($t, $t, $t),
133 #[doc = "Logical `OR` (short-circuiting)\n\nThis is equivalent to `if lhs != 0 { lhs } else { rhs }`"]
134 OrRegReg($t, $t, $t),
135
136 $(
137 $(#[$($a)*])*
138 $foo($($i),*)
139 ),*
140 }
141 };
142}
143
144opcodes!(
145 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
154 pub enum SsaOp<u32> {
155 }
157);
158
159impl SsaOp {
160 pub fn output(&self) -> Option<u32> {
162 match self {
163 SsaOp::Input(out, ..)
164 | SsaOp::CopyImm(out, ..)
165 | SsaOp::NegReg(out, ..)
166 | SsaOp::AbsReg(out, ..)
167 | SsaOp::RecipReg(out, ..)
168 | SsaOp::SqrtReg(out, ..)
169 | SsaOp::SquareReg(out, ..)
170 | SsaOp::FloorReg(out, ..)
171 | SsaOp::CeilReg(out, ..)
172 | SsaOp::RoundReg(out, ..)
173 | SsaOp::CopyReg(out, ..)
174 | SsaOp::SinReg(out, ..)
175 | SsaOp::CosReg(out, ..)
176 | SsaOp::TanReg(out, ..)
177 | SsaOp::AsinReg(out, ..)
178 | SsaOp::AcosReg(out, ..)
179 | SsaOp::AtanReg(out, ..)
180 | SsaOp::ExpReg(out, ..)
181 | SsaOp::LnReg(out, ..)
182 | SsaOp::NotReg(out, ..)
183 | SsaOp::AddRegImm(out, ..)
184 | SsaOp::MulRegImm(out, ..)
185 | SsaOp::DivRegImm(out, ..)
186 | SsaOp::DivImmReg(out, ..)
187 | SsaOp::SubImmReg(out, ..)
188 | SsaOp::SubRegImm(out, ..)
189 | SsaOp::AddRegReg(out, ..)
190 | SsaOp::MulRegReg(out, ..)
191 | SsaOp::DivRegReg(out, ..)
192 | SsaOp::SubRegReg(out, ..)
193 | SsaOp::AtanRegReg(out, ..)
194 | SsaOp::AtanRegImm(out, ..)
195 | SsaOp::AtanImmReg(out, ..)
196 | SsaOp::MinRegImm(out, ..)
197 | SsaOp::MaxRegImm(out, ..)
198 | SsaOp::MinRegReg(out, ..)
199 | SsaOp::MaxRegReg(out, ..)
200 | SsaOp::CompareRegReg(out, ..)
201 | SsaOp::CompareRegImm(out, ..)
202 | SsaOp::CompareImmReg(out, ..)
203 | SsaOp::ModRegReg(out, ..)
204 | SsaOp::ModRegImm(out, ..)
205 | SsaOp::ModImmReg(out, ..)
206 | SsaOp::AndRegImm(out, ..)
207 | SsaOp::AndRegReg(out, ..)
208 | SsaOp::OrRegImm(out, ..)
209 | SsaOp::OrRegReg(out, ..) => Some(*out),
210 SsaOp::Output(..) => None,
211 }
212 }
213 pub fn has_choice(&self) -> bool {
215 match self {
216 SsaOp::Input(..)
217 | SsaOp::Output(..)
218 | SsaOp::CopyImm(..)
219 | SsaOp::NegReg(..)
220 | SsaOp::AbsReg(..)
221 | SsaOp::RecipReg(..)
222 | SsaOp::SqrtReg(..)
223 | SsaOp::SquareReg(..)
224 | SsaOp::FloorReg(..)
225 | SsaOp::CeilReg(..)
226 | SsaOp::RoundReg(..)
227 | SsaOp::CopyReg(..)
228 | SsaOp::SinReg(..)
229 | SsaOp::CosReg(..)
230 | SsaOp::TanReg(..)
231 | SsaOp::AsinReg(..)
232 | SsaOp::AcosReg(..)
233 | SsaOp::AtanReg(..)
234 | SsaOp::ExpReg(..)
235 | SsaOp::LnReg(..)
236 | SsaOp::NotReg(..)
237 | SsaOp::AddRegImm(..)
238 | SsaOp::MulRegImm(..)
239 | SsaOp::SubRegImm(..)
240 | SsaOp::SubImmReg(..)
241 | SsaOp::AddRegReg(..)
242 | SsaOp::MulRegReg(..)
243 | SsaOp::SubRegReg(..)
244 | SsaOp::DivRegReg(..)
245 | SsaOp::DivRegImm(..)
246 | SsaOp::DivImmReg(..)
247 | SsaOp::AtanRegReg(..)
248 | SsaOp::AtanRegImm(..)
249 | SsaOp::AtanImmReg(..)
250 | SsaOp::CompareRegReg(..)
251 | SsaOp::CompareRegImm(..)
252 | SsaOp::CompareImmReg(..)
253 | SsaOp::ModRegReg(..)
254 | SsaOp::ModRegImm(..)
255 | SsaOp::ModImmReg(..) => false,
256 SsaOp::MinRegImm(..)
257 | SsaOp::MaxRegImm(..)
258 | SsaOp::MinRegReg(..)
259 | SsaOp::MaxRegReg(..)
260 | SsaOp::AndRegImm(..)
261 | SsaOp::AndRegReg(..)
262 | SsaOp::OrRegImm(..)
263 | SsaOp::OrRegReg(..) => true,
264 }
265 }
266}
267
268opcodes!(
269 #[derive(
279 Copy,
280 Clone,
281 Debug,
282 PartialEq,
283 Serialize,
284 Deserialize,
285 strum::EnumDiscriminants,
286 )]
287 #[strum_discriminants(derive(
288 strum::EnumIter,
289 strum::EnumCount,
290 strum::IntoStaticStr,
291 strum::FromRepr,
292 ))]
293 #[strum_discriminants(doc = "[`RegOp`] discriminant value")]
294 pub enum RegOp<u8> {
295 Load(u8, u32),
298
299 Store(u8, u32),
301 }
302);