1use super::*;
4use crate::ir::ExternalName;
5use crate::machinst::abi::StackAMode;
6use core::fmt;
7use pulley_interpreter::encode;
8use pulley_interpreter::regs::Reg as _;
9
10macro_rules! newtype_of_reg {
13 (
14 $newtype_reg:ident,
15 $newtype_writable_reg:ident,
16 $class:expr
17 ) => {
18 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
20 pub struct $newtype_reg(Reg);
21
22 impl PartialEq<Reg> for $newtype_reg {
23 fn eq(&self, other: &Reg) -> bool {
24 self.0 == *other
25 }
26 }
27
28 impl From<$newtype_reg> for Reg {
29 fn from(r: $newtype_reg) -> Self {
30 r.0
31 }
32 }
33
34 impl TryFrom<Reg> for $newtype_reg {
35 type Error = ();
36 fn try_from(r: Reg) -> Result<Self, Self::Error> {
37 Self::new(r).ok_or(())
38 }
39 }
40
41 impl $newtype_reg {
42 pub fn new(reg: Reg) -> Option<Self> {
45 if reg.class() == $class {
46 Some(Self(reg))
47 } else {
48 None
49 }
50 }
51
52 pub fn to_reg(self) -> Reg {
54 self.0
55 }
56 }
57
58 impl core::ops::Deref for $newtype_reg {
65 type Target = Reg;
66
67 fn deref(&self) -> &Reg {
68 &self.0
69 }
70 }
71
72 impl AsMut<Reg> for $newtype_reg {
76 fn as_mut(&mut self) -> &mut Reg {
77 &mut self.0
78 }
79 }
80
81 pub type $newtype_writable_reg = Writable<$newtype_reg>;
83
84 impl From<pulley_interpreter::regs::$newtype_reg> for $newtype_reg {
85 fn from(r: pulley_interpreter::regs::$newtype_reg) -> Self {
86 Self::new(regalloc2::PReg::new(usize::from(r as u8), $class).into()).unwrap()
87 }
88 }
89 impl From<$newtype_reg> for pulley_interpreter::regs::$newtype_reg {
90 fn from(r: $newtype_reg) -> Self {
91 Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()
92 }
93 }
94 impl<'a> From<&'a $newtype_reg> for pulley_interpreter::regs::$newtype_reg {
95 fn from(r: &'a $newtype_reg) -> Self {
96 Self::new(r.to_real_reg().unwrap().hw_enc()).unwrap()
97 }
98 }
99 impl From<$newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {
100 fn from(r: $newtype_writable_reg) -> Self {
101 Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()
102 }
103 }
104 impl<'a> From<&'a $newtype_writable_reg> for pulley_interpreter::regs::$newtype_reg {
105 fn from(r: &'a $newtype_writable_reg) -> Self {
106 Self::new(r.to_reg().to_real_reg().unwrap().hw_enc()).unwrap()
107 }
108 }
109
110 impl TryFrom<Writable<Reg>> for $newtype_writable_reg {
111 type Error = ();
112 fn try_from(r: Writable<Reg>) -> Result<Self, Self::Error> {
113 let r = r.to_reg();
114 match $newtype_reg::new(r) {
115 Some(r) => Ok(Writable::from_reg(r)),
116 None => Err(()),
117 }
118 }
119 }
120 };
121}
122
123newtype_of_reg!(XReg, WritableXReg, RegClass::Int);
125newtype_of_reg!(FReg, WritableFReg, RegClass::Float);
126newtype_of_reg!(VReg, WritableVReg, RegClass::Vector);
127
128impl XReg {
129 pub const SPECIAL_START: u8 = pulley_interpreter::regs::XReg::SPECIAL_START;
132
133 pub fn is_special(&self) -> bool {
135 match self.as_pulley() {
136 Some(reg) => reg.is_special(),
137 None => false,
138 }
139 }
140
141 pub fn as_pulley(&self) -> Option<pulley_interpreter::XReg> {
143 let enc = self.to_real_reg()?.hw_enc();
144 Some(pulley_interpreter::XReg::new(enc).unwrap())
145 }
146}
147
148pub use super::super::lower::isle::generated_code::Amode;
149
150impl Amode {
151 pub(crate) fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
153 match self {
154 Amode::RegOffset { base, offset: _ } => collector.reg_use(base),
155 Amode::SpOffset { .. } | Amode::Stack { .. } => {}
157 }
158 }
159
160 pub(crate) fn get_base_register(&self) -> Option<XReg> {
161 match self {
162 Amode::RegOffset { base, offset: _ } => Some(*base),
163 Amode::SpOffset { .. } | Amode::Stack { .. } => Some(XReg::new(stack_reg()).unwrap()),
164 }
165 }
166
167 pub(crate) fn get_offset_with_state<P>(&self, state: &EmitState<P>) -> i32
168 where
169 P: PulleyTargetKind,
170 {
171 match self {
172 Amode::RegOffset { base: _, offset } | Amode::SpOffset { offset } => *offset,
173 Amode::Stack { amode } => {
174 let offset64 = match amode {
175 StackAMode::IncomingArg(offset, stack_args_size) => {
176 let offset = i64::from(*stack_args_size) - *offset;
177 let frame_layout = state.frame_layout();
178 let sp_offset = frame_layout.tail_args_size
179 + frame_layout.setup_area_size
180 + frame_layout.clobber_size
181 + frame_layout.fixed_frame_storage_size
182 + frame_layout.outgoing_args_size;
183 i64::from(sp_offset) - offset
184 }
185 StackAMode::Slot(offset) => {
186 offset + i64::from(state.frame_layout().outgoing_args_size)
187 }
188 StackAMode::OutgoingArg(offset) => *offset,
189 };
190 i32::try_from(offset64).unwrap()
191 }
192 }
193 }
194}
195
196impl core::fmt::Display for Amode {
197 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
198 match self {
199 Amode::SpOffset { offset } => {
200 if *offset >= 0 {
201 write!(f, "sp+{offset}")
202 } else {
203 write!(f, "sp{offset}")
204 }
205 }
206 Amode::RegOffset { base, offset } => {
207 let name = RegNameDisplay(**base);
208 if *offset >= 0 {
209 write!(f, "{name}+{offset}")
210 } else {
211 write!(f, "{name}{offset}")
212 }
213 }
214 Amode::Stack { amode } => core::fmt::Debug::fmt(amode, f),
215 }
216 }
217}
218
219impl From<StackAMode> for Amode {
220 fn from(amode: StackAMode) -> Self {
221 Amode::Stack { amode }
222 }
223}
224
225#[derive(Clone, Copy, Debug, PartialEq, Eq)]
227pub enum OperandSize {
228 Size32,
230 Size64,
232}
233
234pub use crate::isa::pulley_shared::lower::isle::generated_code::Cond;
235
236impl Cond {
237 pub fn get_operands(&mut self, collector: &mut impl OperandVisitor) {
239 match self {
240 Cond::If32 { reg } | Cond::IfNot32 { reg } => collector.reg_use(reg),
241
242 Cond::IfXeq32 { src1, src2 }
243 | Cond::IfXneq32 { src1, src2 }
244 | Cond::IfXslt32 { src1, src2 }
245 | Cond::IfXslteq32 { src1, src2 }
246 | Cond::IfXult32 { src1, src2 }
247 | Cond::IfXulteq32 { src1, src2 }
248 | Cond::IfXeq64 { src1, src2 }
249 | Cond::IfXneq64 { src1, src2 }
250 | Cond::IfXslt64 { src1, src2 }
251 | Cond::IfXslteq64 { src1, src2 }
252 | Cond::IfXult64 { src1, src2 }
253 | Cond::IfXulteq64 { src1, src2 } => {
254 collector.reg_use(src1);
255 collector.reg_use(src2);
256 }
257
258 Cond::IfXeq32I32 { src1, src2 }
259 | Cond::IfXneq32I32 { src1, src2 }
260 | Cond::IfXslt32I32 { src1, src2 }
261 | Cond::IfXslteq32I32 { src1, src2 }
262 | Cond::IfXsgt32I32 { src1, src2 }
263 | Cond::IfXsgteq32I32 { src1, src2 }
264 | Cond::IfXeq64I32 { src1, src2 }
265 | Cond::IfXneq64I32 { src1, src2 }
266 | Cond::IfXslt64I32 { src1, src2 }
267 | Cond::IfXslteq64I32 { src1, src2 }
268 | Cond::IfXsgt64I32 { src1, src2 }
269 | Cond::IfXsgteq64I32 { src1, src2 } => {
270 collector.reg_use(src1);
271 let _: &mut i32 = src2;
272 }
273
274 Cond::IfXult32I32 { src1, src2 }
275 | Cond::IfXulteq32I32 { src1, src2 }
276 | Cond::IfXugt32I32 { src1, src2 }
277 | Cond::IfXugteq32I32 { src1, src2 }
278 | Cond::IfXult64I32 { src1, src2 }
279 | Cond::IfXulteq64I32 { src1, src2 }
280 | Cond::IfXugt64I32 { src1, src2 }
281 | Cond::IfXugteq64I32 { src1, src2 } => {
282 collector.reg_use(src1);
283 let _: &mut u32 = src2;
284 }
285 }
286 }
287
288 pub fn encode(&self, sink: &mut impl Extend<u8>, rel: i32) {
293 match *self {
294 Cond::If32 { reg } => encode::br_if32(sink, reg, rel),
295 Cond::IfNot32 { reg } => encode::br_if_not32(sink, reg, rel),
296 Cond::IfXeq32 { src1, src2 } => encode::br_if_xeq32(sink, src1, src2, rel),
297 Cond::IfXneq32 { src1, src2 } => encode::br_if_xneq32(sink, src1, src2, rel),
298 Cond::IfXslt32 { src1, src2 } => encode::br_if_xslt32(sink, src1, src2, rel),
299 Cond::IfXslteq32 { src1, src2 } => encode::br_if_xslteq32(sink, src1, src2, rel),
300 Cond::IfXult32 { src1, src2 } => encode::br_if_xult32(sink, src1, src2, rel),
301 Cond::IfXulteq32 { src1, src2 } => encode::br_if_xulteq32(sink, src1, src2, rel),
302 Cond::IfXeq64 { src1, src2 } => encode::br_if_xeq64(sink, src1, src2, rel),
303 Cond::IfXneq64 { src1, src2 } => encode::br_if_xneq64(sink, src1, src2, rel),
304 Cond::IfXslt64 { src1, src2 } => encode::br_if_xslt64(sink, src1, src2, rel),
305 Cond::IfXslteq64 { src1, src2 } => encode::br_if_xslteq64(sink, src1, src2, rel),
306 Cond::IfXult64 { src1, src2 } => encode::br_if_xult64(sink, src1, src2, rel),
307 Cond::IfXulteq64 { src1, src2 } => encode::br_if_xulteq64(sink, src1, src2, rel),
308
309 Cond::IfXeq32I32 { src1, src2 } => match i8::try_from(src2) {
310 Ok(src2) => encode::br_if_xeq32_i8(sink, src1, src2, rel),
311 Err(_) => encode::br_if_xeq32_i32(sink, src1, src2, rel),
312 },
313 Cond::IfXneq32I32 { src1, src2 } => match i8::try_from(src2) {
314 Ok(src2) => encode::br_if_xneq32_i8(sink, src1, src2, rel),
315 Err(_) => encode::br_if_xneq32_i32(sink, src1, src2, rel),
316 },
317 Cond::IfXslt32I32 { src1, src2 } => match i8::try_from(src2) {
318 Ok(src2) => encode::br_if_xslt32_i8(sink, src1, src2, rel),
319 Err(_) => encode::br_if_xslt32_i32(sink, src1, src2, rel),
320 },
321 Cond::IfXslteq32I32 { src1, src2 } => match i8::try_from(src2) {
322 Ok(src2) => encode::br_if_xslteq32_i8(sink, src1, src2, rel),
323 Err(_) => encode::br_if_xslteq32_i32(sink, src1, src2, rel),
324 },
325 Cond::IfXsgt32I32 { src1, src2 } => match i8::try_from(src2) {
326 Ok(src2) => encode::br_if_xsgt32_i8(sink, src1, src2, rel),
327 Err(_) => encode::br_if_xsgt32_i32(sink, src1, src2, rel),
328 },
329 Cond::IfXsgteq32I32 { src1, src2 } => match i8::try_from(src2) {
330 Ok(src2) => encode::br_if_xsgteq32_i8(sink, src1, src2, rel),
331 Err(_) => encode::br_if_xsgteq32_i32(sink, src1, src2, rel),
332 },
333 Cond::IfXult32I32 { src1, src2 } => match u8::try_from(src2) {
334 Ok(src2) => encode::br_if_xult32_u8(sink, src1, src2, rel),
335 Err(_) => encode::br_if_xult32_u32(sink, src1, src2, rel),
336 },
337 Cond::IfXulteq32I32 { src1, src2 } => match u8::try_from(src2) {
338 Ok(src2) => encode::br_if_xulteq32_u8(sink, src1, src2, rel),
339 Err(_) => encode::br_if_xulteq32_u32(sink, src1, src2, rel),
340 },
341 Cond::IfXugt32I32 { src1, src2 } => match u8::try_from(src2) {
342 Ok(src2) => encode::br_if_xugt32_u8(sink, src1, src2, rel),
343 Err(_) => encode::br_if_xugt32_u32(sink, src1, src2, rel),
344 },
345 Cond::IfXugteq32I32 { src1, src2 } => match u8::try_from(src2) {
346 Ok(src2) => encode::br_if_xugteq32_u8(sink, src1, src2, rel),
347 Err(_) => encode::br_if_xugteq32_u32(sink, src1, src2, rel),
348 },
349
350 Cond::IfXeq64I32 { src1, src2 } => match i8::try_from(src2) {
351 Ok(src2) => encode::br_if_xeq64_i8(sink, src1, src2, rel),
352 Err(_) => encode::br_if_xeq64_i32(sink, src1, src2, rel),
353 },
354 Cond::IfXneq64I32 { src1, src2 } => match i8::try_from(src2) {
355 Ok(src2) => encode::br_if_xneq64_i8(sink, src1, src2, rel),
356 Err(_) => encode::br_if_xneq64_i32(sink, src1, src2, rel),
357 },
358 Cond::IfXslt64I32 { src1, src2 } => match i8::try_from(src2) {
359 Ok(src2) => encode::br_if_xslt64_i8(sink, src1, src2, rel),
360 Err(_) => encode::br_if_xslt64_i32(sink, src1, src2, rel),
361 },
362 Cond::IfXslteq64I32 { src1, src2 } => match i8::try_from(src2) {
363 Ok(src2) => encode::br_if_xslteq64_i8(sink, src1, src2, rel),
364 Err(_) => encode::br_if_xslteq64_i32(sink, src1, src2, rel),
365 },
366 Cond::IfXsgt64I32 { src1, src2 } => match i8::try_from(src2) {
367 Ok(src2) => encode::br_if_xsgt64_i8(sink, src1, src2, rel),
368 Err(_) => encode::br_if_xsgt64_i32(sink, src1, src2, rel),
369 },
370 Cond::IfXsgteq64I32 { src1, src2 } => match i8::try_from(src2) {
371 Ok(src2) => encode::br_if_xsgteq64_i8(sink, src1, src2, rel),
372 Err(_) => encode::br_if_xsgteq64_i32(sink, src1, src2, rel),
373 },
374 Cond::IfXult64I32 { src1, src2 } => match u8::try_from(src2) {
375 Ok(src2) => encode::br_if_xult64_u8(sink, src1, src2, rel),
376 Err(_) => encode::br_if_xult64_u32(sink, src1, src2, rel),
377 },
378 Cond::IfXulteq64I32 { src1, src2 } => match u8::try_from(src2) {
379 Ok(src2) => encode::br_if_xulteq64_u8(sink, src1, src2, rel),
380 Err(_) => encode::br_if_xulteq64_u32(sink, src1, src2, rel),
381 },
382 Cond::IfXugt64I32 { src1, src2 } => match u8::try_from(src2) {
383 Ok(src2) => encode::br_if_xugt64_u8(sink, src1, src2, rel),
384 Err(_) => encode::br_if_xugt64_u32(sink, src1, src2, rel),
385 },
386 Cond::IfXugteq64I32 { src1, src2 } => match u8::try_from(src2) {
387 Ok(src2) => encode::br_if_xugteq64_u8(sink, src1, src2, rel),
388 Err(_) => encode::br_if_xugteq64_u32(sink, src1, src2, rel),
389 },
390 }
391 }
392
393 pub fn invert(&self) -> Cond {
395 match *self {
396 Cond::If32 { reg } => Cond::IfNot32 { reg },
397 Cond::IfNot32 { reg } => Cond::If32 { reg },
398 Cond::IfXeq32 { src1, src2 } => Cond::IfXneq32 { src1, src2 },
399 Cond::IfXneq32 { src1, src2 } => Cond::IfXeq32 { src1, src2 },
400 Cond::IfXeq64 { src1, src2 } => Cond::IfXneq64 { src1, src2 },
401 Cond::IfXneq64 { src1, src2 } => Cond::IfXeq64 { src1, src2 },
402
403 Cond::IfXslt32 { src1, src2 } => Cond::IfXslteq32 {
406 src1: src2,
407 src2: src1,
408 },
409 Cond::IfXslteq32 { src1, src2 } => Cond::IfXslt32 {
410 src1: src2,
411 src2: src1,
412 },
413 Cond::IfXult32 { src1, src2 } => Cond::IfXulteq32 {
414 src1: src2,
415 src2: src1,
416 },
417 Cond::IfXulteq32 { src1, src2 } => Cond::IfXult32 {
418 src1: src2,
419 src2: src1,
420 },
421 Cond::IfXslt64 { src1, src2 } => Cond::IfXslteq64 {
422 src1: src2,
423 src2: src1,
424 },
425 Cond::IfXslteq64 { src1, src2 } => Cond::IfXslt64 {
426 src1: src2,
427 src2: src1,
428 },
429 Cond::IfXult64 { src1, src2 } => Cond::IfXulteq64 {
430 src1: src2,
431 src2: src1,
432 },
433 Cond::IfXulteq64 { src1, src2 } => Cond::IfXult64 {
434 src1: src2,
435 src2: src1,
436 },
437
438 Cond::IfXeq32I32 { src1, src2 } => Cond::IfXneq32I32 { src1, src2 },
439 Cond::IfXneq32I32 { src1, src2 } => Cond::IfXeq32I32 { src1, src2 },
440 Cond::IfXslt32I32 { src1, src2 } => Cond::IfXsgteq32I32 { src1, src2 },
441 Cond::IfXslteq32I32 { src1, src2 } => Cond::IfXsgt32I32 { src1, src2 },
442 Cond::IfXult32I32 { src1, src2 } => Cond::IfXugteq32I32 { src1, src2 },
443 Cond::IfXulteq32I32 { src1, src2 } => Cond::IfXugt32I32 { src1, src2 },
444 Cond::IfXsgt32I32 { src1, src2 } => Cond::IfXslteq32I32 { src1, src2 },
445 Cond::IfXsgteq32I32 { src1, src2 } => Cond::IfXslt32I32 { src1, src2 },
446 Cond::IfXugt32I32 { src1, src2 } => Cond::IfXulteq32I32 { src1, src2 },
447 Cond::IfXugteq32I32 { src1, src2 } => Cond::IfXult32I32 { src1, src2 },
448
449 Cond::IfXeq64I32 { src1, src2 } => Cond::IfXneq64I32 { src1, src2 },
450 Cond::IfXneq64I32 { src1, src2 } => Cond::IfXeq64I32 { src1, src2 },
451 Cond::IfXslt64I32 { src1, src2 } => Cond::IfXsgteq64I32 { src1, src2 },
452 Cond::IfXslteq64I32 { src1, src2 } => Cond::IfXsgt64I32 { src1, src2 },
453 Cond::IfXult64I32 { src1, src2 } => Cond::IfXugteq64I32 { src1, src2 },
454 Cond::IfXulteq64I32 { src1, src2 } => Cond::IfXugt64I32 { src1, src2 },
455 Cond::IfXsgt64I32 { src1, src2 } => Cond::IfXslteq64I32 { src1, src2 },
456 Cond::IfXsgteq64I32 { src1, src2 } => Cond::IfXslt64I32 { src1, src2 },
457 Cond::IfXugt64I32 { src1, src2 } => Cond::IfXulteq64I32 { src1, src2 },
458 Cond::IfXugteq64I32 { src1, src2 } => Cond::IfXult64I32 { src1, src2 },
459 }
460 }
461}
462
463impl fmt::Display for Cond {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 match self {
466 Cond::If32 { reg } => write!(f, "if32 {}", RegNameDisplay(**reg)),
467 Cond::IfNot32 { reg } => write!(f, "if_not32 {}", RegNameDisplay(**reg)),
468 Cond::IfXeq32 { src1, src2 } => {
469 write!(
470 f,
471 "if_xeq32 {}, {}",
472 RegNameDisplay(**src1),
473 RegNameDisplay(**src2)
474 )
475 }
476 Cond::IfXneq32 { src1, src2 } => {
477 write!(
478 f,
479 "if_xneq32 {}, {}",
480 RegNameDisplay(**src1),
481 RegNameDisplay(**src2)
482 )
483 }
484 Cond::IfXslt32 { src1, src2 } => {
485 write!(
486 f,
487 "if_xslt32 {}, {}",
488 RegNameDisplay(**src1),
489 RegNameDisplay(**src2)
490 )
491 }
492 Cond::IfXslteq32 { src1, src2 } => {
493 write!(
494 f,
495 "if_xslteq32 {}, {}",
496 RegNameDisplay(**src1),
497 RegNameDisplay(**src2)
498 )
499 }
500 Cond::IfXult32 { src1, src2 } => {
501 write!(
502 f,
503 "if_xult32 {}, {}",
504 RegNameDisplay(**src1),
505 RegNameDisplay(**src2)
506 )
507 }
508 Cond::IfXulteq32 { src1, src2 } => {
509 write!(
510 f,
511 "if_xulteq32 {}, {}",
512 RegNameDisplay(**src1),
513 RegNameDisplay(**src2)
514 )
515 }
516 Cond::IfXeq64 { src1, src2 } => {
517 write!(
518 f,
519 "if_xeq64 {}, {}",
520 RegNameDisplay(**src1),
521 RegNameDisplay(**src2)
522 )
523 }
524 Cond::IfXneq64 { src1, src2 } => {
525 write!(
526 f,
527 "if_xneq64 {}, {}",
528 RegNameDisplay(**src1),
529 RegNameDisplay(**src2)
530 )
531 }
532 Cond::IfXslt64 { src1, src2 } => {
533 write!(
534 f,
535 "if_xslt64 {}, {}",
536 RegNameDisplay(**src1),
537 RegNameDisplay(**src2)
538 )
539 }
540 Cond::IfXslteq64 { src1, src2 } => {
541 write!(
542 f,
543 "if_xslteq64 {}, {}",
544 RegNameDisplay(**src1),
545 RegNameDisplay(**src2)
546 )
547 }
548 Cond::IfXult64 { src1, src2 } => {
549 write!(
550 f,
551 "if_xult64 {}, {}",
552 RegNameDisplay(**src1),
553 RegNameDisplay(**src2)
554 )
555 }
556 Cond::IfXulteq64 { src1, src2 } => {
557 write!(
558 f,
559 "if_xulteq64 {}, {}",
560 RegNameDisplay(**src1),
561 RegNameDisplay(**src2)
562 )
563 }
564 Cond::IfXeq32I32 { src1, src2 } => {
565 write!(f, "if_xeq32_i32 {}, {src2}", RegNameDisplay(**src1))
566 }
567 Cond::IfXneq32I32 { src1, src2 } => {
568 write!(f, "if_xneq32_i32 {}, {src2}", RegNameDisplay(**src1))
569 }
570 Cond::IfXslt32I32 { src1, src2 } => {
571 write!(f, "if_xslt32_i32 {}, {src2}", RegNameDisplay(**src1))
572 }
573 Cond::IfXslteq32I32 { src1, src2 } => {
574 write!(f, "if_xslteq32_i32 {}, {src2}", RegNameDisplay(**src1))
575 }
576 Cond::IfXsgt32I32 { src1, src2 } => {
577 write!(f, "if_xsgt32_i32 {}, {src2}", RegNameDisplay(**src1))
578 }
579 Cond::IfXsgteq32I32 { src1, src2 } => {
580 write!(f, "if_xsgteq32_i32 {}, {src2}", RegNameDisplay(**src1))
581 }
582 Cond::IfXult32I32 { src1, src2 } => {
583 write!(f, "if_xult32_i32 {}, {src2}", RegNameDisplay(**src1))
584 }
585 Cond::IfXulteq32I32 { src1, src2 } => {
586 write!(f, "if_xulteq32_i32 {}, {src2}", RegNameDisplay(**src1))
587 }
588 Cond::IfXugt32I32 { src1, src2 } => {
589 write!(f, "if_xugt32_i32 {}, {src2}", RegNameDisplay(**src1))
590 }
591 Cond::IfXugteq32I32 { src1, src2 } => {
592 write!(f, "if_xugteq32_i32 {}, {src2}", RegNameDisplay(**src1))
593 }
594 Cond::IfXeq64I32 { src1, src2 } => {
595 write!(f, "if_xeq64_i32 {}, {src2}", RegNameDisplay(**src1))
596 }
597 Cond::IfXneq64I32 { src1, src2 } => {
598 write!(f, "if_xneq64_i32 {}, {src2}", RegNameDisplay(**src1))
599 }
600 Cond::IfXslt64I32 { src1, src2 } => {
601 write!(f, "if_xslt64_i32 {}, {src2}", RegNameDisplay(**src1))
602 }
603 Cond::IfXslteq64I32 { src1, src2 } => {
604 write!(f, "if_xslteq64_i32 {}, {src2}", RegNameDisplay(**src1))
605 }
606 Cond::IfXsgt64I32 { src1, src2 } => {
607 write!(f, "if_xsgt64_i32 {}, {src2}", RegNameDisplay(**src1))
608 }
609 Cond::IfXsgteq64I32 { src1, src2 } => {
610 write!(f, "if_xsgteq64_i32 {}, {src2}", RegNameDisplay(**src1))
611 }
612 Cond::IfXult64I32 { src1, src2 } => {
613 write!(f, "if_xult64_i32 {}, {src2}", RegNameDisplay(**src1))
614 }
615 Cond::IfXulteq64I32 { src1, src2 } => {
616 write!(f, "if_xulteq64_i32 {}, {src2}", RegNameDisplay(**src1))
617 }
618 Cond::IfXugt64I32 { src1, src2 } => {
619 write!(f, "if_xugt64_i32 {}, {src2}", RegNameDisplay(**src1))
620 }
621 Cond::IfXugteq64I32 { src1, src2 } => {
622 write!(f, "if_xugteq64_i32 {}, {src2}", RegNameDisplay(**src1))
623 }
624 }
625 }
626}
627
628#[derive(Clone, Debug)]
630pub struct PulleyCall {
631 pub name: ExternalName,
634 pub args: SmallVec<[XReg; 4]>,
638}
639
640pub use super::super::lower::isle::generated_code::AddrO32;
641
642impl Copy for AddrO32 {}
643
644impl AddrO32 {
645 pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {
647 match self {
648 AddrO32::Base { addr, offset: _ } => {
649 collector.reg_use(addr);
650 }
651 }
652 }
653}
654
655impl From<AddrO32> for pulley_interpreter::AddrO32 {
656 fn from(addr: AddrO32) -> Self {
657 match addr {
658 AddrO32::Base { addr, offset } => Self {
659 addr: addr.into(),
660 offset,
661 },
662 }
663 }
664}
665
666impl fmt::Display for AddrO32 {
667 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668 match self {
669 AddrO32::Base { addr, offset } => {
670 let addr = RegNameDisplay(**addr);
671 write!(f, "{addr}, {offset}")
672 }
673 }
674 }
675}
676
677pub use super::super::lower::isle::generated_code::AddrZ;
678
679impl Copy for AddrZ {}
680
681impl AddrZ {
682 pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {
684 match self {
685 AddrZ::Base { addr, offset: _ } => {
686 collector.reg_use(addr);
687 }
688 }
689 }
690}
691
692impl From<AddrZ> for pulley_interpreter::AddrZ {
693 fn from(addr: AddrZ) -> Self {
694 match addr {
695 AddrZ::Base { addr, offset } => Self {
696 addr: addr.into(),
697 offset,
698 },
699 }
700 }
701}
702
703impl fmt::Display for AddrZ {
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705 match self {
706 AddrZ::Base { addr, offset } => {
707 let addr = RegNameDisplay(**addr);
708 write!(f, "{addr}, {offset}")
709 }
710 }
711 }
712}
713
714pub use super::super::lower::isle::generated_code::AddrG32;
715
716impl Copy for AddrG32 {}
717
718impl AddrG32 {
719 pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {
721 match self {
722 AddrG32::RegisterBound {
723 host_heap_base,
724 host_heap_bound,
725 wasm_addr,
726 offset: _,
727 } => {
728 collector.reg_use(host_heap_base);
729 collector.reg_use(host_heap_bound);
730 collector.reg_use(wasm_addr);
731 }
732 }
733 }
734}
735
736impl From<AddrG32> for pulley_interpreter::AddrG32 {
737 fn from(addr: AddrG32) -> Self {
738 match addr {
739 AddrG32::RegisterBound {
740 host_heap_base,
741 host_heap_bound,
742 wasm_addr,
743 offset,
744 } => Self {
745 host_heap_base: host_heap_base.into(),
746 host_heap_bound: host_heap_bound.into(),
747 wasm_addr: wasm_addr.into(),
748 offset,
749 },
750 }
751 }
752}
753
754impl fmt::Display for AddrG32 {
755 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
756 match self {
757 AddrG32::RegisterBound {
758 host_heap_base,
759 host_heap_bound,
760 wasm_addr,
761 offset,
762 } => {
763 let host_heap_base = RegNameDisplay(**host_heap_base);
764 let host_heap_bound = RegNameDisplay(**host_heap_bound);
765 let wasm_addr = RegNameDisplay(**wasm_addr);
766 write!(
767 f,
768 "{host_heap_base}, {host_heap_bound}, {wasm_addr}, {offset}",
769 )
770 }
771 }
772 }
773}
774
775pub use super::super::lower::isle::generated_code::AddrG32Bne;
776
777impl Copy for AddrG32Bne {}
778
779impl AddrG32Bne {
780 pub fn collect_operands(&mut self, collector: &mut impl OperandVisitor) {
782 match self {
783 AddrG32Bne::BoundNe {
784 host_heap_base,
785 host_heap_bound_addr,
786 host_heap_bound_offset: _,
787 wasm_addr,
788 offset: _,
789 } => {
790 collector.reg_use(host_heap_base);
791 collector.reg_use(host_heap_bound_addr);
792 collector.reg_use(wasm_addr);
793 }
794 }
795 }
796}
797
798impl From<AddrG32Bne> for pulley_interpreter::AddrG32Bne {
799 fn from(addr: AddrG32Bne) -> Self {
800 match addr {
801 AddrG32Bne::BoundNe {
802 host_heap_base,
803 host_heap_bound_addr,
804 host_heap_bound_offset,
805 wasm_addr,
806 offset,
807 } => Self {
808 host_heap_base: host_heap_base.into(),
809 host_heap_bound_addr: host_heap_bound_addr.into(),
810 host_heap_bound_offset,
811 wasm_addr: wasm_addr.into(),
812 offset,
813 },
814 }
815 }
816}
817
818impl fmt::Display for AddrG32Bne {
819 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
820 match self {
821 AddrG32Bne::BoundNe {
822 host_heap_base,
823 host_heap_bound_addr,
824 host_heap_bound_offset,
825 wasm_addr,
826 offset,
827 } => {
828 let host_heap_base = RegNameDisplay(**host_heap_base);
829 let host_heap_bound_addr = RegNameDisplay(**host_heap_bound_addr);
830 let wasm_addr = RegNameDisplay(**wasm_addr);
831 write!(
832 f,
833 "{host_heap_base}, \
834 *[{host_heap_bound_addr} + {host_heap_bound_offset}], \
835 {wasm_addr}, \
836 {offset}",
837 )
838 }
839 }
840 }
841}