1;; Instruction formats.
2(type MInst
3  (enum
4    ;; A no-op of zero size.
5    (Nop0)
6
7    ;; A no-op of size two bytes.
8    (Nop2)
9
10    ;; An ALU operation with two register sources and a register destination.
11    (AluRRR
12      (alu_op ALUOp)
13      (rd WritableReg)
14      (rn Reg)
15      (rm Reg))
16
17    ;; An ALU operation with a register source and a signed 16-bit
18    ;; immediate source, and a separate register destination.
19    (AluRRSImm16
20      (alu_op ALUOp)
21      (rd WritableReg)
22      (rn Reg)
23      (imm i16))
24
25    ;; An ALU operation with a register in-/out operand and
26    ;; a second register source.
27    (AluRR
28      (alu_op ALUOp)
29      (rd WritableReg)
30      ;; Input side of `rd`. `rd` is constrained to reuse `ri`'s
31      ;; allocation during regalloc. Hence, we have SSA form here (ri
32      ;; is strictly a use, rd is strictly a def) and it becomes a
33      ;; modified-reg form when encoded.
34      (ri Reg)
35      (rm Reg))
36
37    ;; An ALU operation with a register in-/out operand and
38    ;; a memory source.
39    (AluRX
40      (alu_op ALUOp)
41      (rd WritableReg)
42      (ri Reg)
43      (mem MemArg))
44
45    ;; An ALU operation with a register in-/out operand and a signed 16-bit
46    ;; immediate source.
47    (AluRSImm16
48      (alu_op ALUOp)
49      (rd WritableReg)
50      (ri Reg)
51      (imm i16))
52
53    ;; An ALU operation with a register in-/out operand and a signed 32-bit
54    ;; immediate source.
55    (AluRSImm32
56      (alu_op ALUOp)
57      (rd WritableReg)
58      (ri Reg)
59      (imm i32))
60
61    ;; An ALU operation with a register in-/out operand and an unsigned 32-bit
62    ;; immediate source.
63    (AluRUImm32
64      (alu_op ALUOp)
65      (rd WritableReg)
66      (ri Reg)
67      (imm u32))
68
69    ;; An ALU operation with a register in-/out operand and a shifted 16-bit
70    ;; immediate source.
71    (AluRUImm16Shifted
72      (alu_op ALUOp)
73      (rd WritableReg)
74      (ri Reg)
75      (imm UImm16Shifted))
76
77    ;; An ALU operation with a register in-/out operand and a shifted 32-bit
78    ;; immediate source.
79    (AluRUImm32Shifted
80      (alu_op ALUOp)
81      (rd WritableReg)
82      (ri Reg)
83      (imm UImm32Shifted))
84
85    ;; A multiply operation with two register sources and a register pair destination.
86    (SMulWide
87      (rd WritableRegPair)
88      (rn Reg)
89      (rm Reg))
90
91    ;; A multiply operation with an in/out register pair, and an extra register source.
92    ;; Only the lower half of the register pair is used as input.
93    (UMulWide
94      (rd WritableRegPair)
95      (ri Reg)
96      (rn Reg))
97
98    ;; A divide operation with an in/out register pair, and an extra register source.
99    ;; Only the lower half of the register pair is used as input.
100    (SDivMod32
101      (rd WritableRegPair)
102      (ri Reg)
103      (rn Reg))
104    (SDivMod64
105      (rd WritableRegPair)
106      (ri Reg)
107      (rn Reg))
108
109    ;; A divide operation with an in/out register pair, and an extra register source.
110    (UDivMod32
111      (rd WritableRegPair)
112      (ri RegPair)
113      (rn Reg))
114    (UDivMod64
115      (rd WritableRegPair)
116      (ri RegPair)
117      (rn Reg))
118
119    ;; A FLOGR operation with a register source and a register pair destination.
120    (Flogr
121      (rd WritableRegPair)
122      (rn Reg))
123
124    ;; A shift instruction with a register source, a register destination,
125    ;; and an immediate plus an optional register as shift count.
126    (ShiftRR
127      (shift_op ShiftOp)
128      (rd WritableReg)
129      (rn Reg)
130      (shift_imm u8)
131      (shift_reg Reg))
132
133    ;; A rotate-then-<op>-selected-bits instruction with a register
134    ;; in/out-operand, another register source, and three immediates.
135    (RxSBG
136        (op RxSBGOp)
137        (rd WritableReg)
138        (ri Reg)
139        (rn Reg)
140        (start_bit u8)
141        (end_bit u8)
142        (rotate_amt i8))
143
144    ;; The test-only version of RxSBG, which does not modify any register
145    ;; but only sets the condition code.
146    (RxSBGTest
147        (op RxSBGOp)
148        (rd Reg)
149        (rn Reg)
150        (start_bit u8)
151        (end_bit u8)
152        (rotate_amt i8))
153
154    ;; An unary operation with a register source and a register destination.
155    (UnaryRR
156      (op UnaryOp)
157      (rd WritableReg)
158      (rn Reg))
159
160    ;; A compare operation with two register sources.
161    (CmpRR
162      (op CmpOp)
163      (rn Reg)
164      (rm Reg))
165
166    ;; A compare operation with a register source and a memory source.
167    (CmpRX
168      (op CmpOp)
169      (rn Reg)
170      (mem MemArg))
171
172    ;; A compare operation with a register source and a signed 16-bit
173    ;; immediate source.
174    (CmpRSImm16
175      (op CmpOp)
176      (rn Reg)
177      (imm i16))
178
179    ;; A compare operation with a register source and a signed 32-bit
180    ;; immediate source.
181    (CmpRSImm32
182      (op CmpOp)
183      (rn Reg)
184      (imm i32))
185
186    ;; A compare operation with a register source and a unsigned 32-bit
187    ;; immediate source.
188    (CmpRUImm32
189      (op CmpOp)
190      (rn Reg)
191      (imm u32))
192
193    ;; A compare-and-trap instruction with two register sources.
194    (CmpTrapRR
195      (op CmpOp)
196      (rn Reg)
197      (rm Reg)
198      (cond Cond)
199      (trap_code TrapCode))
200
201    ;; A compare-and-trap operation with a register source and a signed 16-bit
202    ;; immediate source.
203    (CmpTrapRSImm16
204      (op CmpOp)
205      (rn Reg)
206      (imm i16)
207      (cond Cond)
208      (trap_code TrapCode))
209
210    ;; A compare-and-trap operation with a register source and an unsigned 16-bit
211    ;; immediate source.
212    (CmpTrapRUImm16
213      (op CmpOp)
214      (rn Reg)
215      (imm u16)
216      (cond Cond)
217      (trap_code TrapCode))
218
219    ;; An atomic read-modify-write operation with a memory in-/out operand,
220    ;; a register destination, and a register source.
221    ;; a memory source.
222    (AtomicRmw
223      (alu_op ALUOp)
224      (rd WritableReg)
225      (rn Reg)
226      (mem MemArg))
227
228    ;; A 32-bit atomic compare-and-swap operation.
229    (AtomicCas32
230      (rd WritableReg)
231      (ri Reg)
232      (rn Reg)
233      (mem MemArg))
234
235    ;; A 64-bit atomic compare-and-swap operation.
236    (AtomicCas64
237      (rd WritableReg)
238      (ri Reg)
239      (rn Reg)
240      (mem MemArg))
241
242    ;; A memory fence operation.
243    (Fence)
244
245    ;; A 32-bit load.
246    (Load32
247      (rd WritableReg)
248      (mem MemArg))
249
250    ;; An unsigned (zero-extending) 8-bit to 32-bit load.
251    (Load32ZExt8
252      (rd WritableReg)
253      (mem MemArg))
254
255    ;; A signed (sign-extending) 8-bit to 32-bit load.
256    (Load32SExt8
257      (rd WritableReg)
258      (mem MemArg))
259
260    ;; An unsigned (zero-extending) 16-bit to 32-bit load.
261    (Load32ZExt16
262      (rd WritableReg)
263      (mem MemArg))
264
265    ;; A signed (sign-extending) 16-bit to 32-bit load.
266    (Load32SExt16
267      (rd WritableReg)
268      (mem MemArg))
269
270    ;; A 64-bit load.
271    (Load64
272      (rd WritableReg)
273      (mem MemArg))
274
275    ;; An unsigned (zero-extending) 8-bit to 64-bit load.
276    (Load64ZExt8
277      (rd WritableReg)
278      (mem MemArg))
279
280    ;; A signed (sign-extending) 8-bit to 64-bit load.
281    (Load64SExt8
282      (rd WritableReg)
283      (mem MemArg))
284
285    ;; An unsigned (zero-extending) 16-bit to 64-bit load.
286    (Load64ZExt16
287      (rd WritableReg)
288      (mem MemArg))
289
290    ;; A signed (sign-extending) 16-bit to 64-bit load.
291    (Load64SExt16
292      (rd WritableReg)
293      (mem MemArg))
294
295    ;; An unsigned (zero-extending) 32-bit to 64-bit load.
296    (Load64ZExt32
297      (rd WritableReg)
298      (mem MemArg))
299
300    ;; A signed (sign-extending) 32-bit to 64-bit load.
301    (Load64SExt32
302      (rd WritableReg)
303      (mem MemArg))
304
305    ;; A 16-bit byte-reversed load.
306    (LoadRev16
307      (rd WritableReg)
308      (mem MemArg))
309
310    ;; A 32-bit byte-reversed load.
311    (LoadRev32
312      (rd WritableReg)
313      (mem MemArg))
314
315    ;; A 64-bit byte-reversed load.
316    (LoadRev64
317      (rd WritableReg)
318      (mem MemArg))
319
320    ;; An 8-bit store.
321    (Store8
322      (rd Reg)
323      (mem MemArg))
324
325    ;; A 16-bit store.
326    (Store16
327      (rd Reg)
328      (mem MemArg))
329
330    ;; A 32-bit store.
331    (Store32
332      (rd Reg)
333      (mem MemArg))
334
335    ;; A 64-bit store.
336    (Store64
337      (rd Reg)
338      (mem MemArg))
339
340    ;; An 8-bit store of an immediate.
341    (StoreImm8
342      (imm u8)
343      (mem MemArg))
344
345    ;; A 16-bit store of an immediate.
346    (StoreImm16
347      (imm i16)
348      (mem MemArg))
349
350    ;; A 32-bit store of a sign-extended 16-bit immediate.
351    (StoreImm32SExt16
352      (imm i16)
353      (mem MemArg))
354
355    ;; A 64-bit store of a sign-extended 16-bit immediate.
356    (StoreImm64SExt16
357      (imm i16)
358      (mem MemArg))
359
360    ;; A 16-bit byte-reversed store.
361    (StoreRev16
362      (rd Reg)
363      (mem MemArg))
364
365    ;; A 32-bit byte-reversed store.
366    (StoreRev32
367      (rd Reg)
368      (mem MemArg))
369
370    ;; A 64-bit byte-reversed store.
371    (StoreRev64
372      (rd Reg)
373      (mem MemArg))
374
375    ;; A load-multiple instruction.
376    (LoadMultiple64
377      (rt WritableReg)
378      (rt2 WritableReg)
379      (mem MemArg))
380
381    ;; A store-multiple instruction.
382    (StoreMultiple64
383      (rt Reg)
384      (rt2 Reg)
385      (mem MemArg))
386
387    ;; A 32-bit move instruction.
388    (Mov32
389      (rd WritableReg)
390      (rm Reg))
391
392    ;; A 64-bit move instruction.
393    (Mov64
394      (rd WritableReg)
395      (rm Reg))
396
397    ;; Like `Mov64` but with a particular physical register source.
398    (MovPReg
399      (rd WritableReg)
400      (rm PReg))
401
402    ;; A 32-bit move instruction with a full 32-bit immediate.
403    (Mov32Imm
404      (rd WritableReg)
405      (imm u32))
406
407    ;; A 32-bit move instruction with a 16-bit signed immediate.
408    (Mov32SImm16
409      (rd WritableReg)
410      (imm i16))
411
412    ;; A 64-bit move instruction with a 16-bit signed immediate.
413    (Mov64SImm16
414      (rd WritableReg)
415      (imm i16))
416
417    ;; A 64-bit move instruction with a 32-bit signed immediate.
418    (Mov64SImm32
419      (rd WritableReg)
420      (imm i32))
421
422    ;; A 64-bit move instruction with a shifted 16-bit immediate.
423    (Mov64UImm16Shifted
424      (rd WritableReg)
425      (imm UImm16Shifted))
426
427    ;; A 64-bit move instruction with a shifted 32-bit immediate.
428    (Mov64UImm32Shifted
429      (rd WritableReg)
430      (imm UImm32Shifted))
431
432    ;; A 64-bit insert instruction with a shifted 16-bit immediate.
433    (Insert64UImm16Shifted
434      (rd WritableReg)
435      (ri Reg)
436      (imm UImm16Shifted))
437
438    ;; A 64-bit insert instruction with a shifted 32-bit immediate.
439    (Insert64UImm32Shifted
440      (rd WritableReg)
441      (ri Reg)
442      (imm UImm32Shifted))
443
444    ;; Load 32-bit access register into GPR.
445    (LoadAR
446      (rd WritableReg)
447      (ar u8))
448
449    ;; Insert 32-bit access register into low half of a GPR.
450    ;; (Identical operation to LoadAR, but considers rd to be use/def.)
451    (InsertAR
452      (rd WritableReg)
453      (ri Reg)
454      (ar u8))
455
456    ;; A sign- or zero-extend operation.
457    (Extend
458      (rd WritableReg)
459      (rn Reg)
460      (signed bool)
461      (from_bits u8)
462      (to_bits u8))
463
464    ;; A 32-bit conditional move instruction. `ri` is the value that's used if
465    ;; the conditional is true, `rm` is used otherwise.
466    (CMov32
467      (rd WritableReg)
468      (cond Cond)
469      (ri Reg)
470      (rm Reg))
471
472    ;; A 64-bit conditional move instruction.
473    (CMov64
474      (rd WritableReg)
475      (cond Cond)
476      (ri Reg)
477      (rm Reg))
478
479    ;; A 32-bit conditional move instruction with a 16-bit signed immediate.
480    (CMov32SImm16
481      (rd WritableReg)
482      (cond Cond)
483      (ri Reg)
484      (imm i16))
485
486    ;; A 64-bit conditional move instruction with a 16-bit signed immediate.
487    (CMov64SImm16
488      (rd WritableReg)
489      (cond Cond)
490      (ri Reg)
491      (imm i16))
492
493    ;; A 32-bit FPU move possibly implemented as vector instruction.
494    (FpuMove32
495      (rd WritableReg)
496      (rn Reg))
497
498    ;; A 64-bit FPU move possibly implemented as vector instruction.
499    (FpuMove64
500      (rd WritableReg)
501      (rn Reg))
502
503    ;; A 32-bit conditional move FPU instruction, possibly as vector instruction.
504    (FpuCMov32
505      (rd WritableReg)
506      (cond Cond)
507      (ri Reg)
508      (rm Reg))
509
510    ;; A 64-bit conditional move FPU instruction, possibly as vector instruction.
511    (FpuCMov64
512      (rd WritableReg)
513      (cond Cond)
514      (ri Reg)
515      (rm Reg))
516
517    ;; 1-op FPU instruction implemented as vector instruction with the W bit.
518    (FpuRR
519      (fpu_op FPUOp1)
520      (rd WritableReg)
521      (rn Reg))
522
523    ;; 2-op FPU instruction implemented as vector instruction with the W bit.
524    (FpuRRR
525      (fpu_op FPUOp2)
526      (rd WritableReg)
527      (rn Reg)
528      (rm Reg))
529
530    ;; 3-op FPU instruction implemented as vector instruction with the W bit.
531    (FpuRRRR
532      (fpu_op FPUOp3)
533      (rd WritableReg)
534      (rn Reg)
535      (rm Reg)
536      (ra Reg))
537
538    ;; 1-op FPU instruction with rounding mode.
539    (FpuRound
540      (op FpuRoundOp)
541      (mode FpuRoundMode)
542      (rd WritableReg)
543      (rn Reg))
544
545    ;; FPU comparison, single-precision (32 bit).
546    (FpuCmp32
547      (rn Reg)
548      (rm Reg))
549
550    ;; FPU comparison, double-precision (64 bit).
551    (FpuCmp64
552      (rn Reg)
553      (rm Reg))
554
555    ;; FPU comparison, extended-precision (128 bit).
556    (FpuCmp128
557      (rn Reg)
558      (rm Reg))
559
560    ;; FPU integer to extended-precision conversion using FP reg pair.
561    (FpuConv128FromInt
562      (op FpuConv128Op)
563      (mode FpuRoundMode)
564      (rd WritableRegPair)
565      (rn Reg))
566
567    ;; FPU extended-precision to integer conversion using FP reg pair.
568    (FpuConv128ToInt
569      (op FpuConv128Op)
570      (mode FpuRoundMode)
571      (rd WritableReg)
572      (rn RegPair))
573
574    ;; A binary vector operation with two vector register sources.
575    (VecRRR
576      (op VecBinaryOp)
577      (rd WritableReg)
578      (rn Reg)
579      (rm Reg))
580
581    ;; A unary vector operation with a vector register source.
582    (VecRR
583      (op VecUnaryOp)
584      (rd WritableReg)
585      (rn Reg))
586
587    ;; Vector shift instruction with a register source, a register destination,
588    ;; and an immediate plus an optional register as shift count.
589    (VecShiftRR
590      (shift_op VecShiftOp)
591      (rd WritableReg)
592      (rn Reg)
593      (shift_imm u8)
594      (shift_reg Reg))
595
596    ;; Vector select instruction.
597    (VecSelect
598      (rd WritableReg)
599      (rn Reg)
600      (rm Reg)
601      (ra Reg))
602
603    ;; Vector merge instruction.
604    (VecBlend
605      (rd WritableReg)
606      (rn Reg)
607      (rm Reg)
608      (ra Reg))
609
610    ;; Vector permute instruction.
611    (VecPermute
612      (rd WritableReg)
613      (rn Reg)
614      (rm Reg)
615      (ra Reg))
616
617    ;; Vector evaluate instruction.
618    (VecEvaluate
619      (imm u8)
620      (rd WritableReg)
621      (rn Reg)
622      (rm Reg)
623      (ra Reg))
624
625    ;; Vector permute doubleword immediate instruction.
626    (VecPermuteDWImm
627      (rd WritableReg)
628      (rn Reg)
629      (rm Reg)
630      (idx1 u8)
631      (idx2 u8))
632
633    ;; Vector integer comparison with two register sources and a register
634    ;; destination.
635    (VecIntCmp
636      (op VecIntCmpOp)
637      (rd WritableReg)
638      (rn Reg)
639      (rm Reg))
640
641    ;; Same, but also set the condition code.
642    (VecIntCmpS
643      (op VecIntCmpOp)
644      (rd WritableReg)
645      (rn Reg)
646      (rm Reg))
647
648    ;; Vector floating-point comparison with two register sources and a register
649    ;; destination.
650    (VecFloatCmp
651      (op VecFloatCmpOp)
652      (rd WritableReg)
653      (rn Reg)
654      (rm Reg))
655
656    ;; Same, but also set the condition code.
657    (VecFloatCmpS
658      (op VecFloatCmpOp)
659      (rd WritableReg)
660      (rn Reg)
661      (rm Reg))
662
663    ;; Vector integer element comparison with two registers sources,
664    ;; setting the condition code.
665    (VecIntEltCmp
666      (op VecIntEltCmpOp)
667      (rn Reg)
668      (rm Reg))
669
670    ;; Synthetic instruction to compare signed 128-bit values.
671    ;; Sets CC 1 if rn > rm, sets a different CC otherwise.
672    (VecInt128SCmpHi
673      (tmp WritableReg)
674      (rn Reg)
675      (rm Reg))
676
677    ;; Synthetic instruction to compare unsigned 128-bit values.
678    ;; Sets CC 1 if rn > rm, sets a different CC otherwise.
679    (VecInt128UCmpHi
680      (tmp WritableReg)
681      (rn Reg)
682      (rm Reg))
683
684    ;; 128-bit vector load instruction.
685    (VecLoad
686      (rd WritableReg)
687      (mem MemArg))
688
689    ;; 128-bit byte-reversed vector load instruction.
690    (VecLoadRev
691      (rd WritableReg)
692      (mem MemArg))
693
694    ;; 8x16-bit byte-reversed vector load instruction.
695    (VecLoadByte16Rev
696      (rd WritableReg)
697      (mem MemArg))
698
699    ;; 4x32-bit byte-reversed vector load instruction.
700    (VecLoadByte32Rev
701      (rd WritableReg)
702      (mem MemArg))
703
704    ;; 2x64-bit byte-reversed vector load instruction.
705    (VecLoadByte64Rev
706      (rd WritableReg)
707      (mem MemArg))
708
709    ;; 8x16-bit element-reversed vector load instruction.
710    (VecLoadElt16Rev
711      (rd WritableReg)
712      (mem MemArg))
713
714    ;; 4x32-bit element-reversed vector load instruction.
715    (VecLoadElt32Rev
716      (rd WritableReg)
717      (mem MemArg))
718
719    ;; 2x64-bit element-reversed vector load instruction.
720    (VecLoadElt64Rev
721      (rd WritableReg)
722      (mem MemArg))
723
724    ;; 128-bit vector store instruction.
725    (VecStore
726      (rd Reg)
727      (mem MemArg))
728
729    ;; 128-bit byte-reversed vector store instruction.
730    (VecStoreRev
731      (rd Reg)
732      (mem MemArg))
733
734    ;; 8x16-bit byte-reversed vector store instruction.
735    (VecStoreByte16Rev
736      (rd Reg)
737      (mem MemArg))
738
739    ;; 4x32-bit byte-reversed vector store instruction.
740    (VecStoreByte32Rev
741      (rd Reg)
742      (mem MemArg))
743
744    ;; 2x64-bit byte-reversed vector store instruction.
745    (VecStoreByte64Rev
746      (rd Reg)
747      (mem MemArg))
748
749    ;; 8x16-bit element-reversed vector store instruction.
750    (VecStoreElt16Rev
751      (rd Reg)
752      (mem MemArg))
753
754    ;; 4x32-bit element-reversed vector store instruction.
755    (VecStoreElt32Rev
756      (rd Reg)
757      (mem MemArg))
758
759    ;; 2x64-bit element-reversed vector store instruction.
760    (VecStoreElt64Rev
761      (rd Reg)
762      (mem MemArg))
763
764    ;; 128-bit vector load replicated element instruction.
765    (VecLoadReplicate
766      (size u32)
767      (rd WritableReg)
768      (mem MemArg))
769
770    ;; 128-bit byte-reversed vector load replicated element instruction.
771    (VecLoadReplicateRev
772      (size u32)
773      (rd WritableReg)
774      (mem MemArg))
775
776    ;; Vector move instruction.
777    (VecMov
778      (rd WritableReg)
779      (rn Reg))
780
781    ;; Conditional vector move instruction.
782    (VecCMov
783      (rd WritableReg)
784      (cond Cond)
785      (ri Reg)
786      (rm Reg))
787
788    ;; A 128-bit move instruction from two GPRs to a VR.
789    (MovToVec128
790      (rd WritableReg)
791      (rn Reg)
792      (rm Reg))
793
794    ;; Load vector immediate generated via byte mask.
795    (VecImmByteMask
796      (rd WritableReg)
797      (mask u16))
798
799    ;; Load vector replicated contiguous bit mask.
800    (VecImmBitMask
801      (size u32)
802      (rd WritableReg)
803      (start_bit u8)
804      (end_bit u8))
805
806    ;; Load vector replicated immediate.
807    (VecImmReplicate
808      (size u32)
809      (rd WritableReg)
810      (imm i16))
811
812    ;; Vector lane insertion with an in/out VR, a memory source,
813    ;; and an immediate as lane index.
814    (VecLoadLane
815      (size u32)
816      (rd WritableReg)
817      (ri Reg)
818      (mem MemArg)
819      (lane_imm u8))
820
821    ;; Same as VecLoadLane, but allow undefined input VR.
822    (VecLoadLaneUndef
823      (size u32)
824      (rd WritableReg)
825      (mem MemArg)
826      (lane_imm u8))
827
828    ;; Byte-reversed vector lane insertion with an in/out VR, a memory source,
829    ;; and an immediate as lane index.
830    (VecLoadLaneRev
831      (size u32)
832      (rd WritableReg)
833      (ri Reg)
834      (mem MemArg)
835      (lane_imm u8))
836
837    ;; Same as VecLoadLaneRev, but allow undefined input VR.
838    (VecLoadLaneRevUndef
839      (size u32)
840      (rd WritableReg)
841      (mem MemArg)
842      (lane_imm u8))
843
844    ;; Vector lane extraction with a memory destination, a VR source,
845    ;; and an immediate as lane index.
846    (VecStoreLane
847      (size u32)
848      (rd Reg)
849      (mem MemArg)
850      (lane_imm u8))
851
852    ;; Byte-reversed vector lane extraction with a memory destination, a VR source,
853    ;; and an immediate as lane index.
854    (VecStoreLaneRev
855      (size u32)
856      (rd Reg)
857      (mem MemArg)
858      (lane_imm u8))
859
860    ;; Vector lane insertion with an in/out VR, a GPR source,
861    ;; and an immediate plus an optional register as lane index.
862    (VecInsertLane
863      (size u32)
864      (rd WritableReg)
865      (ri Reg)
866      (rn Reg)
867      (lane_imm u8)
868      (lane_reg Reg))
869
870    ;; Same as VecInsertLane, but allow undefined input VR.
871    (VecInsertLaneUndef
872      (size u32)
873      (rd WritableReg)
874      (rn Reg)
875      (lane_imm u8)
876      (lane_reg Reg))
877
878    ;; Vector lane extraction with a VR source, a GPR destination,
879    ;; and an immediate plus an optional register as lane index.
880    (VecExtractLane
881      (size u32)
882      (rd WritableReg)
883      (rn Reg)
884      (lane_imm u8)
885      (lane_reg Reg))
886
887    ;; Vector lane insertion with an in/out VR, an immediate source,
888    ;; and an immediate as lane index.
889    (VecInsertLaneImm
890      (size u32)
891      (rd WritableReg)
892      (ri Reg)
893      (imm i16)
894      (lane_imm u8))
895
896    ;; Same as VecInsertLaneImm, but allow undefined input VR.
897    (VecInsertLaneImmUndef
898      (size u32)
899      (rd WritableReg)
900      (imm i16)
901      (lane_imm u8))
902
903    ;; Vector lane replication with a VR source, a VR destination,
904    ;; and an immediate as lane index.
905    (VecReplicateLane
906      (size u32)
907      (rd WritableReg)
908      (rn Reg)
909      (lane_imm u8))
910
911    ;; Synthetic instruction to reverse vector elements in-register.
912    (VecEltRev
913      (lane_count u32)
914      (rd WritableReg)
915      (rn Reg))
916
917    ;; Allocate stack space for outgoing tail-call arguments.
918    (AllocateArgs
919      (size u32))
920
921    ;; A machine call instruction (direct or indirect).
922    (Call
923      (link WritableReg)
924      (info BoxCallInfo))
925
926    ;; A machine tail call instruction (direct or indirect).
927    (ReturnCall
928      (info BoxReturnCallInfo))
929
930    ;; A pseudo-instruction that captures register arguments in vregs.
931    (Args
932      (args VecArgPair))
933
934    ;; A pseudo-instruction that moves vregs to return registers.
935    (Rets
936      (rets VecRetPair))
937
938    ;; ---- branches (exactly one must appear at end of BB) ----
939
940    ;; A machine return instruction.
941    (Ret
942      (link Reg))
943
944    ;; An unconditional branch.
945    (Jump
946      (dest MachLabel))
947
948    ;; A conditional branch. Contains two targets; at emission time, both are emitted, but
949    ;; the MachBuffer knows to truncate the trailing branch if fallthrough. We optimize the
950    ;; choice of taken/not_taken (inverting the branch polarity as needed) based on the
951    ;; fallthrough at the time of lowering.
952    (CondBr
953      (taken MachLabel)
954      (not_taken MachLabel)
955      (cond Cond))
956
957    ;; A conditional trap execute a `Trap` if the condition is true. This is
958    ;; one VCode instruction because it uses embedded control flow; it is
959    ;; logically a single-in, single-out region, but needs to appear as one
960    ;; unit to the register allocator.
961    ;;
962    ;; The `Cond` gives the conditional-branch condition that will
963    ;; *execute* the embedded `Trap`. (In the emitted code, we use the inverse
964    ;; of this condition in a branch that skips the trap instruction.)
965    (TrapIf
966      (cond Cond)
967      (trap_code TrapCode))
968
969    ;; An indirect branch through a register, augmented with set of all
970    ;; possible successors.
971    (IndirectBr
972      (rn Reg)
973      (targets VecMachLabel))
974
975    ;; A "debugtrap" instruction, used for e.g. traps and debug breakpoints.
976    (Debugtrap)
977
978    ;; An instruction guaranteed to always be undefined and to trigger an illegal instruction at
979    ;; runtime.
980    (Trap
981      (trap_code TrapCode))
982
983    ;; Jump-table sequence, as one compound instruction (see note in lower.rs
984    ;; for rationale).
985    (JTSequence
986      ;; The index into the list of targets.
987      (ridx Reg)
988      ;; The default target.
989      (default MachLabel)
990      ;; The condition for taking the default target, based on flags
991      ;; when this instruction executes.
992      (default_cond Cond)
993      ;; All other targets.
994      (targets BoxVecMachLabel))
995
996    ;; Stack probe loop sequence, as one compound instruction.
997    (StackProbeLoop
998      (probe_count WritableReg)
999      (guard_size i16))
1000
1001    ;; Load an inline symbol reference with relocation.
1002    (LoadSymbolReloc
1003      (rd WritableReg)
1004      (symbol_reloc BoxSymbolReloc))
1005
1006    ;; Load address referenced by `mem` into `rd`.
1007    (LoadAddr
1008      (rd WritableReg)
1009      (mem MemArg))
1010
1011    ;; Meta-instruction to emit a loop around a sequence of instructions.
1012    ;; This control flow is not visible to the compiler core, in particular
1013    ;; the register allocator.  Therefore, instructions in the loop may not
1014    ;; write to any virtual register, so any writes must use reserved hard
1015    ;; registers (e.g. %r0, %r1).  *Reading* virtual registers is OK.
1016    (Loop
1017      (body VecMInst)
1018      (cond Cond))
1019
1020    ;; Conditional branch breaking out of a loop emitted via Loop.
1021    (CondBreak
1022      (cond Cond))
1023
1024    ;; Pseudoinstruction to keep a value alive.
1025    (DummyUse
1026     (reg Reg))
1027
1028    ;; An unwind pseudoinstruction describing the state of the
1029    ;; machine at this program point.
1030    (Unwind
1031      (inst UnwindInst))
1032
1033    ;; Pseudo-instruction used for `tls_value` to call the libcall of the same
1034    ;; name.
1035    (ElfTlsGetOffset
1036      (tls_offset WritableReg)
1037      (got Reg)
1038      (got_offset Reg)
1039      (symbol BoxSymbolReloc))
1040
1041    ;; A pseudoinstruction that loads the address of a label.
1042    (LabelAddress (dst WritableReg)
1043                  (label MachLabel))
1044
1045    ;; A pseudoinstruction that serves as a sequence point.
1046    (SequencePoint)
1047))
1048
1049;; Primitive types used in instruction formats.
1050
1051(type CallInstDest (primitive CallInstDest))
1052(type BoxCallInfo (primitive BoxCallInfo))
1053(type BoxReturnCallInfo (primitive BoxReturnCallInfo))
1054(type BoxJTSequenceInfo (primitive BoxJTSequenceInfo))
1055(type VecMachLabel extern (enum))
1056
1057(decl call_inst_dest_direct (ExternalName) CallInstDest)
1058(extern constructor call_inst_dest_direct call_inst_dest_direct)
1059(convert ExternalName CallInstDest call_inst_dest_direct)
1060
1061(decl call_inst_dest_indirect (Reg) CallInstDest)
1062(extern constructor call_inst_dest_indirect call_inst_dest_indirect)
1063(convert Reg CallInstDest call_inst_dest_indirect)
1064
1065;; A symbol reference carrying relocation information.
1066(type SymbolReloc
1067  (enum
1068    ;; Absolute symbol reference (with optional offset).
1069    (Absolute
1070      (name ExternalName)
1071      (offset i64))
1072    ;; Reference to a TLS symbol in general-dynamic mode.
1073    (TlsGd
1074      (name ExternalName))))
1075
1076;; Boxed version of SymbolReloc to save space.
1077(type BoxSymbolReloc (primitive BoxSymbolReloc))
1078(decl box_symbol_reloc (SymbolReloc) BoxSymbolReloc)
1079(extern constructor box_symbol_reloc box_symbol_reloc)
1080(convert SymbolReloc BoxSymbolReloc box_symbol_reloc)
1081
1082;; An ALU operation.
1083(type ALUOp
1084  (enum
1085    (Add32)
1086    (Add32Ext16)
1087    (Add64)
1088    (Add64Ext16)
1089    (Add64Ext32)
1090    (AddLogical32)
1091    (AddLogical64)
1092    (AddLogical64Ext32)
1093    (Sub32)
1094    (Sub32Ext16)
1095    (Sub64)
1096    (Sub64Ext16)
1097    (Sub64Ext32)
1098    (SubLogical32)
1099    (SubLogical64)
1100    (SubLogical64Ext32)
1101    (Mul32)
1102    (Mul32Ext16)
1103    (Mul64)
1104    (Mul64Ext16)
1105    (Mul64Ext32)
1106    (And32)
1107    (And64)
1108    (Orr32)
1109    (Orr64)
1110    (Xor32)
1111    (Xor64)
1112    ;; NAND
1113    (NotAnd32)
1114    (NotAnd64)
1115    ;; NOR
1116    (NotOrr32)
1117    (NotOrr64)
1118    ;; XNOR
1119    (NotXor32)
1120    (NotXor64)
1121    ;; And with complement
1122    (AndNot32)
1123    (AndNot64)
1124    ;; Or with complement
1125    (OrrNot32)
1126    (OrrNot64)
1127))
1128
1129;; A unary operation.
1130(type UnaryOp
1131  (enum
1132    (Abs32)
1133    (Abs64)
1134    (Abs64Ext32)
1135    (Neg32)
1136    (Neg64)
1137    (Neg64Ext32)
1138    (PopcntByte)
1139    (PopcntReg)
1140    (BSwap32)
1141    (BSwap64)
1142    (Clz64)
1143    (Ctz64)
1144))
1145
1146;; A shift operation.
1147(type ShiftOp
1148  (enum
1149    (RotL32)
1150    (RotL64)
1151    (LShL32)
1152    (LShL64)
1153    (LShR32)
1154    (LShR64)
1155    (AShR32)
1156    (AShR64)
1157))
1158
1159;; A rotate-then-<op>-selected-bits operation.
1160(type RxSBGOp
1161  (enum
1162    (Insert)
1163    (And)
1164    (Or)
1165    (Xor)
1166))
1167
1168;; An integer comparison operation.
1169(type CmpOp
1170  (enum
1171    (CmpS32)
1172    (CmpS32Ext16)
1173    (CmpS64)
1174    (CmpS64Ext16)
1175    (CmpS64Ext32)
1176    (CmpL32)
1177    (CmpL32Ext16)
1178    (CmpL64)
1179    (CmpL64Ext16)
1180    (CmpL64Ext32)
1181))
1182
1183;; A binary vector operation.
1184(type VecBinaryOp
1185  (enum
1186    ;; Addition and subtraction
1187    (Add8x16)
1188    (Add16x8)
1189    (Add32x4)
1190    (Add64x2)
1191    (Add128)
1192    (Sub8x16)
1193    (Sub16x8)
1194    (Sub32x4)
1195    (Sub64x2)
1196    (Sub128)
1197    ;; Multiplication
1198    (Mul8x16)
1199    (Mul16x8)
1200    (Mul32x4)
1201    (Mul64x2)
1202    (Mul128)
1203    (UMulHi8x16)
1204    (UMulHi16x8)
1205    (UMulHi32x4)
1206    (UMulHi64x2)
1207    (UMulHi128)
1208    (SMulHi8x16)
1209    (SMulHi16x8)
1210    (SMulHi32x4)
1211    (SMulHi64x2)
1212    (SMulHi128)
1213    (UMulEven8x16)
1214    (UMulEven16x8)
1215    (UMulEven32x4)
1216    (UMulEven64x2)
1217    (SMulEven8x16)
1218    (SMulEven16x8)
1219    (SMulEven32x4)
1220    (SMulEven64x2)
1221    (UMulOdd8x16)
1222    (UMulOdd16x8)
1223    (UMulOdd32x4)
1224    (UMulOdd64x2)
1225    (SMulOdd8x16)
1226    (SMulOdd16x8)
1227    (SMulOdd32x4)
1228    (SMulOdd64x2)
1229    ;; Division and remainder
1230    (UDiv32x4)
1231    (UDiv64x2)
1232    (UDiv128)
1233    (URem32x4)
1234    (URem64x2)
1235    (URem128)
1236    (SDiv32x4)
1237    (SDiv64x2)
1238    (SDiv128)
1239    (SRem32x4)
1240    (SRem64x2)
1241    (SRem128)
1242    ;; Minimum, maximum, and average
1243    (UMax8x16)
1244    (UMax16x8)
1245    (UMax32x4)
1246    (UMax64x2)
1247    (UMax128)
1248    (SMax8x16)
1249    (SMax16x8)
1250    (SMax32x4)
1251    (SMax64x2)
1252    (SMax128)
1253    (UMin8x16)
1254    (UMin16x8)
1255    (UMin32x4)
1256    (UMin64x2)
1257    (UMin128)
1258    (SMin8x16)
1259    (SMin16x8)
1260    (SMin32x4)
1261    (SMin64x2)
1262    (SMin128)
1263    (UAvg8x16)
1264    (UAvg16x8)
1265    (UAvg32x4)
1266    (UAvg64x2)
1267    (UAvg128)
1268    (SAvg8x16)
1269    (SAvg16x8)
1270    (SAvg32x4)
1271    (SAvg64x2)
1272    (SAvg128)
1273    ;; Bitwise operations
1274    (And128)
1275    (Orr128)
1276    (Xor128)
1277    (NotAnd128)
1278    (NotOrr128)
1279    (NotXor128)
1280    (AndNot128)
1281    (OrrNot128)
1282    ;; Bit permute
1283    (BitPermute128)
1284    ;; Full vector shift operations
1285    (LShLByByte128)
1286    (LShRByByte128)
1287    (AShRByByte128)
1288    (LShLByBit128)
1289    (LShRByBit128)
1290    (AShRByBit128)
1291    ;; Pack
1292    (Pack16x8)
1293    (Pack32x4)
1294    (Pack64x2)
1295    ;; Pack saturate (unsigned)
1296    (PackUSat16x8)
1297    (PackUSat32x4)
1298    (PackUSat64x2)
1299    ;; Pack saturate (signed)
1300    (PackSSat16x8)
1301    (PackSSat32x4)
1302    (PackSSat64x2)
1303    ;; Merge
1304    (MergeLow8x16)
1305    (MergeLow16x8)
1306    (MergeLow32x4)
1307    (MergeLow64x2)
1308    (MergeHigh8x16)
1309    (MergeHigh16x8)
1310    (MergeHigh32x4)
1311    (MergeHigh64x2)
1312))
1313
1314;; A vector unary operation.
1315(type VecUnaryOp
1316  (enum
1317    ;; Sign operations
1318    (Abs8x16)
1319    (Abs16x8)
1320    (Abs32x4)
1321    (Abs64x2)
1322    (Abs128)
1323    (Neg8x16)
1324    (Neg16x8)
1325    (Neg32x4)
1326    (Neg64x2)
1327    (Neg128)
1328    ;; Population count
1329    (Popcnt8x16)
1330    (Popcnt16x8)
1331    (Popcnt32x4)
1332    (Popcnt64x2)
1333    ;; Count leading/trailing zeros
1334    (Clz8x16)
1335    (Clz16x8)
1336    (Clz32x4)
1337    (Clz64x2)
1338    (Clz128)
1339    (Ctz8x16)
1340    (Ctz16x8)
1341    (Ctz32x4)
1342    (Ctz64x2)
1343    (Ctz128)
1344    ;; Unpack
1345    (UnpackULow8x16)
1346    (UnpackULow16x8)
1347    (UnpackULow32x4)
1348    (UnpackULow64x2)
1349    (UnpackUHigh8x16)
1350    (UnpackUHigh16x8)
1351    (UnpackUHigh32x4)
1352    (UnpackUHigh64x2)
1353    (UnpackSLow8x16)
1354    (UnpackSLow16x8)
1355    (UnpackSLow32x4)
1356    (UnpackSLow64x2)
1357    (UnpackSHigh8x16)
1358    (UnpackSHigh16x8)
1359    (UnpackSHigh32x4)
1360    (UnpackSHigh64x2)
1361))
1362
1363;; A vector shift operation.
1364(type VecShiftOp
1365  (enum
1366    (RotL8x16)
1367    (RotL16x8)
1368    (RotL32x4)
1369    (RotL64x2)
1370    (LShL8x16)
1371    (LShL16x8)
1372    (LShL32x4)
1373    (LShL64x2)
1374    (LShR8x16)
1375    (LShR16x8)
1376    (LShR32x4)
1377    (LShR64x2)
1378    (AShR8x16)
1379    (AShR16x8)
1380    (AShR32x4)
1381    (AShR64x2)
1382))
1383
1384;; An integer vector comparison operation.
1385(type VecIntCmpOp
1386  (enum
1387    (CmpEq8x16)
1388    (CmpEq16x8)
1389    (CmpEq32x4)
1390    (CmpEq64x2)
1391    (CmpEq128)
1392    (SCmpHi8x16)
1393    (SCmpHi16x8)
1394    (SCmpHi32x4)
1395    (SCmpHi64x2)
1396    (SCmpHi128)
1397    (UCmpHi8x16)
1398    (UCmpHi16x8)
1399    (UCmpHi32x4)
1400    (UCmpHi64x2)
1401    (UCmpHi128)
1402))
1403
1404;; An integer vector element comparison operation.
1405(type VecIntEltCmpOp
1406  (enum
1407    (SCmp128)
1408    (UCmp128)
1409));
1410
1411;; A floating-point vector comparison operation.
1412(type VecFloatCmpOp
1413  (enum
1414    (CmpEq32x4)
1415    (CmpEq64x2)
1416    (CmpHi32x4)
1417    (CmpHi64x2)
1418    (CmpHiEq32x4)
1419    (CmpHiEq64x2)
1420))
1421
1422;; A floating-point unit (FPU) operation with one arg.
1423(type FPUOp1
1424  (enum
1425    (Abs32)
1426    (Abs64)
1427    (Abs128)
1428    (Abs32x4)
1429    (Abs64x2)
1430    (Neg32)
1431    (Neg64)
1432    (Neg128)
1433    (Neg32x4)
1434    (Neg64x2)
1435    (NegAbs32)
1436    (NegAbs64)
1437    (NegAbs128)
1438    (NegAbs32x4)
1439    (NegAbs64x2)
1440    (Sqrt32)
1441    (Sqrt64)
1442    (Sqrt128)
1443    (Sqrt32x4)
1444    (Sqrt64x2)
1445    (Cvt32To64)
1446    (Cvt32x4To64x2)
1447    (Cvt64To128)
1448))
1449
1450;; A floating-point unit (FPU) operation with two args.
1451(type FPUOp2
1452  (enum
1453    (Add32)
1454    (Add64)
1455    (Add128)
1456    (Add32x4)
1457    (Add64x2)
1458    (Sub32)
1459    (Sub64)
1460    (Sub128)
1461    (Sub32x4)
1462    (Sub64x2)
1463    (Mul32)
1464    (Mul64)
1465    (Mul128)
1466    (Mul32x4)
1467    (Mul64x2)
1468    (Div32)
1469    (Div64)
1470    (Div128)
1471    (Div32x4)
1472    (Div64x2)
1473    (Max32)
1474    (Max64)
1475    (Max128)
1476    (Max32x4)
1477    (Max64x2)
1478    (Min32)
1479    (Min64)
1480    (Min128)
1481    (Min32x4)
1482    (Min64x2)
1483    (MaxPseudo32)
1484    (MaxPseudo64)
1485    (MaxPseudo128)
1486    (MaxPseudo32x4)
1487    (MaxPseudo64x2)
1488    (MinPseudo32)
1489    (MinPseudo64)
1490    (MinPseudo128)
1491    (MinPseudo32x4)
1492    (MinPseudo64x2)
1493))
1494
1495;; A floating-point unit (FPU) operation with three args.
1496(type FPUOp3
1497  (enum
1498    (MAdd32)
1499    (MAdd64)
1500    (MAdd128)
1501    (MAdd32x4)
1502    (MAdd64x2)
1503    (MSub32)
1504    (MSub64)
1505    (MSub128)
1506    (MSub32x4)
1507    (MSub64x2)
1508))
1509
1510;; A floating-point unit (FPU) operation with one arg, and rounding mode.
1511(type FpuRoundOp
1512  (enum
1513    (Cvt64To32)
1514    (Cvt64x2To32x4)
1515    (Cvt128To64)
1516    (Round32)
1517    (Round64)
1518    (Round128)
1519    (Round32x4)
1520    (Round64x2)
1521    (ToSInt32)
1522    (ToSInt64)
1523    (ToUInt32)
1524    (ToUInt64)
1525    (ToSInt32x4)
1526    (ToSInt64x2)
1527    (ToUInt32x4)
1528    (ToUInt64x2)
1529    (FromSInt32)
1530    (FromSInt64)
1531    (FromUInt32)
1532    (FromUInt64)
1533    (FromSInt32x4)
1534    (FromSInt64x2)
1535    (FromUInt32x4)
1536    (FromUInt64x2)
1537))
1538
1539;; An extended-precision vs. integer conversion operation.
1540(type FpuConv128Op
1541  (enum
1542    (SInt32)
1543    (UInt32)
1544    (SInt64)
1545    (UInt64)
1546))
1547
1548;; Rounding modes for floating-point ops.
1549(type FpuRoundMode
1550  (enum
1551    (Current)
1552    (ToNearest)
1553    (ShorterPrecision)
1554    (ToNearestTiesToEven)
1555    (ToZero)
1556    (ToPosInfinity)
1557    (ToNegInfinity)
1558))
1559
1560
1561;; Helpers for querying enabled ISA extensions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1562
1563(decl mie3_enabled () Type)
1564(extern extractor mie3_enabled mie3_enabled)
1565(decl mie3_disabled () Type)
1566(extern extractor mie3_disabled mie3_disabled)
1567(decl mie4_enabled () Type)
1568(extern extractor mie4_enabled mie4_enabled)
1569(decl mie4_disabled () Type)
1570(extern extractor mie4_disabled mie4_disabled)
1571
1572(decl vxrs_ext2_enabled () Type)
1573(extern extractor vxrs_ext2_enabled vxrs_ext2_enabled)
1574(decl vxrs_ext2_disabled () Type)
1575(extern extractor vxrs_ext2_disabled vxrs_ext2_disabled)
1576(decl vxrs_ext3_enabled () Type)
1577(extern extractor vxrs_ext3_enabled vxrs_ext3_enabled)
1578(decl vxrs_ext3_disabled () Type)
1579(extern extractor vxrs_ext3_disabled vxrs_ext3_disabled)
1580
1581;; Helpers for SIMD lane number operations ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1582
1583;; There are two ways to map vector types onto the SIMD vector registers
1584;; supported by the ISA, differing by the way lanes are numbered.  In
1585;; little-endian lane order, lane 0 of a multi-lane vector value resides
1586;; in the least-significant parts of a vector register (when interpreted
1587;; as holding a single $I128 value); in big-endian lane order, lane 0
1588;; instead resides in the most-significant parts of the register.
1589;;
1590;; As long as used consistently, output of cranelift may use either lane
1591;; order method to implement CLIF semantics.  However, depending on the
1592;; particular use case, one or the other order will lead to more efficient
1593;; code.  Therefore this back end supports both code generation options.
1594;;
1595;; Note that the ISA instructions use immediate lane number according
1596;; to big-endian lane order; so when using little-endian lane order,
1597;; immediate lane numbers have to be translated.
1598(type LaneOrder
1599  (enum
1600    (LittleEndian)
1601    (BigEndian)))
1602
1603;; Return the lane order to be used when compiling the current function.
1604;; This will be a property of the function ABI.  Functions using the
1605;; the Wasmtime ABI will use little-endian lane order, functions using
1606;; other ABIs will big-endian lane order.
1607(decl pure lane_order () LaneOrder)
1608(extern constructor lane_order lane_order)
1609
1610;; Check whether two lane order values are equal.
1611(decl pure lane_order_equal (LaneOrder LaneOrder) bool)
1612(rule (lane_order_equal (LaneOrder.LittleEndian) (LaneOrder.LittleEndian)) true)
1613(rule (lane_order_equal (LaneOrder.LittleEndian) (LaneOrder.BigEndian)) false)
1614(rule (lane_order_equal (LaneOrder.BigEndian) (LaneOrder.LittleEndian)) false)
1615(rule (lane_order_equal (LaneOrder.BigEndian) (LaneOrder.BigEndian)) true)
1616
1617;; Return lane order matching memory byte order.
1618(decl pure lane_order_from_memflags (MemFlags) LaneOrder)
1619(rule 0 (lane_order_from_memflags (littleendian)) (LaneOrder.LittleEndian))
1620(rule 1 (lane_order_from_memflags (bigendian)) (LaneOrder.BigEndian))
1621
1622;; Convert a CLIF immediate lane index value to big-endian lane order.
1623(decl be_lane_idx (Type u8) u8)
1624(extern constructor be_lane_idx be_lane_idx)
1625
1626;; Convert a CLIF immediate vector constant to big-endian lane order.
1627(decl be_vec_const (Type u128) u128)
1628(extern constructor be_vec_const be_vec_const)
1629
1630
1631;; Helpers for register numbers and types ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1632
1633;; Hard-coded registers.
1634(decl writable_gpr (u8) WritableReg)
1635(extern constructor writable_gpr writable_gpr)
1636
1637;; The zero register.
1638(decl zero_reg () Reg)
1639(extern constructor zero_reg zero_reg)
1640
1641;; Types that can be operated on using 32-bit GPR instructions
1642(decl gpr32_ty (Type) Type)
1643(extern extractor gpr32_ty gpr32_ty)
1644
1645;; Types that can be operated on using 64-bit GPR instructions
1646(decl gpr64_ty (Type) Type)
1647(extern extractor gpr64_ty gpr64_ty)
1648
1649;; Types that can be operated on using 128-bit vector instructions
1650(decl vr128_ty (Type) Type)
1651(extern extractor vr128_ty vr128_ty)
1652
1653
1654;; Helpers for various immediate constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1655
1656;; Special integer types and their constructors
1657
1658(type UImm32Shifted (primitive UImm32Shifted))
1659(decl uimm32shifted (u32 u8) UImm32Shifted)
1660(extern constructor uimm32shifted uimm32shifted)
1661
1662(type UImm16Shifted (primitive UImm16Shifted))
1663(decl uimm16shifted (u16 u8) UImm16Shifted)
1664(extern constructor uimm16shifted uimm16shifted)
1665
1666;; Detect specific integer values
1667
1668(decl pure partial i64_nonequal (i64 i64) i64)
1669(extern constructor i64_nonequal i64_nonequal)
1670
1671(decl pure partial i64_not_neg1 (i64) i64)
1672(rule (i64_not_neg1 x)
1673      (if (i64_nonequal x -1))
1674      x)
1675
1676;; Construct and extract immediate vector constants.
1677
1678(decl u64_pair (u64 u64) u128)
1679(extern constructor u64_pair u64_pair_concat)
1680(extern extractor infallible u64_pair u64_pair_split)
1681
1682(decl u32_pair (u32 u32) u64)
1683(extern constructor u32_pair u32_pair_concat)
1684(extern extractor infallible u32_pair u32_pair_split)
1685
1686(decl u16_pair (u16 u16) u32)
1687(extern constructor u16_pair u16_pair_concat)
1688(extern extractor infallible u16_pair u16_pair_split)
1689
1690(decl u8_pair (u8 u8) u16)
1691(extern constructor u8_pair u8_pair_concat)
1692(extern extractor infallible u8_pair u8_pair_split)
1693
1694(decl imm8x16 (u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8 u8) u128)
1695(extractor (imm8x16 a b c d e f g h i j k l m n o p)
1696           (u64_pair (u32_pair (u16_pair (u8_pair a b) (u8_pair c d))
1697                               (u16_pair (u8_pair e f) (u8_pair g h)))
1698                     (u32_pair (u16_pair (u8_pair i j) (u8_pair k l))
1699                               (u16_pair (u8_pair m n) (u8_pair o p)))))
1700(rule      (imm8x16 a b c d e f g h i j k l m n o p)
1701           (u64_pair (u32_pair (u16_pair (u8_pair a b) (u8_pair c d))
1702                               (u16_pair (u8_pair e f) (u8_pair g h)))
1703                     (u32_pair (u16_pair (u8_pair i j) (u8_pair k l))
1704                               (u16_pair (u8_pair m n) (u8_pair o p)))))
1705
1706;; Construct a VGBM mask to set all bits in one lane of a vector.
1707
1708(decl lane_byte_mask (Type u8) u16)
1709(extern constructor lane_byte_mask lane_byte_mask)
1710
1711;; Extract "permute" and "and" masks from a shuffle constant
1712
1713(decl shuffle_mask_from_u128 (u128 u16) u128)
1714(extern extractor infallible shuffle_mask_from_u128 shuffle_mask_from_u128)
1715
1716(decl shuffle_mask (u128 u16) Immediate)
1717(extractor (shuffle_mask permute_mask and_mask)
1718           (u128_from_immediate (shuffle_mask_from_u128 permute_mask and_mask)))
1719
1720;; Split an u64 into high and low parts.
1721
1722(decl u64_nonzero_hipart (u64) u64)
1723(extern extractor u64_nonzero_hipart u64_nonzero_hipart)
1724
1725(decl u64_nonzero_lopart (u64) u64)
1726(extern extractor u64_nonzero_lopart u64_nonzero_lopart)
1727
1728;; Extract smaller integer type from u64 if it matches.
1729
1730(decl uimm32shifted_from_u64 (UImm32Shifted) u64)
1731(extern extractor uimm32shifted_from_u64 uimm32shifted_from_u64)
1732
1733(decl uimm16shifted_from_u64 (UImm16Shifted) u64)
1734(extern extractor uimm16shifted_from_u64 uimm16shifted_from_u64)
1735
1736;; Extract integer of certain type from value if it matches.
1737
1738(decl u64_from_value (u64) Value)
1739(extern extractor u64_from_value u64_from_value)
1740
1741(decl u32_from_value (u32) Value)
1742(extern extractor u32_from_value u32_from_value)
1743
1744(decl u8_from_value (u8) Value)
1745(extern extractor u8_from_value u8_from_value)
1746
1747(decl u64_from_signed_value (u64) Value)
1748(extern extractor u64_from_signed_value u64_from_signed_value)
1749
1750(decl u64_from_inverted_value (u64) Value)
1751(extern extractor u64_from_inverted_value u64_from_inverted_value)
1752
1753(decl i64_from_value (i64) Value)
1754(extern extractor i64_from_value i64_from_value)
1755
1756(decl i32_from_value (i32) Value)
1757(extern extractor i32_from_value i32_from_value)
1758
1759(decl i16_from_value (i16) Value)
1760(extern extractor i16_from_value i16_from_value)
1761
1762(decl i16_from_swapped_value (i16) Value)
1763(extern extractor i16_from_swapped_value i16_from_swapped_value)
1764
1765(decl i64_from_negated_value (i64) Value)
1766(extern extractor i64_from_negated_value i64_from_negated_value)
1767
1768(decl i32_from_negated_value (i32) Value)
1769(extern extractor i32_from_negated_value i32_from_negated_value)
1770
1771(decl i16_from_negated_value (i16) Value)
1772(extern extractor i16_from_negated_value i16_from_negated_value)
1773
1774(decl uimm16shifted_from_value (UImm16Shifted) Value)
1775(extern extractor uimm16shifted_from_value uimm16shifted_from_value)
1776
1777(decl uimm32shifted_from_value (UImm32Shifted) Value)
1778(extern extractor uimm32shifted_from_value uimm32shifted_from_value)
1779
1780(decl uimm16shifted_from_inverted_value (UImm16Shifted) Value)
1781(extern extractor uimm16shifted_from_inverted_value uimm16shifted_from_inverted_value)
1782
1783(decl uimm32shifted_from_inverted_value (UImm32Shifted) Value)
1784(extern extractor uimm32shifted_from_inverted_value uimm32shifted_from_inverted_value)
1785
1786(decl len_minus_one (u8) u64)
1787(extern extractor len_minus_one len_minus_one)
1788
1789
1790;; Helpers for masking shift amounts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1791
1792;; Mask (immediate) shift amount to the type size.
1793(decl mask_amt_imm (Type i64) u8)
1794(extern constructor mask_amt_imm mask_amt_imm)
1795
1796;; Mask (immediate) shift amount to the type size.
1797;; Note that the hardware instructions always masks to six bits, so
1798;; in the case of a 64-bit type we do not need any explicit masking.
1799(decl mask_amt_reg (Type Reg) Reg)
1800(rule (mask_amt_reg (gpr32_ty ty) reg)
1801      (let ((mask u8 (mask_amt_imm ty -1)))
1802        (and_uimm16shifted ty reg (uimm16shifted mask 0))))
1803(rule 1 (mask_amt_reg (gpr64_ty ty) reg) reg)
1804
1805;; Load a shift amount into a GPR.
1806(decl amt_reg (Value) Reg)
1807(rule 1 (amt_reg amt @ (value_type (fits_in_64 _))) amt)
1808(rule (amt_reg amt @ (value_type (vr128_ty _)))
1809      (vec_extract_lane $I64X2 amt 1 (zero_reg)))
1810
1811;; Load a shift amount into a VR, replicated across all 16 bytes.
1812(decl amt_vr (Value) Reg)
1813(rule (amt_vr amt @ (value_type (fits_in_64 _)))
1814      (vec_replicate_lane $I8X16
1815        (vec_insert_lane_undef $I8X16 amt 0 (zero_reg)) 0))
1816(rule 1 (amt_vr amt @ (value_type (vr128_ty _)))
1817      (vec_replicate_lane $I8X16 amt 15))
1818(rule 2 (amt_vr (u64_from_value amt))
1819      (vec_imm_splat $I8X16 amt))
1820
1821
1822;; Helpers for condition codes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1823
1824(type Cond extern (enum))
1825
1826(decl mask_as_cond (u8) Cond)
1827(extern constructor mask_as_cond mask_as_cond)
1828
1829(decl intcc_as_cond (IntCC) Cond)
1830(extern constructor intcc_as_cond intcc_as_cond)
1831
1832(decl floatcc_as_cond (FloatCC) Cond)
1833(extern constructor floatcc_as_cond floatcc_as_cond)
1834
1835(decl invert_cond (Cond) Cond)
1836(extern constructor invert_cond invert_cond)
1837
1838(decl signed () IntCC)
1839(extern extractor signed signed)
1840
1841(decl unsigned () IntCC)
1842(extern extractor unsigned unsigned)
1843
1844
1845;; Helpers for memory arguments ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1846
1847;; Accessors for `Offset32`.
1848
1849(decl zero_offset () Offset32)
1850(extern constructor zero_offset zero_offset)
1851
1852(decl i64_from_offset (i64) Offset32)
1853(extern extractor infallible i64_from_offset i64_from_offset)
1854
1855(type SImm20 extern (enum))
1856
1857(decl pure partial memarg_imm_from_offset (SImm20) Offset32)
1858(extern extractor memarg_imm_from_offset memarg_imm_from_offset)
1859
1860(decl pure partial memarg_imm_from_offset_plus_bias (Offset32 u8) SImm20)
1861(extern constructor memarg_imm_from_offset_plus_bias memarg_imm_from_offset_plus_bias)
1862
1863;; Accessors for `MemFlags`.
1864
1865(decl littleendian () MemFlags)
1866(extern extractor littleendian littleendian)
1867
1868(decl bigendian () MemFlags)
1869(extern extractor bigendian bigendian)
1870
1871(decl memflags_trusted () MemFlags)
1872(extern constructor memflags_trusted memflags_trusted)
1873
1874;; Accessors for `MemArg`.
1875
1876(type MemArg extern (enum))
1877
1878(decl memarg_reg_plus_reg_plus_off (Reg Reg SImm20 MemFlags) MemArg)
1879(extern constructor memarg_reg_plus_reg_plus_off memarg_reg_plus_reg_plus_off)
1880
1881(decl memarg_reg_plus_reg (Reg Reg u8 MemFlags) MemArg)
1882(extern constructor memarg_reg_plus_reg memarg_reg_plus_reg)
1883
1884(decl memarg_reg_plus_off (Reg i64 u8 MemFlags) MemArg)
1885(extern constructor memarg_reg_plus_off memarg_reg_plus_off)
1886
1887(decl memarg_symbol (ExternalName i32 MemFlags) MemArg)
1888(extern constructor memarg_symbol memarg_symbol)
1889
1890(decl memarg_got () MemArg)
1891(extern constructor memarg_got memarg_got)
1892
1893(decl memarg_const (VCodeConstant) MemArg)
1894(extern constructor memarg_const memarg_const)
1895
1896;; Form the sum of two offset values, and check that the result is
1897;; a valid `MemArg::Symbol` offset (i.e. is even and fits into i32).
1898(decl pure partial memarg_symbol_offset_sum (i64 i64) i32)
1899(extern constructor memarg_symbol_offset_sum memarg_symbol_offset_sum)
1900
1901;; Likewise, but just check a single offset value.
1902(decl pure partial memarg_symbol_offset (i64) i32)
1903(rule (memarg_symbol_offset x)
1904      (memarg_symbol_offset_sum x 0))
1905
1906;; Create a MemArg referring to the saved frame pointer location.
1907(decl memarg_frame_pointer_offset () MemArg)
1908(extern constructor memarg_frame_pointer_offset memarg_frame_pointer_offset)
1909
1910;; Create a MemArg referring to the saved return address location.
1911(decl memarg_return_address_offset () MemArg)
1912(extern constructor memarg_return_address_offset memarg_return_address_offset)
1913
1914;; Lower an address into a `MemArg`.
1915
1916(decl lower_address (MemFlags Value Offset32) MemArg)
1917
1918(rule (lower_address flags addr @ (value_type (ty_addr64 _)) (i64_from_offset offset))
1919      (memarg_reg_plus_off addr offset 0 flags))
1920
1921(rule 1 (lower_address flags (has_type (ty_addr64 _) (iadd _ x y)) (memarg_imm_from_offset z))
1922      (memarg_reg_plus_reg_plus_off x y z flags))
1923
1924(rule 1 (lower_address flags
1925                     (symbol_value _ (symbol_value_data name (RelocDistance.Near) sym_offset))
1926                     (i64_from_offset offset))
1927      (if-let final_offset (memarg_symbol_offset_sum offset sym_offset))
1928      (memarg_symbol name final_offset flags))
1929
1930
1931;; Lower an address plus a small bias into a `MemArg`.
1932
1933(decl lower_address_bias (MemFlags Value Offset32 u8) MemArg)
1934
1935(rule (lower_address_bias flags addr @ (value_type $I64) (i64_from_offset offset) bias)
1936      (memarg_reg_plus_off addr offset bias flags))
1937
1938(rule 1 (lower_address_bias flags (has_type $I64 (iadd _ x y)) z bias)
1939      (if-let final_offset (memarg_imm_from_offset_plus_bias z bias))
1940      (memarg_reg_plus_reg_plus_off x y final_offset flags))
1941
1942
1943;; Test whether a `load` address will be lowered to a `MemArg::Symbol`.
1944
1945(decl pure partial load_sym (Inst) Inst)
1946(rule (load_sym inst)
1947      (if-let (load _ _ (symbol_value _ (symbol_value_data _ (RelocDistance.Near) sym_offset))
1948                    (i64_from_offset load_offset))
1949          inst)
1950      (if (memarg_symbol_offset_sum sym_offset load_offset))
1951      inst)
1952
1953(decl pure partial uload16_sym (Inst) Inst)
1954(rule (uload16_sym inst)
1955      (if-let (uload16 _ _ (symbol_value _ (symbol_value_data _ (RelocDistance.Near) sym_offset))
1956                       (i64_from_offset load_offset))
1957          inst)
1958      (if (memarg_symbol_offset_sum sym_offset load_offset))
1959      inst)
1960
1961
1962;; Helpers for stack-slot addresses ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1963
1964(decl stack_addr_impl (Type StackSlot Offset32) Reg)
1965(rule (stack_addr_impl ty stack_slot offset)
1966      (let ((dst WritableReg (temp_writable_reg ty))
1967            (_ Unit (emit (abi_stackslot_addr dst stack_slot offset))))
1968        dst))
1969
1970
1971;; Helpers for extracting extensions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1972
1973;; A value that is the result of a sign-extend from a 32-bit value.
1974(decl sext32_value (Value) Value)
1975(extractor (sext32_value x) (sextend _ (and x (value_type $I32))))
1976
1977;; A value that is the result of a zero-extend from a 32-bit value.
1978(decl zext32_value (Value) Value)
1979(extractor (zext32_value x) (uextend _ (and x (value_type $I32))))
1980
1981
1982;; Helpers for sinkable loads ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1983
1984;; Extract a sinkable instruction from a value operand.
1985(decl sinkable_inst (Inst) Value)
1986(extern extractor sinkable_inst sinkable_inst)
1987
1988;; Sinkable big-endian load instruction.
1989(decl sinkable_load (Inst) Value)
1990(extractor (sinkable_load inst)
1991           (sinkable_inst (and inst (load _ (bigendian) _addr _offset))))
1992
1993;; Sinkable big-endian load instruction (32/64-bit types only).
1994(decl sinkable_load_32_64 (Inst) Value)
1995(extractor (sinkable_load_32_64 inst)
1996           (and (value_type (ty_32_or_64 _)) (sinkable_load inst)))
1997
1998;; Sinkable big-endian load instruction (16-bit types only).
1999(decl sinkable_load_16 (Inst) Value)
2000(extractor (sinkable_load_16 inst)
2001           (and (value_type $I16) (sinkable_load inst)))
2002
2003;; Sinkable little-endian load instruction.
2004(decl sinkable_load_little (Inst) Value)
2005(extractor (sinkable_load_little inst)
2006           (sinkable_inst (and inst (load _ (littleendian) _addr _offset))))
2007
2008;; Sinkable big-endian sload16 instruction.
2009(decl sinkable_sload16 (Inst) Value)
2010(extractor (sinkable_sload16 inst)
2011           (sinkable_inst (and inst (sload16 _ (bigendian) _addr _offset))))
2012
2013;; Sinkable big-endian sload32 instruction.
2014(decl sinkable_sload32 (Inst) Value)
2015(extractor (sinkable_sload32 inst)
2016           (sinkable_inst (and inst (sload32 _ (bigendian) _addr _offset))))
2017
2018;; Sinkable big-endian uload16 instruction.
2019(decl sinkable_uload16 (Inst) Value)
2020(extractor (sinkable_uload16 inst)
2021           (sinkable_inst (and inst (uload16 _ (bigendian) _addr _offset))))
2022
2023;; Sinkable big-endian uload32 instruction.
2024(decl sinkable_uload32 (Inst) Value)
2025(extractor (sinkable_uload32 inst)
2026           (sinkable_inst (and inst (uload32 _ (bigendian) _addr _offset))))
2027
2028;; Sink a load instruction, returning its address as `MemArg`.
2029;; This is a side-effectful operation, see `sink_inst`.
2030(decl sink_load (Inst) MemArg)
2031(rule (sink_load inst @ (load _ flags addr offset))
2032      (let ((_ Unit (sink_inst inst)))
2033        (lower_address flags addr offset)))
2034
2035;; Sink a sload16 instruction, returning its address as `MemArg`.
2036;; This is a side-effectful operation, see `sink_inst`.
2037(decl sink_sload16 (Inst) MemArg)
2038(rule (sink_sload16 inst @ (sload16 _ flags addr offset))
2039      (let ((_ Unit (sink_inst inst)))
2040        (lower_address flags addr offset)))
2041
2042;; Sink a sload32 instruction, returning its address as `MemArg`.
2043;; This is a side-effectful operation, see `sink_inst`.
2044(decl sink_sload32 (Inst) MemArg)
2045(rule (sink_sload32 inst @ (sload32 _ flags addr offset))
2046      (let ((_ Unit (sink_inst inst)))
2047        (lower_address flags addr offset)))
2048
2049;; Sink a uload16 instruction, returning its address as `MemArg`.
2050;; This is a side-effectful operation, see `sink_inst`.
2051(decl sink_uload16 (Inst) MemArg)
2052(rule (sink_uload16 inst @ (uload16 _ flags addr offset))
2053      (let ((_ Unit (sink_inst inst)))
2054        (lower_address flags addr offset)))
2055
2056;; Sink a uload32 instruction, returning its address as `MemArg`.
2057;; This is a side-effectful operation, see `sink_inst`.
2058(decl sink_uload32 (Inst) MemArg)
2059(rule (sink_uload32 inst @ (uload32 _ flags addr offset))
2060      (let ((_ Unit (sink_inst inst)))
2061        (lower_address flags addr offset)))
2062
2063
2064;; Helpers for register pairs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2065
2066;; A writable register pair.
2067(type WritableRegPair (primitive WritableRegPair))
2068
2069;; Construct a WritableRegPair from two registers.
2070(decl writable_regpair (WritableReg WritableReg) WritableRegPair)
2071(extern constructor writable_regpair writable_regpair)
2072
2073;; Allocate a writable register pair.
2074(decl temp_writable_regpair (Type) WritableRegPair)
2075(rule (temp_writable_regpair ty)
2076      (writable_regpair (temp_writable_reg ty) (temp_writable_reg ty)))
2077
2078;; Retrieve the high word of the writable register pair.
2079(decl writable_regpair_hi (WritableRegPair) WritableReg)
2080(extern constructor writable_regpair_hi writable_regpair_hi)
2081
2082;; Retrieve the low word of the writable register pair.
2083(decl writable_regpair_lo (WritableRegPair) WritableReg)
2084(extern constructor writable_regpair_lo writable_regpair_lo)
2085
2086;; A (read-only) register pair.
2087(type RegPair (primitive RegPair))
2088
2089;; Construct a register pair from a writable register pair.
2090(decl writable_regpair_to_regpair (WritableRegPair) RegPair)
2091(rule (writable_regpair_to_regpair w)
2092      (regpair (writable_regpair_hi w) (writable_regpair_lo w)))
2093
2094;; Construct a regpair from two registers.
2095(decl regpair (Reg Reg) RegPair)
2096(extern constructor regpair regpair)
2097
2098;; Retrieve the high word of the register pair.
2099(decl regpair_hi (RegPair) Reg)
2100(extern constructor regpair_hi regpair_hi)
2101
2102;; Retrieve the low word of the register pair.
2103(decl regpair_lo (RegPair) Reg)
2104(extern constructor regpair_lo regpair_lo)
2105
2106;; Move a $F128 value between a single VR and a pair of FPRs.
2107(decl fp_reg_to_regpair (Reg) RegPair)
2108(rule (fp_reg_to_regpair x) (regpair x (vec_replicate_lane $I64X2 x 1)))
2109(decl fp_regpair_to_reg (RegPair) Reg)
2110(rule (fp_regpair_to_reg x) (vec_merge_high $I64X2 (regpair_hi x) (regpair_lo x)))
2111
2112
2113;; Instruction creation helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2114
2115;; Helper for emitting `MInst.AluRRR` instructions.
2116(decl alu_rrr (Type ALUOp Reg Reg) Reg)
2117(rule (alu_rrr ty op src1 src2)
2118      (let ((dst WritableReg (temp_writable_reg ty))
2119            (_ Unit (emit (MInst.AluRRR op dst src1 src2))))
2120        dst))
2121
2122;; Helper for emitting `MInst.AluRRR` instructions as flag producers.
2123(decl alu_rrr_with_flags_paired (Type ALUOp Reg Reg) ProducesFlags)
2124(rule (alu_rrr_with_flags_paired ty op src1 src2)
2125      (let ((dst WritableReg (temp_writable_reg ty)))
2126        (ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2127          (MInst.AluRRR op dst src1 src2) dst)))
2128
2129;; Helper for emitting `MInst.AluRRSImm16` instructions.
2130(decl alu_rrsimm16 (Type ALUOp Reg i16) Reg)
2131(rule (alu_rrsimm16 ty op src imm)
2132      (let ((dst WritableReg (temp_writable_reg ty))
2133            (_ Unit (emit (MInst.AluRRSImm16 op dst src imm))))
2134        dst))
2135
2136;; Helper for emitting `MInst.AluRR` instructions.
2137(decl alu_rr (Type ALUOp Reg Reg) Reg)
2138(rule (alu_rr ty op src1 src2)
2139      (let ((dst WritableReg (temp_writable_reg ty))
2140            (_ Unit (emit (MInst.AluRR op dst src1 src2))))
2141        dst))
2142
2143;; Helper for emitting `MInst.AluRR` instructions as flag producers.
2144(decl alu_rr_with_flags_paired (Type ALUOp Reg Reg) ProducesFlags)
2145(rule (alu_rr_with_flags_paired ty op src1 src2)
2146      (let ((dst WritableReg (temp_writable_reg ty)))
2147        (ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2148            (MInst.AluRR op dst src1 src2) dst)))
2149
2150;; Helper for emitting `MInst.AluRX` instructions.
2151(decl alu_rx (Type ALUOp Reg MemArg) Reg)
2152(rule (alu_rx ty op src mem)
2153      (let ((dst WritableReg (temp_writable_reg ty))
2154            (_ Unit (emit (MInst.AluRX op dst src mem))))
2155        dst))
2156
2157;; Helper for emitting `MInst.AluRX` instructions as flags producers.
2158(decl alu_rx_with_flags_paired (Type ALUOp Reg MemArg) ProducesFlags)
2159(rule (alu_rx_with_flags_paired ty op src mem)
2160      (let ((dst WritableReg (temp_writable_reg ty)))
2161        (ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2162          (MInst.AluRX op dst src mem) dst)))
2163
2164;; Helper for emitting `MInst.AluRSImm16` instructions.
2165(decl alu_rsimm16 (Type ALUOp Reg i16) Reg)
2166(rule (alu_rsimm16 ty op src imm)
2167      (let ((dst WritableReg (temp_writable_reg ty))
2168            (_ Unit (emit (MInst.AluRSImm16 op dst src imm))))
2169        dst))
2170
2171;; Helper for emitting `MInst.AluRSImm32` instructions.
2172(decl alu_rsimm32 (Type ALUOp Reg i32) Reg)
2173(rule (alu_rsimm32 ty op src imm)
2174      (let ((dst WritableReg (temp_writable_reg ty))
2175            (_ Unit (emit (MInst.AluRSImm32 op dst src imm))))
2176        dst))
2177
2178;; Helper for emitting `MInst.AluRUImm32` instructions.
2179(decl alu_ruimm32 (Type ALUOp Reg u32) Reg)
2180(rule (alu_ruimm32 ty op src imm)
2181      (let ((dst WritableReg (temp_writable_reg ty))
2182            (_ Unit (emit (MInst.AluRUImm32 op dst src imm))))
2183        dst))
2184
2185;; Helper for emitting `MInst.AluRUImm32` instructions as flag producers.
2186(decl alu_ruimm32_with_flags_paired (Type ALUOp Reg u32) ProducesFlags)
2187(rule (alu_ruimm32_with_flags_paired ty op src imm)
2188      (let ((dst WritableReg (temp_writable_reg ty)))
2189        (ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2190          (MInst.AluRUImm32 op dst src imm) dst)))
2191
2192;; Helper for emitting `MInst.AluRUImm16Shifted` instructions.
2193(decl alu_ruimm16shifted (Type ALUOp Reg UImm16Shifted) Reg)
2194(rule (alu_ruimm16shifted ty op src imm)
2195      (let ((dst WritableReg (temp_writable_reg ty))
2196            (_ Unit (emit (MInst.AluRUImm16Shifted op dst src imm))))
2197        dst))
2198
2199;; Helper for emitting `MInst.AluRUImm32Shifted` instructions.
2200(decl alu_ruimm32shifted (Type ALUOp Reg UImm32Shifted) Reg)
2201(rule (alu_ruimm32shifted ty op src imm)
2202      (let ((dst WritableReg (temp_writable_reg ty))
2203            (_ Unit (emit (MInst.AluRUImm32Shifted op dst src imm))))
2204        dst))
2205
2206;; Helper for emitting `MInst.SMulWide` instructions.
2207(decl smul_wide (Reg Reg) RegPair)
2208(rule (smul_wide src1 src2)
2209      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2210            (_ Unit (emit (MInst.SMulWide dst src1 src2))))
2211        dst))
2212
2213;; Helper for emitting `MInst.UMulWide` instructions.
2214(decl umul_wide (Reg Reg) RegPair)
2215(rule (umul_wide src1 src2)
2216      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2217            (_ Unit (emit (MInst.UMulWide dst src1 src2))))
2218        dst))
2219
2220;; Helper for emitting `MInst.SDivMod32` instructions.
2221(decl sdivmod32 (Reg Reg) RegPair)
2222(rule (sdivmod32 src1 src2)
2223      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2224            (_ Unit (emit (MInst.SDivMod32 dst src1 src2))))
2225        dst))
2226
2227;; Helper for emitting `MInst.SDivMod64` instructions.
2228(decl sdivmod64 (Reg Reg) RegPair)
2229(rule (sdivmod64 src1 src2)
2230      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2231            (_ Unit (emit (MInst.SDivMod64 dst src1 src2))))
2232        dst))
2233
2234;; Helper for emitting `MInst.UDivMod32` instructions.
2235(decl udivmod32 (RegPair Reg) RegPair)
2236(rule (udivmod32 src1 src2)
2237      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2238            (_ Unit (emit (MInst.UDivMod32 dst src1 src2))))
2239        dst))
2240
2241;; Helper for emitting `MInst.UDivMod64` instructions.
2242(decl udivmod64 (RegPair Reg) RegPair)
2243(rule (udivmod64 src1 src2)
2244      (let ((dst WritableRegPair (temp_writable_regpair $I64))
2245            (_ Unit (emit (MInst.UDivMod64 dst src1 src2))))
2246        dst))
2247
2248;; Helper for emitting `MInst.ShiftRR` instructions.
2249(decl shift_rr (Type ShiftOp Reg u8 Reg) Reg)
2250(rule (shift_rr ty op src shift_imm shift_reg)
2251      (let ((dst WritableReg (temp_writable_reg ty))
2252            (_ Unit (emit (MInst.ShiftRR op dst src shift_imm shift_reg))))
2253        dst))
2254
2255;; Helper for emitting `MInst.RxSBGTest` instructions.
2256(decl rxsbg_test (RxSBGOp Reg Reg u8 u8 i8) ProducesFlags)
2257(rule (rxsbg_test op src1 src2 start_bit end_bit rotate_amt)
2258      (ProducesFlags.ProducesFlagsSideEffect
2259            (MInst.RxSBGTest op src1 src2 start_bit end_bit rotate_amt)))
2260
2261;; Helper for emitting `MInst.UnaryRR` instructions.
2262(decl unary_rr (Type UnaryOp Reg) Reg)
2263(rule (unary_rr ty op src)
2264      (let ((dst WritableReg (temp_writable_reg ty))
2265            (_ Unit (emit (MInst.UnaryRR op dst src))))
2266        dst))
2267
2268;; Helper for emitting `MInst.CmpRR` instructions.
2269(decl cmp_rr (CmpOp Reg Reg) ProducesFlags)
2270(rule (cmp_rr op src1 src2)
2271      (ProducesFlags.ProducesFlagsSideEffect (MInst.CmpRR op src1 src2)))
2272
2273;; Helper for emitting `MInst.CmpRX` instructions.
2274(decl cmp_rx (CmpOp Reg MemArg) ProducesFlags)
2275(rule (cmp_rx op src mem)
2276      (ProducesFlags.ProducesFlagsSideEffect (MInst.CmpRX op src mem)))
2277
2278;; Helper for emitting `MInst.CmpRSImm16` instructions.
2279(decl cmp_rsimm16 (CmpOp Reg i16) ProducesFlags)
2280(rule (cmp_rsimm16 op src imm)
2281      (ProducesFlags.ProducesFlagsSideEffect (MInst.CmpRSImm16 op src imm)))
2282
2283;; Helper for emitting `MInst.CmpRSImm32` instructions.
2284(decl cmp_rsimm32 (CmpOp Reg i32) ProducesFlags)
2285(rule (cmp_rsimm32 op src imm)
2286      (ProducesFlags.ProducesFlagsSideEffect (MInst.CmpRSImm32 op src imm)))
2287
2288;; Helper for emitting `MInst.CmpRUImm32` instructions.
2289(decl cmp_ruimm32 (CmpOp Reg u32) ProducesFlags)
2290(rule (cmp_ruimm32 op src imm)
2291      (ProducesFlags.ProducesFlagsSideEffect (MInst.CmpRUImm32 op src imm)))
2292
2293;; Helper for emitting `MInst.AtomicRmw` instructions.
2294(decl atomic_rmw_impl (Type ALUOp Reg MemArg) Reg)
2295(rule (atomic_rmw_impl ty op src mem)
2296      (let ((dst WritableReg (temp_writable_reg ty))
2297            (_ Unit (emit (MInst.AtomicRmw op dst src mem))))
2298        dst))
2299
2300;; Helper for emitting `MInst.AtomicCas32` instructions.
2301(decl atomic_cas32 (Reg Reg MemArg) Reg)
2302(rule (atomic_cas32 src1 src2 mem)
2303      (let ((dst WritableReg (temp_writable_reg $I32))
2304            (_ Unit (emit (MInst.AtomicCas32 dst src1 src2 mem))))
2305        dst))
2306
2307;; Helper for emitting `MInst.AtomicCas64` instructions.
2308(decl atomic_cas64 (Reg Reg MemArg) Reg)
2309(rule (atomic_cas64 src1 src2 mem)
2310      (let ((dst WritableReg (temp_writable_reg $I64))
2311            (_ Unit (emit (MInst.AtomicCas64 dst src1 src2 mem))))
2312        dst))
2313
2314;; Helper for emitting `MInst.Fence` instructions.
2315(decl fence_impl () SideEffectNoResult)
2316(rule (fence_impl)
2317      (SideEffectNoResult.Inst (MInst.Fence)))
2318
2319;; Helper for emitting `MInst.Load32` instructions.
2320(decl load32 (MemArg) Reg)
2321(rule (load32 addr)
2322      (let ((dst WritableReg (temp_writable_reg $I32))
2323            (_ Unit (emit (MInst.Load32 dst addr))))
2324        dst))
2325
2326;; Helper for emitting `MInst.Load64` instructions.
2327(decl load64 (MemArg) Reg)
2328(rule (load64 addr)
2329      (let ((dst WritableReg (temp_writable_reg $I64))
2330            (_ Unit (emit (MInst.Load64 dst addr))))
2331        dst))
2332
2333;; Helper for emitting `MInst.LoadRev16` instructions.
2334(decl loadrev16 (MemArg) Reg)
2335(rule (loadrev16 addr)
2336      (let ((dst WritableReg (temp_writable_reg $I32))
2337            (_ Unit (emit (MInst.LoadRev16 dst addr))))
2338        dst))
2339
2340;; Helper for emitting `MInst.LoadRev32` instructions.
2341(decl loadrev32 (MemArg) Reg)
2342(rule (loadrev32 addr)
2343      (let ((dst WritableReg (temp_writable_reg $I32))
2344            (_ Unit (emit (MInst.LoadRev32 dst addr))))
2345        dst))
2346
2347;; Helper for emitting `MInst.LoadRev64` instructions.
2348(decl loadrev64 (MemArg) Reg)
2349(rule (loadrev64 addr)
2350      (let ((dst WritableReg (temp_writable_reg $I64))
2351            (_ Unit (emit (MInst.LoadRev64 dst addr))))
2352        dst))
2353
2354;; Helper for emitting `MInst.Store8` instructions.
2355(decl store8 (Reg MemArg) SideEffectNoResult)
2356(rule (store8 src addr)
2357      (SideEffectNoResult.Inst (MInst.Store8 src addr)))
2358
2359;; Helper for emitting `MInst.Store16` instructions.
2360(decl store16 (Reg MemArg) SideEffectNoResult)
2361(rule (store16 src addr)
2362      (SideEffectNoResult.Inst (MInst.Store16 src addr)))
2363
2364;; Helper for emitting `MInst.Store32` instructions.
2365(decl store32 (Reg MemArg) SideEffectNoResult)
2366(rule (store32 src addr)
2367      (SideEffectNoResult.Inst (MInst.Store32 src addr)))
2368
2369;; Helper for emitting `MInst.Store64` instructions.
2370(decl store64 (Reg MemArg) SideEffectNoResult)
2371(rule (store64 src addr)
2372      (SideEffectNoResult.Inst (MInst.Store64 src addr)))
2373
2374;; Helper for emitting `MInst.StoreImm8` instructions.
2375(decl store8_imm (u8 MemArg) SideEffectNoResult)
2376(rule (store8_imm imm addr)
2377      (SideEffectNoResult.Inst (MInst.StoreImm8 imm addr)))
2378
2379;; Helper for emitting `MInst.StoreImm16` instructions.
2380(decl store16_imm (i16 MemArg) SideEffectNoResult)
2381(rule (store16_imm imm addr)
2382      (SideEffectNoResult.Inst (MInst.StoreImm16 imm addr)))
2383
2384;; Helper for emitting `MInst.StoreImm32SExt16` instructions.
2385(decl store32_simm16 (i16 MemArg) SideEffectNoResult)
2386(rule (store32_simm16 imm addr)
2387      (SideEffectNoResult.Inst (MInst.StoreImm32SExt16 imm addr)))
2388
2389;; Helper for emitting `MInst.StoreImm64SExt16` instructions.
2390(decl store64_simm16 (i16 MemArg) SideEffectNoResult)
2391(rule (store64_simm16 imm addr)
2392      (SideEffectNoResult.Inst (MInst.StoreImm64SExt16 imm addr)))
2393
2394;; Helper for emitting `MInst.StoreRev16` instructions.
2395(decl storerev16 (Reg MemArg) SideEffectNoResult)
2396(rule (storerev16 src addr)
2397      (SideEffectNoResult.Inst (MInst.StoreRev16 src addr)))
2398
2399;; Helper for emitting `MInst.StoreRev32` instructions.
2400(decl storerev32 (Reg MemArg) SideEffectNoResult)
2401(rule (storerev32 src addr)
2402      (SideEffectNoResult.Inst (MInst.StoreRev32 src addr)))
2403
2404;; Helper for emitting `MInst.StoreRev64` instructions.
2405(decl storerev64 (Reg MemArg) SideEffectNoResult)
2406(rule (storerev64 src addr)
2407      (SideEffectNoResult.Inst (MInst.StoreRev64 src addr)))
2408
2409;; Helper for emitting `MInst.LoadAR` instructions.
2410(decl load_ar (u8) Reg)
2411(rule (load_ar ar)
2412      (let ((dst WritableReg (temp_writable_reg $I64))
2413            (_ Unit (emit (MInst.LoadAR dst ar))))
2414        dst))
2415
2416;; Helper for emitting `MInst.InsertAR` instructions.
2417(decl insert_ar (Reg u8) Reg)
2418(rule (insert_ar src ar)
2419      (let ((dst WritableReg (temp_writable_reg $I64))
2420            (_ Unit (emit (MInst.InsertAR dst src ar))))
2421        dst))
2422
2423;; Helper for emitting `MInst.FpuRR` instructions.
2424(decl fpu_rr (Type FPUOp1 Reg) Reg)
2425(rule (fpu_rr ty op src)
2426      (let ((dst WritableReg (temp_writable_reg ty))
2427            (_ Unit (emit (MInst.FpuRR op dst src))))
2428        dst))
2429
2430;; Helper for emitting `MInst.FpuRRR` instructions.
2431(decl fpu_rrr (Type FPUOp2 Reg Reg) Reg)
2432(rule (fpu_rrr ty op src1 src2)
2433      (let ((dst WritableReg (temp_writable_reg ty))
2434            (_ Unit (emit (MInst.FpuRRR op dst src1 src2))))
2435        dst))
2436
2437;; Helper for emitting `MInst.FpuRRRR` instructions.
2438(decl fpu_rrrr (Type FPUOp3 Reg Reg Reg) Reg)
2439(rule (fpu_rrrr ty op src1 src2 src3)
2440      (let ((dst WritableReg (temp_writable_reg ty))
2441            (_ Unit (emit (MInst.FpuRRRR op dst src1 src2 src3))))
2442        dst))
2443
2444;; Helper for emitting `MInst.FpuCmp32` instructions.
2445(decl fpu_cmp32 (Reg Reg) ProducesFlags)
2446(rule (fpu_cmp32 src1 src2)
2447      (ProducesFlags.ProducesFlagsSideEffect (MInst.FpuCmp32 src1 src2)))
2448
2449;; Helper for emitting `MInst.FpuCmp64` instructions.
2450(decl fpu_cmp64 (Reg Reg) ProducesFlags)
2451(rule (fpu_cmp64 src1 src2)
2452      (ProducesFlags.ProducesFlagsSideEffect (MInst.FpuCmp64 src1 src2)))
2453
2454;; Helper for emitting `MInst.FpuCmp128` instructions.
2455(decl fpu_cmp128 (Reg Reg) ProducesFlags)
2456(rule (fpu_cmp128 src1 src2)
2457      (ProducesFlags.ProducesFlagsSideEffect (MInst.FpuCmp128 src1 src2)))
2458
2459;; Helper for emitting `MInst.FpuRound` instructions.
2460(decl fpu_round (Type FpuRoundOp FpuRoundMode Reg) Reg)
2461(rule (fpu_round ty op mode src)
2462      (let ((dst WritableReg (temp_writable_reg ty))
2463            (_ Unit (emit (MInst.FpuRound op mode dst src))))
2464        dst))
2465
2466;; Helper for emitting `MInst.FpuConv128FromInt` instructions.
2467(decl fpu_conv128_from_int (FpuConv128Op FpuRoundMode Reg) RegPair)
2468(rule (fpu_conv128_from_int op mode src)
2469      (let ((dst WritableRegPair (temp_writable_regpair $F64))
2470            (_ Unit (emit (MInst.FpuConv128FromInt op mode dst src))))
2471        dst))
2472
2473;; Helper for emitting `MInst.FpuConv128ToInt` instructions.
2474(decl fpu_conv128_to_int (Type FpuConv128Op FpuRoundMode RegPair) Reg)
2475(rule (fpu_conv128_to_int ty op mode src)
2476      (let ((dst WritableReg (temp_writable_reg ty))
2477            (_ Unit (emit (MInst.FpuConv128ToInt op mode dst src))))
2478        dst))
2479
2480;; Helper for emitting `MInst.VecRRR` instructions.
2481(decl vec_rrr (Type VecBinaryOp Reg Reg) Reg)
2482(rule (vec_rrr ty op src1 src2)
2483      (let ((dst WritableReg (temp_writable_reg ty))
2484            (_ Unit (emit (MInst.VecRRR op dst src1 src2))))
2485        dst))
2486
2487;; Helper for emitting `MInst.VecRR` instructions.
2488(decl vec_rr (Type VecUnaryOp Reg) Reg)
2489(rule (vec_rr ty op src)
2490      (let ((dst WritableReg (temp_writable_reg ty))
2491            (_ Unit (emit (MInst.VecRR op dst src))))
2492        dst))
2493
2494;; Helper for emitting `MInst.VecShiftRR` instructions.
2495(decl vec_shift_rr (Type VecShiftOp Reg u8 Reg) Reg)
2496(rule (vec_shift_rr ty op src shift_imm shift_reg)
2497      (let ((dst WritableReg (temp_writable_reg ty))
2498            (_ Unit (emit (MInst.VecShiftRR op dst src shift_imm shift_reg))))
2499        dst))
2500
2501;; Helper for emitting `MInst.VecSelect` instructions.
2502(decl vec_select (Type Reg Reg Reg) Reg)
2503(rule (vec_select ty src1 src2 src3)
2504      (let ((dst WritableReg (temp_writable_reg ty))
2505            (_ Unit (emit (MInst.VecSelect dst src1 src2 src3))))
2506        dst))
2507
2508;; Helper for emitting `MInst.VecPermute` instructions.
2509(decl vec_permute (Type Reg Reg Reg) Reg)
2510(rule (vec_permute ty src1 src2 src3)
2511      (let ((dst WritableReg (temp_writable_reg ty))
2512            (_ Unit (emit (MInst.VecPermute dst src1 src2 src3))))
2513        dst))
2514
2515;; Helper for emitting `MInst.VecBlend` instructions.
2516(decl vec_blend (Type Reg Reg Reg) Reg)
2517(rule (vec_blend ty src1 src2 src3)
2518      (let ((dst WritableReg (temp_writable_reg ty))
2519            (_ Unit (emit (MInst.VecBlend dst src1 src2 src3))))
2520        dst))
2521
2522;; Helper for emitting `MInst.VecEvaluate` instructions.
2523(decl vec_eval (Type u8 Reg Reg Reg) Reg)
2524(rule (vec_eval ty op src1 src2 src3)
2525      (let ((dst WritableReg (temp_writable_reg ty))
2526            (_ Unit (emit (MInst.VecEvaluate op dst src1 src2 src3))))
2527        dst))
2528
2529;; Helper for emitting `MInst.VecPermuteDWImm` instructions.
2530(decl vec_permute_dw_imm (Type Reg u8 Reg u8) Reg)
2531(rule (vec_permute_dw_imm ty src1 idx1 src2 idx2)
2532      (let ((dst WritableReg (temp_writable_reg ty))
2533            (_ Unit (emit (MInst.VecPermuteDWImm dst src1 src2 idx1 idx2))))
2534        dst))
2535
2536;; Helper for emitting `MInst.VecIntCmp` instructions.
2537(decl vec_int_cmp (Type VecIntCmpOp Reg Reg) Reg)
2538(rule (vec_int_cmp ty op src1 src2)
2539      (let ((dst WritableReg (temp_writable_reg ty))
2540            (_ Unit (emit (MInst.VecIntCmp op dst src1 src2))))
2541        dst))
2542
2543;; Helper for emitting `MInst.VecIntCmpS` instructions.
2544(decl vec_int_cmps (Type VecIntCmpOp Reg Reg) ProducesFlags)
2545(rule (vec_int_cmps ty op src1 src2)
2546      (let ((tmp WritableReg (temp_writable_reg ty)))
2547        (ProducesFlags.ProducesFlagsSideEffect (MInst.VecIntCmpS op tmp src1 src2))))
2548
2549;; Helper for emitting `MInst.VecFloatCmp` instructions.
2550(decl vec_float_cmp (Type VecFloatCmpOp Reg Reg) Reg)
2551(rule (vec_float_cmp ty op src1 src2)
2552      (let ((dst WritableReg (temp_writable_reg ty))
2553            (_ Unit (emit (MInst.VecFloatCmp op dst src1 src2))))
2554        dst))
2555
2556;; Helper for emitting `MInst.VecFloatCmpS` instructions.
2557(decl vec_float_cmps (Type VecFloatCmpOp Reg Reg) ProducesFlags)
2558(rule (vec_float_cmps ty op src1 src2)
2559      (let ((tmp WritableReg (temp_writable_reg ty)))
2560        (ProducesFlags.ProducesFlagsSideEffect (MInst.VecFloatCmpS op tmp src1 src2))))
2561
2562;; Helper for emitting `MInst.VecIntEltCmp` instructions.
2563(decl vec_int_elt_cmp (VecIntEltCmpOp Reg Reg) ProducesFlags)
2564(rule (vec_int_elt_cmp op src1 src2)
2565      (ProducesFlags.ProducesFlagsSideEffect (MInst.VecIntEltCmp op src1 src2)))
2566
2567;; Helper for emitting `MInst.VecInt128SCmpHi` instructions.
2568(decl vec_int128_scmphi (Reg Reg) ProducesBool)
2569(rule (vec_int128_scmphi src1 src2)
2570      (let ((tmp WritableReg (temp_writable_reg $I128)))
2571        (bool (ProducesFlags.ProducesFlagsSideEffect (MInst.VecInt128SCmpHi tmp src1 src2))
2572              (mask_as_cond 4))))
2573
2574;; Helper for emitting `MInst.VecInt128UCmpHi` instructions.
2575(decl vec_int128_ucmphi (Reg Reg) ProducesBool)
2576(rule (vec_int128_ucmphi src1 src2)
2577      (let ((tmp WritableReg (temp_writable_reg $I128)))
2578        (bool (ProducesFlags.ProducesFlagsSideEffect (MInst.VecInt128UCmpHi tmp src1 src2))
2579              (mask_as_cond 4))))
2580
2581;; Helper for emitting `MInst.VecLoad` instructions.
2582(decl vec_load (Type MemArg) Reg)
2583(rule (vec_load ty addr)
2584      (let ((dst WritableReg (temp_writable_reg ty))
2585            (_ Unit (emit (MInst.VecLoad dst addr))))
2586        dst))
2587
2588;; Helper for emitting `MInst.VecLoadRev` instructions.
2589(decl vec_loadrev (Type MemArg) Reg)
2590(rule (vec_loadrev ty addr)
2591      (let ((dst WritableReg (temp_writable_reg ty))
2592            (_ Unit (emit (MInst.VecLoadRev dst addr))))
2593        dst))
2594
2595;; Helper for emitting `MInst.VecLoadByte16Rev` instructions.
2596(decl vec_load_byte16rev (Type MemArg) Reg)
2597(rule (vec_load_byte16rev ty addr)
2598      (let ((dst WritableReg (temp_writable_reg ty))
2599            (_ Unit (emit (MInst.VecLoadByte16Rev dst addr))))
2600        dst))
2601
2602;; Helper for emitting `MInst.VecLoadByte32Rev` instructions.
2603(decl vec_load_byte32rev (Type MemArg) Reg)
2604(rule (vec_load_byte32rev ty addr)
2605      (let ((dst WritableReg (temp_writable_reg ty))
2606            (_ Unit (emit (MInst.VecLoadByte32Rev dst addr))))
2607        dst))
2608
2609;; Helper for emitting `MInst.VecLoadByte64Rev` instructions.
2610(decl vec_load_byte64rev (Type MemArg) Reg)
2611(rule (vec_load_byte64rev ty addr)
2612      (let ((dst WritableReg (temp_writable_reg ty))
2613            (_ Unit (emit (MInst.VecLoadByte64Rev dst addr))))
2614        dst))
2615
2616;; Helper for emitting `MInst.VecLoadElt16Rev` instructions.
2617(decl vec_load_elt16rev (Type MemArg) Reg)
2618(rule (vec_load_elt16rev ty addr)
2619      (let ((dst WritableReg (temp_writable_reg ty))
2620            (_ Unit (emit (MInst.VecLoadElt16Rev dst addr))))
2621        dst))
2622
2623;; Helper for emitting `MInst.VecLoadElt32Rev` instructions.
2624(decl vec_load_elt32rev (Type MemArg) Reg)
2625(rule (vec_load_elt32rev ty addr)
2626      (let ((dst WritableReg (temp_writable_reg ty))
2627            (_ Unit (emit (MInst.VecLoadElt32Rev dst addr))))
2628        dst))
2629
2630;; Helper for emitting `MInst.VecLoadElt64Rev` instructions.
2631(decl vec_load_elt64rev (Type MemArg) Reg)
2632(rule (vec_load_elt64rev ty addr)
2633      (let ((dst WritableReg (temp_writable_reg ty))
2634            (_ Unit (emit (MInst.VecLoadElt64Rev dst addr))))
2635        dst))
2636
2637;; Helper for emitting `MInst.VecStore` instructions.
2638(decl vec_store (Reg MemArg) SideEffectNoResult)
2639(rule (vec_store src addr)
2640      (SideEffectNoResult.Inst (MInst.VecStore src addr)))
2641
2642;; Helper for emitting `MInst.VecStoreRev` instructions.
2643(decl vec_storerev (Reg MemArg) SideEffectNoResult)
2644(rule (vec_storerev src addr)
2645      (SideEffectNoResult.Inst (MInst.VecStoreRev src addr)))
2646
2647;; Helper for emitting `MInst.VecStoreByte16Rev` instructions.
2648(decl vec_store_byte16rev (Reg MemArg) SideEffectNoResult)
2649(rule (vec_store_byte16rev src addr)
2650      (SideEffectNoResult.Inst (MInst.VecStoreByte16Rev src addr)))
2651
2652;; Helper for emitting `MInst.VecStoreByte32Rev` instructions.
2653(decl vec_store_byte32rev (Reg MemArg) SideEffectNoResult)
2654(rule (vec_store_byte32rev src addr)
2655      (SideEffectNoResult.Inst (MInst.VecStoreByte32Rev src addr)))
2656
2657;; Helper for emitting `MInst.VecStoreByte64Rev` instructions.
2658(decl vec_store_byte64rev (Reg MemArg) SideEffectNoResult)
2659(rule (vec_store_byte64rev src addr)
2660      (SideEffectNoResult.Inst (MInst.VecStoreByte64Rev src addr)))
2661
2662;; Helper for emitting `MInst.VecStoreElt16Rev` instructions.
2663(decl vec_store_elt16rev (Reg MemArg) SideEffectNoResult)
2664(rule (vec_store_elt16rev src addr)
2665      (SideEffectNoResult.Inst (MInst.VecStoreElt16Rev src addr)))
2666
2667;; Helper for emitting `MInst.VecStoreElt32Rev` instructions.
2668(decl vec_store_elt32rev (Reg MemArg) SideEffectNoResult)
2669(rule (vec_store_elt32rev src addr)
2670      (SideEffectNoResult.Inst (MInst.VecStoreElt32Rev src addr)))
2671
2672;; Helper for emitting `MInst.VecStoreElt64Rev` instructions.
2673(decl vec_store_elt64rev (Reg MemArg) SideEffectNoResult)
2674(rule (vec_store_elt64rev src addr)
2675      (SideEffectNoResult.Inst (MInst.VecStoreElt64Rev src addr)))
2676
2677;; Helper for emitting `MInst.VecLoadReplicate` instructions.
2678(decl vec_load_replicate (Type MemArg) Reg)
2679(rule (vec_load_replicate (ty_vec128 ty @ (multi_lane size _)) addr)
2680      (let ((dst WritableReg (temp_writable_reg ty))
2681            (_ Unit (emit (MInst.VecLoadReplicate size dst addr))))
2682        dst))
2683
2684;; Helper for emitting `MInst.VecLoadReplicateRev` instructions.
2685(decl vec_load_replicate_rev (Type MemArg) Reg)
2686(rule (vec_load_replicate_rev (ty_vec128 ty @ (multi_lane size _)) addr)
2687      (let ((dst WritableReg (temp_writable_reg ty))
2688            (_ Unit (emit (MInst.VecLoadReplicateRev size dst addr))))
2689        dst))
2690
2691;; Helper for emitting `MInst.MovToVec128` instructions.
2692(decl mov_to_vec128 (Type Reg Reg) Reg)
2693(rule (mov_to_vec128 ty src1 src2)
2694      (let ((dst WritableReg (temp_writable_reg ty))
2695            (_ Unit (emit (MInst.MovToVec128 dst src1 src2))))
2696        dst))
2697
2698;; Helper for emitting `MInst.VecImmByteMask` instructions.
2699(decl vec_imm_byte_mask (Type u16) Reg)
2700(rule (vec_imm_byte_mask (vr128_ty ty) n)
2701      (let ((dst WritableReg (temp_writable_reg ty))
2702            (_ Unit (emit (MInst.VecImmByteMask dst n))))
2703        dst))
2704
2705;; Helper for emitting `MInst.VecImmBitMask` instructions.
2706(decl vec_imm_bit_mask (Type u8 u8) Reg)
2707(rule (vec_imm_bit_mask (ty_vec128 ty @ (multi_lane size _)) start_bit end_bit)
2708      (let ((dst WritableReg (temp_writable_reg ty))
2709            (_ Unit (emit (MInst.VecImmBitMask size dst start_bit end_bit))))
2710        dst))
2711
2712;; Helper for emitting `MInst.VecImmReplicate` instructions.
2713(decl vec_imm_replicate (Type i16) Reg)
2714(rule (vec_imm_replicate (ty_vec128 ty @ (multi_lane size _)) n)
2715      (let ((dst WritableReg (temp_writable_reg ty))
2716            (_ Unit (emit (MInst.VecImmReplicate size dst n))))
2717        dst))
2718
2719;; Helper for emitting `MInst.VecLoadLane` instructions.
2720(decl vec_load_lane (Type Reg MemArg u8) Reg)
2721(rule (vec_load_lane ty @ (multi_lane size _) src addr lane_imm)
2722      (let ((dst WritableReg (temp_writable_reg ty))
2723            (_ Unit (emit (MInst.VecLoadLane size dst src addr lane_imm))))
2724        dst))
2725
2726;; Helper for emitting `MInst.VecLoadLaneUndef` instructions.
2727(decl vec_load_lane_undef (Type MemArg u8) Reg)
2728(rule (vec_load_lane_undef ty @ (multi_lane size _) addr lane_imm)
2729      (let ((dst WritableReg (temp_writable_reg ty))
2730            (_ Unit (emit (MInst.VecLoadLaneUndef size dst addr lane_imm))))
2731        dst))
2732
2733;; Helper for emitting `MInst.VecLoadLaneRev` instructions.
2734(decl vec_load_lane_rev (Type Reg MemArg u8) Reg)
2735(rule (vec_load_lane_rev ty @ (multi_lane size _) src addr lane_imm)
2736      (let ((dst WritableReg (temp_writable_reg ty))
2737            (_ Unit (emit (MInst.VecLoadLaneRev size dst src addr lane_imm))))
2738        dst))
2739
2740;; Helper for emitting `MInst.VecLoadLaneRevUndef` instructions.
2741(decl vec_load_lane_rev_undef (Type MemArg u8) Reg)
2742(rule (vec_load_lane_rev_undef ty @ (multi_lane size _) addr lane_imm)
2743      (let ((dst WritableReg (temp_writable_reg ty))
2744            (_ Unit (emit (MInst.VecLoadLaneRevUndef size dst addr lane_imm))))
2745        dst))
2746
2747;; Helper for emitting `MInst.VecStoreLane` instructions.
2748(decl vec_store_lane (Type Reg MemArg u8) SideEffectNoResult)
2749(rule (vec_store_lane ty @ (multi_lane size _) src addr lane_imm)
2750      (SideEffectNoResult.Inst (MInst.VecStoreLane size src addr lane_imm)))
2751
2752;; Helper for emitting `MInst.VecStoreLaneRev` instructions.
2753(decl vec_store_lane_rev (Type Reg MemArg u8) SideEffectNoResult)
2754(rule (vec_store_lane_rev ty @ (multi_lane size _) src addr lane_imm)
2755      (SideEffectNoResult.Inst (MInst.VecStoreLaneRev size src addr lane_imm)))
2756
2757;; Helper for emitting `MInst.VecInsertLane` instructions.
2758(decl vec_insert_lane (Type Reg Reg u8 Reg) Reg)
2759(rule (vec_insert_lane ty @ (multi_lane size _) src1 src2 lane_imm lane_reg)
2760      (let ((dst WritableReg (temp_writable_reg ty))
2761            (_ Unit (emit (MInst.VecInsertLane size dst src1 src2 lane_imm lane_reg))))
2762        dst))
2763
2764;; Helper for emitting `MInst.VecInsertLaneUndef` instructions.
2765(decl vec_insert_lane_undef (Type Reg u8 Reg) Reg)
2766(rule (vec_insert_lane_undef ty @ (multi_lane size _) src lane_imm lane_reg)
2767      (let ((dst WritableReg (temp_writable_reg ty))
2768            (_ Unit (emit (MInst.VecInsertLaneUndef size dst src lane_imm lane_reg))))
2769        dst))
2770
2771;; Helper for emitting `MInst.VecExtractLane` instructions.
2772(decl vec_extract_lane (Type Reg u8 Reg) Reg)
2773(rule (vec_extract_lane (multi_lane size _) src lane_imm lane_reg)
2774      (let ((dst WritableReg (temp_writable_reg $I64))
2775            (_ Unit (emit (MInst.VecExtractLane size dst src lane_imm lane_reg))))
2776        dst))
2777
2778;; Helper for emitting `MInst.VecInsertLaneImm` instructions.
2779(decl vec_insert_lane_imm (Type Reg i16 u8) Reg)
2780(rule (vec_insert_lane_imm ty @ (multi_lane size _) src imm lane_imm)
2781      (let ((dst WritableReg (temp_writable_reg ty))
2782            (_ Unit (emit (MInst.VecInsertLaneImm size dst src imm lane_imm))))
2783        dst))
2784
2785;; Helper for emitting `MInst.VecInsertLaneImmUndef` instructions.
2786(decl vec_insert_lane_imm_undef (Type i16 u8) Reg)
2787(rule (vec_insert_lane_imm_undef ty @ (multi_lane size _) imm lane_imm)
2788      (let ((dst WritableReg (temp_writable_reg ty))
2789            (_ Unit (emit (MInst.VecInsertLaneImmUndef size dst imm lane_imm))))
2790        dst))
2791
2792;; Helper for emitting `MInst.VecReplicateLane` instructions.
2793(decl vec_replicate_lane (Type Reg u8) Reg)
2794(rule (vec_replicate_lane ty @ (multi_lane size _) src lane_imm)
2795      (let ((dst WritableReg (temp_writable_reg ty))
2796            (_ Unit (emit (MInst.VecReplicateLane size dst src lane_imm))))
2797        dst))
2798
2799;; Helper for emitting `MInst.VecEltRev` instructions.
2800(decl vec_elt_rev (Type Reg) Reg)
2801(rule (vec_elt_rev ty @ (multi_lane _ lanes) src)
2802      (let ((dst WritableReg (temp_writable_reg ty))
2803            (_ Unit (emit (MInst.VecEltRev lanes dst src))))
2804        dst))
2805
2806;; Helper for emitting `MInst.LoadSymbolReloc` instructions.
2807(decl load_symbol_reloc (SymbolReloc) Reg)
2808(rule (load_symbol_reloc symbol_reloc)
2809      (let ((dst WritableReg (temp_writable_reg $I64))
2810            (_ Unit (emit (MInst.LoadSymbolReloc dst symbol_reloc))))
2811        dst))
2812
2813;; Helper for emitting `MInst.LoadAddr` instructions.
2814(decl load_addr (MemArg) Reg)
2815(rule (load_addr mem)
2816      (let ((dst WritableReg (temp_writable_reg $I64))
2817            (_ Unit (emit (MInst.LoadAddr dst mem))))
2818        dst))
2819
2820;; Helper for emitting `MInst.Call` instructions.
2821(decl call_impl (WritableReg BoxCallInfo) SideEffectNoResult)
2822(rule (call_impl reg info)
2823      (SideEffectNoResult.Inst (MInst.Call reg info)))
2824
2825;; Helper for emitting `MInst.ReturnCall` instructions.
2826(decl return_call_impl (BoxReturnCallInfo) SideEffectNoResult)
2827(rule (return_call_impl info)
2828      (SideEffectNoResult.Inst (MInst.ReturnCall info)))
2829
2830;; Helper for emitting `MInst.Jump` instructions.
2831(decl jump_impl (MachLabel) SideEffectNoResult)
2832(rule (jump_impl target)
2833      (SideEffectNoResult.Inst (MInst.Jump target)))
2834
2835;; Helper for emitting `MInst.CondBr` instructions.
2836(decl cond_br (MachLabel MachLabel Cond) ConsumesFlags)
2837(rule (cond_br taken not_taken cond)
2838      (ConsumesFlags.ConsumesFlagsSideEffect (MInst.CondBr taken not_taken cond)))
2839
2840;; Helper for emitting `MInst.JTSequence` instructions.
2841(decl jt_sequence (Reg MachLabel Cond BoxVecMachLabel) ConsumesFlags)
2842(rule (jt_sequence ridx default default_cond targets)
2843      (ConsumesFlags.ConsumesFlagsSideEffect (MInst.JTSequence ridx default default_cond targets)))
2844
2845;; Emit a jump-table sequence based on a boolean condition for the
2846;; default label.
2847(decl jt_sequence_default_bool (Reg MachLabel ProducesBool BoxVecMachLabel) SideEffectNoResult)
2848(rule (jt_sequence_default_bool ridx default (ProducesBool.ProducesBool default_producer default_cond) targets)
2849      (with_flags_side_effect
2850       default_producer
2851       (jt_sequence ridx default default_cond targets)))
2852
2853;; Helpers for instruction sequences ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2854
2855;; Completed instruction sequence for use in MInst.Loop.
2856(type VecMInst (primitive VecMInst))
2857
2858;; Partial (mutable) instruction sequence in the process of being created.
2859(type VecMInstBuilder extern (enum))
2860
2861;; Create a new empty instruction sequence builder.
2862(decl inst_builder_new () VecMInstBuilder)
2863(extern constructor inst_builder_new inst_builder_new)
2864
2865;; Push an instruction to a sequence under construction.
2866(decl inst_builder_push (VecMInstBuilder MInst) Unit)
2867(extern constructor inst_builder_push inst_builder_push)
2868
2869;; Complete the sequence under construction.
2870(decl inst_builder_finish (VecMInstBuilder) VecMInst)
2871(extern constructor inst_builder_finish inst_builder_finish)
2872
2873;; It is not safe to write to virtual registers in the loop, so all destination
2874;; registers must be real.  This must be handled by the user of these helpers,
2875;; so we simply verify this constraint here.
2876(decl real_reg (WritableReg) WritableReg)
2877(extern extractor real_reg real_reg)
2878
2879;; Similarly, because we cannot allocate temp registers, if an instruction
2880;; requires matching source and destination registers, this needs to be handled
2881;; by the user.  Another helper to verify that constraint.
2882(decl pure partial same_reg (WritableReg Reg) Reg)
2883(extern constructor same_reg same_reg)
2884
2885;; Push a `MInst.AluRRR` instruction to a sequence.
2886(decl push_alu_reg (VecMInstBuilder ALUOp WritableReg Reg Reg) Reg)
2887(rule (push_alu_reg ib op (real_reg dst) src1 src2)
2888      (let ((_ Unit (inst_builder_push ib (MInst.AluRRR op dst src1 src2))))
2889        dst))
2890
2891;; Push a `MInst.AluRUImm32Shifted` instruction to a sequence.
2892(decl push_alu_uimm32shifted (VecMInstBuilder ALUOp WritableReg Reg UImm32Shifted) Reg)
2893(rule (push_alu_uimm32shifted ib op (real_reg dst) r imm)
2894      (let ((_ Unit (inst_builder_push ib (MInst.AluRUImm32Shifted op dst r imm))))
2895        dst))
2896
2897;; Push a `MInst.ShiftRR` instruction to a sequence.
2898(decl push_shift (VecMInstBuilder ShiftOp WritableReg Reg u8 Reg) Reg)
2899(rule (push_shift ib op (real_reg dst) src shift_imm shift_reg)
2900      (let ((_ Unit (inst_builder_push ib
2901                      (MInst.ShiftRR op dst src shift_imm shift_reg))))
2902        dst))
2903
2904;; Push a `MInst.RxSBG` instruction to a sequence.
2905(decl push_rxsbg (VecMInstBuilder RxSBGOp WritableReg Reg Reg u8 u8 i8) Reg)
2906(rule (push_rxsbg ib op (real_reg dst) r src start_bit end_bit rotate_amt)
2907      (if (same_reg dst r))
2908      (let ((_ Unit (inst_builder_push ib
2909                      (MInst.RxSBG op dst r src start_bit end_bit rotate_amt))))
2910        dst))
2911
2912;; Push a `MInst.UnaryRR` instruction to a sequence.
2913(decl push_unary (VecMInstBuilder UnaryOp WritableReg Reg) Reg)
2914(rule (push_unary ib op (real_reg dst) src)
2915      (let ((_ Unit (inst_builder_push ib (MInst.UnaryRR op dst src))))
2916        dst))
2917
2918;; Push a `MInst.AtomicCas32` instruction to a sequence.
2919(decl push_atomic_cas32 (VecMInstBuilder WritableReg Reg MemArg) Reg)
2920(rule (push_atomic_cas32 ib (real_reg dst_src1) src2 mem)
2921      (let ((_ Unit (inst_builder_push ib (MInst.AtomicCas32 dst_src1 dst_src1 src2 mem))))
2922        dst_src1))
2923
2924;; Push a `MInst.AtomicCas64` instruction to a sequence.
2925(decl push_atomic_cas64 (VecMInstBuilder WritableReg Reg MemArg) Reg)
2926(rule (push_atomic_cas64 ib (real_reg dst_src1) src2 mem)
2927      (let ((_ Unit (inst_builder_push ib (MInst.AtomicCas64 dst_src1 dst_src1 src2 mem))))
2928        dst_src1))
2929
2930;; Push instructions to break out of the loop if condition is met.
2931(decl push_break_if (VecMInstBuilder ProducesFlags Cond) Reg)
2932(rule (push_break_if ib (ProducesFlags.ProducesFlagsSideEffect inst) cond)
2933      (let ((_ Unit (inst_builder_push ib inst))
2934            (_ Unit (inst_builder_push ib (MInst.CondBreak cond))))
2935        (invalid_reg)))
2936
2937;; Emit a `MInst.Loop` instruction holding a loop body instruction sequence.
2938(decl emit_loop (VecMInstBuilder Cond) Unit)
2939(rule (emit_loop ib cond)
2940      (emit (MInst.Loop (inst_builder_finish ib) cond)))
2941
2942
2943;; Helpers for generating register moves ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2944
2945;; Copy GPR into a virtual register.
2946(decl copy_reg (Type Reg) Reg)
2947(rule 1 (copy_reg (gpr32_ty ty) src)
2948      (let ((dst WritableReg (temp_writable_reg ty))
2949            (_ Unit (emit (MInst.Mov32 dst src))))
2950        dst))
2951(rule 2 (copy_reg (gpr64_ty ty) src)
2952      (let ((dst WritableReg (temp_writable_reg ty))
2953            (_ Unit (emit (MInst.Mov64 dst src))))
2954        dst))
2955
2956;; Move from memory location into destination.
2957(decl emit_load (Type WritableReg MemArg) Unit)
2958(rule (emit_load $I32 dst addr)
2959      (emit (MInst.Load32 dst addr)))
2960(rule (emit_load $I64 dst addr)
2961      (emit (MInst.Load64 dst addr)))
2962
2963;; Helper for creating `MInst.MovPReg` instructions.
2964(decl mov_preg (PReg) Reg)
2965(rule (mov_preg src)
2966      (let ((dst WritableReg (temp_writable_reg $I64))
2967            (_ Unit (emit (MInst.MovPReg dst src))))
2968        dst))
2969
2970(decl preg_stack () PReg)
2971(extern constructor preg_stack preg_stack)
2972
2973(decl preg_gpr_0 () PReg)
2974(extern constructor preg_gpr_0 preg_gpr_0)
2975
2976;; Copy the physical stack register into a virtual register.
2977(decl sp () Reg)
2978(rule (sp)
2979      (mov_preg (preg_stack)))
2980
2981
2982;; Helpers for generating immediate values ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2983
2984;; Allocate a temporary register, initialized with an immediate.
2985(decl rec imm (Type u64) Reg)
2986
2987;; 16-bit (or smaller) result type, any value
2988(rule 7 (imm (fits_in_16 (ty_int ty)) n)
2989      (let ((dst WritableReg (temp_writable_reg ty))
2990            (_ Unit (emit (MInst.Mov32SImm16 dst (u16_cast_signed (u64_truncate_into_u16 n))))))
2991        dst))
2992
2993;; 32-bit result type, value fits in i16
2994(rule 6 (imm (gpr32_ty ty) (u32_pair _ m))
2995      (if-let (i16_from_i32 n) (u32_cast_signed m))
2996      (let ((dst WritableReg (temp_writable_reg ty))
2997            (_ Unit (emit (MInst.Mov32SImm16 dst n))))
2998        dst))
2999
3000;; 32-bit result type, any value
3001(rule 5 (imm (gpr32_ty ty) n)
3002      (let ((dst WritableReg (temp_writable_reg ty))
3003            (_ Unit (emit (MInst.Mov32Imm dst (u64_truncate_into_u32 n)))))
3004        dst))
3005
3006;; 64-bit result type, value fits in i16
3007(rule 4 (imm (gpr64_ty ty) m)
3008      (if-let (i16_from_i64 n) (u64_cast_signed m))
3009      (let ((dst WritableReg (temp_writable_reg ty))
3010            (_ Unit (emit (MInst.Mov64SImm16 dst n))))
3011        dst))
3012
3013;; 64-bit result type, value fits in i32
3014(rule 3 (imm (gpr64_ty ty) m)
3015      (if-let (i32_from_i64 n) (u64_cast_signed m))
3016      (let ((dst WritableReg (temp_writable_reg ty))
3017            (_ Unit (emit (MInst.Mov64SImm32 dst n))))
3018        dst))
3019
3020;; 64-bit result type, value fits in UImm16Shifted
3021(rule 2 (imm (gpr64_ty ty) (uimm16shifted_from_u64 n))
3022      (let ((dst WritableReg (temp_writable_reg ty))
3023            (_ Unit (emit (MInst.Mov64UImm16Shifted dst n))))
3024        dst))
3025
3026;; 64-bit result type, value fits in UImm32Shifted
3027(rule 1 (imm (gpr64_ty ty) (uimm32shifted_from_u64 n))
3028      (let ((dst WritableReg (temp_writable_reg ty))
3029            (_ Unit (emit (MInst.Mov64UImm32Shifted dst n))))
3030        dst))
3031
3032;; 64-bit result type, value with non-zero low-/high-parts.
3033(rule 0 (imm (gpr64_ty ty) (and (u64_nonzero_hipart hi)
3034                                (u64_nonzero_lopart lo)))
3035      (insert_imm ty (imm ty hi) lo))
3036
3037;; Replace low 32 bits of 64-bit value with immediate.
3038(decl insert_imm (Type Reg u64) Reg)
3039
3040;; Insertion, value fits in UImm16Shifted
3041(rule 1 (insert_imm ty src (uimm16shifted_from_u64 n))
3042      (let ((dst WritableReg (temp_writable_reg ty))
3043            (_ Unit (emit (MInst.Insert64UImm16Shifted dst src n))))
3044        dst))
3045
3046;; Insertion, value fits in UImm32Shifted
3047(rule (insert_imm ty src (uimm32shifted_from_u64 n))
3048      (let ((dst WritableReg (temp_writable_reg ty))
3049            (_ Unit (emit (MInst.Insert64UImm32Shifted dst src n))))
3050        dst))
3051
3052;; 16-bit floating-point type, any value.
3053(rule 8 (imm $F16 n)
3054      (vec_insert_lane_imm_undef $F16X8
3055                                 (u16_cast_signed (u64_truncate_into_u16 n))
3056                                 0))
3057
3058;; 32-bit floating-point type, any value.  Loaded from literal pool.
3059;; FIXME: This wastes 4 bytes of constant pool space.
3060;; TODO: use LZER to load 0.0
3061(rule 8 (imm $F32 n)
3062      (vec_load_lane_undef $F32X4
3063        (memarg_const (emit_u64_be_const (u32_pair (u64_truncate_into_u32 n) 0))) 0))
3064
3065;; 64-bit floating-point type, any value.  Loaded from literal pool.
3066;; TODO: use LZDR to load 0.0
3067(rule 8 (imm $F64 n)
3068      (vec_load_lane_undef $F64X2 (memarg_const (emit_u64_be_const n)) 0))
3069
3070;; Variant used for negative constants.
3071(decl imm32 (Type i32) Reg)
3072(rule (imm32 $I64 n)
3073      (let ((dst WritableReg (temp_writable_reg $I64))
3074            (_ Unit (emit (MInst.Mov64SImm32 dst n))))
3075        (writable_reg_to_reg dst)))
3076
3077;; Allocate a temporary register, initialized with a vector immediate.
3078(decl vec_imm (Type u128) Reg)
3079(rule 2 (vec_imm (vr128_ty ty) 0)
3080      (vec_imm_byte_mask ty 0))
3081(rule 1 (vec_imm (vr128_ty ty) (u64_pair n n))
3082      (vec_imm_splat $I64X2 n))
3083(rule (vec_imm (vr128_ty ty) n)
3084      (vec_load ty (memarg_const (emit_u128_be_const n))))
3085
3086;; Variant with replicated immediate.
3087;;
3088;; Recursion: bounded since recursive rules reduce number of lanes.
3089(decl rec vec_imm_splat (Type u64) Reg)
3090(rule 1 (vec_imm_splat (ty_vec128 ty) 0)
3091      (vec_imm_byte_mask ty 0))
3092(rule 2 (vec_imm_splat ty @ (multi_lane 8 _) n)
3093      (vec_imm_replicate ty (u16_cast_signed (u64_truncate_into_u16 n))))
3094(rule 2 (vec_imm_splat ty @ (multi_lane 16 _) n)
3095      (vec_imm_replicate ty (u16_cast_signed (u64_truncate_into_u16 n))))
3096(rule 2 (vec_imm_splat ty @ (multi_lane 32 _) (u32_pair _ m))
3097      (if-let (i16_from_i32 n) (u32_cast_signed m))
3098      (vec_imm_replicate ty n))
3099(rule 2 (vec_imm_splat ty @ (multi_lane 64 _) m)
3100      (if-let (i16_from_i64 n) (u64_cast_signed m))
3101      (vec_imm_replicate ty n))
3102(rule 3 (vec_imm_splat (multi_lane 16 _) (u32_pair _ (u16_pair _ (u8_pair n n))))
3103      (vec_imm_splat $I8X16 n))
3104(rule 3 (vec_imm_splat (multi_lane 32 _) (u32_pair _ (u16_pair n n)))
3105      (vec_imm_splat $I16X8 n))
3106(rule 3 (vec_imm_splat (multi_lane 64 _) (u32_pair n n))
3107      (vec_imm_splat $I32X4 n))
3108;; FIXME: This wastes 4 bytes of constant pool space.
3109(rule 0 (vec_imm_splat ty @ (multi_lane 32 _) n)
3110      (vec_load_replicate ty
3111        (memarg_const (emit_u64_be_const (u32_pair (u64_truncate_into_u32 n) 0)))))
3112(rule 0 (vec_imm_splat ty @ (multi_lane 64 _) n)
3113      (vec_load_replicate ty (memarg_const (emit_u64_be_const n))))
3114
3115;; Helpers for generating extensions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3116
3117;; Result type of extending integer `Type` to 32 bits if smaller.
3118(decl ty_ext32 (Type) Type)
3119(rule (ty_ext32 $I8) $I32)
3120(rule (ty_ext32 $I16) $I32)
3121(rule (ty_ext32 $I32) $I32)
3122(rule (ty_ext32 $I64) $I64)
3123
3124;; Result type of extending integer `Type` to 64 bits if smaller.
3125(decl ty_ext64 (Type) Type)
3126(rule (ty_ext64 $I8) $I64)
3127(rule (ty_ext64 $I16) $I64)
3128(rule (ty_ext64 $I32) $I64)
3129(rule (ty_ext64 $I64) $I64)
3130
3131
3132;; Zero-extend a register from a smaller `Type` into a 32-bit register.
3133(decl zext32_reg (Type Reg) Reg)
3134(rule (zext32_reg ty src)
3135      (let ((dst WritableReg (temp_writable_reg $I32))
3136            (_ Unit (emit (MInst.Extend dst src false (ty_bits ty) 32))))
3137        dst))
3138
3139;; Sign-extend a register from a smaller `Type` into a 32-bit register.
3140(decl sext32_reg (Type Reg) Reg)
3141(rule (sext32_reg ty src)
3142      (let ((dst WritableReg (temp_writable_reg $I32))
3143            (_ Unit (emit (MInst.Extend dst src true (ty_bits ty) 32))))
3144        dst))
3145
3146;; Zero-extend a register from a smaller `Type` into a 64-bit register.
3147(decl zext64_reg (Type Reg) Reg)
3148(rule (zext64_reg ty src)
3149      (let ((dst WritableReg (temp_writable_reg $I64))
3150            (_ Unit (emit (MInst.Extend dst src false (ty_bits ty) 64))))
3151        dst))
3152
3153;; Sign-extend a register from a smaller `Type` into a 64-bit register.
3154(decl sext64_reg (Type Reg) Reg)
3155(rule (sext64_reg ty src)
3156      (let ((dst WritableReg (temp_writable_reg $I64))
3157            (_ Unit (emit (MInst.Extend dst src true (ty_bits ty) 64))))
3158        dst))
3159
3160
3161;; Zero-extend memory from a smaller `Type` into a 32-bit register.
3162(decl zext32_mem (Type MemArg) Reg)
3163(rule (zext32_mem $I8 mem)
3164      (let ((dst WritableReg (temp_writable_reg $I32))
3165            (_ Unit (emit (MInst.Load32ZExt8 dst mem))))
3166        dst))
3167(rule (zext32_mem $I16 mem)
3168      (let ((dst WritableReg (temp_writable_reg $I32))
3169            (_ Unit (emit (MInst.Load32ZExt16 dst mem))))
3170        dst))
3171
3172;; Sign-extend memory from a smaller `Type` into a 32-bit register.
3173(decl sext32_mem (Type MemArg) Reg)
3174(rule (sext32_mem $I8 mem)
3175      (let ((dst WritableReg (temp_writable_reg $I32))
3176            (_ Unit (emit (MInst.Load32SExt8 dst mem))))
3177        dst))
3178(rule (sext32_mem $I16 mem)
3179      (let ((dst WritableReg (temp_writable_reg $I32))
3180            (_ Unit (emit (MInst.Load32SExt16 dst mem))))
3181        dst))
3182
3183;; Zero-extend memory from a smaller `Type` into a 64-bit register.
3184(decl zext64_mem (Type MemArg) Reg)
3185(rule (zext64_mem $I8 mem)
3186      (let ((dst WritableReg (temp_writable_reg $I64))
3187            (_ Unit (emit (MInst.Load64ZExt8 dst mem))))
3188        dst))
3189(rule (zext64_mem $I16 mem)
3190      (let ((dst WritableReg (temp_writable_reg $I64))
3191            (_ Unit (emit (MInst.Load64ZExt16 dst mem))))
3192        dst))
3193(rule (zext64_mem $I32 mem)
3194      (let ((dst WritableReg (temp_writable_reg $I64))
3195            (_ Unit (emit (MInst.Load64ZExt32 dst mem))))
3196        dst))
3197
3198;; Sign-extend memory from a smaller `Type` into a 64-bit register.
3199(decl sext64_mem (Type MemArg) Reg)
3200(rule (sext64_mem $I8 mem)
3201      (let ((dst WritableReg (temp_writable_reg $I64))
3202            (_ Unit (emit (MInst.Load64SExt8 dst mem))))
3203        dst))
3204(rule (sext64_mem $I16 mem)
3205      (let ((dst WritableReg (temp_writable_reg $I64))
3206            (_ Unit (emit (MInst.Load64SExt16 dst mem))))
3207        dst))
3208(rule (sext64_mem $I32 mem)
3209      (let ((dst WritableReg (temp_writable_reg $I64))
3210            (_ Unit (emit (MInst.Load64SExt32 dst mem))))
3211        dst))
3212
3213
3214;; Place `Value` into a register, zero-extending to 32 bits if smaller.
3215(decl put_in_reg_zext32 (Value) Reg)
3216(rule 3 (put_in_reg_zext32 (and (value_type ty) (u64_from_value val)))
3217      (imm (ty_ext32 ty) val))
3218(rule 1 (put_in_reg_zext32 (and (value_type (fits_in_16 ty)) (sinkable_load load)))
3219      (zext32_mem ty (sink_load load)))
3220(rule 0 (put_in_reg_zext32 val @ (value_type (fits_in_16 ty)))
3221      (zext32_reg ty val))
3222(rule 2 (put_in_reg_zext32 val @ (value_type (ty_32_or_64 _ty)))
3223      val)
3224
3225;; Place `Value` into a register, sign-extending to 32 bits if smaller.
3226(decl put_in_reg_sext32 (Value) Reg)
3227(rule 3 (put_in_reg_sext32 (and (value_type ty) (u64_from_signed_value val)))
3228      (imm (ty_ext32 ty) val))
3229(rule 1 (put_in_reg_sext32 (and (value_type (fits_in_16 ty)) (sinkable_load load)))
3230      (sext32_mem ty (sink_load load)))
3231(rule 0 (put_in_reg_sext32 val @ (value_type (fits_in_16 ty)))
3232      (sext32_reg ty val))
3233(rule 2 (put_in_reg_sext32 val @ (value_type (ty_32_or_64 _ty)))
3234      val)
3235
3236;; Place `Value` into a register, zero-extending to 64 bits if smaller.
3237(decl put_in_reg_zext64 (Value) Reg)
3238(rule 3 (put_in_reg_zext64 (and (value_type ty) (u64_from_value val)))
3239      (imm (ty_ext64 ty) val))
3240(rule 1 (put_in_reg_zext64 (and (value_type (gpr32_ty ty)) (sinkable_load load)))
3241      (zext64_mem ty (sink_load load)))
3242(rule 0 (put_in_reg_zext64 val @ (value_type (gpr32_ty ty)))
3243      (zext64_reg ty val))
3244(rule 2 (put_in_reg_zext64 val @ (value_type (gpr64_ty ty)))
3245      val)
3246
3247;; Place `Value` into a register, sign-extending to 64 bits if smaller.
3248(decl put_in_reg_sext64 (Value) Reg)
3249(rule 3 (put_in_reg_sext64 (and (value_type ty) (u64_from_signed_value val)))
3250      (imm (ty_ext64 ty) val))
3251(rule 1 (put_in_reg_sext64 (and (value_type (gpr32_ty ty)) (sinkable_load load)))
3252      (sext64_mem ty (sink_load load)))
3253(rule 0 (put_in_reg_sext64 val @ (value_type (gpr32_ty ty)))
3254      (sext64_reg ty val))
3255(rule 2 (put_in_reg_sext64 val @ (value_type (gpr64_ty ty)))
3256      val)
3257
3258
3259;; Helpers for generating conditional moves ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3260
3261;; Conditionally select between immediate and source register.
3262(decl cmov_imm (Type Cond i16 Reg) ConsumesFlags)
3263(rule 0 (cmov_imm (gpr32_ty ty) cond imm_true reg_false)
3264      (let ((dst WritableReg (temp_writable_reg ty))
3265            (inst MInst (MInst.CMov32SImm16 dst cond reg_false imm_true)))
3266        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3267(rule 1 (cmov_imm (gpr64_ty ty) cond imm_true reg_false)
3268      (let ((dst WritableReg (temp_writable_reg ty))
3269            (inst MInst (MInst.CMov64SImm16 dst cond reg_false imm_true)))
3270        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3271
3272;; Conditionally select between two immediates.
3273(decl cmov_imm_imm (Type Cond i16 i16) ConsumesFlags)
3274(rule 0 (cmov_imm_imm (gpr32_ty ty) cond imm_true imm_false)
3275      (let ((tmp1 WritableReg (temp_writable_reg ty))
3276            (tmp2 WritableReg (temp_writable_reg ty))
3277            (inst1 MInst (MInst.Mov32SImm16 tmp1 imm_false))
3278            (inst2 MInst (MInst.CMov32SImm16 tmp2 cond tmp1 imm_true))
3279            (dst ValueRegs (value_reg tmp2)))
3280        (ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs inst1 inst2 dst)))
3281(rule 1 (cmov_imm_imm (gpr64_ty ty) cond imm_true imm_false)
3282      (let ((tmp1 WritableReg (temp_writable_reg ty))
3283            (tmp2 WritableReg (temp_writable_reg ty))
3284            (inst1 MInst (MInst.Mov64SImm16 tmp1 imm_false))
3285            (inst2 MInst (MInst.CMov64SImm16 tmp2 cond tmp1 imm_true))
3286            (dst ValueRegs (value_reg tmp2)))
3287        (ConsumesFlags.ConsumesFlagsTwiceReturnsValueRegs inst1 inst2 dst)))
3288
3289;; Conditionally select between two source registers.
3290(decl cmov_reg_reg (Type Cond Reg Reg) ConsumesFlags)
3291(rule 1 (cmov_reg_reg (gpr32_ty ty) cond reg_true reg_false)
3292      (let ((dst WritableReg (temp_writable_reg ty))
3293            (inst MInst (MInst.CMov32 dst cond reg_false reg_true)))
3294        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3295(rule 2 (cmov_reg_reg (gpr64_ty ty) cond reg_true reg_false)
3296      (let ((dst WritableReg (temp_writable_reg ty))
3297            (inst MInst (MInst.CMov64 dst cond reg_false reg_true)))
3298        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3299(rule 3 (cmov_reg_reg $F16 cond reg_true reg_false)
3300      (let ((dst WritableReg (temp_writable_reg $F16))
3301            (inst MInst (MInst.FpuCMov32 dst cond reg_false reg_true)))
3302        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3303(rule 3 (cmov_reg_reg $F32 cond reg_true reg_false)
3304      (let ((dst WritableReg (temp_writable_reg $F32))
3305            (inst MInst (MInst.FpuCMov32 dst cond reg_false reg_true)))
3306        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3307(rule 3 (cmov_reg_reg $F64 cond reg_true reg_false)
3308      (let ((dst WritableReg (temp_writable_reg $F64))
3309            (inst MInst (MInst.FpuCMov64 dst cond reg_false reg_true)))
3310        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3311(rule 0 (cmov_reg_reg (vr128_ty ty) cond reg_true reg_false)
3312      (let ((dst WritableReg (temp_writable_reg $F64))
3313            (inst MInst (MInst.VecCMov dst cond reg_false reg_true)))
3314        (ConsumesFlags.ConsumesFlagsReturnsReg inst dst)))
3315
3316
3317;; Helpers for generating conditional traps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3318
3319(decl trap_if (ProducesFlags Cond TrapCode) Reg)
3320(rule (trap_if producer cond trap_code)
3321      (let ((consumer ConsumesFlags (trap_if_impl cond trap_code))
3322            (_ InstOutput (side_effect (with_flags_side_effect producer consumer))))
3323        (invalid_reg)))
3324
3325(decl icmps_reg_and_trap (Type Reg Reg Cond TrapCode) Reg)
3326(rule (icmps_reg_and_trap ty src1 src2 cond trap_code)
3327      (let ((_ Unit (emit (MInst.CmpTrapRR (cmpop_cmps ty)
3328                                           src1 src2 cond trap_code))))
3329        (invalid_reg)))
3330
3331(decl icmps_simm16_and_trap (Type Reg i16 Cond TrapCode) Reg)
3332(rule (icmps_simm16_and_trap ty src imm cond trap_code)
3333      (let ((_ Unit (emit (MInst.CmpTrapRSImm16 (cmpop_cmps ty)
3334                                                src imm cond trap_code))))
3335        (invalid_reg)))
3336
3337(decl icmpu_reg_and_trap (Type Reg Reg Cond TrapCode) Reg)
3338(rule (icmpu_reg_and_trap ty src1 src2 cond trap_code)
3339      (let ((_ Unit (emit (MInst.CmpTrapRR (cmpop_cmpu ty)
3340                                           src1 src2 cond trap_code))))
3341        (invalid_reg)))
3342
3343(decl icmpu_uimm16_and_trap (Type Reg u16 Cond TrapCode) Reg)
3344(rule (icmpu_uimm16_and_trap ty src imm cond trap_code)
3345      (let ((_ Unit (emit (MInst.CmpTrapRUImm16 (cmpop_cmpu ty)
3346                                                src imm cond trap_code))))
3347        (invalid_reg)))
3348
3349(decl trap_impl (TrapCode) SideEffectNoResult)
3350(rule (trap_impl trap_code)
3351      (SideEffectNoResult.Inst (MInst.Trap trap_code)))
3352
3353(decl trap_if_impl (Cond TrapCode) ConsumesFlags)
3354(rule (trap_if_impl cond trap_code)
3355      (ConsumesFlags.ConsumesFlagsSideEffect (MInst.TrapIf cond trap_code)))
3356
3357(decl debugtrap_impl () SideEffectNoResult)
3358(rule (debugtrap_impl)
3359      (SideEffectNoResult.Inst (MInst.Debugtrap)))
3360
3361
3362;; Helpers for handling boolean conditions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3363
3364;; Capture a flags-producing instruction together with a condition code mask
3365;; that tells how to interpret the resulting condition code.  The result can
3366;; be used to represent a boolean condition.
3367(type ProducesBool (enum (ProducesBool (producer ProducesFlags) (cond Cond))))
3368(decl bool (ProducesFlags Cond) ProducesBool)
3369(rule (bool producer cond) (ProducesBool.ProducesBool producer cond))
3370
3371;; Invert boolean condition.
3372(decl invert_bool (ProducesBool) ProducesBool)
3373(rule (invert_bool (ProducesBool.ProducesBool producer cond))
3374      (bool producer (invert_cond cond)))
3375
3376;; Use a boolean condition to select between two registers.
3377(decl select_bool_reg (Type ProducesBool Reg Reg) Reg)
3378(rule (select_bool_reg ty (ProducesBool.ProducesBool producer cond) reg_true reg_false)
3379      (with_flags_reg producer (cmov_reg_reg ty cond reg_true reg_false)))
3380
3381;; Use a boolean condition to select between two immediate values.
3382(decl select_bool_imm (Type ProducesBool i16 i16) Reg)
3383(rule (select_bool_imm ty (ProducesBool.ProducesBool producer cond) imm_true imm_false)
3384      (with_flags_reg producer (cmov_imm_imm ty cond imm_true imm_false)))
3385
3386;; Lower a boolean condition to the values 1/0. This rule is only used in the
3387;; context of instructions that return $I8 results.
3388(decl lower_bool (Type ProducesBool) Reg)
3389(rule (lower_bool $I8 cond) (select_bool_imm $I8 cond 1 0))
3390
3391;; Lower a boolean condition to the values -1/0.
3392;;
3393;; Recursion: at most once to reduce 128-bit to 64-bit case.
3394(decl rec lower_bool_to_mask (Type ProducesBool) Reg)
3395(rule 0 (lower_bool_to_mask (fits_in_64 ty) producer)
3396      (select_bool_imm ty producer -1 0))
3397
3398(rule 1 (lower_bool_to_mask $I128 producer)
3399      (let ((res Reg (lower_bool_to_mask $I64 producer)))
3400        (mov_to_vec128 $I128 res res)))
3401
3402;; Emit a conditional branch based on a boolean condition.
3403(decl cond_br_bool (ProducesBool MachLabel MachLabel) SideEffectNoResult)
3404(rule (cond_br_bool (ProducesBool.ProducesBool producer cond) taken not_taken)
3405      (with_flags_side_effect producer (cond_br taken not_taken cond)))
3406
3407;; Emit a conditional trap based on a boolean condition.
3408(decl trap_if_bool (ProducesBool TrapCode) SideEffectNoResult)
3409(rule (trap_if_bool (ProducesBool.ProducesBool producer cond) trap_code)
3410      (with_flags_side_effect producer (trap_if_impl cond trap_code)))
3411
3412
3413;;;; Helpers for compare-and-swap loops ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3414
3415;; We use the emit_loop functionality to create compare-and-swap loops.
3416;; As noted there, code inside a loop emitted via emit_loop cannot write
3417;; to any virtual register, only hard registers.  We use the two reserved
3418;; registers %r0 and %r1 in compare-and-swap loops.
3419
3420;; %r0 always holds the value currently loaded from the memory location.
3421(decl casloop_val_reg () WritableReg)
3422(rule (casloop_val_reg) (writable_gpr 0))
3423
3424;; %r1 is available to compute the new value to be written.
3425(decl casloop_tmp_reg () WritableReg)
3426(rule (casloop_tmp_reg) (writable_gpr 1))
3427
3428;; This takes a loop body for a compare-and-swap loop, completes it by
3429;; adding the actual compare-and-swap instruction, and emits the initial
3430;; memory load followed by the loop itself.  "val" is the new value to
3431;; be written if the memory location still holds the old value in %r0.
3432;; The result should be passed to "casloop_result" or (in the case of
3433;; subword loops) to "casloop_rotate_result".
3434(decl casloop_emit (VecMInstBuilder Type MemFlags Reg Reg) PReg)
3435(rule (casloop_emit ib ty flags aligned_addr val)
3436      (let (
3437            ;; Construct a memory argument for the aligned word.
3438            (aligned_mem MemArg (memarg_reg_plus_off aligned_addr 0 0 flags))
3439            ;; Add the compare-and-swap instruction to the builder.
3440            (result Reg (push_atomic_cas ib (ty_ext32 ty)
3441                          (casloop_val_reg) val aligned_mem))
3442            ;; Emit initial load followed by compare-and-swap loop.
3443            (_ Unit (emit_load (ty_ext32 ty) (casloop_val_reg) aligned_mem))
3444            (_ Unit (emit_loop ib (intcc_as_cond (IntCC.NotEqual)))))
3445
3446        ;; push_atomic_cas above returns its destination register argument,
3447        ;; cas_loop_val_reg, as its result. As cas_loop_val_reg is a writable
3448        ;; version of `gpr 0`, we return that directly here as a physical
3449        ;; register to avoid accidentally using it with a non-preg move
3450        ;; instruction.
3451        (preg_gpr_0)))
3452
3453;; Compute the previous memory value after a (fullword) compare-and-swap loop.
3454;; In the big-endian case, the value is already correct, but may need to be
3455;; copied out of the hard register.  In the little-endian case, we need to
3456;; byte-swap since the compare-and-swap instruction is always big-endian.
3457(decl casloop_result (Type MemFlags PReg) Reg)
3458(rule 1 (casloop_result (ty_32_or_64 ty) (bigendian) result)
3459      (mov_preg result))
3460(rule (casloop_result (ty_32_or_64 ty) (littleendian) result)
3461      (bswap_reg ty (preg_to_reg result)))
3462
3463;; Emit a fullword compare-and-swap loop, returning the previous memory value.
3464(decl casloop (VecMInstBuilder Type MemFlags Reg Reg) Reg)
3465(rule (casloop ib ty flags aligned_addr val)
3466      (casloop_result ty flags (casloop_emit ib ty flags aligned_addr val)))
3467
3468;; For types smaller than $I32, we have no native compare-and-swap
3469;; instruction, so we need to perform the compare-and-swap loop on the
3470;; surrounding aligned word.  To actually operate on the target $I8 or
3471;; $I16 data, that aligned word then needs to be rotated by an amount
3472;; determined by the low address bits.
3473
3474;; Determine the rotate amount to bring the target data into a position
3475;; in the high bytes of the enclosing $I32.  Since the compare-and-swap
3476;; instruction performs a big-endian memory access, this can be done by
3477;; rotating (left) by "(addr & 3) * 8" bits, or "(addr << 3) & 31" bits.
3478;; We can omit the "& 31" since this is implicit with a 32-bit rotate.
3479(decl casloop_bitshift (Reg) Reg)
3480(rule (casloop_bitshift addr)
3481      (lshl_imm $I32 addr 3))
3482
3483;; The address of the surrounding 32-bit word, by masking off low bits.
3484(decl casloop_aligned_addr (Reg) Reg)
3485(rule (casloop_aligned_addr addr)
3486      (and_uimm16shifted $I64 addr (uimm16shifted 0xfffc 0)))
3487
3488;; Push an instruction sequence to rotate a value loaded from memory
3489;; to the well-defined location: the high bytes in case of a big-endian
3490;; memory operation, and the low bytes in the little-endian case.
3491;; (This is somewhat arbitrary but chosen to allow the most efficient
3492;; sequences to compute the various atomic operations.)
3493;; Note that $I8 accesses always use the big-endian case.
3494(decl casloop_rotate_in (VecMInstBuilder Type MemFlags Reg Reg) Reg)
3495(rule (casloop_rotate_in ib $I8 _ bitshift val)
3496      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 0 bitshift))
3497(rule 1 (casloop_rotate_in ib $I16 (bigendian) bitshift val)
3498      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 0 bitshift))
3499(rule (casloop_rotate_in ib $I16 (littleendian) bitshift val)
3500      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 16 bitshift))
3501
3502;; The inverse operation: rotate values back to the original memory order.
3503;; This can be done by simply using the negated shift count.  As an extra
3504;; optimization, we note that in the $I16 case the shift count can only
3505;; take the values 0 or 16, both of which negate to themselves (mod 32),
3506;; so the explicit negation operation can be omitted here.
3507(decl casloop_rotate_out (VecMInstBuilder Type MemFlags Reg Reg) Reg)
3508(rule (casloop_rotate_out ib $I8 _ bitshift val)
3509      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 0 (neg_reg $I32 bitshift)))
3510(rule 1 (casloop_rotate_out ib $I16 (bigendian) bitshift val)
3511      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 0 bitshift))
3512(rule (casloop_rotate_out ib $I16 (littleendian) bitshift val)
3513      (push_rot_imm_reg ib $I32 (casloop_tmp_reg) val 16 bitshift))
3514
3515;; Compute the previous memory value after a subword compare-and-swap loop.
3516;; This is similar to casloop_rotate_in, but brings the value to the *low*
3517;; bytes.  This can be achieved simply by adding the type size to the rotate
3518;; amount, which can be done within the same instruction.  In the little-
3519;; endian case, we also need to byte-swap the result.  Since we only have
3520;; a 32-bit byte-swap instruction, we load the value to the high bytes in
3521;; this case before performing the 32-bit byte-swap.
3522(decl casloop_rotate_result (Type MemFlags Reg Reg) Reg)
3523(rule (casloop_rotate_result $I8 _ bitshift result)
3524      (rot_imm_reg $I32 result 8 bitshift))
3525(rule 1 (casloop_rotate_result $I16 (bigendian) bitshift result)
3526      (rot_imm_reg $I32 result 16 bitshift))
3527(rule (casloop_rotate_result $I16 (littleendian) bitshift result)
3528      (bswap_reg $I32 (rot_reg $I32 result bitshift)))
3529
3530;; Emit a subword compare-and-swap loop, returning the previous memory value.
3531(decl casloop_subword (VecMInstBuilder Type MemFlags Reg Reg Reg) Reg)
3532(rule (casloop_subword ib ty flags aligned_addr bitshift val)
3533      (casloop_rotate_result ty flags bitshift
3534        (casloop_emit ib ty flags aligned_addr val)))
3535
3536
3537;; Helpers for generating `call` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3538
3539(decl gen_call_info (Sig CallInstDest CallArgList CallRetList OptionTryCallInfo bool) BoxCallInfo)
3540(extern constructor gen_call_info gen_call_info)
3541
3542(decl gen_return_call_info (Sig CallInstDest CallArgList) BoxReturnCallInfo)
3543(extern constructor gen_return_call_info gen_return_call_info)
3544
3545(decl abi_emit_call_adjust_stack (Sig) Unit)
3546(extern constructor abi_emit_call_adjust_stack abi_emit_call_adjust_stack)
3547
3548(decl abi_emit_return_call_adjust_stack (Sig) Unit)
3549(extern constructor abi_emit_return_call_adjust_stack abi_emit_return_call_adjust_stack)
3550
3551(decl abi_prepare_args (Sig ValueSlice) ValueRegsVec)
3552(extern constructor abi_prepare_args abi_prepare_args)
3553
3554(decl writable_link_reg () WritableReg)
3555(rule (writable_link_reg) (writable_gpr 14))
3556
3557
3558;; Helpers for generating vector pack and unpack instructions ;;;;;;;;;;;;;;;;;;
3559
3560(decl vec_widen_type (Type) Type)
3561(rule (vec_widen_type $I8X16) $I16X8)
3562(rule (vec_widen_type $I16X8) $I32X4)
3563(rule (vec_widen_type $I32X4) $I64X2)
3564
3565(decl vecop_pack (Type) VecBinaryOp)
3566(rule (vecop_pack $I16X8) (VecBinaryOp.Pack16x8))
3567(rule (vecop_pack $I32X4) (VecBinaryOp.Pack32x4))
3568(rule (vecop_pack $I64X2) (VecBinaryOp.Pack64x2))
3569
3570(decl vec_pack (Type Reg Reg) Reg)
3571(rule (vec_pack ty x y) (vec_rrr ty (vecop_pack ty) x y))
3572
3573(decl vecop_pack_ssat (Type) VecBinaryOp)
3574(rule (vecop_pack_ssat $I16X8) (VecBinaryOp.PackSSat16x8))
3575(rule (vecop_pack_ssat $I32X4) (VecBinaryOp.PackSSat32x4))
3576(rule (vecop_pack_ssat $I64X2) (VecBinaryOp.PackSSat64x2))
3577
3578(decl vec_pack_ssat (Type Reg Reg) Reg)
3579(rule (vec_pack_ssat ty x y) (vec_rrr ty (vecop_pack_ssat ty) x y))
3580
3581(decl vecop_pack_usat (Type) VecBinaryOp)
3582(rule (vecop_pack_usat $I16X8) (VecBinaryOp.PackUSat16x8))
3583(rule (vecop_pack_usat $I32X4) (VecBinaryOp.PackUSat32x4))
3584(rule (vecop_pack_usat $I64X2) (VecBinaryOp.PackUSat64x2))
3585
3586(decl vec_pack_usat (Type Reg Reg) Reg)
3587(rule (vec_pack_usat ty x y) (vec_rrr ty (vecop_pack_usat ty) x y))
3588
3589(decl vecop_unpacks_low (Type) VecUnaryOp)
3590(rule (vecop_unpacks_low $I8X16) (VecUnaryOp.UnpackSLow8x16))
3591(rule (vecop_unpacks_low $I16X8) (VecUnaryOp.UnpackSLow16x8))
3592(rule (vecop_unpacks_low $I32X4) (VecUnaryOp.UnpackSLow32x4))
3593
3594(decl vec_unpacks_low (Type Reg) Reg)
3595(rule (vec_unpacks_low ty x) (vec_rr ty (vecop_unpacks_low ty) x))
3596
3597(decl vecop_unpacks_high (Type) VecUnaryOp)
3598(rule (vecop_unpacks_high $I8X16) (VecUnaryOp.UnpackSHigh8x16))
3599(rule (vecop_unpacks_high $I16X8) (VecUnaryOp.UnpackSHigh16x8))
3600(rule (vecop_unpacks_high $I32X4) (VecUnaryOp.UnpackSHigh32x4))
3601
3602(decl vec_unpacks_high (Type Reg) Reg)
3603(rule (vec_unpacks_high ty x) (vec_rr ty (vecop_unpacks_high ty) x))
3604
3605(decl vecop_unpacku_low (Type) VecUnaryOp)
3606(rule (vecop_unpacku_low $I8X16) (VecUnaryOp.UnpackULow8x16))
3607(rule (vecop_unpacku_low $I16X8) (VecUnaryOp.UnpackULow16x8))
3608(rule (vecop_unpacku_low $I32X4) (VecUnaryOp.UnpackULow32x4))
3609
3610(decl vec_unpacku_low (Type Reg) Reg)
3611(rule (vec_unpacku_low ty x) (vec_rr ty (vecop_unpacku_low ty) x))
3612
3613(decl vecop_unpacku_high (Type) VecUnaryOp)
3614(rule (vecop_unpacku_high $I8X16) (VecUnaryOp.UnpackUHigh8x16))
3615(rule (vecop_unpacku_high $I16X8) (VecUnaryOp.UnpackUHigh16x8))
3616(rule (vecop_unpacku_high $I32X4) (VecUnaryOp.UnpackUHigh32x4))
3617
3618(decl vec_unpacku_high (Type Reg) Reg)
3619(rule (vec_unpacku_high ty x) (vec_rr ty (vecop_unpacku_high ty) x))
3620
3621;; Versions of pack using current lane order semantics.
3622;; First source operand contains values that will end up in the
3623;; lower-numbered lanes of the result, second operand contains
3624;; values that will end up in the higher-numbered lanes.
3625
3626(decl vec_pack_lane_order (Type Reg Reg) Reg)
3627(rule 1 (vec_pack_lane_order ty x y)
3628      (if-let (LaneOrder.BigEndian) (lane_order))
3629      (vec_pack ty x y))
3630(rule (vec_pack_lane_order ty x y)
3631      (if-let (LaneOrder.LittleEndian) (lane_order))
3632      (vec_pack ty y x))
3633
3634(decl vec_pack_ssat_lane_order (Type Reg Reg) Reg)
3635(rule 1 (vec_pack_ssat_lane_order ty x y)
3636      (if-let (LaneOrder.BigEndian) (lane_order))
3637      (vec_pack_ssat ty x y))
3638(rule (vec_pack_ssat_lane_order ty x y)
3639      (if-let (LaneOrder.LittleEndian) (lane_order))
3640      (vec_pack_ssat ty y x))
3641
3642(decl vec_pack_usat_lane_order (Type Reg Reg) Reg)
3643(rule 1 (vec_pack_usat_lane_order ty x y)
3644      (if-let (LaneOrder.BigEndian) (lane_order))
3645      (vec_pack_usat ty x y))
3646(rule (vec_pack_usat_lane_order ty x y)
3647      (if-let (LaneOrder.LittleEndian) (lane_order))
3648      (vec_pack_usat ty y x))
3649
3650;; Versions of unpack using current lane order semantics.
3651;; unpack_low will consume values from the lower-numbered
3652;; lanes of the input, and unpack_high will consume values
3653;; from higher-numbered lanes.
3654
3655(decl vec_unpacks_low_lane_order (Type Reg) Reg)
3656(rule 1 (vec_unpacks_low_lane_order ty x)
3657      (if-let (LaneOrder.BigEndian) (lane_order))
3658      (vec_unpacks_high ty x))
3659(rule (vec_unpacks_low_lane_order ty x)
3660      (if-let (LaneOrder.LittleEndian) (lane_order))
3661      (vec_unpacks_low ty x))
3662
3663(decl vec_unpacks_high_lane_order (Type Reg) Reg)
3664(rule 1 (vec_unpacks_high_lane_order ty x)
3665      (if-let (LaneOrder.BigEndian) (lane_order))
3666      (vec_unpacks_low ty x))
3667(rule (vec_unpacks_high_lane_order ty x)
3668      (if-let (LaneOrder.LittleEndian) (lane_order))
3669      (vec_unpacks_high ty x))
3670
3671(decl vec_unpacku_low_lane_order (Type Reg) Reg)
3672(rule 1 (vec_unpacku_low_lane_order ty x)
3673      (if-let (LaneOrder.BigEndian) (lane_order))
3674      (vec_unpacku_high ty x))
3675(rule (vec_unpacku_low_lane_order ty x)
3676      (if-let (LaneOrder.LittleEndian) (lane_order))
3677      (vec_unpacku_low ty x))
3678
3679(decl vec_unpacku_high_lane_order (Type Reg) Reg)
3680(rule 1 (vec_unpacku_high_lane_order ty x)
3681      (if-let (LaneOrder.BigEndian) (lane_order))
3682      (vec_unpacku_low ty x))
3683(rule (vec_unpacku_high_lane_order ty x)
3684      (if-let (LaneOrder.LittleEndian) (lane_order))
3685      (vec_unpacku_high ty x))
3686
3687
3688;; Helpers for generating vector merge instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3689
3690(decl vecop_merge_low (Type) VecBinaryOp)
3691(rule (vecop_merge_low $I8X16) (VecBinaryOp.MergeLow8x16))
3692(rule (vecop_merge_low $I16X8) (VecBinaryOp.MergeLow16x8))
3693(rule (vecop_merge_low $I32X4) (VecBinaryOp.MergeLow32x4))
3694(rule (vecop_merge_low $I64X2) (VecBinaryOp.MergeLow64x2))
3695
3696(decl vec_merge_low (Type Reg Reg) Reg)
3697(rule (vec_merge_low ty x y) (vec_rrr ty (vecop_merge_low ty) x y))
3698
3699(decl vecop_merge_high (Type) VecBinaryOp)
3700(rule (vecop_merge_high $I8X16) (VecBinaryOp.MergeHigh8x16))
3701(rule (vecop_merge_high $I16X8) (VecBinaryOp.MergeHigh16x8))
3702(rule (vecop_merge_high $I32X4) (VecBinaryOp.MergeHigh32x4))
3703(rule (vecop_merge_high $I64X2) (VecBinaryOp.MergeHigh64x2))
3704
3705(decl vec_merge_high (Type Reg Reg) Reg)
3706(rule (vec_merge_high ty x y) (vec_rrr ty (vecop_merge_high ty) x y))
3707
3708;; Versions of merge using current lane order semantics.
3709;; merge_low will consume values from the lower-numbered
3710;; lanes of the inputs, and merge_high will consume values
3711;; from higher-numbered lanes.  In both cases, values from
3712;; the first input will end up in even-numbered lanes, and
3713;; values from the second input will end up in odd-numbered
3714;; lanes of the output.
3715
3716(decl vec_merge_low_lane_order (Type Reg Reg) Reg)
3717(rule 1 (vec_merge_low_lane_order ty x y)
3718      (if-let (LaneOrder.BigEndian) (lane_order))
3719      (vec_merge_high ty x y))
3720(rule (vec_merge_low_lane_order ty x y)
3721      (if-let (LaneOrder.LittleEndian) (lane_order))
3722      (vec_merge_low ty y x))
3723
3724(decl vec_merge_high_lane_order (Type Reg Reg) Reg)
3725(rule 1 (vec_merge_high_lane_order ty x y)
3726      (if-let (LaneOrder.BigEndian) (lane_order))
3727      (vec_merge_low ty x y))
3728(rule (vec_merge_high_lane_order ty x y)
3729      (if-let (LaneOrder.LittleEndian) (lane_order))
3730      (vec_merge_high ty y x))
3731
3732
3733;; Helpers for generating `clz` and `ctz` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;
3734
3735;; Count leading zeroes via FLOGR.  For a zero input, return the specified value.
3736(decl clz_flogr_reg (i16 Reg) Reg)
3737
3738;; The flogr instruction returns 64 for zero input by default.
3739(rule (clz_flogr_reg 64 x)
3740      (let ((dst WritableRegPair (temp_writable_regpair $I64))
3741            (_ Unit (emit (MInst.Flogr dst x))))
3742        (regpair_hi dst)))
3743
3744;; If another zero return value was requested, we need to override the flogr result.
3745(rule -1 (clz_flogr_reg zeroval x)
3746      (let ((tmp WritableRegPair (temp_writable_regpair $I64)))
3747        (with_flags_reg
3748          (ProducesFlags.ProducesFlagsSideEffect (MInst.Flogr tmp x))
3749          (cmov_imm $I64 (intcc_as_cond (IntCC.Equal)) zeroval (regpair_hi tmp)))))
3750
3751;; Count leading zeros (z17 instruction).
3752(decl clz_reg (Reg) Reg)
3753(rule (clz_reg x) (unary_rr $I64 (UnaryOp.Clz64) x))
3754
3755;; Count trailing zeros (z17 instruction).
3756(decl ctz_reg (Reg) Reg)
3757(rule (ctz_reg x) (unary_rr $I64 (UnaryOp.Ctz64) x))
3758
3759;; Vector count leading zeros.
3760(decl vecop_clz (Type) VecUnaryOp)
3761(rule (vecop_clz $I8X16) (VecUnaryOp.Clz8x16))
3762(rule (vecop_clz $I16X8) (VecUnaryOp.Clz16x8))
3763(rule (vecop_clz $I32X4) (VecUnaryOp.Clz32x4))
3764(rule (vecop_clz $I64X2) (VecUnaryOp.Clz64x2))
3765(rule (vecop_clz $I128) (VecUnaryOp.Clz128))
3766
3767(decl vec_clz (Type Reg) Reg)
3768(rule (vec_clz ty x) (vec_rr ty (vecop_clz ty) x))
3769
3770;; Vector count trailing zeros.
3771(decl vecop_ctz (Type) VecUnaryOp)
3772(rule (vecop_ctz $I8X16) (VecUnaryOp.Ctz8x16))
3773(rule (vecop_ctz $I16X8) (VecUnaryOp.Ctz16x8))
3774(rule (vecop_ctz $I32X4) (VecUnaryOp.Ctz32x4))
3775(rule (vecop_ctz $I64X2) (VecUnaryOp.Ctz64x2))
3776(rule (vecop_ctz $I128) (VecUnaryOp.Ctz128))
3777
3778(decl vec_ctz (Type Reg) Reg)
3779(rule (vec_ctz ty x) (vec_rr ty (vecop_ctz ty) x))
3780
3781
3782;; Helpers for generating saturating integer instructions ;;;;;;;;;;;;;;;;;;;;;;
3783
3784(decl uint_sat_reg (Type Type Reg) Reg)
3785(rule 1 (uint_sat_reg ty ty reg) reg)
3786(rule (uint_sat_reg $I8 (ty_32_or_64 ty) reg)
3787      (with_flags_reg (icmpu_uimm32 ty reg 256)
3788        (cmov_imm ty (intcc_as_cond (IntCC.UnsignedGreaterThan)) 255 reg)))
3789(rule (uint_sat_reg $I16 (ty_32_or_64 ty) reg)
3790      (with_flags_reg (icmpu_uimm32 ty reg 65535)
3791        (cmov_imm ty (intcc_as_cond (IntCC.UnsignedGreaterThan)) -1 reg)))
3792(rule (uint_sat_reg $I32 $I64 reg)
3793      (let ((bound Reg (imm $I64 4294967295))
3794            (cond ProducesBool
3795              (bool (icmpu_reg $I64 reg bound)
3796                    (intcc_as_cond (IntCC.UnsignedGreaterThan)))))
3797        (select_bool_reg $I64 cond bound reg)))
3798
3799(decl sint_sat_reg (Type Type Reg) Reg)
3800(rule 1 (sint_sat_reg ty ty reg) reg)
3801(rule (sint_sat_reg $I8 (ty_32_or_64 ty) reg)
3802      (let ((ub Reg (with_flags_reg (icmps_simm16 ty reg 127)
3803                      (cmov_imm ty
3804                        (intcc_as_cond (IntCC.SignedGreaterThan)) 127 reg))))
3805        (with_flags_reg (icmps_simm16 ty ub -128)
3806          (cmov_imm ty (intcc_as_cond (IntCC.SignedLessThan)) -128 ub))))
3807(rule (sint_sat_reg $I16 (ty_32_or_64 ty) reg)
3808      (let ((ub Reg (with_flags_reg (icmps_simm16 ty reg 32767)
3809                      (cmov_imm ty
3810                        (intcc_as_cond (IntCC.SignedGreaterThan)) 32767 reg))))
3811        (with_flags_reg (icmps_simm16 ty ub -32768)
3812          (cmov_imm ty (intcc_as_cond (IntCC.SignedLessThan)) -32768 ub))))
3813(rule (sint_sat_reg $I32 $I64 reg)
3814      (let ((u_bound Reg (imm32 $I64 2147483647))
3815            (u_cond ProducesBool
3816              (bool (icmps_reg $I64 reg u_bound)
3817                    (intcc_as_cond (IntCC.SignedGreaterThan))))
3818            (ub Reg (select_bool_reg $I64 u_cond u_bound reg))
3819            (l_bound Reg (imm32 $I64 -2147483648))
3820            (l_cond ProducesBool
3821              (bool (icmps_reg $I64 ub l_bound)
3822                    (intcc_as_cond (IntCC.SignedLessThan)))))
3823        (select_bool_reg $I64 l_cond l_bound ub)))
3824
3825
3826;; Helpers for generating `add` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3827
3828(decl aluop_add (Type) ALUOp)
3829(rule (aluop_add $I8) (ALUOp.Add32))
3830(rule (aluop_add $I16) (ALUOp.Add32))
3831(rule (aluop_add $I32) (ALUOp.Add32))
3832(rule (aluop_add $I64) (ALUOp.Add64))
3833
3834(decl aluop_add_sext16 (Type) ALUOp)
3835(rule (aluop_add_sext16 $I16) (ALUOp.Add32Ext16))
3836(rule (aluop_add_sext16 $I32) (ALUOp.Add32Ext16))
3837(rule (aluop_add_sext16 $I64) (ALUOp.Add64Ext16))
3838
3839(decl aluop_add_sext32 (Type) ALUOp)
3840(rule (aluop_add_sext32 $I64) (ALUOp.Add64Ext32))
3841
3842(decl add_reg (Type Reg Reg) Reg)
3843(rule (add_reg ty x y) (alu_rrr ty (aluop_add ty) x y))
3844
3845(decl add_reg_sext32 (Type Reg Reg) Reg)
3846(rule (add_reg_sext32 ty x y) (alu_rr ty (aluop_add_sext32 ty) x y))
3847
3848(decl add_simm16 (Type Reg i16) Reg)
3849(rule (add_simm16 ty x y) (alu_rrsimm16 ty (aluop_add ty) x y))
3850
3851(decl add_simm32 (Type Reg i32) Reg)
3852(rule (add_simm32 ty x y) (alu_rsimm32 ty (aluop_add ty) x y))
3853
3854(decl add_mem (Type Reg MemArg) Reg)
3855(rule (add_mem ty x y) (alu_rx ty (aluop_add ty) x y))
3856
3857(decl add_mem_sext16 (Type Reg MemArg) Reg)
3858(rule (add_mem_sext16 ty x y) (alu_rx ty (aluop_add_sext16 ty) x y))
3859
3860(decl add_mem_sext32 (Type Reg MemArg) Reg)
3861(rule (add_mem_sext32 ty x y) (alu_rx ty (aluop_add_sext32 ty) x y))
3862
3863(decl vecop_add (Type) VecBinaryOp)
3864(rule (vecop_add $I8X16) (VecBinaryOp.Add8x16))
3865(rule (vecop_add $I16X8) (VecBinaryOp.Add16x8))
3866(rule (vecop_add $I32X4) (VecBinaryOp.Add32x4))
3867(rule (vecop_add $I64X2) (VecBinaryOp.Add64x2))
3868(rule (vecop_add $I128) (VecBinaryOp.Add128))
3869
3870(decl vec_add (Type Reg Reg) Reg)
3871(rule (vec_add ty x y) (vec_rrr ty (vecop_add ty) x y))
3872
3873
3874;; Helpers for generating `add_logical` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
3875
3876(decl aluop_add_logical (Type) ALUOp)
3877(rule (aluop_add_logical $I32) (ALUOp.AddLogical32))
3878(rule (aluop_add_logical $I64) (ALUOp.AddLogical64))
3879
3880(decl aluop_add_logical_zext32 (Type) ALUOp)
3881(rule (aluop_add_logical_zext32 $I64) (ALUOp.AddLogical64Ext32))
3882
3883(decl add_logical_reg (Type Reg Reg) Reg)
3884(rule (add_logical_reg ty x y) (alu_rrr ty (aluop_add_logical ty) x y))
3885
3886(decl add_logical_reg_with_flags_paired (Type Reg Reg) ProducesFlags)
3887(rule (add_logical_reg_with_flags_paired ty x y)
3888      (alu_rrr_with_flags_paired ty (aluop_add_logical ty) x y))
3889
3890(decl add_logical_reg_zext32 (Type Reg Reg) Reg)
3891(rule (add_logical_reg_zext32 ty x y) (alu_rr ty (aluop_add_logical_zext32 ty) x y))
3892
3893(decl add_logical_reg_zext32_with_flags_paired (Type Reg Reg) ProducesFlags)
3894(rule (add_logical_reg_zext32_with_flags_paired ty x y)
3895      (alu_rr_with_flags_paired ty (aluop_add_logical_zext32 ty) x y))
3896
3897(decl add_logical_zimm32 (Type Reg u32) Reg)
3898(rule (add_logical_zimm32 ty x y) (alu_ruimm32 ty (aluop_add_logical ty) x y))
3899
3900(decl add_logical_zimm32_with_flags_paired (Type Reg u32) ProducesFlags)
3901(rule (add_logical_zimm32_with_flags_paired ty x y)
3902      (alu_ruimm32_with_flags_paired ty (aluop_add_logical ty) x y))
3903
3904(decl add_logical_mem (Type Reg MemArg) Reg)
3905(rule (add_logical_mem ty x y) (alu_rx ty (aluop_add_logical ty) x y))
3906
3907(decl add_logical_mem_with_flags_paired (Type Reg MemArg) ProducesFlags)
3908(rule (add_logical_mem_with_flags_paired ty x y)
3909      (alu_rx_with_flags_paired ty (aluop_add_logical ty) x y))
3910
3911(decl add_logical_mem_zext32 (Type Reg MemArg) Reg)
3912(rule (add_logical_mem_zext32 ty x y) (alu_rx ty (aluop_add_logical_zext32 ty) x y))
3913
3914(decl add_logical_mem_zext32_with_flags_paired (Type Reg MemArg) ProducesFlags)
3915(rule (add_logical_mem_zext32_with_flags_paired ty x y)
3916      (alu_rx_with_flags_paired ty (aluop_add_logical_zext32 ty) x y))
3917
3918
3919;; Helpers for generating `sub` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3920
3921(decl aluop_sub (Type) ALUOp)
3922(rule (aluop_sub $I8) (ALUOp.Sub32))
3923(rule (aluop_sub $I16) (ALUOp.Sub32))
3924(rule (aluop_sub $I32) (ALUOp.Sub32))
3925(rule (aluop_sub $I64) (ALUOp.Sub64))
3926
3927(decl aluop_sub_sext16 (Type) ALUOp)
3928(rule (aluop_sub_sext16 $I16) (ALUOp.Sub32Ext16))
3929(rule (aluop_sub_sext16 $I32) (ALUOp.Sub32Ext16))
3930(rule (aluop_sub_sext16 $I64) (ALUOp.Sub64Ext16))
3931
3932(decl aluop_sub_sext32 (Type) ALUOp)
3933(rule (aluop_sub_sext32 $I64) (ALUOp.Sub64Ext32))
3934
3935(decl sub_reg (Type Reg Reg) Reg)
3936(rule (sub_reg ty x y) (alu_rrr ty (aluop_sub ty) x y))
3937
3938(decl sub_reg_sext32 (Type Reg Reg) Reg)
3939(rule (sub_reg_sext32 ty x y) (alu_rr ty (aluop_sub_sext32 ty) x y))
3940
3941(decl sub_mem (Type Reg MemArg) Reg)
3942(rule (sub_mem ty x y) (alu_rx ty (aluop_sub ty) x y))
3943
3944(decl sub_mem_sext16 (Type Reg MemArg) Reg)
3945(rule (sub_mem_sext16 ty x y) (alu_rx ty (aluop_sub_sext16 ty) x y))
3946
3947(decl sub_mem_sext32 (Type Reg MemArg) Reg)
3948(rule (sub_mem_sext32 ty x y) (alu_rx ty (aluop_sub_sext32 ty) x y))
3949
3950(decl vecop_sub (Type) VecBinaryOp)
3951(rule (vecop_sub $I8X16) (VecBinaryOp.Sub8x16))
3952(rule (vecop_sub $I16X8) (VecBinaryOp.Sub16x8))
3953(rule (vecop_sub $I32X4) (VecBinaryOp.Sub32x4))
3954(rule (vecop_sub $I64X2) (VecBinaryOp.Sub64x2))
3955(rule (vecop_sub $I128) (VecBinaryOp.Sub128))
3956
3957(decl vec_sub (Type Reg Reg) Reg)
3958(rule (vec_sub ty x y) (vec_rrr ty (vecop_sub ty) x y))
3959
3960
3961;; Helpers for generating `sub_logical` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
3962
3963(decl aluop_sub_logical (Type) ALUOp)
3964(rule (aluop_sub_logical $I32) (ALUOp.SubLogical32))
3965(rule (aluop_sub_logical $I64) (ALUOp.SubLogical64))
3966
3967(decl aluop_sub_logical_zext32 (Type) ALUOp)
3968(rule (aluop_sub_logical_zext32 $I64) (ALUOp.SubLogical64Ext32))
3969
3970(decl sub_logical_reg (Type Reg Reg) Reg)
3971(rule (sub_logical_reg ty x y) (alu_rrr ty (aluop_sub_logical ty) x y))
3972
3973(decl sub_logical_reg_zext32 (Type Reg Reg) Reg)
3974(rule (sub_logical_reg_zext32 ty x y) (alu_rr ty (aluop_sub_logical_zext32 ty) x y))
3975
3976(decl sub_logical_zimm32 (Type Reg u32) Reg)
3977(rule (sub_logical_zimm32 ty x y) (alu_ruimm32 ty (aluop_sub_logical ty) x y))
3978
3979(decl sub_logical_mem (Type Reg MemArg) Reg)
3980(rule (sub_logical_mem ty x y) (alu_rx ty (aluop_sub_logical ty) x y))
3981
3982(decl sub_logical_mem_zext32 (Type Reg MemArg) Reg)
3983(rule (sub_logical_mem_zext32 ty x y) (alu_rx ty (aluop_sub_logical ty) x y))
3984
3985
3986;; Helpers for generating `mul` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3987
3988(decl aluop_mul (Type) ALUOp)
3989(rule (aluop_mul $I8) (ALUOp.Mul32))
3990(rule (aluop_mul $I16) (ALUOp.Mul32))
3991(rule (aluop_mul $I32) (ALUOp.Mul32))
3992(rule (aluop_mul $I64) (ALUOp.Mul64))
3993
3994(decl aluop_mul_sext16 (Type) ALUOp)
3995(rule (aluop_mul_sext16 $I16) (ALUOp.Mul32Ext16))
3996(rule (aluop_mul_sext16 $I32) (ALUOp.Mul32Ext16))
3997(rule (aluop_mul_sext16 $I64) (ALUOp.Mul64Ext16))
3998
3999(decl aluop_mul_sext32 (Type) ALUOp)
4000(rule (aluop_mul_sext32 $I64) (ALUOp.Mul64Ext32))
4001
4002(decl mul_reg (Type Reg Reg) Reg)
4003(rule (mul_reg ty x y) (alu_rrr ty (aluop_mul ty) x y))
4004
4005(decl mul_reg_sext32 (Type Reg Reg) Reg)
4006(rule (mul_reg_sext32 ty x y) (alu_rr ty (aluop_mul_sext32 ty) x y))
4007
4008(decl mul_simm16 (Type Reg i16) Reg)
4009(rule (mul_simm16 ty x y) (alu_rsimm16 ty (aluop_mul ty) x y))
4010
4011(decl mul_simm32 (Type Reg i32) Reg)
4012(rule (mul_simm32 ty x y) (alu_rsimm32 ty (aluop_mul ty) x y))
4013
4014(decl mul_mem (Type Reg MemArg) Reg)
4015(rule (mul_mem ty x y) (alu_rx ty (aluop_mul ty) x y))
4016
4017(decl mul_mem_sext16 (Type Reg MemArg) Reg)
4018(rule (mul_mem_sext16 ty x y) (alu_rx ty (aluop_mul_sext16 ty) x y))
4019
4020(decl mul_mem_sext32 (Type Reg MemArg) Reg)
4021(rule (mul_mem_sext32 ty x y) (alu_rx ty (aluop_mul_sext32 ty) x y))
4022
4023(decl vecop_mul (Type) VecBinaryOp)
4024(rule (vecop_mul $I8X16) (VecBinaryOp.Mul8x16))
4025(rule (vecop_mul $I16X8) (VecBinaryOp.Mul16x8))
4026(rule (vecop_mul $I32X4) (VecBinaryOp.Mul32x4))
4027(rule (vecop_mul $I64X2) (VecBinaryOp.Mul64x2))
4028(rule (vecop_mul $I128) (VecBinaryOp.Mul128))
4029
4030(decl vec_mul (Type Reg Reg) Reg)
4031(rule (vec_mul ty x y) (vec_rrr ty (vecop_mul ty) x y))
4032
4033(decl vecop_umulhi (Type) VecBinaryOp)
4034(rule (vecop_umulhi $I8X16) (VecBinaryOp.UMulHi8x16))
4035(rule (vecop_umulhi $I16X8) (VecBinaryOp.UMulHi16x8))
4036(rule (vecop_umulhi $I32X4) (VecBinaryOp.UMulHi32x4))
4037(rule (vecop_umulhi $I64X2) (VecBinaryOp.UMulHi64x2))
4038(rule (vecop_umulhi $I128) (VecBinaryOp.UMulHi128))
4039
4040(decl vec_umulhi (Type Reg Reg) Reg)
4041(rule (vec_umulhi ty x y) (vec_rrr ty (vecop_umulhi ty) x y))
4042
4043(decl vecop_smulhi (Type) VecBinaryOp)
4044(rule (vecop_smulhi $I8X16) (VecBinaryOp.SMulHi8x16))
4045(rule (vecop_smulhi $I16X8) (VecBinaryOp.SMulHi16x8))
4046(rule (vecop_smulhi $I32X4) (VecBinaryOp.SMulHi32x4))
4047(rule (vecop_smulhi $I64X2) (VecBinaryOp.SMulHi64x2))
4048(rule (vecop_smulhi $I128) (VecBinaryOp.SMulHi128))
4049
4050(decl vec_smulhi (Type Reg Reg) Reg)
4051(rule (vec_smulhi ty x y) (vec_rrr ty (vecop_smulhi ty) x y))
4052
4053(decl vecop_umul_even (Type) VecBinaryOp)
4054(rule (vecop_umul_even $I8X16) (VecBinaryOp.UMulEven8x16))
4055(rule (vecop_umul_even $I16X8) (VecBinaryOp.UMulEven16x8))
4056(rule (vecop_umul_even $I32X4) (VecBinaryOp.UMulEven32x4))
4057(rule (vecop_umul_even $I64X2) (VecBinaryOp.UMulEven64x2))
4058
4059(decl vec_umul_even (Type Reg Reg) Reg)
4060(rule (vec_umul_even ty x y) (vec_rrr ty (vecop_umul_even ty) x y))
4061
4062(decl vecop_smul_even (Type) VecBinaryOp)
4063(rule (vecop_smul_even $I8X16) (VecBinaryOp.SMulEven8x16))
4064(rule (vecop_smul_even $I16X8) (VecBinaryOp.SMulEven16x8))
4065(rule (vecop_smul_even $I32X4) (VecBinaryOp.SMulEven32x4))
4066(rule (vecop_smul_even $I64X2) (VecBinaryOp.SMulEven64x2))
4067
4068(decl vec_smul_even (Type Reg Reg) Reg)
4069(rule (vec_smul_even ty x y) (vec_rrr ty (vecop_smul_even ty) x y))
4070
4071(decl vecop_umul_odd (Type) VecBinaryOp)
4072(rule (vecop_umul_odd $I8X16) (VecBinaryOp.UMulOdd8x16))
4073(rule (vecop_umul_odd $I16X8) (VecBinaryOp.UMulOdd16x8))
4074(rule (vecop_umul_odd $I32X4) (VecBinaryOp.UMulOdd32x4))
4075(rule (vecop_umul_odd $I64X2) (VecBinaryOp.UMulOdd64x2))
4076
4077(decl vec_umul_odd (Type Reg Reg) Reg)
4078(rule (vec_umul_odd ty x y) (vec_rrr ty (vecop_umul_odd ty) x y))
4079
4080(decl vecop_smul_odd (Type) VecBinaryOp)
4081(rule (vecop_smul_odd $I8X16) (VecBinaryOp.SMulOdd8x16))
4082(rule (vecop_smul_odd $I16X8) (VecBinaryOp.SMulOdd16x8))
4083(rule (vecop_smul_odd $I32X4) (VecBinaryOp.SMulOdd32x4))
4084(rule (vecop_smul_odd $I64X2) (VecBinaryOp.SMulOdd64x2))
4085
4086(decl vec_smul_odd (Type Reg Reg) Reg)
4087(rule (vec_smul_odd ty x y) (vec_rrr ty (vecop_smul_odd ty) x y))
4088
4089
4090;; Helpers for generating vector divide instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
4091
4092(decl vecop_sdiv (Type) VecBinaryOp)
4093(rule (vecop_sdiv $I32X4) (VecBinaryOp.SDiv32x4))
4094(rule (vecop_sdiv $I64X2) (VecBinaryOp.SDiv64x2))
4095(rule (vecop_sdiv $I128) (VecBinaryOp.SDiv128))
4096
4097(decl vec_sdiv (Type Reg Reg) Reg)
4098(rule (vec_sdiv ty x y) (vec_rrr ty (vecop_sdiv ty) x y))
4099
4100(decl vecop_udiv (Type) VecBinaryOp)
4101(rule (vecop_udiv $I32X4) (VecBinaryOp.UDiv32x4))
4102(rule (vecop_udiv $I64X2) (VecBinaryOp.UDiv64x2))
4103(rule (vecop_udiv $I128) (VecBinaryOp.UDiv128))
4104
4105(decl vec_udiv (Type Reg Reg) Reg)
4106(rule (vec_udiv ty x y) (vec_rrr ty (vecop_udiv ty) x y))
4107
4108(decl vecop_srem (Type) VecBinaryOp)
4109(rule (vecop_srem $I32X4) (VecBinaryOp.SRem32x4))
4110(rule (vecop_srem $I64X2) (VecBinaryOp.SRem64x2))
4111(rule (vecop_srem $I128) (VecBinaryOp.SRem128))
4112
4113(decl vec_srem (Type Reg Reg) Reg)
4114(rule (vec_srem ty x y) (vec_rrr ty (vecop_srem ty) x y))
4115
4116(decl vecop_urem (Type) VecBinaryOp)
4117(rule (vecop_urem $I32X4) (VecBinaryOp.URem32x4))
4118(rule (vecop_urem $I64X2) (VecBinaryOp.URem64x2))
4119(rule (vecop_urem $I128) (VecBinaryOp.URem128))
4120
4121(decl vec_urem (Type Reg Reg) Reg)
4122(rule (vec_urem ty x y) (vec_rrr ty (vecop_urem ty) x y))
4123
4124
4125;; Helpers for generating `udivmod` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4126
4127(decl udivmod (Type RegPair Reg) RegPair)
4128(rule (udivmod $I32 x y) (udivmod32 x y))
4129(rule (udivmod $I64 x y) (udivmod64 x y))
4130
4131
4132;; Helpers for generating `sdivmod` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4133
4134(decl sdivmod (Type Reg Reg) RegPair)
4135(rule (sdivmod $I32 x y) (sdivmod32 x y))
4136(rule (sdivmod $I64 x y) (sdivmod64 x y))
4137
4138
4139;; Helpers for generating `umax` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4140
4141(decl vecop_umax (Type) VecBinaryOp)
4142(rule (vecop_umax $I8X16) (VecBinaryOp.UMax8x16))
4143(rule (vecop_umax $I16X8) (VecBinaryOp.UMax16x8))
4144(rule (vecop_umax $I32X4) (VecBinaryOp.UMax32x4))
4145(rule (vecop_umax $I64X2) (VecBinaryOp.UMax64x2))
4146(rule (vecop_umax $I128) (VecBinaryOp.UMax128))
4147
4148(decl vec_umax (Type Reg Reg) Reg)
4149(rule (vec_umax ty x y) (vec_rrr ty (vecop_umax ty) x y))
4150
4151
4152;; Helpers for generating `smax` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4153
4154(decl vecop_smax (Type) VecBinaryOp)
4155(rule (vecop_smax $I8X16) (VecBinaryOp.SMax8x16))
4156(rule (vecop_smax $I16X8) (VecBinaryOp.SMax16x8))
4157(rule (vecop_smax $I32X4) (VecBinaryOp.SMax32x4))
4158(rule (vecop_smax $I64X2) (VecBinaryOp.SMax64x2))
4159(rule (vecop_smax $I128) (VecBinaryOp.SMax128))
4160
4161(decl vec_smax (Type Reg Reg) Reg)
4162(rule (vec_smax ty x y) (vec_rrr ty (vecop_smax ty) x y))
4163
4164
4165;; Helpers for generating `umin` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4166
4167(decl vecop_umin (Type) VecBinaryOp)
4168(rule (vecop_umin $I8X16) (VecBinaryOp.UMin8x16))
4169(rule (vecop_umin $I16X8) (VecBinaryOp.UMin16x8))
4170(rule (vecop_umin $I32X4) (VecBinaryOp.UMin32x4))
4171(rule (vecop_umin $I64X2) (VecBinaryOp.UMin64x2))
4172(rule (vecop_umin $I128) (VecBinaryOp.UMin128))
4173
4174(decl vec_umin (Type Reg Reg) Reg)
4175(rule (vec_umin ty x y) (vec_rrr ty (vecop_umin ty) x y))
4176
4177
4178;; Helpers for generating `smin` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4179
4180(decl vecop_smin (Type) VecBinaryOp)
4181(rule (vecop_smin $I8X16) (VecBinaryOp.SMin8x16))
4182(rule (vecop_smin $I16X8) (VecBinaryOp.SMin16x8))
4183(rule (vecop_smin $I32X4) (VecBinaryOp.SMin32x4))
4184(rule (vecop_smin $I64X2) (VecBinaryOp.SMin64x2))
4185(rule (vecop_smin $I128) (VecBinaryOp.SMin128))
4186
4187(decl vec_smin (Type Reg Reg) Reg)
4188(rule (vec_smin ty x y) (vec_rrr ty (vecop_smin ty) x y))
4189
4190
4191;; Helpers for generating `avg_round` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4192
4193(decl vecop_uavg (Type) VecBinaryOp)
4194(rule (vecop_uavg $I8X16) (VecBinaryOp.UAvg8x16))
4195(rule (vecop_uavg $I16X8) (VecBinaryOp.UAvg16x8))
4196(rule (vecop_uavg $I32X4) (VecBinaryOp.UAvg32x4))
4197(rule (vecop_uavg $I64X2) (VecBinaryOp.UAvg64x2))
4198
4199(decl vec_uavg (Type Reg Reg) Reg)
4200(rule (vec_uavg ty x y) (vec_rrr ty (vecop_uavg ty) x y))
4201
4202
4203;; Helpers for generating `and` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4204
4205(decl aluop_and (Type) ALUOp)
4206(rule (aluop_and (gpr32_ty _ty)) (ALUOp.And32))
4207(rule 1 (aluop_and (gpr64_ty _ty)) (ALUOp.And64))
4208
4209(decl and_reg (Type Reg Reg) Reg)
4210(rule (and_reg ty x y) (alu_rrr ty (aluop_and ty) x y))
4211
4212(decl and_uimm16shifted (Type Reg UImm16Shifted) Reg)
4213(rule (and_uimm16shifted ty x y) (alu_ruimm16shifted ty (aluop_and ty) x y))
4214
4215(decl and_uimm32shifted (Type Reg UImm32Shifted) Reg)
4216(rule (and_uimm32shifted ty x y) (alu_ruimm32shifted ty (aluop_and ty) x y))
4217
4218(decl and_mem (Type Reg MemArg) Reg)
4219(rule (and_mem ty x y) (alu_rx ty (aluop_and ty) x y))
4220
4221(decl vec_and (Type Reg Reg) Reg)
4222(rule (vec_and (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.And128) x y))
4223
4224
4225;; Helpers for generating `or` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4226
4227(decl aluop_or (Type) ALUOp)
4228(rule (aluop_or (gpr32_ty _ty)) (ALUOp.Orr32))
4229(rule 1 (aluop_or (gpr64_ty _ty)) (ALUOp.Orr64))
4230
4231(decl or_reg (Type Reg Reg) Reg)
4232(rule (or_reg ty x y) (alu_rrr ty (aluop_or ty) x y))
4233
4234(decl or_uimm16shifted (Type Reg UImm16Shifted) Reg)
4235(rule (or_uimm16shifted ty x y) (alu_ruimm16shifted ty (aluop_or ty) x y))
4236
4237(decl or_uimm32shifted (Type Reg UImm32Shifted) Reg)
4238(rule (or_uimm32shifted ty x y) (alu_ruimm32shifted ty (aluop_or ty) x y))
4239
4240(decl or_mem (Type Reg MemArg) Reg)
4241(rule (or_mem ty x y) (alu_rx ty (aluop_or ty) x y))
4242
4243(decl vec_or (Type Reg Reg) Reg)
4244(rule (vec_or (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.Orr128) x y))
4245
4246
4247;; Helpers for generating `xor` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4248
4249(decl aluop_xor (Type) ALUOp)
4250(rule (aluop_xor (gpr32_ty _ty)) (ALUOp.Xor32))
4251(rule 1 (aluop_xor (gpr64_ty _ty)) (ALUOp.Xor64))
4252
4253(decl xor_reg (Type Reg Reg) Reg)
4254(rule (xor_reg ty x y) (alu_rrr ty (aluop_xor ty) x y))
4255
4256(decl xor_uimm32shifted (Type Reg UImm32Shifted) Reg)
4257(rule (xor_uimm32shifted ty x y) (alu_ruimm32shifted ty (aluop_xor ty) x y))
4258
4259(decl xor_mem (Type Reg MemArg) Reg)
4260(rule (xor_mem ty x y) (alu_rx ty (aluop_xor ty) x y))
4261
4262(decl push_xor_uimm32shifted (VecMInstBuilder Type WritableReg Reg UImm32Shifted) Reg)
4263(rule (push_xor_uimm32shifted ib ty dst src imm)
4264      (push_alu_uimm32shifted ib (aluop_xor ty) dst src imm))
4265
4266(decl vec_xor (Type Reg Reg) Reg)
4267(rule (vec_xor (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.Xor128) x y))
4268
4269
4270;; Helpers for generating `not` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4271
4272(decl not_reg (Type Reg) Reg)
4273(rule (not_reg (gpr32_ty ty) x)
4274      (xor_uimm32shifted ty x (uimm32shifted 0xffffffff 0)))
4275(rule 1 (not_reg (gpr64_ty ty) x)
4276      (xor_uimm32shifted ty
4277        (xor_uimm32shifted ty x (uimm32shifted 0xffffffff 0))
4278        (uimm32shifted 0xffffffff 32)))
4279
4280(decl push_not_reg (VecMInstBuilder Type WritableReg Reg) Reg)
4281(rule (push_not_reg ib (gpr32_ty ty) dst src)
4282      (push_xor_uimm32shifted ib ty dst src (uimm32shifted 0xffffffff 0)))
4283(rule 1 (push_not_reg ib (gpr64_ty ty) dst src)
4284      (let ((val Reg (push_xor_uimm32shifted ib ty dst src (uimm32shifted 0xffffffff 0))))
4285        (push_xor_uimm32shifted ib ty dst val (uimm32shifted 0xffffffff 32))))
4286
4287(decl vec_not (Type Reg) Reg)
4288(rule (vec_not ty x) (vec_not_or ty x x))
4289
4290
4291;; Helpers for generating `not_and` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4292
4293(decl aluop_not_and (Type) ALUOp)
4294(rule (aluop_not_and (gpr32_ty _ty)) (ALUOp.NotAnd32))
4295(rule 1 (aluop_not_and (gpr64_ty _ty)) (ALUOp.NotAnd64))
4296
4297(decl not_and_reg (Type Reg Reg) Reg)
4298(rule (not_and_reg ty x y) (alu_rrr ty (aluop_not_and ty) x y))
4299
4300(decl vec_not_and (Type Reg Reg) Reg)
4301(rule (vec_not_and (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.NotAnd128) x y))
4302
4303
4304;; Helpers for generating `not_or` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4305
4306(decl aluop_not_or (Type) ALUOp)
4307(rule (aluop_not_or (gpr32_ty _ty)) (ALUOp.NotOrr32))
4308(rule 1 (aluop_not_or (gpr64_ty _ty)) (ALUOp.NotOrr64))
4309
4310(decl not_or_reg (Type Reg Reg) Reg)
4311(rule (not_or_reg ty x y) (alu_rrr ty (aluop_not_or ty) x y))
4312
4313(decl vec_not_or (Type Reg Reg) Reg)
4314(rule (vec_not_or (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.NotOrr128) x y))
4315
4316
4317;; Helpers for generating `not_xor` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4318
4319(decl aluop_not_xor (Type) ALUOp)
4320(rule (aluop_not_xor (gpr32_ty _ty)) (ALUOp.NotXor32))
4321(rule 1 (aluop_not_xor (gpr64_ty _ty)) (ALUOp.NotXor64))
4322
4323(decl not_xor_reg (Type Reg Reg) Reg)
4324(rule (not_xor_reg ty x y) (alu_rrr ty (aluop_not_xor ty) x y))
4325
4326(decl vec_not_xor (Type Reg Reg) Reg)
4327(rule (vec_not_xor (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.NotXor128) x y))
4328
4329
4330;; Helpers for generating `and_not` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4331
4332(decl aluop_and_not (Type) ALUOp)
4333(rule (aluop_and_not (gpr32_ty _ty)) (ALUOp.AndNot32))
4334(rule 1 (aluop_and_not (gpr64_ty _ty)) (ALUOp.AndNot64))
4335
4336(decl and_not_reg (Type Reg Reg) Reg)
4337(rule (and_not_reg ty x y) (alu_rrr ty (aluop_and_not ty) x y))
4338
4339(decl vec_and_not (Type Reg Reg) Reg)
4340(rule (vec_and_not (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.AndNot128) x y))
4341
4342
4343;; Helpers for generating `or_not` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4344
4345(decl aluop_or_not (Type) ALUOp)
4346(rule (aluop_or_not (gpr32_ty _ty)) (ALUOp.OrrNot32))
4347(rule 1 (aluop_or_not (gpr64_ty _ty)) (ALUOp.OrrNot64))
4348
4349(decl or_not_reg (Type Reg Reg) Reg)
4350(rule (or_not_reg ty x y) (alu_rrr ty (aluop_or_not ty) x y))
4351
4352(decl vec_or_not (Type Reg Reg) Reg)
4353(rule (vec_or_not (vr128_ty ty) x y) (vec_rrr ty (VecBinaryOp.OrrNot128) x y))
4354
4355
4356;; Helpers for generating `bitpermute` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4357
4358(decl vec_bitpermute (Reg Reg) Reg)
4359(rule (vec_bitpermute x y) (vec_rrr $I64X2 (VecBinaryOp.BitPermute128) x y))
4360
4361
4362;; Helpers for generating `abs` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4363
4364(decl unaryop_abs (Type) UnaryOp)
4365(rule (unaryop_abs $I32) (UnaryOp.Abs32))
4366(rule (unaryop_abs $I64) (UnaryOp.Abs64))
4367
4368(decl unaryop_abs_sext32 (Type) UnaryOp)
4369(rule (unaryop_abs_sext32 $I64) (UnaryOp.Abs64Ext32))
4370
4371(decl abs_reg (Type Reg) Reg)
4372(rule (abs_reg ty x) (unary_rr ty (unaryop_abs ty) x))
4373
4374(decl abs_reg_sext32 (Type Reg) Reg)
4375(rule (abs_reg_sext32 ty x) (unary_rr ty (unaryop_abs_sext32 ty) x))
4376
4377(decl vecop_abs (Type) VecUnaryOp)
4378(rule (vecop_abs $I8X16) (VecUnaryOp.Abs8x16))
4379(rule (vecop_abs $I16X8) (VecUnaryOp.Abs16x8))
4380(rule (vecop_abs $I32X4) (VecUnaryOp.Abs32x4))
4381(rule (vecop_abs $I64X2) (VecUnaryOp.Abs64x2))
4382(rule (vecop_abs $I128) (VecUnaryOp.Abs128))
4383
4384(decl vec_abs (Type Reg) Reg)
4385(rule (vec_abs ty x) (vec_rr ty (vecop_abs ty) x))
4386
4387
4388;; Helpers for generating `neg` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4389
4390(decl unaryop_neg (Type) UnaryOp)
4391(rule (unaryop_neg $I8) (UnaryOp.Neg32))
4392(rule (unaryop_neg $I16) (UnaryOp.Neg32))
4393(rule (unaryop_neg $I32) (UnaryOp.Neg32))
4394(rule (unaryop_neg $I64) (UnaryOp.Neg64))
4395
4396(decl unaryop_neg_sext32 (Type) UnaryOp)
4397(rule (unaryop_neg_sext32 $I64) (UnaryOp.Neg64Ext32))
4398
4399(decl neg_reg (Type Reg) Reg)
4400(rule (neg_reg ty x) (unary_rr ty (unaryop_neg ty) x))
4401
4402(decl neg_reg_sext32 (Type Reg) Reg)
4403(rule (neg_reg_sext32 ty x) (unary_rr ty (unaryop_neg_sext32 ty) x))
4404
4405(decl vecop_neg (Type) VecUnaryOp)
4406(rule (vecop_neg $I8X16) (VecUnaryOp.Neg8x16))
4407(rule (vecop_neg $I16X8) (VecUnaryOp.Neg16x8))
4408(rule (vecop_neg $I32X4) (VecUnaryOp.Neg32x4))
4409(rule (vecop_neg $I64X2) (VecUnaryOp.Neg64x2))
4410(rule (vecop_neg $I128) (VecUnaryOp.Neg128))
4411
4412(decl vec_neg (Type Reg) Reg)
4413(rule (vec_neg ty x) (vec_rr ty (vecop_neg ty) x))
4414
4415
4416;; Helpers for generating `bswap` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4417
4418(decl unaryop_bswap (Type) UnaryOp)
4419(rule (unaryop_bswap $I32) (UnaryOp.BSwap32))
4420(rule (unaryop_bswap $I64) (UnaryOp.BSwap64))
4421
4422(decl bswap_reg (Type Reg) Reg)
4423(rule (bswap_reg ty x) (unary_rr ty (unaryop_bswap ty) x))
4424
4425(decl push_bswap_reg (VecMInstBuilder Type WritableReg Reg) Reg)
4426(rule (push_bswap_reg ib ty dst src) (push_unary ib (unaryop_bswap ty) dst src))
4427
4428
4429;; Helpers for generating `rot` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4430
4431(decl shiftop_rot (Type) ShiftOp)
4432(rule (shiftop_rot $I32) (ShiftOp.RotL32))
4433(rule (shiftop_rot $I64) (ShiftOp.RotL64))
4434
4435(decl rot_reg (Type Reg Reg) Reg)
4436(rule (rot_reg ty x shift_reg)
4437      (shift_rr ty (shiftop_rot ty) x 0 shift_reg))
4438
4439(decl rot_imm (Type Reg u8) Reg)
4440(rule (rot_imm ty x shift_imm)
4441      (shift_rr ty (shiftop_rot ty) x shift_imm (zero_reg)))
4442
4443(decl rot_imm_reg (Type Reg u8 Reg) Reg)
4444(rule (rot_imm_reg ty x shift_imm shift_reg)
4445      (shift_rr ty (shiftop_rot ty) x shift_imm shift_reg))
4446
4447(decl push_rot_imm_reg (VecMInstBuilder Type WritableReg Reg u8 Reg) Reg)
4448(rule (push_rot_imm_reg ib ty dst src shift_imm shift_reg)
4449      (push_shift ib (shiftop_rot ty) dst src shift_imm shift_reg))
4450
4451(decl vec_shiftop_rot (Type) VecShiftOp)
4452(rule (vec_shiftop_rot $I8X16) (VecShiftOp.RotL8x16))
4453(rule (vec_shiftop_rot $I16X8) (VecShiftOp.RotL16x8))
4454(rule (vec_shiftop_rot $I32X4) (VecShiftOp.RotL32x4))
4455(rule (vec_shiftop_rot $I64X2) (VecShiftOp.RotL64x2))
4456
4457(decl vec_rot_reg (Type Reg Reg) Reg)
4458(rule (vec_rot_reg ty x shift_reg)
4459      (vec_shift_rr ty (vec_shiftop_rot ty) x 0 shift_reg))
4460
4461(decl vec_rot_imm (Type Reg u8) Reg)
4462(rule (vec_rot_imm ty x shift_imm)
4463      (vec_shift_rr ty (vec_shiftop_rot ty) x shift_imm (zero_reg)))
4464
4465
4466;; Helpers for generating `lshl` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4467
4468(decl shiftop_lshl (Type) ShiftOp)
4469(rule (shiftop_lshl $I8) (ShiftOp.LShL32))
4470(rule (shiftop_lshl $I16) (ShiftOp.LShL32))
4471(rule (shiftop_lshl $I32) (ShiftOp.LShL32))
4472(rule (shiftop_lshl $I64) (ShiftOp.LShL64))
4473
4474(decl lshl_reg (Type Reg Reg) Reg)
4475(rule (lshl_reg ty x shift_reg)
4476      (shift_rr ty (shiftop_lshl ty) x 0 shift_reg))
4477
4478(decl lshl_imm (Type Reg u8) Reg)
4479(rule (lshl_imm ty x shift_imm)
4480      (shift_rr ty (shiftop_lshl ty) x shift_imm (zero_reg)))
4481
4482(decl vec_shiftop_lshl (Type) VecShiftOp)
4483(rule (vec_shiftop_lshl $I8X16) (VecShiftOp.LShL8x16))
4484(rule (vec_shiftop_lshl $I16X8) (VecShiftOp.LShL16x8))
4485(rule (vec_shiftop_lshl $I32X4) (VecShiftOp.LShL32x4))
4486(rule (vec_shiftop_lshl $I64X2) (VecShiftOp.LShL64x2))
4487
4488(decl vec_lshl_reg (Type Reg Reg) Reg)
4489(rule (vec_lshl_reg ty x shift_reg)
4490      (vec_shift_rr ty (vec_shiftop_lshl ty) x 0 shift_reg))
4491
4492(decl vec_lshl_imm (Type Reg u8) Reg)
4493(rule (vec_lshl_imm ty x shift_imm)
4494      (vec_shift_rr ty (vec_shiftop_lshl ty) x shift_imm (zero_reg)))
4495
4496(decl vec_lshl_by_byte (Reg Reg) Reg)
4497(rule (vec_lshl_by_byte x y) (vec_rrr $I8X16 (VecBinaryOp.LShLByByte128) x y))
4498
4499(decl vec_lshl_by_bit (Reg Reg) Reg)
4500(rule (vec_lshl_by_bit x y) (vec_rrr $I8X16 (VecBinaryOp.LShLByBit128) x y))
4501
4502
4503;; Helpers for generating `lshr` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4504
4505(decl shiftop_lshr (Type) ShiftOp)
4506(rule (shiftop_lshr $I32) (ShiftOp.LShR32))
4507(rule (shiftop_lshr $I64) (ShiftOp.LShR64))
4508
4509(decl lshr_reg (Type Reg Reg) Reg)
4510(rule (lshr_reg ty x shift_reg)
4511      (shift_rr ty (shiftop_lshr ty) x 0 shift_reg))
4512
4513(decl lshr_imm (Type Reg u8) Reg)
4514(rule (lshr_imm ty x shift_imm)
4515      (shift_rr ty (shiftop_lshr ty) x shift_imm (zero_reg)))
4516
4517(decl vec_shiftop_lshr (Type) VecShiftOp)
4518(rule (vec_shiftop_lshr $I8X16) (VecShiftOp.LShR8x16))
4519(rule (vec_shiftop_lshr $I16X8) (VecShiftOp.LShR16x8))
4520(rule (vec_shiftop_lshr $I32X4) (VecShiftOp.LShR32x4))
4521(rule (vec_shiftop_lshr $I64X2) (VecShiftOp.LShR64x2))
4522
4523(decl vec_lshr_reg (Type Reg Reg) Reg)
4524(rule (vec_lshr_reg ty x shift_reg)
4525      (vec_shift_rr ty (vec_shiftop_lshr ty) x 0 shift_reg))
4526
4527(decl vec_lshr_imm (Type Reg u8) Reg)
4528(rule (vec_lshr_imm ty x shift_imm)
4529      (vec_shift_rr ty (vec_shiftop_lshr ty) x shift_imm (zero_reg)))
4530
4531(decl vec_lshr_by_byte (Reg Reg) Reg)
4532(rule (vec_lshr_by_byte x y) (vec_rrr $I8X16 (VecBinaryOp.LShRByByte128) x y))
4533
4534(decl vec_lshr_by_bit (Reg Reg) Reg)
4535(rule (vec_lshr_by_bit x y) (vec_rrr $I8X16 (VecBinaryOp.LShRByBit128) x y))
4536
4537
4538;; Helpers for generating `ashr` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4539
4540(decl shiftop_ashr (Type) ShiftOp)
4541(rule (shiftop_ashr $I32) (ShiftOp.AShR32))
4542(rule (shiftop_ashr $I64) (ShiftOp.AShR64))
4543
4544(decl ashr_reg (Type Reg Reg) Reg)
4545(rule (ashr_reg ty x shift_reg)
4546      (shift_rr ty (shiftop_ashr ty) x 0 shift_reg))
4547
4548(decl ashr_imm (Type Reg u8) Reg)
4549(rule (ashr_imm ty x shift_imm)
4550      (shift_rr ty (shiftop_ashr ty) x shift_imm (zero_reg)))
4551
4552(decl vec_shiftop_ashr (Type) VecShiftOp)
4553(rule (vec_shiftop_ashr $I8X16) (VecShiftOp.AShR8x16))
4554(rule (vec_shiftop_ashr $I16X8) (VecShiftOp.AShR16x8))
4555(rule (vec_shiftop_ashr $I32X4) (VecShiftOp.AShR32x4))
4556(rule (vec_shiftop_ashr $I64X2) (VecShiftOp.AShR64x2))
4557
4558(decl vec_ashr_reg (Type Reg Reg) Reg)
4559(rule (vec_ashr_reg ty x shift_reg)
4560      (vec_shift_rr ty (vec_shiftop_ashr ty) x 0 shift_reg))
4561
4562(decl vec_ashr_imm (Type Reg u8) Reg)
4563(rule (vec_ashr_imm ty x shift_imm)
4564      (vec_shift_rr ty (vec_shiftop_ashr ty) x shift_imm (zero_reg)))
4565
4566(decl vec_ashr_by_byte (Reg Reg) Reg)
4567(rule (vec_ashr_by_byte x y) (vec_rrr $I8X16 (VecBinaryOp.AShRByByte128) x y))
4568
4569(decl vec_ashr_by_bit (Reg Reg) Reg)
4570(rule (vec_ashr_by_bit x y) (vec_rrr $I8X16 (VecBinaryOp.AShRByBit128) x y))
4571
4572
4573;; Helpers for generating `popcnt` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4574
4575(decl popcnt_byte (Reg) Reg)
4576(rule (popcnt_byte x) (unary_rr $I64 (UnaryOp.PopcntByte) x))
4577
4578(decl popcnt_reg (Reg) Reg)
4579(rule (popcnt_reg x) (unary_rr $I64 (UnaryOp.PopcntReg) x))
4580
4581(decl vecop_popcnt (Type) VecUnaryOp)
4582(rule (vecop_popcnt $I8X16) (VecUnaryOp.Popcnt8x16))
4583(rule (vecop_popcnt $I16X8) (VecUnaryOp.Popcnt16x8))
4584(rule (vecop_popcnt $I32X4) (VecUnaryOp.Popcnt32x4))
4585(rule (vecop_popcnt $I64X2) (VecUnaryOp.Popcnt64x2))
4586
4587(decl vec_popcnt (Type Reg) Reg)
4588(rule (vec_popcnt ty x) (vec_rr ty (vecop_popcnt ty) x))
4589
4590
4591;; Helpers for generating `atomic_rmw` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4592
4593(decl atomic_rmw_and (Type Reg MemArg) Reg)
4594(rule (atomic_rmw_and $I32 src mem) (atomic_rmw_impl $I32 (ALUOp.And32) src mem))
4595(rule (atomic_rmw_and $I64 src mem) (atomic_rmw_impl $I64 (ALUOp.And64) src mem))
4596
4597(decl atomic_rmw_or (Type Reg MemArg) Reg)
4598(rule (atomic_rmw_or $I32 src mem) (atomic_rmw_impl $I32 (ALUOp.Orr32) src mem))
4599(rule (atomic_rmw_or $I64 src mem) (atomic_rmw_impl $I64 (ALUOp.Orr64) src mem))
4600
4601(decl atomic_rmw_xor (Type Reg MemArg) Reg)
4602(rule (atomic_rmw_xor $I32 src mem) (atomic_rmw_impl $I32 (ALUOp.Xor32) src mem))
4603(rule (atomic_rmw_xor $I64 src mem) (atomic_rmw_impl $I64 (ALUOp.Xor64) src mem))
4604
4605(decl atomic_rmw_add (Type Reg MemArg) Reg)
4606(rule (atomic_rmw_add $I32 src mem) (atomic_rmw_impl $I32 (ALUOp.Add32) src mem))
4607(rule (atomic_rmw_add $I64 src mem) (atomic_rmw_impl $I64 (ALUOp.Add64) src mem))
4608
4609
4610;; Helpers for generating `atomic_cas` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4611
4612(decl atomic_cas_impl (Type Reg Reg MemArg) Reg)
4613(rule (atomic_cas_impl $I32 src1 src2 mem) (atomic_cas32 src1 src2 mem))
4614(rule (atomic_cas_impl $I64 src1 src2 mem) (atomic_cas64 src1 src2 mem))
4615
4616(decl push_atomic_cas (VecMInstBuilder Type WritableReg Reg MemArg) Reg)
4617(rule (push_atomic_cas ib $I32 src1 src2 mem) (push_atomic_cas32 ib src1 src2 mem))
4618(rule (push_atomic_cas ib $I64 src1 src2 mem) (push_atomic_cas64 ib src1 src2 mem))
4619
4620
4621;; Helpers for generating `fadd` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4622
4623(decl fpuop2_add (Type) FPUOp2)
4624(rule (fpuop2_add $F32) (FPUOp2.Add32))
4625(rule (fpuop2_add $F64) (FPUOp2.Add64))
4626(rule (fpuop2_add $F128) (FPUOp2.Add128))
4627(rule (fpuop2_add $F32X4) (FPUOp2.Add32x4))
4628(rule (fpuop2_add $F64X2) (FPUOp2.Add64x2))
4629
4630(decl fadd_reg (Type Reg Reg) Reg)
4631(rule (fadd_reg ty x y) (fpu_rrr ty (fpuop2_add ty) x y))
4632
4633
4634;; Helpers for generating `fsub` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4635
4636(decl fpuop2_sub (Type) FPUOp2)
4637(rule (fpuop2_sub $F32) (FPUOp2.Sub32))
4638(rule (fpuop2_sub $F64) (FPUOp2.Sub64))
4639(rule (fpuop2_sub $F128) (FPUOp2.Sub128))
4640(rule (fpuop2_sub $F32X4) (FPUOp2.Sub32x4))
4641(rule (fpuop2_sub $F64X2) (FPUOp2.Sub64x2))
4642
4643(decl fsub_reg (Type Reg Reg) Reg)
4644(rule (fsub_reg ty x y) (fpu_rrr ty (fpuop2_sub ty) x y))
4645
4646
4647;; Helpers for generating `fmul` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4648
4649(decl fpuop2_mul (Type) FPUOp2)
4650(rule (fpuop2_mul $F32) (FPUOp2.Mul32))
4651(rule (fpuop2_mul $F64) (FPUOp2.Mul64))
4652(rule (fpuop2_mul $F128) (FPUOp2.Mul128))
4653(rule (fpuop2_mul $F32X4) (FPUOp2.Mul32x4))
4654(rule (fpuop2_mul $F64X2) (FPUOp2.Mul64x2))
4655
4656(decl fmul_reg (Type Reg Reg) Reg)
4657(rule (fmul_reg ty x y) (fpu_rrr ty (fpuop2_mul ty) x y))
4658
4659
4660;; Helpers for generating `fdiv` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4661
4662(decl fpuop2_div (Type) FPUOp2)
4663(rule (fpuop2_div $F32) (FPUOp2.Div32))
4664(rule (fpuop2_div $F64) (FPUOp2.Div64))
4665(rule (fpuop2_div $F128) (FPUOp2.Div128))
4666(rule (fpuop2_div $F32X4) (FPUOp2.Div32x4))
4667(rule (fpuop2_div $F64X2) (FPUOp2.Div64x2))
4668
4669(decl fdiv_reg (Type Reg Reg) Reg)
4670(rule (fdiv_reg ty x y) (fpu_rrr ty (fpuop2_div ty) x y))
4671
4672
4673;; Helpers for generating `fmin` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4674
4675(decl fpuop2_min (Type) FPUOp2)
4676(rule (fpuop2_min $F32) (FPUOp2.Min32))
4677(rule (fpuop2_min $F64) (FPUOp2.Min64))
4678(rule (fpuop2_min $F128) (FPUOp2.Min128))
4679(rule (fpuop2_min $F32X4) (FPUOp2.Min32x4))
4680(rule (fpuop2_min $F64X2) (FPUOp2.Min64x2))
4681
4682(decl fmin_reg (Type Reg Reg) Reg)
4683(rule (fmin_reg ty x y) (fpu_rrr ty (fpuop2_min ty) x y))
4684
4685
4686;; Helpers for generating `fmax` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4687
4688(decl fpuop2_max (Type) FPUOp2)
4689(rule (fpuop2_max $F32) (FPUOp2.Max32))
4690(rule (fpuop2_max $F64) (FPUOp2.Max64))
4691(rule (fpuop2_max $F128) (FPUOp2.Max128))
4692(rule (fpuop2_max $F32X4) (FPUOp2.Max32x4))
4693(rule (fpuop2_max $F64X2) (FPUOp2.Max64x2))
4694
4695(decl fmax_reg (Type Reg Reg) Reg)
4696(rule (fmax_reg ty x y) (fpu_rrr ty (fpuop2_max ty) x y))
4697
4698
4699;; Helpers for generating `fmin_pseudo` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
4700
4701(decl fpuop2_min_pseudo (Type) FPUOp2)
4702(rule (fpuop2_min_pseudo $F32) (FPUOp2.MinPseudo32))
4703(rule (fpuop2_min_pseudo $F64) (FPUOp2.MinPseudo64))
4704(rule (fpuop2_min_pseudo $F128) (FPUOp2.MinPseudo128))
4705(rule (fpuop2_min_pseudo $F32X4) (FPUOp2.MinPseudo32x4))
4706(rule (fpuop2_min_pseudo $F64X2) (FPUOp2.MinPseudo64x2))
4707
4708(decl fmin_pseudo_reg (Type Reg Reg) Reg)
4709(rule (fmin_pseudo_reg ty x y) (fpu_rrr ty (fpuop2_min_pseudo ty) x y))
4710
4711
4712;; Helpers for generating `fmax_pseudo` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
4713
4714(decl fpuop2_max_pseudo (Type) FPUOp2)
4715(rule (fpuop2_max_pseudo $F32) (FPUOp2.MaxPseudo32))
4716(rule (fpuop2_max_pseudo $F64) (FPUOp2.MaxPseudo64))
4717(rule (fpuop2_max_pseudo $F128) (FPUOp2.MaxPseudo128))
4718(rule (fpuop2_max_pseudo $F32X4) (FPUOp2.MaxPseudo32x4))
4719(rule (fpuop2_max_pseudo $F64X2) (FPUOp2.MaxPseudo64x2))
4720
4721(decl fmax_pseudo_reg (Type Reg Reg) Reg)
4722(rule (fmax_pseudo_reg ty x y) (fpu_rrr ty (fpuop2_max_pseudo ty) x y))
4723
4724
4725;; Helpers for generating `fma` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4726
4727(decl fpuop3_fma (Type) FPUOp3)
4728(rule (fpuop3_fma $F32) (FPUOp3.MAdd32))
4729(rule (fpuop3_fma $F64) (FPUOp3.MAdd64))
4730(rule (fpuop3_fma $F128) (FPUOp3.MAdd128))
4731(rule (fpuop3_fma $F32X4) (FPUOp3.MAdd32x4))
4732(rule (fpuop3_fma $F64X2) (FPUOp3.MAdd64x2))
4733
4734(decl fma_reg (Type Reg Reg Reg) Reg)
4735(rule (fma_reg ty x y acc) (fpu_rrrr ty (fpuop3_fma ty) x y acc))
4736
4737
4738;; Helpers for generating `sqrt` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4739
4740(decl fpuop1_sqrt (Type) FPUOp1)
4741(rule (fpuop1_sqrt $F32) (FPUOp1.Sqrt32))
4742(rule (fpuop1_sqrt $F64) (FPUOp1.Sqrt64))
4743(rule (fpuop1_sqrt $F128) (FPUOp1.Sqrt128))
4744(rule (fpuop1_sqrt $F32X4) (FPUOp1.Sqrt32x4))
4745(rule (fpuop1_sqrt $F64X2) (FPUOp1.Sqrt64x2))
4746
4747(decl sqrt_reg (Type Reg) Reg)
4748(rule (sqrt_reg ty x) (fpu_rr ty (fpuop1_sqrt ty) x))
4749
4750
4751;; Helpers for generating `fneg` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4752
4753(decl fpuop1_neg (Type) FPUOp1)
4754(rule (fpuop1_neg $F32) (FPUOp1.Neg32))
4755(rule (fpuop1_neg $F64) (FPUOp1.Neg64))
4756(rule (fpuop1_neg $F128) (FPUOp1.Neg128))
4757(rule (fpuop1_neg $F32X4) (FPUOp1.Neg32x4))
4758(rule (fpuop1_neg $F64X2) (FPUOp1.Neg64x2))
4759
4760(decl fneg_reg (Type Reg) Reg)
4761(rule (fneg_reg ty x) (fpu_rr ty (fpuop1_neg ty) x))
4762
4763
4764;; Helpers for generating `fabs` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4765
4766(decl fpuop1_abs (Type) FPUOp1)
4767(rule (fpuop1_abs $F32) (FPUOp1.Abs32))
4768(rule (fpuop1_abs $F64) (FPUOp1.Abs64))
4769(rule (fpuop1_abs $F128) (FPUOp1.Abs128))
4770(rule (fpuop1_abs $F32X4) (FPUOp1.Abs32x4))
4771(rule (fpuop1_abs $F64X2) (FPUOp1.Abs64x2))
4772
4773(decl fabs_reg (Type Reg) Reg)
4774(rule (fabs_reg ty x) (fpu_rr ty (fpuop1_abs ty) x))
4775
4776
4777;; Helpers for generating `ceil`, `floor`, `trunc`, `nearest`  instructions ;;;;
4778
4779(decl fpuroundop_round (Type) FpuRoundOp)
4780(rule (fpuroundop_round $F32) (FpuRoundOp.Round32))
4781(rule (fpuroundop_round $F64) (FpuRoundOp.Round64))
4782(rule (fpuroundop_round $F128) (FpuRoundOp.Round128))
4783(rule (fpuroundop_round $F32X4) (FpuRoundOp.Round32x4))
4784(rule (fpuroundop_round $F64X2) (FpuRoundOp.Round64x2))
4785
4786(decl ceil_reg (Type Reg) Reg)
4787(rule (ceil_reg ty x) (fpu_round ty (fpuroundop_round ty)
4788                                    (FpuRoundMode.ToPosInfinity) x))
4789
4790(decl floor_reg (Type Reg) Reg)
4791(rule (floor_reg ty x) (fpu_round ty (fpuroundop_round ty)
4792                                     (FpuRoundMode.ToNegInfinity) x))
4793
4794(decl trunc_reg (Type Reg) Reg)
4795(rule (trunc_reg ty x) (fpu_round ty (fpuroundop_round ty)
4796                                     (FpuRoundMode.ToZero) x))
4797
4798(decl nearest_reg (Type Reg) Reg)
4799(rule (nearest_reg ty x) (fpu_round ty (fpuroundop_round ty)
4800                                       (FpuRoundMode.ToNearestTiesToEven) x))
4801
4802
4803;; Helpers for generating `fpromote` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4804
4805(decl fpromote_reg (Type Type Reg) Reg)
4806(rule 1 (fpromote_reg ty ty x) x)
4807(rule (fpromote_reg $F64 $F32 x)
4808      (fpu_rr $F64 (FPUOp1.Cvt32To64) x))
4809(rule (fpromote_reg $F64X2 $F32X4 x)
4810      (fpu_rr $F64 (FPUOp1.Cvt32x4To64x2) x))
4811(rule (fpromote_reg $F128 $F64 x)
4812      (fpu_rr $F128 (FPUOp1.Cvt64To128) x))
4813
4814
4815;; Helpers for generating `fdemote` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4816
4817(decl fdemote_reg (Type Type FpuRoundMode Reg) Reg)
4818(rule 1 (fdemote_reg ty ty mode x) x)
4819(rule (fdemote_reg $F32 $F64 mode x)
4820      (fpu_round $F32 (FpuRoundOp.Cvt64To32) mode x))
4821(rule (fdemote_reg $F32X4 $F64X2 mode x)
4822      (fpu_round $F32X4 (FpuRoundOp.Cvt64x2To32x4) mode x))
4823(rule (fdemote_reg $F64 $F128 mode x)
4824      (fpu_round $F64 (FpuRoundOp.Cvt128To64) mode x))
4825
4826
4827;; Helpers for generating `fcvt_from_uint` instructions ;;;;;;;;;;;;;;;;;;;;;;;;
4828
4829(decl fcvt_from_uint_reg (Type Type FpuRoundMode Reg) Reg)
4830(rule (fcvt_from_uint_reg $F32 $I32 mode x)
4831      (fpu_round $F32 (FpuRoundOp.FromUInt32) mode (vec_insert_lane_undef $I32X4 x 0 (zero_reg))))
4832(rule (fcvt_from_uint_reg $F64 $I64 mode x)
4833      (fpu_round $F64 (FpuRoundOp.FromUInt64) mode (vec_insert_lane_undef $I64X2 x 0 (zero_reg))))
4834(rule (fcvt_from_uint_reg $F32X4 $I32X4 mode x)
4835      (fpu_round $F32X4 (FpuRoundOp.FromUInt32x4) mode x))
4836(rule (fcvt_from_uint_reg $F64X2 $I64X2 mode x)
4837      (fpu_round $F64X2 (FpuRoundOp.FromUInt64x2) mode x))
4838(rule (fcvt_from_uint_reg $F128 $I32 mode x)
4839      (fp_regpair_to_reg (fpu_conv128_from_int (FpuConv128Op.UInt32) mode x)))
4840(rule (fcvt_from_uint_reg $F128 $I64 mode x)
4841      (fp_regpair_to_reg (fpu_conv128_from_int (FpuConv128Op.UInt64) mode x)))
4842
4843
4844;; Helpers for generating `fcvt_from_sint` instructions ;;;;;;;;;;;;;;;;;;;;;;;;
4845
4846(decl fcvt_from_sint_reg (Type Type FpuRoundMode Reg) Reg)
4847(rule (fcvt_from_sint_reg $F32 $I32 mode x)
4848      (fpu_round $F32 (FpuRoundOp.FromSInt32) mode (vec_insert_lane_undef $I32X4 x 0 (zero_reg))))
4849(rule (fcvt_from_sint_reg $F64 $I64 mode x)
4850      (fpu_round $F64 (FpuRoundOp.FromSInt64) mode (vec_insert_lane_undef $I64X2 x 0 (zero_reg))))
4851(rule (fcvt_from_sint_reg $F32X4 $I32X4 mode x)
4852      (fpu_round $F32X4 (FpuRoundOp.FromSInt32x4) mode x))
4853(rule (fcvt_from_sint_reg $F64X2 $I64X2 mode x)
4854      (fpu_round $F64X2 (FpuRoundOp.FromSInt64x2) mode x))
4855(rule (fcvt_from_sint_reg $F128 $I32 mode x)
4856      (fp_regpair_to_reg (fpu_conv128_from_int (FpuConv128Op.SInt32) mode x)))
4857(rule (fcvt_from_sint_reg $F128 $I64 mode x)
4858      (fp_regpair_to_reg (fpu_conv128_from_int (FpuConv128Op.SInt64) mode x)))
4859
4860
4861;; Helpers for generating `fcvt_to_[us]int` instructions ;;;;;;;;;;;;;;;;;;;;;;;
4862
4863(decl fcvt_flt_ty (Type Type) Type)
4864(rule 1 (fcvt_flt_ty (fits_in_32 ty) (and (vxrs_ext2_enabled) $F32)) $F32)
4865(rule (fcvt_flt_ty (fits_in_64 ty) $F32) $F64)
4866(rule (fcvt_flt_ty (fits_in_64 ty) $F64) $F64)
4867(rule (fcvt_flt_ty (fits_in_64 ty) $F128) $F128)
4868
4869(decl fcvt_int_ty (Type Type) Type)
4870(rule 1 (fcvt_int_ty (fits_in_32 ty) (and (vxrs_ext2_enabled) $F32)) $I32)
4871(rule (fcvt_int_ty (fits_in_64 ty) $F32) $I64)
4872(rule (fcvt_int_ty (fits_in_64 ty) $F64) $I64)
4873(rule 1 (fcvt_int_ty (fits_in_32 ty) $F128) $I32)
4874(rule (fcvt_int_ty (fits_in_64 ty) $F128) $I64)
4875
4876
4877;; Helpers for generating `fcvt_to_uint` instructions ;;;;;;;;;;;;;;;;;;;;;;;;
4878
4879(decl fcvt_to_uint_reg (Type Type FpuRoundMode Reg) Reg)
4880(rule (fcvt_to_uint_reg $I32 $F32 mode x)
4881      (vec_extract_lane $I32X4 (fpu_round $F32 (FpuRoundOp.ToUInt32) mode x) 0 (zero_reg)))
4882(rule (fcvt_to_uint_reg $I64 $F64 mode x)
4883      (vec_extract_lane $I64X2 (fpu_round $F64 (FpuRoundOp.ToUInt64) mode x) 0 (zero_reg)))
4884(rule (fcvt_to_uint_reg $I32X4 $F32X4 mode x)
4885      (fpu_round $F32X4 (FpuRoundOp.ToUInt32x4) mode x))
4886(rule (fcvt_to_uint_reg $I64X2 $F64X2 mode x)
4887      (fpu_round $F64X2 (FpuRoundOp.ToUInt64x2) mode x))
4888(rule (fcvt_to_uint_reg $I32 $F128 mode x)
4889      (fpu_conv128_to_int $I32 (FpuConv128Op.UInt32) mode (fp_reg_to_regpair x)))
4890(rule (fcvt_to_uint_reg $I64 $F128 mode x)
4891      (fpu_conv128_to_int $I64 (FpuConv128Op.UInt64) mode (fp_reg_to_regpair x)))
4892
4893(decl fcvt_to_uint_ub (Type Type) Reg)
4894(rule (fcvt_to_uint_ub $F32 dst_ty)
4895      (imm $F32 (fcvt_to_uint_ub32 (ty_bits dst_ty))))
4896(rule (fcvt_to_uint_ub $F64 dst_ty)
4897      (imm $F64 (fcvt_to_uint_ub64 (ty_bits dst_ty))))
4898(rule (fcvt_to_uint_ub $F128 dst_ty)
4899      (vec_imm $F128 (fcvt_to_uint_ub128 (ty_bits dst_ty))))
4900
4901(decl fcvt_to_uint_lb (Type) Reg)
4902(rule (fcvt_to_uint_lb $F32) (imm $F32 (fcvt_to_uint_lb32)))
4903(rule (fcvt_to_uint_lb $F64) (imm $F64 (fcvt_to_uint_lb64)))
4904(rule (fcvt_to_uint_lb $F128) (vec_imm $F128 (fcvt_to_uint_lb128)))
4905
4906(decl fcvt_to_uint_ub32 (u8) u64)
4907(extern constructor fcvt_to_uint_ub32 fcvt_to_uint_ub32)
4908(decl fcvt_to_uint_lb32 () u64)
4909(extern constructor fcvt_to_uint_lb32 fcvt_to_uint_lb32)
4910(decl fcvt_to_uint_ub64 (u8) u64)
4911(extern constructor fcvt_to_uint_ub64 fcvt_to_uint_ub64)
4912(decl fcvt_to_uint_lb64 () u64)
4913(extern constructor fcvt_to_uint_lb64 fcvt_to_uint_lb64)
4914(decl fcvt_to_uint_ub128 (u8) u128)
4915(extern constructor fcvt_to_uint_ub128 fcvt_to_uint_ub128)
4916(decl fcvt_to_uint_lb128 () u128)
4917(extern constructor fcvt_to_uint_lb128 fcvt_to_uint_lb128)
4918
4919
4920;; Helpers for generating `fcvt_to_sint` instructions ;;;;;;;;;;;;;;;;;;;;;;;;
4921
4922(decl fcvt_to_sint_reg (Type Type FpuRoundMode Reg) Reg)
4923(rule (fcvt_to_sint_reg $I32 $F32 mode x)
4924      (vec_extract_lane $F32X4 (fpu_round $F32 (FpuRoundOp.ToSInt32) mode x) 0 (zero_reg)))
4925(rule (fcvt_to_sint_reg $I64 $F64 mode x)
4926      (vec_extract_lane $F64X2 (fpu_round $F64 (FpuRoundOp.ToSInt64) mode x) 0 (zero_reg)))
4927(rule (fcvt_to_sint_reg $I32X4 $F32X4 mode x)
4928      (fpu_round $F32X4 (FpuRoundOp.ToSInt32x4) mode x))
4929(rule (fcvt_to_sint_reg $I64X2 $F64X2 mode x)
4930      (fpu_round $F64X2 (FpuRoundOp.ToSInt64x2) mode x))
4931(rule (fcvt_to_sint_reg $I32 $F128 mode x)
4932      (fpu_conv128_to_int $I32 (FpuConv128Op.SInt32) mode (fp_reg_to_regpair x)))
4933(rule (fcvt_to_sint_reg $I64 $F128 mode x)
4934      (fpu_conv128_to_int $I64 (FpuConv128Op.SInt64) mode (fp_reg_to_regpair x)))
4935
4936(decl fcvt_to_sint_ub (Type Type) Reg)
4937(rule (fcvt_to_sint_ub $F32 dst_ty)
4938      (imm $F32 (fcvt_to_sint_ub32 (ty_bits dst_ty))))
4939(rule (fcvt_to_sint_ub $F64 dst_ty)
4940      (imm $F64 (fcvt_to_sint_ub64 (ty_bits dst_ty))))
4941(rule (fcvt_to_sint_ub $F128 dst_ty)
4942      (vec_imm $F128 (fcvt_to_sint_ub128 (ty_bits dst_ty))))
4943
4944(decl fcvt_to_sint_lb (Type Type) Reg)
4945(rule (fcvt_to_sint_lb $F32 dst_ty)
4946      (imm $F32 (fcvt_to_sint_lb32 (ty_bits dst_ty))))
4947(rule (fcvt_to_sint_lb $F64 dst_ty)
4948      (imm $F64 (fcvt_to_sint_lb64 (ty_bits dst_ty))))
4949(rule (fcvt_to_sint_lb $F128 dst_ty)
4950      (vec_imm $F128 (fcvt_to_sint_lb128 (ty_bits dst_ty))))
4951
4952(decl fcvt_to_sint_ub32 (u8) u64)
4953(extern constructor fcvt_to_sint_ub32 fcvt_to_sint_ub32)
4954(decl fcvt_to_sint_lb32 (u8) u64)
4955(extern constructor fcvt_to_sint_lb32 fcvt_to_sint_lb32)
4956(decl fcvt_to_sint_ub64 (u8) u64)
4957(extern constructor fcvt_to_sint_ub64 fcvt_to_sint_ub64)
4958(decl fcvt_to_sint_lb64 (u8) u64)
4959(extern constructor fcvt_to_sint_lb64 fcvt_to_sint_lb64)
4960(decl fcvt_to_sint_ub128 (u8) u128)
4961(extern constructor fcvt_to_sint_ub128 fcvt_to_sint_ub128)
4962(decl fcvt_to_sint_lb128 (u8) u128)
4963(extern constructor fcvt_to_sint_lb128 fcvt_to_sint_lb128)
4964
4965
4966;; Helpers for generating signed `icmp` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
4967
4968(decl cmpop_cmps (Type) CmpOp)
4969(rule (cmpop_cmps $I32) (CmpOp.CmpS32))
4970(rule (cmpop_cmps $I64) (CmpOp.CmpS64))
4971
4972(decl cmpop_cmps_sext16 (Type) CmpOp)
4973(rule (cmpop_cmps_sext16 $I32) (CmpOp.CmpS32Ext16))
4974(rule (cmpop_cmps_sext16 $I64) (CmpOp.CmpS64Ext16))
4975
4976(decl cmpop_cmps_sext32 (Type) CmpOp)
4977(rule (cmpop_cmps_sext32 $I64) (CmpOp.CmpS64Ext32))
4978
4979(decl icmps_reg (Type Reg Reg) ProducesFlags)
4980(rule (icmps_reg ty src1 src2) (cmp_rr (cmpop_cmps ty) src1 src2))
4981
4982(decl icmps_reg_sext32 (Type Reg Reg) ProducesFlags)
4983(rule (icmps_reg_sext32 ty src1 src2) (cmp_rr (cmpop_cmps_sext32 ty) src1 src2))
4984
4985(decl icmps_simm16 (Type Reg i16) ProducesFlags)
4986(rule (icmps_simm16 ty src imm) (cmp_rsimm16 (cmpop_cmps ty) src imm))
4987
4988(decl icmps_simm32 (Type Reg i32) ProducesFlags)
4989(rule (icmps_simm32 ty src imm) (cmp_rsimm32 (cmpop_cmps ty) src imm))
4990
4991(decl icmps_mem (Type Reg MemArg) ProducesFlags)
4992(rule (icmps_mem ty src mem) (cmp_rx (cmpop_cmps ty) src mem))
4993
4994(decl icmps_mem_sext16 (Type Reg MemArg) ProducesFlags)
4995(rule (icmps_mem_sext16 ty src mem) (cmp_rx (cmpop_cmps_sext16 ty) src mem))
4996
4997(decl icmps_mem_sext32 (Type Reg MemArg) ProducesFlags)
4998(rule (icmps_mem_sext32 ty src mem) (cmp_rx (cmpop_cmps_sext32 ty) src mem))
4999
5000
5001;; Helpers for generating unsigned `icmp` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;
5002
5003(decl cmpop_cmpu (Type) CmpOp)
5004(rule (cmpop_cmpu $I32) (CmpOp.CmpL32))
5005(rule (cmpop_cmpu $I64) (CmpOp.CmpL64))
5006
5007(decl cmpop_cmpu_zext16 (Type) CmpOp)
5008(rule (cmpop_cmpu_zext16 $I32) (CmpOp.CmpL32Ext16))
5009(rule (cmpop_cmpu_zext16 $I64) (CmpOp.CmpL64Ext16))
5010
5011(decl cmpop_cmpu_zext32 (Type) CmpOp)
5012(rule (cmpop_cmpu_zext32 $I64) (CmpOp.CmpL64Ext32))
5013
5014(decl icmpu_reg (Type Reg Reg) ProducesFlags)
5015(rule (icmpu_reg ty src1 src2) (cmp_rr (cmpop_cmpu ty) src1 src2))
5016
5017(decl icmpu_reg_zext32 (Type Reg Reg) ProducesFlags)
5018(rule (icmpu_reg_zext32 ty src1 src2) (cmp_rr (cmpop_cmpu_zext32 ty) src1 src2))
5019
5020(decl icmpu_uimm32 (Type Reg u32) ProducesFlags)
5021(rule (icmpu_uimm32 ty src imm) (cmp_ruimm32 (cmpop_cmpu ty) src imm))
5022
5023(decl icmpu_mem (Type Reg MemArg) ProducesFlags)
5024(rule (icmpu_mem ty src mem) (cmp_rx (cmpop_cmpu ty) src mem))
5025
5026(decl icmpu_mem_zext16 (Type Reg MemArg) ProducesFlags)
5027(rule (icmpu_mem_zext16 ty src mem) (cmp_rx (cmpop_cmpu_zext16 ty) src mem))
5028
5029(decl icmpu_mem_zext32 (Type Reg MemArg) ProducesFlags)
5030(rule (icmpu_mem_zext32 ty src mem) (cmp_rx (cmpop_cmpu_zext32 ty) src mem))
5031
5032
5033;; Helpers for generating vector `icmp` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
5034
5035(decl vecop_int_cmpeq (Type) VecIntCmpOp)
5036(rule (vecop_int_cmpeq (multi_lane 8 16)) (VecIntCmpOp.CmpEq8x16))
5037(rule (vecop_int_cmpeq (multi_lane 16 8)) (VecIntCmpOp.CmpEq16x8))
5038(rule (vecop_int_cmpeq (multi_lane 32 4)) (VecIntCmpOp.CmpEq32x4))
5039(rule (vecop_int_cmpeq (multi_lane 64 2)) (VecIntCmpOp.CmpEq64x2))
5040
5041(decl vec_cmpeq (Type Reg Reg) Reg)
5042(rule (vec_cmpeq (vr128_ty ty) x y) (vec_int_cmp ty (vecop_int_cmpeq ty) x y))
5043(decl vec_cmpeqs (Type Reg Reg) ProducesFlags)
5044(rule (vec_cmpeqs (vr128_ty ty) x y) (vec_int_cmps ty (vecop_int_cmpeq ty) x y))
5045
5046(decl vecop_int_cmph (Type) VecIntCmpOp)
5047(rule (vecop_int_cmph (multi_lane 8 16)) (VecIntCmpOp.SCmpHi8x16))
5048(rule (vecop_int_cmph (multi_lane 16 8)) (VecIntCmpOp.SCmpHi16x8))
5049(rule (vecop_int_cmph (multi_lane 32 4)) (VecIntCmpOp.SCmpHi32x4))
5050(rule (vecop_int_cmph (multi_lane 64 2)) (VecIntCmpOp.SCmpHi64x2))
5051
5052(decl vec_cmph (Type Reg Reg) Reg)
5053(rule (vec_cmph (vr128_ty ty) x y) (vec_int_cmp ty (vecop_int_cmph ty) x y))
5054(decl vec_cmphs (Type Reg Reg) ProducesFlags)
5055(rule (vec_cmphs (vr128_ty ty) x y) (vec_int_cmps ty (vecop_int_cmph ty) x y))
5056
5057(decl vecop_int_cmphl (Type) VecIntCmpOp)
5058(rule (vecop_int_cmphl (multi_lane 8 16)) (VecIntCmpOp.UCmpHi8x16))
5059(rule (vecop_int_cmphl (multi_lane 16 8)) (VecIntCmpOp.UCmpHi16x8))
5060(rule (vecop_int_cmphl (multi_lane 32 4)) (VecIntCmpOp.UCmpHi32x4))
5061(rule (vecop_int_cmphl (multi_lane 64 2)) (VecIntCmpOp.UCmpHi64x2))
5062
5063(decl vec_cmphl (Type Reg Reg) Reg)
5064(rule (vec_cmphl (vr128_ty ty) x y) (vec_int_cmp ty (vecop_int_cmphl ty) x y))
5065(decl vec_cmphls (Type Reg Reg) ProducesFlags)
5066(rule (vec_cmphls (vr128_ty ty) x y) (vec_int_cmps ty (vecop_int_cmphl ty) x y))
5067
5068(decl vec_elt_icmps (Reg Reg) ProducesFlags)
5069(rule (vec_elt_icmps x y) (vec_int_elt_cmp (VecIntEltCmpOp.SCmp128) x y))
5070
5071(decl vec_elt_icmpu (Reg Reg) ProducesFlags)
5072(rule (vec_elt_icmpu x y) (vec_int_elt_cmp (VecIntEltCmpOp.UCmp128) x y))
5073
5074
5075;; Helpers for generating `fcmp` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5076
5077(decl fcmp_reg (Type Reg Reg) ProducesFlags)
5078(rule (fcmp_reg $F32 src1 src2) (fpu_cmp32 src1 src2))
5079(rule (fcmp_reg $F64 src1 src2) (fpu_cmp64 src1 src2))
5080(rule (fcmp_reg $F128 src1 src2) (fpu_cmp128 src1 src2))
5081
5082
5083;; Helpers for generating vector `fcmp` instructions ;;;;;;;;;;;;;;;;;;;;;;;;;;;
5084
5085(decl vecop_float_cmpeq (Type) VecFloatCmpOp)
5086(rule (vecop_float_cmpeq (multi_lane 32 4)) (VecFloatCmpOp.CmpEq32x4))
5087(rule (vecop_float_cmpeq (multi_lane 64 2)) (VecFloatCmpOp.CmpEq64x2))
5088
5089(decl vec_fcmpeq (Type Reg Reg) Reg)
5090(rule (vec_fcmpeq (ty_vec128 ty) x y) (vec_float_cmp ty (vecop_float_cmpeq ty) x y))
5091(decl vec_fcmpeqs (Type Reg Reg) ProducesFlags)
5092(rule (vec_fcmpeqs (ty_vec128 ty) x y) (vec_float_cmps ty (vecop_float_cmpeq ty) x y))
5093
5094(decl vecop_float_cmph (Type) VecFloatCmpOp)
5095(rule (vecop_float_cmph (multi_lane 32 4)) (VecFloatCmpOp.CmpHi32x4))
5096(rule (vecop_float_cmph (multi_lane 64 2)) (VecFloatCmpOp.CmpHi64x2))
5097
5098(decl vec_fcmph (Type Reg Reg) Reg)
5099(rule (vec_fcmph (ty_vec128 ty) x y) (vec_float_cmp ty (vecop_float_cmph ty) x y))
5100(decl vec_fcmphs (Type Reg Reg) ProducesFlags)
5101(rule (vec_fcmphs (ty_vec128 ty) x y) (vec_float_cmps ty (vecop_float_cmph ty) x y))
5102
5103(decl vecop_float_cmphe (Type) VecFloatCmpOp)
5104(rule (vecop_float_cmphe (multi_lane 32 4)) (VecFloatCmpOp.CmpHiEq32x4))
5105(rule (vecop_float_cmphe (multi_lane 64 2)) (VecFloatCmpOp.CmpHiEq64x2))
5106
5107(decl vec_fcmphe (Type Reg Reg) Reg)
5108(rule (vec_fcmphe (ty_vec128 ty) x y) (vec_float_cmp ty (vecop_float_cmphe ty) x y))
5109(decl vec_fcmphes (Type Reg Reg) ProducesFlags)
5110(rule (vec_fcmphes (ty_vec128 ty) x y) (vec_float_cmps ty (vecop_float_cmphe ty) x y))
5111
5112;; Other helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5113
5114;; Helper for creating an `LabelAddress` instruction.
5115(decl s390x_label_address (MachLabel) Reg)
5116(rule (s390x_label_address label)
5117      (let ((dst WritableReg (temp_writable_reg $I64))
5118            (_ Unit (emit (MInst.LabelAddress dst label))))
5119        dst))
5120
5121;; Helper for creating a `SequencePoint` instruction.
5122(decl s390x_sequence_point () SideEffectNoResult)
5123(rule (s390x_sequence_point)
5124      (SideEffectNoResult.Inst (MInst.SequencePoint)))
5125
5126;; Implicit conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5127
5128(convert WritableRegPair RegPair writable_regpair_to_regpair)
5129