[JSC] Remove some invalid immediate instruction forms from ARM64 Air
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirOpcode.opcodes
1 # Copyright (C) 2015-2016 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
23
24 # Syllabus:
25 #
26 # Examples of some roles, types, and widths:
27 # U:G:32 => use of the low 32 bits of a general-purpose register or value
28 # D:G:32 => def of the low 32 bits of a general-purpose register or value
29 # UD:G:32 => use and def of the low 32 bits of a general-purpose register or value
30 # U:G:64 => use of the low 64 bits of a general-purpose register or value
31 # ZD:G:32 => def of all bits of a general-purpose register, where all but the low 32 bits are guaranteed to be zeroed.
32 # UA:G:Ptr => UseAddr (see comment in Arg.h)
33 # U:F:32 => use of a float register or value
34 # U:F:64 => use of a double register or value
35 # D:F:32 => def of a float register or value
36 # UD:F:32 => use and def of a float register or value
37 # S:F:32 => scratch float register.
38 #
39 # Argument kinds:
40 # Tmp => temporary or register
41 # Imm => 32-bit immediate int
42 # Imm64 => TrustedImm64
43 # Addr => address as temporary/register+offset
44 # Index => BaseIndex address
45 # Abs => AbsoluteAddress
46 #
47 # The parser views these things as keywords, and understands that they fall into two distinct classes
48 # of things. So, although this file uses a particular indentation style, none of the whitespace or
49 # even newlines are meaningful to the parser. For example, you could write:
50 #
51 # Foo42 U:G:32, UD:F:32 Imm, Tmp Addr, Tmp
52 #
53 # And the parser would know that this is the same as:
54 #
55 # Foo42 U:G:32, UD:F:32
56 #     Imm, Tmp
57 #     Addr, Tmp
58 #
59 # I.e. a two-form instruction that uses a GPR or an int immediate and uses+defs a float register.
60 #
61 # Any opcode or opcode form can be preceded with an architecture list, which restricts the opcode to the
62 # union of those architectures. For example, if this is the only overload of the opcode, then it makes the
63 # opcode only available on x86_64:
64 #
65 # x86_64: Fuzz UD:G:64, D:G:64
66 #     Tmp, Tmp
67 #     Tmp, Addr
68 #
69 # But this only restricts the two-operand form, the other form is allowed on all architectures:
70 #
71 # x86_64: Fuzz UD:G:64, D:G:64
72 #     Tmp, Tmp
73 #     Tmp, Addr
74 # Fuzz UD:G:Ptr, D:G:Ptr, U:F:Ptr
75 #     Tmp, Tmp, Tmp
76 #     Tmp, Addr, Tmp
77 #
78 # And you can also restrict individual forms:
79 #
80 # Thingy UD:G:32, D:G:32
81 #     Tmp, Tmp
82 #     arm64: Tmp, Addr
83 #
84 # Additionally, you can have an intersection between the architectures of the opcode overload and the
85 # form. In this example, the version that takes an address is only available on armv7 while the other
86 # versions are available on armv7 or x86_64:
87 #
88 # x86_64 armv7: Buzz U:G:32, UD:F:32
89 #     Tmp, Tmp
90 #     Imm, Tmp
91 #     armv7: Addr, Tmp
92 #
93 # Finally, you can specify architectures using helpful architecture groups. Here are all of the
94 # architecture keywords that we support:
95 #
96 # x86: means x86-32 or x86-64.
97 # x86_32: means just x86-32.
98 # x86_64: means just x86-64.
99 # arm: means armv7 or arm64.
100 # armv7: means just armv7.
101 # arm64: means just arm64.
102 # 32: means x86-32 or armv7.
103 # 64: means x86-64 or arm64.
104
105 # Note that the opcodes here have a leading capital (Add32) but must correspond to MacroAssembler
106 # API that has a leading lower-case (add32).
107
108 Nop
109
110 Add32 U:G:32, UZD:G:32
111     Tmp, Tmp
112     x86: Imm, Addr
113     Imm, Tmp
114     x86: Addr, Tmp
115     x86: Tmp, Addr
116
117 Add32 U:G:32, U:G:32, ZD:G:32
118     Imm, Tmp, Tmp
119     Tmp, Tmp, Tmp
120
121 64: Add64 U:G:64, UD:G:64
122     Tmp, Tmp
123     x86: Imm, Addr
124     Imm, Tmp
125     x86: Addr, Tmp
126     x86: Tmp, Addr
127
128 64: Add64 U:G:64, U:G:64, D:G:64
129     Imm, Tmp, Tmp
130     Tmp, Tmp, Tmp
131
132 arm64: AddDouble U:F:64, U:F:64, D:F:64
133     Tmp, Tmp, Tmp
134
135 x86: AddDouble U:F:64, UD:F:64
136     Tmp, Tmp
137     Addr, Tmp
138
139 arm64: AddFloat U:F:32, U:F:32, D:F:32
140     Tmp, Tmp, Tmp
141
142 x86: AddFloat U:F:32, UD:F:32
143     Tmp, Tmp
144     Addr, Tmp
145
146 Sub32 U:G:32, UZD:G:32
147     Tmp, Tmp
148     x86: Imm, Addr
149     Imm, Tmp
150     x86: Addr, Tmp
151     x86: Tmp, Addr
152
153 64: Sub64 U:G:64, UD:G:64
154     Tmp, Tmp
155     x86: Imm, Addr
156     Imm, Tmp
157     x86: Addr, Tmp
158     x86: Tmp, Addr
159
160 arm64: SubDouble U:F:64, U:F:64, D:F:64
161     Tmp, Tmp, Tmp
162
163 x86: SubDouble U:F:64, UD:F:64
164     Tmp, Tmp
165     Addr, Tmp
166
167 arm64: SubFloat U:F:32, U:F:32, D:F:32
168     Tmp, Tmp, Tmp
169
170 x86: SubFloat U:F:32, UD:F:32
171     Tmp, Tmp
172     Addr, Tmp
173
174 Neg32 UZD:G:32
175     Tmp
176     x86: Addr
177
178 64: Neg64 UD:G:64
179     Tmp
180
181 arm64: NegateDouble U:F:64, D:F:64
182     Tmp, Tmp
183
184 Mul32 U:G:32, UZD:G:32
185     Tmp, Tmp
186     x86: Addr, Tmp
187
188 Mul32 U:G:32, U:G:32, ZD:G:32
189     arm64: Tmp, Tmp, Tmp
190     x86: Imm, Tmp, Tmp
191
192 64: Mul64 U:G:64, UD:G:64
193     Tmp, Tmp
194
195 arm64: Mul64 U:G:64, U:G:64, D:G:64
196     Tmp, Tmp, Tmp
197
198 arm64: Div32 U:G:32, U:G:32, ZD:G:32
199     Tmp, Tmp, Tmp
200
201 arm64: Div64 U:G:64, U:G:64, D:G:64
202     Tmp, Tmp, Tmp
203
204 arm64: MulDouble U:F:64, U:F:64, D:F:64
205     Tmp, Tmp, Tmp
206
207 x86: MulDouble U:F:64, UD:F:64
208     Tmp, Tmp
209     Addr, Tmp
210
211 arm64: MulFloat U:F:32, U:F:32, D:F:32
212     Tmp, Tmp, Tmp
213
214 x86: MulFloat U:F:32, UD:F:32
215     Tmp, Tmp
216     Addr, Tmp
217
218 arm64: DivDouble U:F:64, U:F:32, D:F:64
219     Tmp, Tmp, Tmp
220
221 x86: DivDouble U:F:64, UD:F:64
222     Tmp, Tmp
223     Addr, Tmp
224
225 arm64: DivFloat U:F:32, U:F:32, D:F:32
226     Tmp, Tmp, Tmp
227
228 x86: DivFloat U:F:32, UD:F:32
229     Tmp, Tmp
230     Addr, Tmp
231
232 x86: X86ConvertToDoubleWord32 U:G:32, ZD:G:32
233     Tmp*, Tmp*
234
235 x86_64: X86ConvertToQuadWord64 U:G:64, D:G:64
236     Tmp*, Tmp*
237
238 x86: X86Div32 UZD:G:32, UZD:G:32, U:G:32
239     Tmp*, Tmp*, Tmp
240
241 x86_64: X86Div64 UZD:G:64, UZD:G:64, U:G:64
242     Tmp*, Tmp*, Tmp
243
244 Lea UA:G:Ptr, D:G:Ptr
245     Addr, Tmp
246
247 And32 U:G:32, UZD:G:32
248     Tmp, Tmp
249     x86: Imm, Tmp
250     x86: Tmp, Addr
251     x86: Addr, Tmp
252     x86: Imm, Addr
253
254 64: And64 U:G:64, UD:G:64
255     Tmp, Tmp
256     x86: Imm, Tmp
257
258 arm64: AndDouble U:F:64, U:F:64, D:F:64
259     Tmp, Tmp, Tmp
260
261 x86: AndDouble U:F:64, UD:F:64
262     Tmp, Tmp
263
264 arm64: AndFloat U:F:32, U:F:32, D:F:32
265     Tmp, Tmp, Tmp
266
267 x86: AndFloat U:F:32, UD:F:32
268     Tmp, Tmp
269
270 x86: XorDouble U:F:64, UD:F:64
271     Tmp, Tmp
272
273 x86: XorFloat U:F:32, UD:F:32
274     Tmp, Tmp
275
276 arm64: Lshift32 U:G:32, U:G:32, ZD:G:32
277     Tmp, Tmp, Tmp
278     Tmp, Imm, Tmp
279
280 x86:Lshift32 U:G:32, UZD:G:32
281     Tmp*, Tmp
282     Imm, Tmp
283
284 arm64: Lshift64 U:G:64, U:G:64, ZD:G:64
285     Tmp, Tmp, Tmp
286     Tmp, Imm, Tmp
287
288 x86_64: Lshift64 U:G:64, UD:G:64
289     Tmp*, Tmp
290     Imm, Tmp
291
292 arm64: Rshift32 U:G:32, U:G:32, ZD:G:32
293     Tmp, Tmp, Tmp
294     Tmp, Imm, Tmp
295
296 x86: Rshift32 U:G:32, UZD:G:32
297     Tmp*, Tmp
298     Imm, Tmp
299
300 arm64: Rshift64 U:G:64, U:G:64, ZD:G:64
301     Tmp, Tmp, Tmp
302     Tmp, Imm, Tmp
303
304 x86_64: Rshift64 U:G:64, UD:G:64
305     Tmp*, Tmp
306     Imm, Tmp
307
308 arm64: Urshift32 U:G:32, U:G:32, ZD:G:32
309     Tmp, Tmp, Tmp
310     Tmp, Imm, Tmp
311
312 x86: Urshift32 U:G:32, UZD:G:32
313     Tmp*, Tmp
314     Imm, Tmp
315
316 arm64: Urshift64 U:G:64, U:G:64, ZD:G:64
317     Tmp, Tmp, Tmp
318     Tmp, Imm, Tmp
319
320 x86_64: Urshift64 U:G:64, UD:G:64
321     Tmp*, Tmp
322     Imm, Tmp
323
324 Or32 U:G:32, UZD:G:32
325     Tmp, Tmp
326     x86: Imm, Tmp
327     x86: Tmp, Addr
328     x86: Addr, Tmp
329     x86: Imm, Addr
330
331 64: Or64 U:G:64, UD:G:64
332     Tmp, Tmp
333     x86: Imm, Tmp
334
335 Xor32 U:G:32, UZD:G:32
336     Tmp, Tmp
337     x86: Imm, Tmp
338     x86: Tmp, Addr
339     x86: Addr, Tmp
340     x86: Imm, Addr
341
342 64: Xor64 U:G:64, UD:G:64
343     Tmp, Tmp
344     x86: Tmp, Addr
345     x86: Imm, Tmp
346
347 arm64: Not32 U:G:32, ZD:G:32
348     Tmp, Tmp
349
350 x86: Not32 UZD:G:32
351     Tmp
352     Addr
353
354 arm64: Not64 U:G:64, D:G:64
355     Tmp, Tmp
356
357 x86: Not64 UD:G:64
358     Tmp
359     Addr
360
361 arm64: AbsDouble U:F:64, D:F:64
362     Tmp, Tmp
363
364 arm64: AbsFloat U:F:32, D:F:32
365     Tmp, Tmp
366
367 CeilDouble U:F:64, UD:F:64
368     Tmp, Tmp
369     x86: Addr, Tmp
370
371 CeilFloat U:F:32, UD:F:32
372     Tmp, Tmp
373     x86: Addr, Tmp
374
375 SqrtDouble U:F:64, UD:F:64
376     Tmp, Tmp
377     x86: Addr, Tmp
378
379 SqrtFloat U:F:32, UD:F:32
380     Tmp, Tmp
381     x86: Addr, Tmp
382
383 ConvertInt32ToDouble U:G:32, D:F:64
384     Tmp, Tmp
385     x86: Addr, Tmp
386
387 64: ConvertInt64ToDouble U:G:64, D:F:64
388     Tmp, Tmp
389
390 CountLeadingZeros32 U:G:32, ZD:G:32
391     Tmp, Tmp
392     x86: Addr, Tmp
393
394 64: CountLeadingZeros64 U:G:64, D:G:64
395     Tmp, Tmp
396     x86: Addr, Tmp
397
398 ConvertDoubleToFloat U:F:64, D:F:32
399     Tmp, Tmp
400     x86: Addr, Tmp
401
402 ConvertFloatToDouble U:F:32, D:F:64
403     Tmp, Tmp
404     x86: Addr, Tmp
405
406 # Note that Move operates over the full register size, which is either 32-bit or 64-bit depending on
407 # the platform. I'm not entirely sure that this is a good thing; it might be better to just have a
408 # Move64 instruction. OTOH, our MacroAssemblers already have this notion of "move()" that basically
409 # means movePtr.
410 Move U:G:Ptr, D:G:Ptr
411     Tmp, Tmp
412     Imm, Tmp as signExtend32ToPtr
413     Imm64, Tmp
414     Addr, Tmp as loadPtr # This means that "Move Addr, Tmp" is code-generated as "load" not "move".
415     Index, Tmp as loadPtr
416     Tmp, Addr as storePtr
417     Tmp, Index as storePtr
418     x86: Imm, Addr as storePtr
419
420 Move32 U:G:32, ZD:G:32
421     Tmp, Tmp as zeroExtend32ToPtr
422     Addr, Tmp as load32
423     Index, Tmp as load32
424     Tmp, Addr as store32
425     Tmp, Index as store32
426     x86: Imm, Addr as store32
427     x86: Imm, Index as store32
428
429 SignExtend32ToPtr U:G:32, D:G:Ptr
430     Tmp, Tmp
431
432 ZeroExtend8To32 U:G:8, ZD:G:32
433     Tmp, Tmp
434     Addr, Tmp as load8
435     Index, Tmp as load8
436
437 SignExtend8To32 U:G:8, ZD:G:32
438     Tmp, Tmp
439     Addr, Tmp as load8SignedExtendTo32
440     Index, Tmp as load8SignedExtendTo32
441
442 ZeroExtend16To32 U:G:16, ZD:G:32
443     Tmp, Tmp
444     Addr, Tmp as load16
445     Index, Tmp as load16
446
447 SignExtend16To32 U:G:16, ZD:G:32
448     Tmp, Tmp
449     Addr, Tmp as load16SignedExtendTo32
450     Index, Tmp as load16SignedExtendTo32
451
452 MoveFloat U:F:32, D:F:32
453     Tmp, Tmp as moveDouble
454     Addr, Tmp as loadFloat
455     Index, Tmp as loadFloat
456     Tmp, Addr as storeFloat
457     Tmp, Index as storeFloat
458
459 MoveDouble U:F:64, D:F:64
460     Tmp, Tmp
461     Addr, Tmp as loadDouble
462     Index, Tmp as loadDouble
463     Tmp, Addr as storeDouble
464     Tmp, Index as storeDouble
465
466 MoveZeroToDouble D:F:64
467     Tmp
468
469 64: Move64ToDouble U:G:64, D:F:64
470     Tmp, Tmp
471     x86: Addr, Tmp as loadDouble
472     Index, Tmp as loadDouble
473
474 Move32ToFloat U:G:32, D:F:32
475     Tmp, Tmp
476     x86: Addr, Tmp as loadFloat
477     Index, Tmp as loadFloat
478
479 64: MoveDoubleTo64 U:F:64, D:G:64
480     Tmp, Tmp
481     Addr, Tmp as load64
482     Index, Tmp as load64
483
484 MoveFloatTo32 U:F:32, D:G:32
485     Tmp, Tmp
486     Addr, Tmp as load32
487     Index, Tmp as load32
488
489 Load8 U:G:8, ZD:G:32
490     Addr, Tmp
491     Index, Tmp
492
493 Store8 U:G:8, D:G:8
494     Tmp, Index
495     Tmp, Addr
496     x86: Imm, Index
497     x86: Imm, Addr
498
499 Load8SignedExtendTo32 U:G:8, ZD:G:32
500     Addr, Tmp
501     Index, Tmp
502
503 Load16 U:G:16, ZD:G:32
504     Addr, Tmp
505     Index, Tmp
506
507 Load16SignedExtendTo32 U:G:16, ZD:G:32
508     Addr, Tmp
509     Index, Tmp
510
511 Store16 U:G:16, D:G:16
512     Tmp, Index
513     Tmp, Addr
514
515 Compare32 U:G:32, U:G:32, U:G:32, ZD:G:32
516     RelCond, Tmp, Tmp, Tmp
517     x86: RelCond, Tmp, Imm, Tmp
518
519 64: Compare64 U:G:32, U:G:64, U:G:64, ZD:G:32
520     RelCond, Tmp, Tmp, Tmp
521     x86: RelCond, Tmp, Imm, Tmp
522
523 Test32 U:G:32, U:G:32, U:G:32, ZD:G:32
524     x86: ResCond, Addr, Imm, Tmp
525     ResCond, Tmp, Tmp, Tmp
526
527 64: Test64 U:G:32, U:G:64, U:G:64, ZD:G:32
528     x86: ResCond, Tmp, Imm, Tmp
529     ResCond, Tmp, Tmp, Tmp
530
531 CompareDouble U:G:32, U:F:64, U:F:64, ZD:G:32
532     DoubleCond, Tmp, Tmp, Tmp
533
534 CompareFloat U:G:32, U:F:32, U:F:32, ZD:G:32
535     DoubleCond, Tmp, Tmp, Tmp
536
537 # Note that branches have some logic in AirOptimizeBlockOrder.cpp. If you add new branches, please make sure
538 # you opt them into the block order optimizations.
539
540 Branch8 U:G:32, U:G:8, U:G:8 /branch
541     x86: RelCond, Addr, Imm
542     x86: RelCond, Index, Imm
543
544 Branch32 U:G:32, U:G:32, U:G:32 /branch
545     x86: RelCond, Addr, Imm
546     RelCond, Tmp, Tmp
547     RelCond, Tmp, Imm
548     x86: RelCond, Tmp, Addr
549     x86: RelCond, Addr, Tmp
550     x86: RelCond, Index, Imm
551
552 64: Branch64 U:G:32, U:G:64, U:G:64 /branch
553     RelCond, Tmp, Tmp
554     x86: RelCond, Tmp, Imm
555     x86: RelCond, Tmp, Addr
556     x86: RelCond, Addr, Tmp
557     x86: RelCond, Addr, Imm
558     x86: RelCond, Index, Tmp
559
560 BranchTest8 U:G:32, U:G:8, U:G:8 /branch
561     x86: ResCond, Addr, Imm
562     x86: ResCond, Index, Imm
563
564 BranchTest32 U:G:32, U:G:32, U:G:32 /branch
565     ResCond, Tmp, Tmp
566     x86: ResCond, Tmp, Imm
567     x86: ResCond, Addr, Imm
568     x86: ResCond, Index, Imm
569
570 # Warning: forms that take an immediate will sign-extend their immediate. You probably want
571 # BranchTest32 in most cases where you use an immediate.
572 64: BranchTest64 U:G:32, U:G:64, U:G:64 /branch
573     ResCond, Tmp, Tmp
574     x86: ResCond, Tmp, Imm
575     x86: ResCond, Addr, Imm
576     x86: ResCond, Addr, Tmp
577     x86: ResCond, Index, Imm
578
579 BranchDouble U:G:32, U:F:64, U:F:64 /branch
580     DoubleCond, Tmp, Tmp
581
582 BranchFloat U:G:32, U:F:32, U:F:32 /branch
583     DoubleCond, Tmp, Tmp
584
585 BranchAdd32 U:G:32, U:G:32, UZD:G:32 /branch
586     ResCond, Tmp, Tmp
587     ResCond, Imm, Tmp
588     x86: ResCond, Imm, Addr
589     x86: ResCond, Tmp, Addr
590     x86: ResCond, Addr, Tmp
591
592 64: BranchAdd64 U:G:32, U:G:64, UD:G:64 /branch
593     ResCond, Imm, Tmp
594     ResCond, Tmp, Tmp
595
596 x86: BranchMul32 U:G:32, U:G:32, UZD:G:32 /branch
597     ResCond, Tmp, Tmp
598     ResCond, Addr, Tmp
599
600 x86: BranchMul32 U:G:32, U:G:32, U:G:32, ZD:G:32 /branch
601     ResCond, Tmp, Imm, Tmp
602
603 arm64: BranchMul32 U:G:32, U:G:32, U:G:32, S:G:32, S:G:32, ZD:G:32 /branch
604     ResCond, Tmp, Tmp, Tmp, Tmp, Tmp
605
606 x86_64: BranchMul64 U:G:32, U:G:64, UZD:G:64 /branch
607     ResCond, Tmp, Tmp
608
609 arm64: BranchMul64 U:G:32, U:G:64, U:G:64, S:G:64, S:G:64, ZD:G:64 /branch
610     ResCond, Tmp, Tmp, Tmp, Tmp, Tmp
611
612 BranchSub32 U:G:32, U:G:32, UZD:G:32 /branch
613     ResCond, Tmp, Tmp
614     ResCond, Imm, Tmp
615     x86: ResCond, Imm, Addr
616     x86: ResCond, Tmp, Addr
617     x86: ResCond, Addr, Tmp
618
619 64: BranchSub64 U:G:32, U:G:64, UD:G:64 /branch
620     ResCond, Imm, Tmp
621     ResCond, Tmp, Tmp
622
623 BranchNeg32 U:G:32, UZD:G:32 /branch
624     ResCond, Tmp
625
626 64: BranchNeg64 U:G:32, UZD:G:64 /branch
627     ResCond, Tmp
628
629 MoveConditionally32 U:G:32, U:G:32, U:G:32, U:G:Ptr, UD:G:Ptr
630     RelCond, Tmp, Tmp, Tmp, Tmp
631
632 64: MoveConditionally64 U:G:32, U:G:64, U:G:64, U:G:Ptr, UD:G:Ptr
633     RelCond, Tmp, Tmp, Tmp, Tmp
634
635 MoveConditionallyTest32 U:G:32, U:G:32, U:G:32, U:G:Ptr, UD:G:Ptr
636     ResCond, Tmp, Tmp, Tmp, Tmp
637     x86: ResCond, Tmp, Imm, Tmp, Tmp
638
639 64: MoveConditionallyTest64 U:G:32, U:G:64, U:G:64, U:G:Ptr, UD:G:Ptr
640     ResCond, Tmp, Tmp, Tmp, Tmp
641     x86: ResCond, Tmp, Imm, Tmp, Tmp
642
643 MoveConditionallyDouble U:G:32, U:F:64, U:F:64, U:G:Ptr, UD:G:Ptr
644     DoubleCond, Tmp, Tmp, Tmp, Tmp
645
646 MoveConditionallyFloat U:G:32, U:F:32, U:F:32, U:G:Ptr, UD:G:Ptr
647     DoubleCond, Tmp, Tmp, Tmp, Tmp
648
649 MoveDoubleConditionally32 U:G:32, U:G:32, U:G:32, U:F:64, UD:F:64
650     RelCond, Tmp, Tmp, Tmp, Tmp
651
652 64: MoveDoubleConditionally64 U:G:32, U:G:64, U:G:64, U:F:64, UD:F:64
653     RelCond, Tmp, Tmp, Tmp, Tmp
654
655 MoveDoubleConditionallyTest32 U:G:32, U:G:32, U:G:32, U:F:64, UD:F:64
656     ResCond, Tmp, Tmp, Tmp, Tmp
657     x86: ResCond, Tmp, Imm, Tmp, Tmp
658
659 64: MoveDoubleConditionallyTest64 U:G:32, U:G:64, U:G:64, U:F:64, UD:F:64
660     ResCond, Tmp, Tmp, Tmp, Tmp
661     ResCond, Tmp, Imm, Tmp, Tmp
662
663 MoveDoubleConditionallyDouble U:G:32, U:F:64, U:F:64, U:F:64, UD:F:64
664     DoubleCond, Tmp, Tmp, Tmp, Tmp
665
666 MoveDoubleConditionallyFloat U:G:32, U:F:32, U:F:32, U:F:64, UD:F:64
667     DoubleCond, Tmp, Tmp, Tmp, Tmp
668
669 Jump /branch
670
671 Ret32 U:G:32 /return
672     Tmp
673
674 64: Ret64 U:G:64 /return
675     Tmp
676
677 RetFloat U:F:32 /return
678     Tmp
679
680 RetDouble U:F:64 /return
681     Tmp
682
683 Oops /terminal
684
685 # Air allows for exotic behavior. A Patch's behavior is determined entirely by the Special operand,
686 # which must be the first operand.
687 custom Patch
688