145b60bd6SAlex Crichton #![expect(non_snake_case, reason = "DSL style here")]
286430abcSBenjamin Bouvier 
3d9277f24SBenjamin Bouvier use crate::cdsl::instructions::{
418bd27e9Sbjorn3     AllInstructions, InstructionBuilder as Inst, InstructionGroupBuilder,
5d9277f24SBenjamin Bouvier };
64632d351SBenjamin Bouvier use crate::cdsl::operands::Operand;
786430abcSBenjamin Bouvier use crate::cdsl::types::{LaneType, ValueType};
860532011SBenjamin Bouvier use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
90243b642SBenjamin Bouvier use crate::shared::formats::Formats;
108fba449bSBenjamin Bouvier use crate::shared::types;
118fba449bSBenjamin Bouvier use crate::shared::{entities::EntityRefs, immediates::Immediates};
1286430abcSBenjamin Bouvier 
133a4b1cc9SBenjamin Bouvier #[inline(never)]
define_control_flow( ig: &mut InstructionGroupBuilder, formats: &Formats, imm: &Immediates, entities: &EntityRefs, )143a4b1cc9SBenjamin Bouvier fn define_control_flow(
153a4b1cc9SBenjamin Bouvier     ig: &mut InstructionGroupBuilder,
163a4b1cc9SBenjamin Bouvier     formats: &Formats,
173a4b1cc9SBenjamin Bouvier     imm: &Immediates,
183a4b1cc9SBenjamin Bouvier     entities: &EntityRefs,
193a4b1cc9SBenjamin Bouvier ) {
203a4b1cc9SBenjamin Bouvier     ig.push(
213a4b1cc9SBenjamin Bouvier         Inst::new(
223a4b1cc9SBenjamin Bouvier             "jump",
233a4b1cc9SBenjamin Bouvier             r#"
243a4b1cc9SBenjamin Bouvier         Jump.
253a4b1cc9SBenjamin Bouvier 
26832666c4SRyan Hunt         Unconditionally jump to a basic block, passing the specified
27832666c4SRyan Hunt         block arguments. The number and types of arguments must match the
28832666c4SRyan Hunt         destination block.
293a4b1cc9SBenjamin Bouvier         "#,
303a4b1cc9SBenjamin Bouvier             &formats.jump,
313a4b1cc9SBenjamin Bouvier         )
3290ac295eSAlex Crichton         .operands_in(vec![
3390ac295eSAlex Crichton             Operand::new("block_call", &entities.block_call)
3490ac295eSAlex Crichton                 .with_doc("Destination basic block, with its arguments provided"),
3590ac295eSAlex Crichton         ])
36b5692db7STrevor Elliott         .branches(),
373a4b1cc9SBenjamin Bouvier     );
383a4b1cc9SBenjamin Bouvier 
3932a7593cSTrevor Elliott     let ScalarTruthy = &TypeVar::new(
4032a7593cSTrevor Elliott         "ScalarTruthy",
4132a7593cSTrevor Elliott         "A scalar truthy type",
4232a7593cSTrevor Elliott         TypeSetBuilder::new().ints(Interval::All).build(),
433a4b1cc9SBenjamin Bouvier     );
443a4b1cc9SBenjamin Bouvier 
45b58a197dSTrevor Elliott     ig.push(
46b58a197dSTrevor Elliott         Inst::new(
47b58a197dSTrevor Elliott             "brif",
48b58a197dSTrevor Elliott             r#"
49b58a197dSTrevor Elliott         Conditional branch when cond is non-zero.
50b58a197dSTrevor Elliott 
51b58a197dSTrevor Elliott         Take the ``then`` branch when ``c != 0``, and the ``else`` branch otherwise.
52b58a197dSTrevor Elliott         "#,
53b58a197dSTrevor Elliott             &formats.brif,
54b58a197dSTrevor Elliott         )
55f8771416SJamey Sharp         .operands_in(vec![
56f8771416SJamey Sharp             Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
57f8771416SJamey Sharp             Operand::new("block_then", &entities.block_then).with_doc("Then block"),
58f8771416SJamey Sharp             Operand::new("block_else", &entities.block_else).with_doc("Else block"),
59f8771416SJamey Sharp         ])
60b5692db7STrevor Elliott         .branches(),
61b58a197dSTrevor Elliott     );
62b58a197dSTrevor Elliott 
63b58a197dSTrevor Elliott     {
64af62037fSAfonso Bordado         let _i32 = &TypeVar::new(
65af62037fSAfonso Bordado             "i32",
66af62037fSAfonso Bordado             "A 32 bit scalar integer type",
67af62037fSAfonso Bordado             TypeSetBuilder::new().ints(32..32).build(),
68af62037fSAfonso Bordado         );
693a4b1cc9SBenjamin Bouvier 
703a4b1cc9SBenjamin Bouvier         ig.push(
713a4b1cc9SBenjamin Bouvier             Inst::new(
723a4b1cc9SBenjamin Bouvier                 "br_table",
733a4b1cc9SBenjamin Bouvier                 r#"
743a4b1cc9SBenjamin Bouvier         Indirect branch via jump table.
753a4b1cc9SBenjamin Bouvier 
763a4b1cc9SBenjamin Bouvier         Use ``x`` as an unsigned index into the jump table ``JT``. If a jump
77832666c4SRyan Hunt         table entry is found, branch to the corresponding block. If no entry was
7880c147d9STrevor Elliott         found or the index is out-of-bounds, branch to the default block of the
7980c147d9STrevor Elliott         table.
803a4b1cc9SBenjamin Bouvier 
813a4b1cc9SBenjamin Bouvier         Note that this branch instruction can't pass arguments to the targeted
823a4b1cc9SBenjamin Bouvier         blocks. Split critical edges as needed to work around this.
833a4b1cc9SBenjamin Bouvier 
843a4b1cc9SBenjamin Bouvier         Do not confuse this with "tables" in WebAssembly. ``br_table`` is for
853a4b1cc9SBenjamin Bouvier         jump tables with destinations within the current function only -- think
863a4b1cc9SBenjamin Bouvier         of a ``match`` in Rust or a ``switch`` in C.  If you want to call a
873a4b1cc9SBenjamin Bouvier         function in a dynamic library, that will typically use
883a4b1cc9SBenjamin Bouvier         ``call_indirect``.
893a4b1cc9SBenjamin Bouvier         "#,
903a4b1cc9SBenjamin Bouvier                 &formats.branch_table,
913a4b1cc9SBenjamin Bouvier             )
92f8771416SJamey Sharp             .operands_in(vec![
93f8771416SJamey Sharp                 Operand::new("x", _i32).with_doc("i32 index into jump table"),
94f8771416SJamey Sharp                 Operand::new("JT", &entities.jump_table),
95f8771416SJamey Sharp             ])
96b5692db7STrevor Elliott             .branches(),
973a4b1cc9SBenjamin Bouvier         );
983a4b1cc9SBenjamin Bouvier     }
993a4b1cc9SBenjamin Bouvier 
1003a4b1cc9SBenjamin Bouvier     let iAddr = &TypeVar::new(
1013a4b1cc9SBenjamin Bouvier         "iAddr",
1023a4b1cc9SBenjamin Bouvier         "An integer address type",
103b81ef46cSNick Fitzgerald         TypeSetBuilder::new().ints(32..64).build(),
1043a4b1cc9SBenjamin Bouvier     );
1053a4b1cc9SBenjamin Bouvier 
1063a4b1cc9SBenjamin Bouvier     ig.push(
1073a4b1cc9SBenjamin Bouvier         Inst::new(
1083a4b1cc9SBenjamin Bouvier             "debugtrap",
1093a4b1cc9SBenjamin Bouvier             r#"
1103a4b1cc9SBenjamin Bouvier         Encodes an assembly debug trap.
1113a4b1cc9SBenjamin Bouvier         "#,
1123a4b1cc9SBenjamin Bouvier             &formats.nullary,
1133a4b1cc9SBenjamin Bouvier         )
114b5692db7STrevor Elliott         .other_side_effects()
115b5692db7STrevor Elliott         .can_load()
116b5692db7STrevor Elliott         .can_store(),
1173a4b1cc9SBenjamin Bouvier     );
1183a4b1cc9SBenjamin Bouvier 
1193a4b1cc9SBenjamin Bouvier     ig.push(
1203a4b1cc9SBenjamin Bouvier         Inst::new(
1213a4b1cc9SBenjamin Bouvier             "trap",
1223a4b1cc9SBenjamin Bouvier             r#"
1233a4b1cc9SBenjamin Bouvier         Terminate execution unconditionally.
1243a4b1cc9SBenjamin Bouvier         "#,
1253a4b1cc9SBenjamin Bouvier             &formats.trap,
1263a4b1cc9SBenjamin Bouvier         )
127f8771416SJamey Sharp         .operands_in(vec![Operand::new("code", &imm.trapcode)])
128b5692db7STrevor Elliott         .can_trap()
129b5692db7STrevor Elliott         .terminates_block(),
1303a4b1cc9SBenjamin Bouvier     );
1313a4b1cc9SBenjamin Bouvier 
1323a4b1cc9SBenjamin Bouvier     ig.push(
1333a4b1cc9SBenjamin Bouvier         Inst::new(
1343a4b1cc9SBenjamin Bouvier             "trapz",
1353a4b1cc9SBenjamin Bouvier             r#"
1363a4b1cc9SBenjamin Bouvier         Trap when zero.
1373a4b1cc9SBenjamin Bouvier 
1383a4b1cc9SBenjamin Bouvier         if ``c`` is non-zero, execution continues at the following instruction.
1393a4b1cc9SBenjamin Bouvier         "#,
1403a4b1cc9SBenjamin Bouvier             &formats.cond_trap,
1413a4b1cc9SBenjamin Bouvier         )
142f8771416SJamey Sharp         .operands_in(vec![
143f8771416SJamey Sharp             Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
144f8771416SJamey Sharp             Operand::new("code", &imm.trapcode),
145f8771416SJamey Sharp         ])
146a88eb702SNick Fitzgerald         .can_trap()
147a88eb702SNick Fitzgerald         // When one `trapz` dominates another `trapz` and they have identical
148a88eb702SNick Fitzgerald         // conditions and trap codes, it is safe to deduplicate them (like GVN,
149a88eb702SNick Fitzgerald         // although there is not actually any value being numbered). Either the
150a88eb702SNick Fitzgerald         // first `trapz` raised a trap and execution halted, or it didn't and
151a88eb702SNick Fitzgerald         // therefore the dominated `trapz` will not raise a trap either.
152a88eb702SNick Fitzgerald         .side_effects_idempotent(),
1533a4b1cc9SBenjamin Bouvier     );
1543a4b1cc9SBenjamin Bouvier 
1553a4b1cc9SBenjamin Bouvier     ig.push(
1563a4b1cc9SBenjamin Bouvier         Inst::new(
1573a4b1cc9SBenjamin Bouvier             "trapnz",
1583a4b1cc9SBenjamin Bouvier             r#"
1593a4b1cc9SBenjamin Bouvier         Trap when non-zero.
1603a4b1cc9SBenjamin Bouvier 
161dad56a24SBenjamin Bouvier         If ``c`` is zero, execution continues at the following instruction.
162dad56a24SBenjamin Bouvier         "#,
163dad56a24SBenjamin Bouvier             &formats.cond_trap,
164dad56a24SBenjamin Bouvier         )
165f8771416SJamey Sharp         .operands_in(vec![
166f8771416SJamey Sharp             Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
167f8771416SJamey Sharp             Operand::new("code", &imm.trapcode),
168f8771416SJamey Sharp         ])
169a88eb702SNick Fitzgerald         .can_trap()
170a88eb702SNick Fitzgerald         // See the above comment for `trapz` and idempotent side effects.
171a88eb702SNick Fitzgerald         .side_effects_idempotent(),
172dad56a24SBenjamin Bouvier     );
173dad56a24SBenjamin Bouvier 
174dad56a24SBenjamin Bouvier     ig.push(
175dad56a24SBenjamin Bouvier         Inst::new(
1763a4b1cc9SBenjamin Bouvier             "return",
1773a4b1cc9SBenjamin Bouvier             r#"
1783a4b1cc9SBenjamin Bouvier         Return from the function.
1793a4b1cc9SBenjamin Bouvier 
1803a4b1cc9SBenjamin Bouvier         Unconditionally transfer control to the calling function, passing the
1813a4b1cc9SBenjamin Bouvier         provided return values. The list of return values must match the
1823a4b1cc9SBenjamin Bouvier         function signature's return types.
1833a4b1cc9SBenjamin Bouvier         "#,
1843a4b1cc9SBenjamin Bouvier             &formats.multiary,
1853a4b1cc9SBenjamin Bouvier         )
186f8771416SJamey Sharp         .operands_in(vec![
18790ac295eSAlex Crichton             Operand::new("rvals", &entities.varargs).with_doc("return values"),
188f8771416SJamey Sharp         ])
189b5692db7STrevor Elliott         .returns(),
1903a4b1cc9SBenjamin Bouvier     );
1913a4b1cc9SBenjamin Bouvier 
1923a4b1cc9SBenjamin Bouvier     ig.push(
1933a4b1cc9SBenjamin Bouvier         Inst::new(
1943a4b1cc9SBenjamin Bouvier             "call",
1953a4b1cc9SBenjamin Bouvier             r#"
1963a4b1cc9SBenjamin Bouvier         Direct function call.
1973a4b1cc9SBenjamin Bouvier 
1983a4b1cc9SBenjamin Bouvier         Call a function which has been declared in the preamble. The argument
1993a4b1cc9SBenjamin Bouvier         types must match the function's signature.
2003a4b1cc9SBenjamin Bouvier         "#,
2013a4b1cc9SBenjamin Bouvier             &formats.call,
2023a4b1cc9SBenjamin Bouvier         )
203f8771416SJamey Sharp         .operands_in(vec![
204f8771416SJamey Sharp             Operand::new("FN", &entities.func_ref)
205f8771416SJamey Sharp                 .with_doc("function to call, declared by `function`"),
206f8771416SJamey Sharp             Operand::new("args", &entities.varargs).with_doc("call arguments"),
207f8771416SJamey Sharp         ])
208f8771416SJamey Sharp         .operands_out(vec![
20990ac295eSAlex Crichton             Operand::new("rvals", &entities.varargs).with_doc("return values"),
210f8771416SJamey Sharp         ])
211b5692db7STrevor Elliott         .call(),
2123a4b1cc9SBenjamin Bouvier     );
2133a4b1cc9SBenjamin Bouvier 
2143a4b1cc9SBenjamin Bouvier     ig.push(
2153a4b1cc9SBenjamin Bouvier         Inst::new(
2163a4b1cc9SBenjamin Bouvier             "call_indirect",
2173a4b1cc9SBenjamin Bouvier             r#"
2183a4b1cc9SBenjamin Bouvier         Indirect function call.
2193a4b1cc9SBenjamin Bouvier 
2203a4b1cc9SBenjamin Bouvier         Call the function pointed to by `callee` with the given arguments. The
2213a4b1cc9SBenjamin Bouvier         called function must match the specified signature.
2223a4b1cc9SBenjamin Bouvier 
2233a4b1cc9SBenjamin Bouvier         Note that this is different from WebAssembly's ``call_indirect``; the
2243a4b1cc9SBenjamin Bouvier         callee is a native address, rather than a table index. For WebAssembly,
2253a4b1cc9SBenjamin Bouvier         `table_addr` and `load` are used to obtain a native address
2263a4b1cc9SBenjamin Bouvier         from a table.
2273a4b1cc9SBenjamin Bouvier         "#,
2283a4b1cc9SBenjamin Bouvier             &formats.call_indirect,
2293a4b1cc9SBenjamin Bouvier         )
230f8771416SJamey Sharp         .operands_in(vec![
231f8771416SJamey Sharp             Operand::new("SIG", &entities.sig_ref).with_doc("function signature"),
232f8771416SJamey Sharp             Operand::new("callee", iAddr).with_doc("address of function to call"),
233f8771416SJamey Sharp             Operand::new("args", &entities.varargs).with_doc("call arguments"),
234f8771416SJamey Sharp         ])
235f8771416SJamey Sharp         .operands_out(vec![
23690ac295eSAlex Crichton             Operand::new("rvals", &entities.varargs).with_doc("return values"),
237f8771416SJamey Sharp         ])
238b5692db7STrevor Elliott         .call(),
2393a4b1cc9SBenjamin Bouvier     );
2403a4b1cc9SBenjamin Bouvier 
241bdfb7465SNick Fitzgerald     ig.push(
242bdfb7465SNick Fitzgerald         Inst::new(
243bdfb7465SNick Fitzgerald             "return_call",
244bdfb7465SNick Fitzgerald             r#"
245bdfb7465SNick Fitzgerald         Direct tail call.
246bdfb7465SNick Fitzgerald 
247bdfb7465SNick Fitzgerald         Tail call a function which has been declared in the preamble. The
248bdfb7465SNick Fitzgerald         argument types must match the function's signature, the caller and
249bdfb7465SNick Fitzgerald         callee calling conventions must be the same, and must be a calling
250bdfb7465SNick Fitzgerald         convention that supports tail calls.
251bdfb7465SNick Fitzgerald 
252bdfb7465SNick Fitzgerald         This instruction is a block terminator.
253bdfb7465SNick Fitzgerald         "#,
254bdfb7465SNick Fitzgerald             &formats.call,
255bdfb7465SNick Fitzgerald         )
256f8771416SJamey Sharp         .operands_in(vec![
257f8771416SJamey Sharp             Operand::new("FN", &entities.func_ref)
258f8771416SJamey Sharp                 .with_doc("function to call, declared by `function`"),
259f8771416SJamey Sharp             Operand::new("args", &entities.varargs).with_doc("call arguments"),
260f8771416SJamey Sharp         ])
261bdfb7465SNick Fitzgerald         .returns()
262bdfb7465SNick Fitzgerald         .call(),
263bdfb7465SNick Fitzgerald     );
264bdfb7465SNick Fitzgerald 
265bdfb7465SNick Fitzgerald     ig.push(
266bdfb7465SNick Fitzgerald         Inst::new(
267bdfb7465SNick Fitzgerald             "return_call_indirect",
268bdfb7465SNick Fitzgerald             r#"
269bdfb7465SNick Fitzgerald         Indirect tail call.
270bdfb7465SNick Fitzgerald 
271bdfb7465SNick Fitzgerald         Call the function pointed to by `callee` with the given arguments. The
272bdfb7465SNick Fitzgerald         argument types must match the function's signature, the caller and
273bdfb7465SNick Fitzgerald         callee calling conventions must be the same, and must be a calling
274bdfb7465SNick Fitzgerald         convention that supports tail calls.
275bdfb7465SNick Fitzgerald 
276bdfb7465SNick Fitzgerald         This instruction is a block terminator.
277bdfb7465SNick Fitzgerald 
278bdfb7465SNick Fitzgerald         Note that this is different from WebAssembly's ``tail_call_indirect``;
279bdfb7465SNick Fitzgerald         the callee is a native address, rather than a table index. For
280bdfb7465SNick Fitzgerald         WebAssembly, `table_addr` and `load` are used to obtain a native address
281bdfb7465SNick Fitzgerald         from a table.
282bdfb7465SNick Fitzgerald         "#,
283bdfb7465SNick Fitzgerald             &formats.call_indirect,
284bdfb7465SNick Fitzgerald         )
285f8771416SJamey Sharp         .operands_in(vec![
286f8771416SJamey Sharp             Operand::new("SIG", &entities.sig_ref).with_doc("function signature"),
287f8771416SJamey Sharp             Operand::new("callee", iAddr).with_doc("address of function to call"),
288f8771416SJamey Sharp             Operand::new("args", &entities.varargs).with_doc("call arguments"),
289f8771416SJamey Sharp         ])
290bdfb7465SNick Fitzgerald         .returns()
291bdfb7465SNick Fitzgerald         .call(),
292bdfb7465SNick Fitzgerald     );
293bdfb7465SNick Fitzgerald 
2943a4b1cc9SBenjamin Bouvier     ig.push(
2953a4b1cc9SBenjamin Bouvier         Inst::new(
2963a4b1cc9SBenjamin Bouvier             "func_addr",
2973a4b1cc9SBenjamin Bouvier             r#"
2983a4b1cc9SBenjamin Bouvier         Get the address of a function.
2993a4b1cc9SBenjamin Bouvier 
3003a4b1cc9SBenjamin Bouvier         Compute the absolute address of a function declared in the preamble.
3013a4b1cc9SBenjamin Bouvier         The returned address can be used as a ``callee`` argument to
3023a4b1cc9SBenjamin Bouvier         `call_indirect`. This is also a method for calling functions that
3033a4b1cc9SBenjamin Bouvier         are too far away to be addressable by a direct `call`
3043a4b1cc9SBenjamin Bouvier         instruction.
3053a4b1cc9SBenjamin Bouvier         "#,
3063a4b1cc9SBenjamin Bouvier             &formats.func_addr,
3073a4b1cc9SBenjamin Bouvier         )
30890ac295eSAlex Crichton         .operands_in(vec![
30990ac295eSAlex Crichton             Operand::new("FN", &entities.func_ref)
31090ac295eSAlex Crichton                 .with_doc("function to call, declared by `function`"),
31190ac295eSAlex Crichton         ])
312f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
3133a4b1cc9SBenjamin Bouvier     );
31494ec88eaSChris Fallin 
31594ec88eaSChris Fallin     ig.push(
31694ec88eaSChris Fallin         Inst::new(
31794ec88eaSChris Fallin             "try_call",
31894ec88eaSChris Fallin             r#"
31994ec88eaSChris Fallin         Call a function, catching the specified exceptions.
32094ec88eaSChris Fallin 
32194ec88eaSChris Fallin         Call the function pointed to by `callee` with the given arguments. On
32294ec88eaSChris Fallin         normal return, branch to the first target, with function returns
32394ec88eaSChris Fallin         available as `retN` block arguments. On exceptional return,
32494ec88eaSChris Fallin         look up the thrown exception tag in the provided exception table;
32594ec88eaSChris Fallin         if the tag matches one of the targets, branch to the matching
32694ec88eaSChris Fallin         target with the exception payloads available as `exnN` block arguments.
32794ec88eaSChris Fallin         If no tag matches, then propagate the exception up the stack.
32894ec88eaSChris Fallin 
32994ec88eaSChris Fallin         It is the Cranelift embedder's responsibility to define the meaning
33094ec88eaSChris Fallin         of tags: they are accepted by this instruction and passed through
33194ec88eaSChris Fallin         to unwind metadata tables in Cranelift's output. Actual unwinding is
33294ec88eaSChris Fallin         outside the purview of the core Cranelift compiler.
33394ec88eaSChris Fallin 
33494ec88eaSChris Fallin         Payload values on exception are passed in fixed register(s) that are
33594ec88eaSChris Fallin         defined by the platform and ABI. See the documentation on `CallConv`
33694ec88eaSChris Fallin         for details.
33794ec88eaSChris Fallin         "#,
33894ec88eaSChris Fallin             &formats.try_call,
33994ec88eaSChris Fallin         )
34094ec88eaSChris Fallin         .operands_in(vec![
34194ec88eaSChris Fallin             Operand::new("callee", &entities.func_ref)
34294ec88eaSChris Fallin                 .with_doc("function to call, declared by `function`"),
34394ec88eaSChris Fallin             Operand::new("args", &entities.varargs).with_doc("call arguments"),
34494ec88eaSChris Fallin             Operand::new("ET", &entities.exception_table).with_doc("exception table"),
34594ec88eaSChris Fallin         ])
34694ec88eaSChris Fallin         .call()
34794ec88eaSChris Fallin         .branches(),
34894ec88eaSChris Fallin     );
34994ec88eaSChris Fallin 
35094ec88eaSChris Fallin     ig.push(
35194ec88eaSChris Fallin         Inst::new(
35294ec88eaSChris Fallin             "try_call_indirect",
35394ec88eaSChris Fallin             r#"
35494ec88eaSChris Fallin         Call a function, catching the specified exceptions.
35594ec88eaSChris Fallin 
35694ec88eaSChris Fallin         Call the function pointed to by `callee` with the given arguments. On
35794ec88eaSChris Fallin         normal return, branch to the first target, with function returns
35894ec88eaSChris Fallin         available as `retN` block arguments. On exceptional return,
35994ec88eaSChris Fallin         look up the thrown exception tag in the provided exception table;
36094ec88eaSChris Fallin         if the tag matches one of the targets, branch to the matching
36194ec88eaSChris Fallin         target with the exception payloads available as `exnN` block arguments.
36294ec88eaSChris Fallin         If no tag matches, then propagate the exception up the stack.
36394ec88eaSChris Fallin 
36494ec88eaSChris Fallin         It is the Cranelift embedder's responsibility to define the meaning
36594ec88eaSChris Fallin         of tags: they are accepted by this instruction and passed through
36694ec88eaSChris Fallin         to unwind metadata tables in Cranelift's output. Actual unwinding is
36794ec88eaSChris Fallin         outside the purview of the core Cranelift compiler.
36894ec88eaSChris Fallin 
36994ec88eaSChris Fallin         Payload values on exception are passed in fixed register(s) that are
37094ec88eaSChris Fallin         defined by the platform and ABI. See the documentation on `CallConv`
37194ec88eaSChris Fallin         for details.
37294ec88eaSChris Fallin         "#,
37394ec88eaSChris Fallin             &formats.try_call_indirect,
37494ec88eaSChris Fallin         )
37594ec88eaSChris Fallin         .operands_in(vec![
37694ec88eaSChris Fallin             Operand::new("callee", iAddr).with_doc("address of function to call"),
37794ec88eaSChris Fallin             Operand::new("args", &entities.varargs).with_doc("call arguments"),
37894ec88eaSChris Fallin             Operand::new("ET", &entities.exception_table).with_doc("exception table"),
37994ec88eaSChris Fallin         ])
38094ec88eaSChris Fallin         .call()
38194ec88eaSChris Fallin         .branches(),
38294ec88eaSChris Fallin     );
3833a4b1cc9SBenjamin Bouvier }
3843a4b1cc9SBenjamin Bouvier 
3853ae1af1aSAndrew Brown #[inline(never)]
define_simd_lane_access( ig: &mut InstructionGroupBuilder, formats: &Formats, imm: &Immediates, _: &EntityRefs, )3866e0401b8SAndrew Brown fn define_simd_lane_access(
3876e0401b8SAndrew Brown     ig: &mut InstructionGroupBuilder,
3886e0401b8SAndrew Brown     formats: &Formats,
3896e0401b8SAndrew Brown     imm: &Immediates,
3906e0401b8SAndrew Brown     _: &EntityRefs,
3916e0401b8SAndrew Brown ) {
3926e0401b8SAndrew Brown     let TxN = &TypeVar::new(
3936e0401b8SAndrew Brown         "TxN",
3946e0401b8SAndrew Brown         "A SIMD vector type",
3956e0401b8SAndrew Brown         TypeSetBuilder::new()
3966e0401b8SAndrew Brown             .ints(Interval::All)
3976e0401b8SAndrew Brown             .floats(Interval::All)
3986e0401b8SAndrew Brown             .simd_lanes(Interval::All)
3999c43749dSSam Parker             .dynamic_simd_lanes(Interval::All)
4006e0401b8SAndrew Brown             .includes_scalars(false)
4016e0401b8SAndrew Brown             .build(),
4026e0401b8SAndrew Brown     );
4036e0401b8SAndrew Brown 
4046e0401b8SAndrew Brown     ig.push(
4056e0401b8SAndrew Brown         Inst::new(
4066e0401b8SAndrew Brown             "splat",
4076e0401b8SAndrew Brown             r#"
4086e0401b8SAndrew Brown         Vector splat.
4096e0401b8SAndrew Brown 
4106e0401b8SAndrew Brown         Return a vector whose lanes are all ``x``.
4116e0401b8SAndrew Brown         "#,
4126e0401b8SAndrew Brown             &formats.unary,
4136e0401b8SAndrew Brown         )
414f8771416SJamey Sharp         .operands_in(vec![
41590ac295eSAlex Crichton             Operand::new("x", &TxN.lane_of()).with_doc("Value to splat to all lanes"),
416f8771416SJamey Sharp         ])
417f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", TxN)]),
4186e0401b8SAndrew Brown     );
4196e0401b8SAndrew Brown 
420fa7481a6SAndrew Brown     let I8x16 = &TypeVar::new(
421fa7481a6SAndrew Brown         "I8x16",
422fa7481a6SAndrew Brown         "A SIMD vector type consisting of 16 lanes of 8-bit integers",
423fa7481a6SAndrew Brown         TypeSetBuilder::new()
424fa7481a6SAndrew Brown             .ints(8..8)
425fa7481a6SAndrew Brown             .simd_lanes(16..16)
426fa7481a6SAndrew Brown             .includes_scalars(false)
427fa7481a6SAndrew Brown             .build(),
428fa7481a6SAndrew Brown     );
429fa7481a6SAndrew Brown 
430fa7481a6SAndrew Brown     ig.push(
431fa7481a6SAndrew Brown         Inst::new(
432fa7481a6SAndrew Brown             "swizzle",
433fa7481a6SAndrew Brown             r#"
434fa7481a6SAndrew Brown         Vector swizzle.
435fa7481a6SAndrew Brown 
436fa7481a6SAndrew Brown         Returns a new vector with byte-width lanes selected from the lanes of the first input
437fa7481a6SAndrew Brown         vector ``x`` specified in the second input vector ``s``. The indices ``i`` in range
438fa7481a6SAndrew Brown         ``[0, 15]`` select the ``i``-th element of ``x``. For indices outside of the range the
439fa7481a6SAndrew Brown         resulting lane is 0. Note that this operates on byte-width lanes.
440fa7481a6SAndrew Brown         "#,
441fa7481a6SAndrew Brown             &formats.binary,
442fa7481a6SAndrew Brown         )
443f8771416SJamey Sharp         .operands_in(vec![
444f8771416SJamey Sharp             Operand::new("x", I8x16).with_doc("Vector to modify by re-arranging lanes"),
445f8771416SJamey Sharp             Operand::new("y", I8x16).with_doc("Mask for re-arranging lanes"),
446f8771416SJamey Sharp         ])
447f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I8x16)]),
448fa7481a6SAndrew Brown     );
449fa7481a6SAndrew Brown 
4508bb183f1SAlex Crichton     ig.push(
4518bb183f1SAlex Crichton         Inst::new(
4528bb183f1SAlex Crichton             "x86_pshufb",
4538bb183f1SAlex Crichton             r#"
4548bb183f1SAlex Crichton         A vector swizzle lookalike which has the semantics of `pshufb` on x64.
4558bb183f1SAlex Crichton 
4568bb183f1SAlex Crichton         This instruction will permute the 8-bit lanes of `x` with the indices
4578bb183f1SAlex Crichton         specified in `y`. Each lane in the mask, `y`, uses the bottom four
4588bb183f1SAlex Crichton         bits for selecting the lane from `x` unless the most significant bit
4598bb183f1SAlex Crichton         is set, in which case the lane is zeroed. The output vector will have
4608bb183f1SAlex Crichton         the following contents when the element of `y` is in these ranges:
4618bb183f1SAlex Crichton 
4628bb183f1SAlex Crichton         * `[0, 127]` -> `x[y[i] % 16]`
4638bb183f1SAlex Crichton         * `[128, 255]` -> 0
4648bb183f1SAlex Crichton         "#,
4658bb183f1SAlex Crichton             &formats.binary,
4668bb183f1SAlex Crichton         )
467f8771416SJamey Sharp         .operands_in(vec![
468f8771416SJamey Sharp             Operand::new("x", I8x16).with_doc("Vector to modify by re-arranging lanes"),
469f8771416SJamey Sharp             Operand::new("y", I8x16).with_doc("Mask for re-arranging lanes"),
470f8771416SJamey Sharp         ])
471f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I8x16)]),
4728bb183f1SAlex Crichton     );
4738bb183f1SAlex Crichton 
4746e0401b8SAndrew Brown     ig.push(
4756e0401b8SAndrew Brown         Inst::new(
4766e0401b8SAndrew Brown             "insertlane",
4776e0401b8SAndrew Brown             r#"
4786e0401b8SAndrew Brown         Insert ``y`` as lane ``Idx`` in x.
4796e0401b8SAndrew Brown 
4806e0401b8SAndrew Brown         The lane index, ``Idx``, is an immediate value, not an SSA value. It
4816e0401b8SAndrew Brown         must indicate a valid lane index for the type of ``x``.
4826e0401b8SAndrew Brown         "#,
4837d6e94b9SAndrew Brown             &formats.ternary_imm8,
4846e0401b8SAndrew Brown         )
485f8771416SJamey Sharp         .operands_in(vec![
486f8771416SJamey Sharp             Operand::new("x", TxN).with_doc("The vector to modify"),
487f8771416SJamey Sharp             Operand::new("y", &TxN.lane_of()).with_doc("New lane value"),
488f8771416SJamey Sharp             Operand::new("Idx", &imm.uimm8).with_doc("Lane index"),
489f8771416SJamey Sharp         ])
490f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", TxN)]),
4916e0401b8SAndrew Brown     );
4926e0401b8SAndrew Brown 
4936e0401b8SAndrew Brown     ig.push(
4946e0401b8SAndrew Brown         Inst::new(
4956e0401b8SAndrew Brown             "extractlane",
4966e0401b8SAndrew Brown             r#"
4976e0401b8SAndrew Brown         Extract lane ``Idx`` from ``x``.
4986e0401b8SAndrew Brown 
4996e0401b8SAndrew Brown         The lane index, ``Idx``, is an immediate value, not an SSA value. It
5006e0401b8SAndrew Brown         must indicate a valid lane index for the type of ``x``. Note that the upper bits of ``a``
5016e0401b8SAndrew Brown         may or may not be zeroed depending on the ISA but the type system should prevent using
5026e0401b8SAndrew Brown         ``a`` as anything other than the extracted value.
5036e0401b8SAndrew Brown         "#,
504a27a079dSAndrew Brown             &formats.binary_imm8,
5056e0401b8SAndrew Brown         )
506f8771416SJamey Sharp         .operands_in(vec![
507f8771416SJamey Sharp             Operand::new("x", TxN),
508f8771416SJamey Sharp             Operand::new("Idx", &imm.uimm8).with_doc("Lane index"),
509f8771416SJamey Sharp         ])
510f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &TxN.lane_of())]),
5116e0401b8SAndrew Brown     );
5126e0401b8SAndrew Brown }
5136e0401b8SAndrew Brown 
5146e0401b8SAndrew Brown #[inline(never)]
define_simd_arithmetic( ig: &mut InstructionGroupBuilder, formats: &Formats, _: &Immediates, _: &EntityRefs, )5153ae1af1aSAndrew Brown fn define_simd_arithmetic(
5163ae1af1aSAndrew Brown     ig: &mut InstructionGroupBuilder,
5173ae1af1aSAndrew Brown     formats: &Formats,
5183ae1af1aSAndrew Brown     _: &Immediates,
5193ae1af1aSAndrew Brown     _: &EntityRefs,
5203ae1af1aSAndrew Brown ) {
5213ae1af1aSAndrew Brown     let Int = &TypeVar::new(
5223ae1af1aSAndrew Brown         "Int",
5233ae1af1aSAndrew Brown         "A scalar or vector integer type",
5243ae1af1aSAndrew Brown         TypeSetBuilder::new()
5253ae1af1aSAndrew Brown             .ints(Interval::All)
5263ae1af1aSAndrew Brown             .simd_lanes(Interval::All)
5273ae1af1aSAndrew Brown             .build(),
5283ae1af1aSAndrew Brown     );
5293ae1af1aSAndrew Brown 
5303ae1af1aSAndrew Brown     ig.push(
5313ae1af1aSAndrew Brown         Inst::new(
5323ef30b5bSAfonso Bordado             "smin",
5333ae1af1aSAndrew Brown             r#"
5343ae1af1aSAndrew Brown         Signed integer minimum.
5353ae1af1aSAndrew Brown         "#,
5363ae1af1aSAndrew Brown             &formats.binary,
5373ae1af1aSAndrew Brown         )
538f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
539f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
5403ae1af1aSAndrew Brown     );
5413ae1af1aSAndrew Brown 
5423ae1af1aSAndrew Brown     ig.push(
5433ae1af1aSAndrew Brown         Inst::new(
5443ae1af1aSAndrew Brown             "umin",
5453ae1af1aSAndrew Brown             r#"
5463ae1af1aSAndrew Brown         Unsigned integer minimum.
5473ae1af1aSAndrew Brown         "#,
5483ae1af1aSAndrew Brown             &formats.binary,
5493ae1af1aSAndrew Brown         )
550f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
551f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
5523ae1af1aSAndrew Brown     );
5533ae1af1aSAndrew Brown 
5543ae1af1aSAndrew Brown     ig.push(
5553ae1af1aSAndrew Brown         Inst::new(
5563ef30b5bSAfonso Bordado             "smax",
5573ae1af1aSAndrew Brown             r#"
5583ae1af1aSAndrew Brown         Signed integer maximum.
5593ae1af1aSAndrew Brown         "#,
5603ae1af1aSAndrew Brown             &formats.binary,
5613ae1af1aSAndrew Brown         )
562f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
563f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
5643ae1af1aSAndrew Brown     );
5653ae1af1aSAndrew Brown 
5663ae1af1aSAndrew Brown     ig.push(
5673ae1af1aSAndrew Brown         Inst::new(
5683ae1af1aSAndrew Brown             "umax",
5693ae1af1aSAndrew Brown             r#"
5703ae1af1aSAndrew Brown         Unsigned integer maximum.
5713ae1af1aSAndrew Brown         "#,
5723ae1af1aSAndrew Brown             &formats.binary,
5733ae1af1aSAndrew Brown         )
574f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
575f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
5763ae1af1aSAndrew Brown     );
577032e81fdSAndrew Brown 
578032e81fdSAndrew Brown     let IxN = &TypeVar::new(
579032e81fdSAndrew Brown         "IxN",
580032e81fdSAndrew Brown         "A SIMD vector type containing integers",
581032e81fdSAndrew Brown         TypeSetBuilder::new()
582032e81fdSAndrew Brown             .ints(Interval::All)
583032e81fdSAndrew Brown             .simd_lanes(Interval::All)
584032e81fdSAndrew Brown             .includes_scalars(false)
585032e81fdSAndrew Brown             .build(),
586032e81fdSAndrew Brown     );
587032e81fdSAndrew Brown 
588032e81fdSAndrew Brown     ig.push(
589032e81fdSAndrew Brown         Inst::new(
590032e81fdSAndrew Brown             "avg_round",
591032e81fdSAndrew Brown             r#"
592032e81fdSAndrew Brown         Unsigned average with rounding: `a := (x + y + 1) // 2`
593e463890fSDamian Heaton 
594e463890fSDamian Heaton         The addition does not lose any information (such as from overflow).
595032e81fdSAndrew Brown         "#,
596032e81fdSAndrew Brown             &formats.binary,
597032e81fdSAndrew Brown         )
598f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", IxN), Operand::new("y", IxN)])
599f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IxN)]),
600032e81fdSAndrew Brown     );
6011fe76768SAndrew Brown 
6021fe76768SAndrew Brown     ig.push(
6031fe76768SAndrew Brown         Inst::new(
6041fe76768SAndrew Brown             "uadd_sat",
6051fe76768SAndrew Brown             r#"
6061fe76768SAndrew Brown         Add with unsigned saturation.
6071fe76768SAndrew Brown 
6081fe76768SAndrew Brown         This is similar to `iadd` but the operands are interpreted as unsigned integers and their
6091fe76768SAndrew Brown         summed result, instead of wrapping, will be saturated to the highest unsigned integer for
6101fe76768SAndrew Brown         the controlling type (e.g. `0xFF` for i8).
6111fe76768SAndrew Brown         "#,
6121fe76768SAndrew Brown             &formats.binary,
6131fe76768SAndrew Brown         )
614f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", IxN), Operand::new("y", IxN)])
615f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IxN)]),
6161fe76768SAndrew Brown     );
6171fe76768SAndrew Brown 
6181fe76768SAndrew Brown     ig.push(
6191fe76768SAndrew Brown         Inst::new(
6201fe76768SAndrew Brown             "sadd_sat",
6211fe76768SAndrew Brown             r#"
6221fe76768SAndrew Brown         Add with signed saturation.
6231fe76768SAndrew Brown 
6241fe76768SAndrew Brown         This is similar to `iadd` but the operands are interpreted as signed integers and their
6251fe76768SAndrew Brown         summed result, instead of wrapping, will be saturated to the lowest or highest
6261fe76768SAndrew Brown         signed integer for the controlling type (e.g. `0x80` or `0x7F` for i8). For example,
6271fe76768SAndrew Brown         since an `sadd_sat.i8` of `0x70` and `0x70` is greater than `0x7F`, the result will be
6281fe76768SAndrew Brown         clamped to `0x7F`.
6291fe76768SAndrew Brown         "#,
6301fe76768SAndrew Brown             &formats.binary,
6311fe76768SAndrew Brown         )
632f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", IxN), Operand::new("y", IxN)])
633f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IxN)]),
6341fe76768SAndrew Brown     );
6351fe76768SAndrew Brown 
6361fe76768SAndrew Brown     ig.push(
6371fe76768SAndrew Brown         Inst::new(
6381fe76768SAndrew Brown             "usub_sat",
6391fe76768SAndrew Brown             r#"
6401fe76768SAndrew Brown         Subtract with unsigned saturation.
6411fe76768SAndrew Brown 
6421fe76768SAndrew Brown         This is similar to `isub` but the operands are interpreted as unsigned integers and their
6431fe76768SAndrew Brown         difference, instead of wrapping, will be saturated to the lowest unsigned integer for
6441fe76768SAndrew Brown         the controlling type (e.g. `0x00` for i8).
6451fe76768SAndrew Brown         "#,
6461fe76768SAndrew Brown             &formats.binary,
6471fe76768SAndrew Brown         )
648f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", IxN), Operand::new("y", IxN)])
649f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IxN)]),
6501fe76768SAndrew Brown     );
6511fe76768SAndrew Brown 
6521fe76768SAndrew Brown     ig.push(
6531fe76768SAndrew Brown         Inst::new(
6541fe76768SAndrew Brown             "ssub_sat",
6551fe76768SAndrew Brown             r#"
6561fe76768SAndrew Brown         Subtract with signed saturation.
6571fe76768SAndrew Brown 
6581fe76768SAndrew Brown         This is similar to `isub` but the operands are interpreted as signed integers and their
6591fe76768SAndrew Brown         difference, instead of wrapping, will be saturated to the lowest or highest
6601fe76768SAndrew Brown         signed integer for the controlling type (e.g. `0x80` or `0x7F` for i8).
6611fe76768SAndrew Brown         "#,
6621fe76768SAndrew Brown             &formats.binary,
6631fe76768SAndrew Brown         )
664f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", IxN), Operand::new("y", IxN)])
665f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IxN)]),
6661fe76768SAndrew Brown     );
6673ae1af1aSAndrew Brown }
6683ae1af1aSAndrew Brown 
define( all_instructions: &mut AllInstructions, formats: &Formats, imm: &Immediates, entities: &EntityRefs, )669d1d2e790SBenjamin Bouvier pub(crate) fn define(
670f1d1d1e9SBenjamin Bouvier     all_instructions: &mut AllInstructions,
6710243b642SBenjamin Bouvier     formats: &Formats,
67229e3ec51SBenjamin Bouvier     imm: &Immediates,
6738fba449bSBenjamin Bouvier     entities: &EntityRefs,
67418bd27e9Sbjorn3 ) {
6750243b642SBenjamin Bouvier     let mut ig = InstructionGroupBuilder::new(all_instructions);
67686430abcSBenjamin Bouvier 
6773a4b1cc9SBenjamin Bouvier     define_control_flow(&mut ig, formats, imm, entities);
6786e0401b8SAndrew Brown     define_simd_lane_access(&mut ig, formats, imm, entities);
6793ae1af1aSAndrew Brown     define_simd_arithmetic(&mut ig, formats, imm, entities);
6803a4b1cc9SBenjamin Bouvier 
68186430abcSBenjamin Bouvier     // Operand kind shorthands.
68232a7593cSTrevor Elliott     let i8: &TypeVar = &ValueType::from(LaneType::from(types::Int::I8)).into();
68341eca60bSbeetrees     let f16_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F16)).into();
68486430abcSBenjamin Bouvier     let f32_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F32)).into();
68586430abcSBenjamin Bouvier     let f64_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F64)).into();
68641eca60bSbeetrees     let f128_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F128)).into();
68786430abcSBenjamin Bouvier 
68886430abcSBenjamin Bouvier     // Starting definitions.
68960532011SBenjamin Bouvier     let Int = &TypeVar::new(
69060532011SBenjamin Bouvier         "Int",
69160532011SBenjamin Bouvier         "A scalar or vector integer type",
69260532011SBenjamin Bouvier         TypeSetBuilder::new()
69386430abcSBenjamin Bouvier             .ints(Interval::All)
69486430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
6959c43749dSSam Parker             .dynamic_simd_lanes(Interval::All)
69670f79d23SBenjamin Bouvier             .build(),
69760532011SBenjamin Bouvier     );
69886430abcSBenjamin Bouvier 
699c8791073SAfonso Bordado     let NarrowInt = &TypeVar::new(
700c8791073SAfonso Bordado         "NarrowInt",
701861220c4STrevor Elliott         "An integer type of width up to `i64`",
702861220c4STrevor Elliott         TypeSetBuilder::new().ints(8..64).build(),
703c8791073SAfonso Bordado     );
704c8791073SAfonso Bordado 
70532a7593cSTrevor Elliott     let ScalarTruthy = &TypeVar::new(
70632a7593cSTrevor Elliott         "ScalarTruthy",
70732a7593cSTrevor Elliott         "A scalar truthy type",
70832a7593cSTrevor Elliott         TypeSetBuilder::new().ints(Interval::All).build(),
70987007c58SAfonso Bordado     );
71087007c58SAfonso Bordado 
71160532011SBenjamin Bouvier     let iB = &TypeVar::new(
71260532011SBenjamin Bouvier         "iB",
71360532011SBenjamin Bouvier         "A scalar integer type",
71470f79d23SBenjamin Bouvier         TypeSetBuilder::new().ints(Interval::All).build(),
71560532011SBenjamin Bouvier     );
71686430abcSBenjamin Bouvier 
7174ca9e82bS11evan     let iSwappable = &TypeVar::new(
7184ca9e82bS11evan         "iSwappable",
7194ca9e82bS11evan         "A multi byte scalar integer type",
7204ca9e82bS11evan         TypeSetBuilder::new().ints(16..128).build(),
7214ca9e82bS11evan     );
7224ca9e82bS11evan 
72360532011SBenjamin Bouvier     let iAddr = &TypeVar::new(
72460532011SBenjamin Bouvier         "iAddr",
72560532011SBenjamin Bouvier         "An integer address type",
726b81ef46cSNick Fitzgerald         TypeSetBuilder::new().ints(32..64).build(),
72719257f80SCarmen Kwan     );
72819257f80SCarmen Kwan 
72960532011SBenjamin Bouvier     let TxN = &TypeVar::new(
73060532011SBenjamin Bouvier         "TxN",
73160532011SBenjamin Bouvier         "A SIMD vector type",
73260532011SBenjamin Bouvier         TypeSetBuilder::new()
73386430abcSBenjamin Bouvier             .ints(Interval::All)
73486430abcSBenjamin Bouvier             .floats(Interval::All)
73586430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
73686430abcSBenjamin Bouvier             .includes_scalars(false)
73770f79d23SBenjamin Bouvier             .build(),
73860532011SBenjamin Bouvier     );
73960532011SBenjamin Bouvier     let Any = &TypeVar::new(
74086430abcSBenjamin Bouvier         "Any",
74132a7593cSTrevor Elliott         "Any integer, float, or reference scalar or vector type",
74260532011SBenjamin Bouvier         TypeSetBuilder::new()
74386430abcSBenjamin Bouvier             .ints(Interval::All)
74486430abcSBenjamin Bouvier             .floats(Interval::All)
74586430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
74686430abcSBenjamin Bouvier             .includes_scalars(true)
74770f79d23SBenjamin Bouvier             .build(),
74860532011SBenjamin Bouvier     );
74986430abcSBenjamin Bouvier 
75060532011SBenjamin Bouvier     let Mem = &TypeVar::new(
75160532011SBenjamin Bouvier         "Mem",
75260532011SBenjamin Bouvier         "Any type that can be stored in memory",
75360532011SBenjamin Bouvier         TypeSetBuilder::new()
75486430abcSBenjamin Bouvier             .ints(Interval::All)
75586430abcSBenjamin Bouvier             .floats(Interval::All)
75686430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
7579c43749dSSam Parker             .dynamic_simd_lanes(Interval::All)
75870f79d23SBenjamin Bouvier             .build(),
75960532011SBenjamin Bouvier     );
76086430abcSBenjamin Bouvier 
76161772e97SAndrew Brown     let MemTo = &TypeVar::copy_from(Mem, "MemTo".to_string());
76286430abcSBenjamin Bouvier 
76386430abcSBenjamin Bouvier     ig.push(
76486430abcSBenjamin Bouvier         Inst::new(
76586430abcSBenjamin Bouvier             "load",
76686430abcSBenjamin Bouvier             r#"
76786430abcSBenjamin Bouvier         Load from memory at ``p + Offset``.
76886430abcSBenjamin Bouvier 
76986430abcSBenjamin Bouvier         This is a polymorphic instruction that can load any value type which
77086430abcSBenjamin Bouvier         has a memory representation.
77186430abcSBenjamin Bouvier         "#,
7720243b642SBenjamin Bouvier             &formats.load,
77386430abcSBenjamin Bouvier         )
774f8771416SJamey Sharp         .operands_in(vec![
775f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
776f8771416SJamey Sharp             Operand::new("p", iAddr),
777f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
778f8771416SJamey Sharp         ])
779f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")])
780b5692db7STrevor Elliott         .can_load(),
78186430abcSBenjamin Bouvier     );
78286430abcSBenjamin Bouvier 
78386430abcSBenjamin Bouvier     ig.push(
78486430abcSBenjamin Bouvier         Inst::new(
78586430abcSBenjamin Bouvier             "store",
78686430abcSBenjamin Bouvier             r#"
78786430abcSBenjamin Bouvier         Store ``x`` to memory at ``p + Offset``.
78886430abcSBenjamin Bouvier 
78986430abcSBenjamin Bouvier         This is a polymorphic instruction that can store any value type with a
79086430abcSBenjamin Bouvier         memory representation.
79186430abcSBenjamin Bouvier         "#,
7920243b642SBenjamin Bouvier             &formats.store,
79386430abcSBenjamin Bouvier         )
794f8771416SJamey Sharp         .operands_in(vec![
795f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
796f8771416SJamey Sharp             Operand::new("x", Mem).with_doc("Value to be stored"),
797f8771416SJamey Sharp             Operand::new("p", iAddr),
798f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
799f8771416SJamey Sharp         ])
800b5692db7STrevor Elliott         .can_store(),
80186430abcSBenjamin Bouvier     );
80286430abcSBenjamin Bouvier 
80360532011SBenjamin Bouvier     let iExt8 = &TypeVar::new(
80460532011SBenjamin Bouvier         "iExt8",
80560532011SBenjamin Bouvier         "An integer type with more than 8 bits",
80670f79d23SBenjamin Bouvier         TypeSetBuilder::new().ints(16..64).build(),
80760532011SBenjamin Bouvier     );
80886430abcSBenjamin Bouvier 
80986430abcSBenjamin Bouvier     ig.push(
81086430abcSBenjamin Bouvier         Inst::new(
81186430abcSBenjamin Bouvier             "uload8",
81286430abcSBenjamin Bouvier             r#"
81386430abcSBenjamin Bouvier         Load 8 bits from memory at ``p + Offset`` and zero-extend.
81486430abcSBenjamin Bouvier 
81586430abcSBenjamin Bouvier         This is equivalent to ``load.i8`` followed by ``uextend``.
81686430abcSBenjamin Bouvier         "#,
8170243b642SBenjamin Bouvier             &formats.load,
81886430abcSBenjamin Bouvier         )
819f8771416SJamey Sharp         .operands_in(vec![
820f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
821f8771416SJamey Sharp             Operand::new("p", iAddr),
822f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
823f8771416SJamey Sharp         ])
824f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt8)])
825b5692db7STrevor Elliott         .can_load(),
82686430abcSBenjamin Bouvier     );
82786430abcSBenjamin Bouvier 
82886430abcSBenjamin Bouvier     ig.push(
82986430abcSBenjamin Bouvier         Inst::new(
83086430abcSBenjamin Bouvier             "sload8",
83186430abcSBenjamin Bouvier             r#"
83286430abcSBenjamin Bouvier         Load 8 bits from memory at ``p + Offset`` and sign-extend.
83386430abcSBenjamin Bouvier 
83486430abcSBenjamin Bouvier         This is equivalent to ``load.i8`` followed by ``sextend``.
83586430abcSBenjamin Bouvier         "#,
8360243b642SBenjamin Bouvier             &formats.load,
83786430abcSBenjamin Bouvier         )
838f8771416SJamey Sharp         .operands_in(vec![
839f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
840f8771416SJamey Sharp             Operand::new("p", iAddr),
841f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
842f8771416SJamey Sharp         ])
843f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt8)])
844b5692db7STrevor Elliott         .can_load(),
84586430abcSBenjamin Bouvier     );
84686430abcSBenjamin Bouvier 
84786430abcSBenjamin Bouvier     ig.push(
84886430abcSBenjamin Bouvier         Inst::new(
84986430abcSBenjamin Bouvier             "istore8",
85086430abcSBenjamin Bouvier             r#"
85186430abcSBenjamin Bouvier         Store the low 8 bits of ``x`` to memory at ``p + Offset``.
85286430abcSBenjamin Bouvier 
85386430abcSBenjamin Bouvier         This is equivalent to ``ireduce.i8`` followed by ``store.i8``.
85486430abcSBenjamin Bouvier         "#,
8550243b642SBenjamin Bouvier             &formats.store,
85686430abcSBenjamin Bouvier         )
857f8771416SJamey Sharp         .operands_in(vec![
858f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
859f8771416SJamey Sharp             Operand::new("x", iExt8),
860f8771416SJamey Sharp             Operand::new("p", iAddr),
861f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
862f8771416SJamey Sharp         ])
863b5692db7STrevor Elliott         .can_store(),
86486430abcSBenjamin Bouvier     );
86586430abcSBenjamin Bouvier 
86660532011SBenjamin Bouvier     let iExt16 = &TypeVar::new(
86760532011SBenjamin Bouvier         "iExt16",
86860532011SBenjamin Bouvier         "An integer type with more than 16 bits",
86970f79d23SBenjamin Bouvier         TypeSetBuilder::new().ints(32..64).build(),
87060532011SBenjamin Bouvier     );
87186430abcSBenjamin Bouvier 
87286430abcSBenjamin Bouvier     ig.push(
87386430abcSBenjamin Bouvier         Inst::new(
87486430abcSBenjamin Bouvier             "uload16",
87586430abcSBenjamin Bouvier             r#"
87686430abcSBenjamin Bouvier         Load 16 bits from memory at ``p + Offset`` and zero-extend.
87786430abcSBenjamin Bouvier 
87886430abcSBenjamin Bouvier         This is equivalent to ``load.i16`` followed by ``uextend``.
87986430abcSBenjamin Bouvier         "#,
8800243b642SBenjamin Bouvier             &formats.load,
88186430abcSBenjamin Bouvier         )
882f8771416SJamey Sharp         .operands_in(vec![
883f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
884f8771416SJamey Sharp             Operand::new("p", iAddr),
885f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
886f8771416SJamey Sharp         ])
887f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt16)])
888b5692db7STrevor Elliott         .can_load(),
88986430abcSBenjamin Bouvier     );
89086430abcSBenjamin Bouvier 
89186430abcSBenjamin Bouvier     ig.push(
89286430abcSBenjamin Bouvier         Inst::new(
89386430abcSBenjamin Bouvier             "sload16",
89486430abcSBenjamin Bouvier             r#"
89586430abcSBenjamin Bouvier         Load 16 bits from memory at ``p + Offset`` and sign-extend.
89686430abcSBenjamin Bouvier 
89786430abcSBenjamin Bouvier         This is equivalent to ``load.i16`` followed by ``sextend``.
89886430abcSBenjamin Bouvier         "#,
8990243b642SBenjamin Bouvier             &formats.load,
90086430abcSBenjamin Bouvier         )
901f8771416SJamey Sharp         .operands_in(vec![
902f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
903f8771416SJamey Sharp             Operand::new("p", iAddr),
904f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
905f8771416SJamey Sharp         ])
906f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt16)])
907b5692db7STrevor Elliott         .can_load(),
90886430abcSBenjamin Bouvier     );
90986430abcSBenjamin Bouvier 
91086430abcSBenjamin Bouvier     ig.push(
91186430abcSBenjamin Bouvier         Inst::new(
91286430abcSBenjamin Bouvier             "istore16",
91386430abcSBenjamin Bouvier             r#"
91486430abcSBenjamin Bouvier         Store the low 16 bits of ``x`` to memory at ``p + Offset``.
91586430abcSBenjamin Bouvier 
91686430abcSBenjamin Bouvier         This is equivalent to ``ireduce.i16`` followed by ``store.i16``.
91786430abcSBenjamin Bouvier         "#,
9180243b642SBenjamin Bouvier             &formats.store,
91986430abcSBenjamin Bouvier         )
920f8771416SJamey Sharp         .operands_in(vec![
921f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
922f8771416SJamey Sharp             Operand::new("x", iExt16),
923f8771416SJamey Sharp             Operand::new("p", iAddr),
924f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
925f8771416SJamey Sharp         ])
926b5692db7STrevor Elliott         .can_store(),
92786430abcSBenjamin Bouvier     );
92886430abcSBenjamin Bouvier 
92960532011SBenjamin Bouvier     let iExt32 = &TypeVar::new(
93060532011SBenjamin Bouvier         "iExt32",
93160532011SBenjamin Bouvier         "An integer type with more than 32 bits",
93270f79d23SBenjamin Bouvier         TypeSetBuilder::new().ints(64..64).build(),
93360532011SBenjamin Bouvier     );
93486430abcSBenjamin Bouvier 
93586430abcSBenjamin Bouvier     ig.push(
93686430abcSBenjamin Bouvier         Inst::new(
93786430abcSBenjamin Bouvier             "uload32",
93886430abcSBenjamin Bouvier             r#"
93986430abcSBenjamin Bouvier         Load 32 bits from memory at ``p + Offset`` and zero-extend.
94086430abcSBenjamin Bouvier 
94186430abcSBenjamin Bouvier         This is equivalent to ``load.i32`` followed by ``uextend``.
94286430abcSBenjamin Bouvier         "#,
9430243b642SBenjamin Bouvier             &formats.load,
94486430abcSBenjamin Bouvier         )
945f8771416SJamey Sharp         .operands_in(vec![
946f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
947f8771416SJamey Sharp             Operand::new("p", iAddr),
948f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
949f8771416SJamey Sharp         ])
950f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt32)])
951b5692db7STrevor Elliott         .can_load(),
95286430abcSBenjamin Bouvier     );
95386430abcSBenjamin Bouvier 
95486430abcSBenjamin Bouvier     ig.push(
95586430abcSBenjamin Bouvier         Inst::new(
95686430abcSBenjamin Bouvier             "sload32",
95786430abcSBenjamin Bouvier             r#"
95886430abcSBenjamin Bouvier         Load 32 bits from memory at ``p + Offset`` and sign-extend.
95986430abcSBenjamin Bouvier 
96086430abcSBenjamin Bouvier         This is equivalent to ``load.i32`` followed by ``sextend``.
96186430abcSBenjamin Bouvier         "#,
9620243b642SBenjamin Bouvier             &formats.load,
96386430abcSBenjamin Bouvier         )
964f8771416SJamey Sharp         .operands_in(vec![
965f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
966f8771416SJamey Sharp             Operand::new("p", iAddr),
967f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
968f8771416SJamey Sharp         ])
969f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iExt32)])
970b5692db7STrevor Elliott         .can_load(),
97186430abcSBenjamin Bouvier     );
97286430abcSBenjamin Bouvier 
97386430abcSBenjamin Bouvier     ig.push(
97486430abcSBenjamin Bouvier         Inst::new(
97586430abcSBenjamin Bouvier             "istore32",
97686430abcSBenjamin Bouvier             r#"
97786430abcSBenjamin Bouvier         Store the low 32 bits of ``x`` to memory at ``p + Offset``.
97886430abcSBenjamin Bouvier 
97986430abcSBenjamin Bouvier         This is equivalent to ``ireduce.i32`` followed by ``store.i32``.
98086430abcSBenjamin Bouvier         "#,
9810243b642SBenjamin Bouvier             &formats.store,
98286430abcSBenjamin Bouvier         )
983f8771416SJamey Sharp         .operands_in(vec![
984f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
985f8771416SJamey Sharp             Operand::new("x", iExt32),
986f8771416SJamey Sharp             Operand::new("p", iAddr),
987f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
988f8771416SJamey Sharp         ])
989b5692db7STrevor Elliott         .can_store(),
99086430abcSBenjamin Bouvier     );
991dbc11c30SFrank Emrich     ig.push(
992dbc11c30SFrank Emrich         Inst::new(
993dbc11c30SFrank Emrich             "stack_switch",
994dbc11c30SFrank Emrich             r#"
995dbc11c30SFrank Emrich         Suspends execution of the current stack and resumes execution of another
996dbc11c30SFrank Emrich         one.
997dbc11c30SFrank Emrich 
998dbc11c30SFrank Emrich         The target stack to switch to is identified by the data stored at
999dbc11c30SFrank Emrich         ``load_context_ptr``. Before switching, this instruction stores
1000dbc11c30SFrank Emrich         analogous information about the
1001dbc11c30SFrank Emrich         current (i.e., original) stack at ``store_context_ptr``, to
1002dbc11c30SFrank Emrich         enabled switching back to the original stack at a later point.
1003dbc11c30SFrank Emrich 
1004dbc11c30SFrank Emrich         The size, alignment and layout of the information stored at
1005dbc11c30SFrank Emrich         ``load_context_ptr`` and ``store_context_ptr`` is platform-dependent.
1006dbc11c30SFrank Emrich         The instruction assumes that ``load_context_ptr`` and
1007dbc11c30SFrank Emrich         ``store_context_ptr`` are valid pointers to memory with said layout and
1008dbc11c30SFrank Emrich         alignment, and does not perform any checks on these pointers or the data
1009dbc11c30SFrank Emrich         stored there.
1010dbc11c30SFrank Emrich 
1011dbc11c30SFrank Emrich         The instruction is experimental and only supported on x64 Linux at the
1012dbc11c30SFrank Emrich         moment.
1013dbc11c30SFrank Emrich 
1014dbc11c30SFrank Emrich         When switching from a stack A to a stack B, one of the following cases
1015dbc11c30SFrank Emrich         must apply:
1016dbc11c30SFrank Emrich         1. Stack B was previously suspended using a ``stack_switch`` instruction.
1017dbc11c30SFrank Emrich         2. Stack B is a newly initialized stack. The necessary initialization is
1018dbc11c30SFrank Emrich         platform-dependent and will generally involve running some kind of
1019dbc11c30SFrank Emrich         trampoline to start execution of a function on the new stack.
1020dbc11c30SFrank Emrich 
1021dbc11c30SFrank Emrich         In both cases, the ``in_payload`` argument of the ``stack_switch``
1022dbc11c30SFrank Emrich         instruction executed on A is passed to stack B. In the first case above,
1023dbc11c30SFrank Emrich         it will be the result value of the earlier ``stack_switch`` instruction
1024dbc11c30SFrank Emrich         executed on stack B. In the second case, the value will be accessible to
1025dbc11c30SFrank Emrich         the trampoline in a platform-dependent register.
1026dbc11c30SFrank Emrich 
1027dbc11c30SFrank Emrich         The pointers ``load_context_ptr`` and ``store_context_ptr`` are allowed
1028dbc11c30SFrank Emrich         to be equal; the instruction ensures that all data is loaded from the
1029dbc11c30SFrank Emrich         former before writing to the latter.
1030dbc11c30SFrank Emrich 
1031dbc11c30SFrank Emrich         Stack switching is one-shot in the sense that each ``stack_switch``
1032dbc11c30SFrank Emrich         operation effectively consumes the context identified by
1033dbc11c30SFrank Emrich         ``load_context_ptr``. In other words, performing two ``stack_switches``
1034dbc11c30SFrank Emrich         using the same ``load_context_ptr`` causes undefined behavior, unless
1035dbc11c30SFrank Emrich         the context at ``load_context_ptr`` is overwritten by another
1036dbc11c30SFrank Emrich         `stack_switch` in between.
1037dbc11c30SFrank Emrich         "#,
1038dbc11c30SFrank Emrich             &formats.ternary,
1039dbc11c30SFrank Emrich         )
1040dbc11c30SFrank Emrich         .operands_in(vec![
1041dbc11c30SFrank Emrich             Operand::new("store_context_ptr", iAddr),
1042dbc11c30SFrank Emrich             Operand::new("load_context_ptr", iAddr),
1043dbc11c30SFrank Emrich             Operand::new("in_payload0", iAddr),
1044dbc11c30SFrank Emrich         ])
1045dbc11c30SFrank Emrich         .operands_out(vec![Operand::new("out_payload0", iAddr)])
1046dbc11c30SFrank Emrich         .other_side_effects()
1047dbc11c30SFrank Emrich         .can_load()
1048dbc11c30SFrank Emrich         .can_store()
1049dbc11c30SFrank Emrich         .call(),
1050dbc11c30SFrank Emrich     );
105186430abcSBenjamin Bouvier 
1052cf1cfdcaSAndrew Brown     let I16x8 = &TypeVar::new(
1053cf1cfdcaSAndrew Brown         "I16x8",
1054cf1cfdcaSAndrew Brown         "A SIMD vector with exactly 8 lanes of 16-bit values",
1055cf1cfdcaSAndrew Brown         TypeSetBuilder::new()
1056cf1cfdcaSAndrew Brown             .ints(16..16)
1057cf1cfdcaSAndrew Brown             .simd_lanes(8..8)
1058cf1cfdcaSAndrew Brown             .includes_scalars(false)
1059cf1cfdcaSAndrew Brown             .build(),
1060cf1cfdcaSAndrew Brown     );
1061cf1cfdcaSAndrew Brown 
1062cf1cfdcaSAndrew Brown     ig.push(
1063cf1cfdcaSAndrew Brown         Inst::new(
1064cf1cfdcaSAndrew Brown             "uload8x8",
1065cf1cfdcaSAndrew Brown             r#"
1066cf1cfdcaSAndrew Brown         Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i16x8
1067cf1cfdcaSAndrew Brown         vector.
1068cf1cfdcaSAndrew Brown         "#,
1069cf1cfdcaSAndrew Brown             &formats.load,
1070cf1cfdcaSAndrew Brown         )
1071f8771416SJamey Sharp         .operands_in(vec![
1072f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1073f8771416SJamey Sharp             Operand::new("p", iAddr),
1074f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1075f8771416SJamey Sharp         ])
1076f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I16x8).with_doc("Value loaded")])
1077b5692db7STrevor Elliott         .can_load(),
1078cf1cfdcaSAndrew Brown     );
1079cf1cfdcaSAndrew Brown 
1080cf1cfdcaSAndrew Brown     ig.push(
1081cf1cfdcaSAndrew Brown         Inst::new(
1082cf1cfdcaSAndrew Brown             "sload8x8",
1083cf1cfdcaSAndrew Brown             r#"
1084cf1cfdcaSAndrew Brown         Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i16x8
1085cf1cfdcaSAndrew Brown         vector.
1086cf1cfdcaSAndrew Brown         "#,
1087cf1cfdcaSAndrew Brown             &formats.load,
1088cf1cfdcaSAndrew Brown         )
1089f8771416SJamey Sharp         .operands_in(vec![
1090f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1091f8771416SJamey Sharp             Operand::new("p", iAddr),
1092f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1093f8771416SJamey Sharp         ])
1094f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I16x8).with_doc("Value loaded")])
1095b5692db7STrevor Elliott         .can_load(),
1096cf1cfdcaSAndrew Brown     );
1097cf1cfdcaSAndrew Brown 
1098cf1cfdcaSAndrew Brown     let I32x4 = &TypeVar::new(
1099cf1cfdcaSAndrew Brown         "I32x4",
1100cf1cfdcaSAndrew Brown         "A SIMD vector with exactly 4 lanes of 32-bit values",
1101cf1cfdcaSAndrew Brown         TypeSetBuilder::new()
1102cf1cfdcaSAndrew Brown             .ints(32..32)
1103cf1cfdcaSAndrew Brown             .simd_lanes(4..4)
1104cf1cfdcaSAndrew Brown             .includes_scalars(false)
1105cf1cfdcaSAndrew Brown             .build(),
1106cf1cfdcaSAndrew Brown     );
1107cf1cfdcaSAndrew Brown 
1108cf1cfdcaSAndrew Brown     ig.push(
1109cf1cfdcaSAndrew Brown         Inst::new(
1110cf1cfdcaSAndrew Brown             "uload16x4",
1111cf1cfdcaSAndrew Brown             r#"
1112a3125062SAndrew Brown         Load a 16x4 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i32x4
1113cf1cfdcaSAndrew Brown         vector.
1114cf1cfdcaSAndrew Brown         "#,
1115cf1cfdcaSAndrew Brown             &formats.load,
1116cf1cfdcaSAndrew Brown         )
1117f8771416SJamey Sharp         .operands_in(vec![
1118f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1119f8771416SJamey Sharp             Operand::new("p", iAddr),
1120f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1121f8771416SJamey Sharp         ])
1122f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I32x4).with_doc("Value loaded")])
1123b5692db7STrevor Elliott         .can_load(),
1124cf1cfdcaSAndrew Brown     );
1125cf1cfdcaSAndrew Brown 
1126cf1cfdcaSAndrew Brown     ig.push(
1127cf1cfdcaSAndrew Brown         Inst::new(
1128cf1cfdcaSAndrew Brown             "sload16x4",
1129cf1cfdcaSAndrew Brown             r#"
1130cf1cfdcaSAndrew Brown         Load a 16x4 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i32x4
1131cf1cfdcaSAndrew Brown         vector.
1132cf1cfdcaSAndrew Brown         "#,
1133cf1cfdcaSAndrew Brown             &formats.load,
1134cf1cfdcaSAndrew Brown         )
1135f8771416SJamey Sharp         .operands_in(vec![
1136f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1137f8771416SJamey Sharp             Operand::new("p", iAddr),
1138f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1139f8771416SJamey Sharp         ])
1140f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I32x4).with_doc("Value loaded")])
1141b5692db7STrevor Elliott         .can_load(),
1142cf1cfdcaSAndrew Brown     );
1143cf1cfdcaSAndrew Brown 
1144cf1cfdcaSAndrew Brown     let I64x2 = &TypeVar::new(
1145cf1cfdcaSAndrew Brown         "I64x2",
1146cf1cfdcaSAndrew Brown         "A SIMD vector with exactly 2 lanes of 64-bit values",
1147cf1cfdcaSAndrew Brown         TypeSetBuilder::new()
1148cf1cfdcaSAndrew Brown             .ints(64..64)
1149cf1cfdcaSAndrew Brown             .simd_lanes(2..2)
1150cf1cfdcaSAndrew Brown             .includes_scalars(false)
1151cf1cfdcaSAndrew Brown             .build(),
1152cf1cfdcaSAndrew Brown     );
1153cf1cfdcaSAndrew Brown 
1154cf1cfdcaSAndrew Brown     ig.push(
1155cf1cfdcaSAndrew Brown         Inst::new(
1156cf1cfdcaSAndrew Brown             "uload32x2",
1157cf1cfdcaSAndrew Brown             r#"
1158cf1cfdcaSAndrew Brown         Load an 32x2 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i64x2
1159cf1cfdcaSAndrew Brown         vector.
1160cf1cfdcaSAndrew Brown         "#,
1161cf1cfdcaSAndrew Brown             &formats.load,
1162cf1cfdcaSAndrew Brown         )
1163f8771416SJamey Sharp         .operands_in(vec![
1164f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1165f8771416SJamey Sharp             Operand::new("p", iAddr),
1166f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1167f8771416SJamey Sharp         ])
1168f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I64x2).with_doc("Value loaded")])
1169b5692db7STrevor Elliott         .can_load(),
1170cf1cfdcaSAndrew Brown     );
1171cf1cfdcaSAndrew Brown 
1172cf1cfdcaSAndrew Brown     ig.push(
1173cf1cfdcaSAndrew Brown         Inst::new(
1174cf1cfdcaSAndrew Brown             "sload32x2",
1175cf1cfdcaSAndrew Brown             r#"
1176cf1cfdcaSAndrew Brown         Load a 32x2 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i64x2
1177cf1cfdcaSAndrew Brown         vector.
1178cf1cfdcaSAndrew Brown         "#,
1179cf1cfdcaSAndrew Brown             &formats.load,
1180cf1cfdcaSAndrew Brown         )
1181f8771416SJamey Sharp         .operands_in(vec![
1182f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
1183f8771416SJamey Sharp             Operand::new("p", iAddr),
1184f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1185f8771416SJamey Sharp         ])
1186f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I64x2).with_doc("Value loaded")])
1187b5692db7STrevor Elliott         .can_load(),
1188cf1cfdcaSAndrew Brown     );
1189cf1cfdcaSAndrew Brown 
119086430abcSBenjamin Bouvier     ig.push(
119186430abcSBenjamin Bouvier         Inst::new(
119286430abcSBenjamin Bouvier             "stack_load",
119386430abcSBenjamin Bouvier             r#"
119486430abcSBenjamin Bouvier         Load a value from a stack slot at the constant offset.
119586430abcSBenjamin Bouvier 
119686430abcSBenjamin Bouvier         This is a polymorphic instruction that can load any value type which
119786430abcSBenjamin Bouvier         has a memory representation.
119886430abcSBenjamin Bouvier 
119986430abcSBenjamin Bouvier         The offset is an immediate constant, not an SSA value. The memory
120086430abcSBenjamin Bouvier         access cannot go out of bounds, i.e.
1201062ed8f6SBenjamin Bouvier         `sizeof(a) + Offset <= sizeof(SS)`.
120286430abcSBenjamin Bouvier         "#,
12030243b642SBenjamin Bouvier             &formats.stack_load,
120486430abcSBenjamin Bouvier         )
1205f8771416SJamey Sharp         .operands_in(vec![
1206f8771416SJamey Sharp             Operand::new("SS", &entities.stack_slot),
1207f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
1208f8771416SJamey Sharp         ])
1209f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")])
1210b5692db7STrevor Elliott         .can_load(),
121186430abcSBenjamin Bouvier     );
121286430abcSBenjamin Bouvier 
121386430abcSBenjamin Bouvier     ig.push(
121486430abcSBenjamin Bouvier         Inst::new(
121586430abcSBenjamin Bouvier             "stack_store",
121686430abcSBenjamin Bouvier             r#"
121786430abcSBenjamin Bouvier         Store a value to a stack slot at a constant offset.
121886430abcSBenjamin Bouvier 
121986430abcSBenjamin Bouvier         This is a polymorphic instruction that can store any value type with a
122086430abcSBenjamin Bouvier         memory representation.
122186430abcSBenjamin Bouvier 
122286430abcSBenjamin Bouvier         The offset is an immediate constant, not an SSA value. The memory
122386430abcSBenjamin Bouvier         access cannot go out of bounds, i.e.
1224062ed8f6SBenjamin Bouvier         `sizeof(a) + Offset <= sizeof(SS)`.
122586430abcSBenjamin Bouvier         "#,
12260243b642SBenjamin Bouvier             &formats.stack_store,
122786430abcSBenjamin Bouvier         )
1228f8771416SJamey Sharp         .operands_in(vec![
1229f8771416SJamey Sharp             Operand::new("x", Mem).with_doc("Value to be stored"),
1230f8771416SJamey Sharp             Operand::new("SS", &entities.stack_slot),
1231f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
1232f8771416SJamey Sharp         ])
1233b5692db7STrevor Elliott         .can_store(),
123486430abcSBenjamin Bouvier     );
123586430abcSBenjamin Bouvier 
123686430abcSBenjamin Bouvier     ig.push(
123786430abcSBenjamin Bouvier         Inst::new(
123886430abcSBenjamin Bouvier             "stack_addr",
123986430abcSBenjamin Bouvier             r#"
124086430abcSBenjamin Bouvier         Get the address of a stack slot.
124186430abcSBenjamin Bouvier 
124286430abcSBenjamin Bouvier         Compute the absolute address of a byte in a stack slot. The offset must
124386430abcSBenjamin Bouvier         refer to a byte inside the stack slot:
1244062ed8f6SBenjamin Bouvier         `0 <= Offset < sizeof(SS)`.
124586430abcSBenjamin Bouvier         "#,
12460243b642SBenjamin Bouvier             &formats.stack_load,
124786430abcSBenjamin Bouvier         )
1248f8771416SJamey Sharp         .operands_in(vec![
1249f8771416SJamey Sharp             Operand::new("SS", &entities.stack_slot),
1250f8771416SJamey Sharp             Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
1251f8771416SJamey Sharp         ])
1252f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
125386430abcSBenjamin Bouvier     );
125486430abcSBenjamin Bouvier 
12559c43749dSSam Parker     ig.push(
12569c43749dSSam Parker         Inst::new(
12579c43749dSSam Parker             "dynamic_stack_load",
12589c43749dSSam Parker             r#"
12599c43749dSSam Parker         Load a value from a dynamic stack slot.
12609c43749dSSam Parker 
12619c43749dSSam Parker         This is a polymorphic instruction that can load any value type which
12629c43749dSSam Parker         has a memory representation.
12639c43749dSSam Parker         "#,
12649c43749dSSam Parker             &formats.dynamic_stack_load,
12659c43749dSSam Parker         )
1266f8771416SJamey Sharp         .operands_in(vec![Operand::new("DSS", &entities.dynamic_stack_slot)])
1267f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")])
1268b5692db7STrevor Elliott         .can_load(),
12699c43749dSSam Parker     );
12709c43749dSSam Parker 
12719c43749dSSam Parker     ig.push(
12729c43749dSSam Parker         Inst::new(
12739c43749dSSam Parker             "dynamic_stack_store",
12749c43749dSSam Parker             r#"
12759c43749dSSam Parker         Store a value to a dynamic stack slot.
12769c43749dSSam Parker 
12779c43749dSSam Parker         This is a polymorphic instruction that can store any dynamic value type with a
12789c43749dSSam Parker         memory representation.
12799c43749dSSam Parker         "#,
12809c43749dSSam Parker             &formats.dynamic_stack_store,
12819c43749dSSam Parker         )
1282f8771416SJamey Sharp         .operands_in(vec![
1283f8771416SJamey Sharp             Operand::new("x", Mem).with_doc("Value to be stored"),
1284f8771416SJamey Sharp             Operand::new("DSS", &entities.dynamic_stack_slot),
1285f8771416SJamey Sharp         ])
1286b5692db7STrevor Elliott         .can_store(),
12879c43749dSSam Parker     );
12889c43749dSSam Parker 
12899c43749dSSam Parker     ig.push(
12909c43749dSSam Parker         Inst::new(
12919c43749dSSam Parker             "dynamic_stack_addr",
12929c43749dSSam Parker             r#"
12939c43749dSSam Parker         Get the address of a dynamic stack slot.
12949c43749dSSam Parker 
12959c43749dSSam Parker         Compute the absolute address of the first byte of a dynamic stack slot.
12969c43749dSSam Parker         "#,
12979c43749dSSam Parker             &formats.dynamic_stack_load,
12989c43749dSSam Parker         )
1299f8771416SJamey Sharp         .operands_in(vec![Operand::new("DSS", &entities.dynamic_stack_slot)])
1300f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
13019c43749dSSam Parker     );
130286430abcSBenjamin Bouvier 
130386430abcSBenjamin Bouvier     ig.push(
130486430abcSBenjamin Bouvier         Inst::new(
130586430abcSBenjamin Bouvier             "global_value",
130686430abcSBenjamin Bouvier             r#"
130786430abcSBenjamin Bouvier         Compute the value of global GV.
130886430abcSBenjamin Bouvier         "#,
13090243b642SBenjamin Bouvier             &formats.unary_global_value,
131086430abcSBenjamin Bouvier         )
1311f8771416SJamey Sharp         .operands_in(vec![Operand::new("GV", &entities.global_value)])
1312f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")]),
131386430abcSBenjamin Bouvier     );
131486430abcSBenjamin Bouvier 
131586430abcSBenjamin Bouvier     ig.push(
131686430abcSBenjamin Bouvier         Inst::new(
131786430abcSBenjamin Bouvier             "symbol_value",
131886430abcSBenjamin Bouvier             r#"
131986430abcSBenjamin Bouvier         Compute the value of global GV, which is a symbolic value.
132086430abcSBenjamin Bouvier         "#,
13210243b642SBenjamin Bouvier             &formats.unary_global_value,
132286430abcSBenjamin Bouvier         )
1323f8771416SJamey Sharp         .operands_in(vec![Operand::new("GV", &entities.global_value)])
1324f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")]),
132586430abcSBenjamin Bouvier     );
132686430abcSBenjamin Bouvier 
13270a1bb3baSbjorn3     ig.push(
13280a1bb3baSbjorn3         Inst::new(
13290a1bb3baSbjorn3             "tls_value",
13300a1bb3baSbjorn3             r#"
13310a1bb3baSbjorn3         Compute the value of global GV, which is a TLS (thread local storage) value.
13320a1bb3baSbjorn3         "#,
13330a1bb3baSbjorn3             &formats.unary_global_value,
13340a1bb3baSbjorn3         )
1335f8771416SJamey Sharp         .operands_in(vec![Operand::new("GV", &entities.global_value)])
1336f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Mem).with_doc("Value loaded")]),
13370a1bb3baSbjorn3     );
13380a1bb3baSbjorn3 
1339660b8b28SBenjamin Bouvier     // Note this instruction is marked as having other side-effects, so GVN won't try to hoist it,
1340660b8b28SBenjamin Bouvier     // which would result in it being subject to spilling. While not hoisting would generally hurt
1341660b8b28SBenjamin Bouvier     // performance, since a computed value used many times may need to be regenerated before each
1342660b8b28SBenjamin Bouvier     // use, it is not the case here: this instruction doesn't generate any code.  That's because,
1343660b8b28SBenjamin Bouvier     // by definition the pinned register is never used by the register allocator, but is written to
1344660b8b28SBenjamin Bouvier     // and read explicitly and exclusively by set_pinned_reg and get_pinned_reg.
1345660b8b28SBenjamin Bouvier     ig.push(
1346660b8b28SBenjamin Bouvier         Inst::new(
1347660b8b28SBenjamin Bouvier             "get_pinned_reg",
1348660b8b28SBenjamin Bouvier             r#"
1349660b8b28SBenjamin Bouvier             Gets the content of the pinned register, when it's enabled.
1350660b8b28SBenjamin Bouvier         "#,
13510243b642SBenjamin Bouvier             &formats.nullary,
1352660b8b28SBenjamin Bouvier         )
1353f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)])
1354b5692db7STrevor Elliott         .other_side_effects(),
1355660b8b28SBenjamin Bouvier     );
1356660b8b28SBenjamin Bouvier 
1357660b8b28SBenjamin Bouvier     ig.push(
1358660b8b28SBenjamin Bouvier         Inst::new(
1359660b8b28SBenjamin Bouvier             "set_pinned_reg",
1360660b8b28SBenjamin Bouvier             r#"
1361660b8b28SBenjamin Bouvier         Sets the content of the pinned register, when it's enabled.
1362660b8b28SBenjamin Bouvier         "#,
13630243b642SBenjamin Bouvier             &formats.unary,
1364660b8b28SBenjamin Bouvier         )
1365f8771416SJamey Sharp         .operands_in(vec![Operand::new("addr", iAddr)])
1366b5692db7STrevor Elliott         .other_side_effects(),
1367660b8b28SBenjamin Bouvier     );
1368660b8b28SBenjamin Bouvier 
136942bba452SNick Fitzgerald     ig.push(
137042bba452SNick Fitzgerald         Inst::new(
137142bba452SNick Fitzgerald             "get_frame_pointer",
137242bba452SNick Fitzgerald             r#"
137342bba452SNick Fitzgerald         Get the address in the frame pointer register.
137442bba452SNick Fitzgerald 
137542bba452SNick Fitzgerald         Usage of this instruction requires setting `preserve_frame_pointers` to `true`.
137642bba452SNick Fitzgerald         "#,
137742bba452SNick Fitzgerald             &formats.nullary,
137842bba452SNick Fitzgerald         )
1379f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
138042bba452SNick Fitzgerald     );
138142bba452SNick Fitzgerald 
138242bba452SNick Fitzgerald     ig.push(
138342bba452SNick Fitzgerald         Inst::new(
138442bba452SNick Fitzgerald             "get_stack_pointer",
138542bba452SNick Fitzgerald             r#"
138642bba452SNick Fitzgerald         Get the address in the stack pointer register.
138742bba452SNick Fitzgerald         "#,
138842bba452SNick Fitzgerald             &formats.nullary,
138942bba452SNick Fitzgerald         )
1390f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
139142bba452SNick Fitzgerald     );
139242bba452SNick Fitzgerald 
139342bba452SNick Fitzgerald     ig.push(
139442bba452SNick Fitzgerald         Inst::new(
139542bba452SNick Fitzgerald             "get_return_address",
139642bba452SNick Fitzgerald             r#"
139742bba452SNick Fitzgerald         Get the PC where this function will transfer control to when it returns.
139842bba452SNick Fitzgerald 
139942bba452SNick Fitzgerald         Usage of this instruction requires setting `preserve_frame_pointers` to `true`.
140042bba452SNick Fitzgerald         "#,
140142bba452SNick Fitzgerald             &formats.nullary,
140242bba452SNick Fitzgerald         )
1403f8771416SJamey Sharp         .operands_out(vec![Operand::new("addr", iAddr)]),
140442bba452SNick Fitzgerald     );
140542bba452SNick Fitzgerald 
140686430abcSBenjamin Bouvier     ig.push(
140786430abcSBenjamin Bouvier         Inst::new(
14084c01ee2fSChris Fallin             "get_exception_handler_address",
14094c01ee2fSChris Fallin             r#"
14104c01ee2fSChris Fallin         Get the handler PC for the given exceptional edge for an
14114c01ee2fSChris Fallin         exception return from the given `try_call`-terminated block.
14124c01ee2fSChris Fallin 
14134c01ee2fSChris Fallin         This instruction provides the PC for the handler resume point,
14144c01ee2fSChris Fallin         as defined by the exception-handling aspect of the given
14154c01ee2fSChris Fallin         callee ABI, for a return from the given calling block.  It can
14164c01ee2fSChris Fallin         be used when the exception unwind mechanism requires manual
14174c01ee2fSChris Fallin         plumbing for this information which must be set up before the call
14184c01ee2fSChris Fallin         itself: for example, if the resume address needs to be stored in
14194c01ee2fSChris Fallin         some context structure for a runtime to resume to on error.
14204c01ee2fSChris Fallin 
14214c01ee2fSChris Fallin         The given caller block must end in a `try_call` and the given
14224c01ee2fSChris Fallin         exception-handling block must be one of its exceptional
14234c01ee2fSChris Fallin         successors in the associated exception-handling table. The
14244c01ee2fSChris Fallin         returned PC is *only* valid to resume to when the `try_call`
14254c01ee2fSChris Fallin         is on the stack having called the callee; in other words, when
14264c01ee2fSChris Fallin         a normal exception unwinder might otherwise resume to that
14274c01ee2fSChris Fallin         handler.
14284c01ee2fSChris Fallin         "#,
14294c01ee2fSChris Fallin             &formats.exception_handler_address,
14304c01ee2fSChris Fallin         )
14314c01ee2fSChris Fallin         .operands_in(vec![
14324c01ee2fSChris Fallin             Operand::new("block", &entities.raw_block),
14334c01ee2fSChris Fallin             Operand::new("index", &imm.imm64),
14344c01ee2fSChris Fallin         ])
14354c01ee2fSChris Fallin         .operands_out(vec![Operand::new("addr", iAddr)]),
14364c01ee2fSChris Fallin     );
14374c01ee2fSChris Fallin 
14384c01ee2fSChris Fallin     ig.push(
14394c01ee2fSChris Fallin         Inst::new(
144086430abcSBenjamin Bouvier             "iconst",
144186430abcSBenjamin Bouvier             r#"
144286430abcSBenjamin Bouvier         Integer constant.
144386430abcSBenjamin Bouvier 
144486430abcSBenjamin Bouvier         Create a scalar integer SSA value with an immediate constant value, or
144586430abcSBenjamin Bouvier         an integer vector where all the lanes have the same value.
144686430abcSBenjamin Bouvier         "#,
14470243b642SBenjamin Bouvier             &formats.unary_imm,
144886430abcSBenjamin Bouvier         )
1449f8771416SJamey Sharp         .operands_in(vec![Operand::new("N", &imm.imm64)])
1450f8771416SJamey Sharp         .operands_out(vec![
145190ac295eSAlex Crichton             Operand::new("a", NarrowInt).with_doc("A constant integer scalar or vector value"),
1452f8771416SJamey Sharp         ]),
145386430abcSBenjamin Bouvier     );
145486430abcSBenjamin Bouvier 
145586430abcSBenjamin Bouvier     ig.push(
145686430abcSBenjamin Bouvier         Inst::new(
145741eca60bSbeetrees             "f16const",
145841eca60bSbeetrees             r#"
145941eca60bSbeetrees         Floating point constant.
146041eca60bSbeetrees 
146141eca60bSbeetrees         Create a `f16` SSA value with an immediate constant value.
146241eca60bSbeetrees         "#,
146341eca60bSbeetrees             &formats.unary_ieee16,
146441eca60bSbeetrees         )
146541eca60bSbeetrees         .operands_in(vec![Operand::new("N", &imm.ieee16)])
146641eca60bSbeetrees         .operands_out(vec![
146790ac295eSAlex Crichton             Operand::new("a", f16_).with_doc("A constant f16 scalar value"),
146841eca60bSbeetrees         ]),
146941eca60bSbeetrees     );
147041eca60bSbeetrees 
147141eca60bSbeetrees     ig.push(
147241eca60bSbeetrees         Inst::new(
147386430abcSBenjamin Bouvier             "f32const",
147486430abcSBenjamin Bouvier             r#"
147586430abcSBenjamin Bouvier         Floating point constant.
147686430abcSBenjamin Bouvier 
1477062ed8f6SBenjamin Bouvier         Create a `f32` SSA value with an immediate constant value.
147886430abcSBenjamin Bouvier         "#,
14790243b642SBenjamin Bouvier             &formats.unary_ieee32,
148086430abcSBenjamin Bouvier         )
1481f8771416SJamey Sharp         .operands_in(vec![Operand::new("N", &imm.ieee32)])
1482f8771416SJamey Sharp         .operands_out(vec![
148390ac295eSAlex Crichton             Operand::new("a", f32_).with_doc("A constant f32 scalar value"),
1484f8771416SJamey Sharp         ]),
148586430abcSBenjamin Bouvier     );
148686430abcSBenjamin Bouvier 
148786430abcSBenjamin Bouvier     ig.push(
148886430abcSBenjamin Bouvier         Inst::new(
148986430abcSBenjamin Bouvier             "f64const",
149086430abcSBenjamin Bouvier             r#"
149186430abcSBenjamin Bouvier         Floating point constant.
149286430abcSBenjamin Bouvier 
1493062ed8f6SBenjamin Bouvier         Create a `f64` SSA value with an immediate constant value.
149486430abcSBenjamin Bouvier         "#,
14950243b642SBenjamin Bouvier             &formats.unary_ieee64,
149686430abcSBenjamin Bouvier         )
1497f8771416SJamey Sharp         .operands_in(vec![Operand::new("N", &imm.ieee64)])
1498f8771416SJamey Sharp         .operands_out(vec![
149990ac295eSAlex Crichton             Operand::new("a", f64_).with_doc("A constant f64 scalar value"),
1500f8771416SJamey Sharp         ]),
150186430abcSBenjamin Bouvier     );
150286430abcSBenjamin Bouvier 
1503407d24c0SAndrew Brown     ig.push(
1504407d24c0SAndrew Brown         Inst::new(
150541eca60bSbeetrees             "f128const",
150641eca60bSbeetrees             r#"
150741eca60bSbeetrees         Floating point constant.
150841eca60bSbeetrees 
150941eca60bSbeetrees         Create a `f128` SSA value with an immediate constant value.
151041eca60bSbeetrees         "#,
151141eca60bSbeetrees             &formats.unary_const,
151241eca60bSbeetrees         )
15138a23cc74SNick Fitzgerald         .operands_in(vec![Operand::new("N", &entities.pool_constant)])
151441eca60bSbeetrees         .operands_out(vec![
151590ac295eSAlex Crichton             Operand::new("a", f128_).with_doc("A constant f128 scalar value"),
151641eca60bSbeetrees         ]),
151741eca60bSbeetrees     );
151841eca60bSbeetrees 
151941eca60bSbeetrees     ig.push(
152041eca60bSbeetrees         Inst::new(
1521407d24c0SAndrew Brown             "vconst",
1522407d24c0SAndrew Brown             r#"
1523407d24c0SAndrew Brown         SIMD vector constant.
1524407d24c0SAndrew Brown 
1525407d24c0SAndrew Brown         Construct a vector with the given immediate bytes.
1526407d24c0SAndrew Brown         "#,
15270243b642SBenjamin Bouvier             &formats.unary_const,
1528407d24c0SAndrew Brown         )
152990ac295eSAlex Crichton         .operands_in(vec![
15308a23cc74SNick Fitzgerald             Operand::new("N", &entities.pool_constant)
153190ac295eSAlex Crichton                 .with_doc("The 16 immediate bytes of a 128-bit vector"),
153290ac295eSAlex Crichton         ])
1533f8771416SJamey Sharp         .operands_out(vec![
153490ac295eSAlex Crichton             Operand::new("a", TxN).with_doc("A constant vector value"),
1535f8771416SJamey Sharp         ]),
1536407d24c0SAndrew Brown     );
1537407d24c0SAndrew Brown 
1538af1499ceSAndrew Brown     let Tx16 = &TypeVar::new(
1539af1499ceSAndrew Brown         "Tx16",
1540af1499ceSAndrew Brown         "A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \
1541af1499ceSAndrew Brown          lane counts and widths",
1542af1499ceSAndrew Brown         TypeSetBuilder::new()
1543af1499ceSAndrew Brown             .ints(8..8)
1544af1499ceSAndrew Brown             .simd_lanes(16..16)
1545af1499ceSAndrew Brown             .includes_scalars(false)
1546af1499ceSAndrew Brown             .build(),
1547af1499ceSAndrew Brown     );
1548af1499ceSAndrew Brown 
1549af1499ceSAndrew Brown     ig.push(
1550af1499ceSAndrew Brown         Inst::new(
1551af1499ceSAndrew Brown             "shuffle",
1552af1499ceSAndrew Brown             r#"
1553af1499ceSAndrew Brown         SIMD vector shuffle.
1554af1499ceSAndrew Brown 
1555af1499ceSAndrew Brown         Shuffle two vectors using the given immediate bytes. For each of the 16 bytes of the
1556af1499ceSAndrew Brown         immediate, a value i of 0-15 selects the i-th element of the first vector and a value i of
1557af1499ceSAndrew Brown         16-31 selects the (i-16)th element of the second vector. Immediate values outside of the
15587956dc6bSAlex Crichton         0-31 range are not valid.
1559af1499ceSAndrew Brown         "#,
15600243b642SBenjamin Bouvier             &formats.shuffle,
1561af1499ceSAndrew Brown         )
1562f8771416SJamey Sharp         .operands_in(vec![
1563f8771416SJamey Sharp             Operand::new("a", Tx16).with_doc("A vector value"),
1564f8771416SJamey Sharp             Operand::new("b", Tx16).with_doc("A vector value"),
15658a23cc74SNick Fitzgerald             Operand::new("mask", &entities.uimm128)
1566f8771416SJamey Sharp                 .with_doc("The 16 immediate bytes used for selecting the elements to shuffle"),
1567f8771416SJamey Sharp         ])
1568f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Tx16).with_doc("A vector value")]),
1569af1499ceSAndrew Brown     );
1570af1499ceSAndrew Brown 
1571d9277f24SBenjamin Bouvier     ig.push(Inst::new(
157286430abcSBenjamin Bouvier         "nop",
157386430abcSBenjamin Bouvier         r#"
15740243b642SBenjamin Bouvier         Just a dummy instruction.
157586430abcSBenjamin Bouvier 
15760243b642SBenjamin Bouvier         Note: this doesn't compile to a machine code nop.
157786430abcSBenjamin Bouvier         "#,
15780243b642SBenjamin Bouvier         &formats.nullary,
1579d9277f24SBenjamin Bouvier     ));
158086430abcSBenjamin Bouvier 
158186430abcSBenjamin Bouvier     ig.push(
158286430abcSBenjamin Bouvier         Inst::new(
158386430abcSBenjamin Bouvier             "select",
158486430abcSBenjamin Bouvier             r#"
158586430abcSBenjamin Bouvier         Conditional select.
158686430abcSBenjamin Bouvier 
158707518dfdSAlex Crichton         This instruction selects whole values. Use `bitselect` to choose each
158807518dfdSAlex Crichton         bit according to a mask.
158986430abcSBenjamin Bouvier         "#,
15900243b642SBenjamin Bouvier             &formats.ternary,
159186430abcSBenjamin Bouvier         )
1592f8771416SJamey Sharp         .operands_in(vec![
1593f8771416SJamey Sharp             Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
1594f8771416SJamey Sharp             Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1595f8771416SJamey Sharp             Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1596f8771416SJamey Sharp         ])
1597f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Any)]),
159886430abcSBenjamin Bouvier     );
159986430abcSBenjamin Bouvier 
160086430abcSBenjamin Bouvier     ig.push(
160186430abcSBenjamin Bouvier         Inst::new(
1602ec12415bSTrevor Elliott             "select_spectre_guard",
1603e694fb13SChris Fallin             r#"
1604e694fb13SChris Fallin             Conditional select intended for Spectre guards.
1605e694fb13SChris Fallin 
1606ec12415bSTrevor Elliott             This operation is semantically equivalent to a select instruction.
1607f59b3246SJamey Sharp             However, this instruction prohibits all speculation on the
1608f59b3246SJamey Sharp             controlling value when determining which input to use as the result.
1609f59b3246SJamey Sharp             As such, it is suitable for use in Spectre guards.
1610f59b3246SJamey Sharp 
1611f59b3246SJamey Sharp             For example, on a target which may speculatively execute branches,
1612f59b3246SJamey Sharp             the lowering of this instruction is guaranteed to not conditionally
1613f59b3246SJamey Sharp             branch. Instead it will typically lower to a conditional move
1614f59b3246SJamey Sharp             instruction. (No Spectre-vulnerable processors are known to perform
1615f59b3246SJamey Sharp             value speculation on conditional move instructions.)
1616f59b3246SJamey Sharp 
1617f59b3246SJamey Sharp             Ensure that the instruction you're trying to protect from Spectre
1618f59b3246SJamey Sharp             attacks has a data dependency on the result of this instruction.
1619f59b3246SJamey Sharp             That prevents an out-of-order CPU from evaluating that instruction
1620f59b3246SJamey Sharp             until the result of this one is known, which in turn will be blocked
1621f59b3246SJamey Sharp             until the controlling value is known.
1622f59b3246SJamey Sharp 
1623f59b3246SJamey Sharp             Typical usage is to use a bounds-check as the controlling value,
1624f59b3246SJamey Sharp             and select between either a null pointer if the bounds-check
1625f59b3246SJamey Sharp             fails, or an in-bounds address otherwise, so that dereferencing
1626f59b3246SJamey Sharp             the resulting address with a load or store instruction will trap if
1627f59b3246SJamey Sharp             the bounds-check failed. When this instruction is used in this way,
1628f59b3246SJamey Sharp             any microarchitectural side effects of the memory access will only
1629f59b3246SJamey Sharp             occur after the bounds-check finishes, which ensures that no Spectre
1630f59b3246SJamey Sharp             vulnerability will exist.
1631f59b3246SJamey Sharp 
1632f59b3246SJamey Sharp             Optimization opportunities for this instruction are limited compared
1633f59b3246SJamey Sharp             to a normal select instruction, but it is allowed to be replaced
1634f59b3246SJamey Sharp             by other values which are functionally equivalent as long as doing
1635f59b3246SJamey Sharp             so does not introduce any new opportunities to speculate on the
1636f59b3246SJamey Sharp             controlling value.
1637e694fb13SChris Fallin             "#,
1638ec12415bSTrevor Elliott             &formats.ternary,
1639e694fb13SChris Fallin         )
1640f8771416SJamey Sharp         .operands_in(vec![
1641f8771416SJamey Sharp             Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
1642f8771416SJamey Sharp             Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1643f8771416SJamey Sharp             Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1644f8771416SJamey Sharp         ])
1645f59b3246SJamey Sharp         .operands_out(vec![Operand::new("a", Any)]),
1646e694fb13SChris Fallin     );
1647e694fb13SChris Fallin 
1648b927c555SAndrew Brown     ig.push(
1649b927c555SAndrew Brown         Inst::new(
1650b927c555SAndrew Brown             "bitselect",
1651b927c555SAndrew Brown             r#"
1652b927c555SAndrew Brown         Conditional select of bits.
1653b927c555SAndrew Brown 
1654b927c555SAndrew Brown         For each bit in `c`, this instruction selects the corresponding bit from `x` if the bit
1655*58633f35Stsudzuki         in `c` is 1 and the corresponding bit from `y` if the bit in `c` is 0. See also:
165607518dfdSAlex Crichton         `select`.
1657b927c555SAndrew Brown         "#,
16580243b642SBenjamin Bouvier             &formats.ternary,
1659b927c555SAndrew Brown         )
1660f8771416SJamey Sharp         .operands_in(vec![
1661f8771416SJamey Sharp             Operand::new("c", Any).with_doc("Controlling value to test"),
1662f8771416SJamey Sharp             Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1663f8771416SJamey Sharp             Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1664f8771416SJamey Sharp         ])
1665f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Any)]),
1666b927c555SAndrew Brown     );
1667b927c555SAndrew Brown 
16688bb183f1SAlex Crichton     ig.push(
16698bb183f1SAlex Crichton         Inst::new(
16707ac4b818SJimmy Brisson             "blendv",
16718bb183f1SAlex Crichton             r#"
16728bb183f1SAlex Crichton         A bitselect-lookalike instruction except with the semantics of
16738bb183f1SAlex Crichton         `blendv`-related instructions on x86.
16748bb183f1SAlex Crichton 
16758bb183f1SAlex Crichton         This instruction will use the top bit of each lane in `c`, the condition
16768bb183f1SAlex Crichton         mask. If the bit is 1 then the corresponding lane from `x` is chosen.
16778bb183f1SAlex Crichton         Otherwise the corresponding lane from `y` is chosen.
16788bb183f1SAlex Crichton 
16798bb183f1SAlex Crichton             "#,
16808bb183f1SAlex Crichton             &formats.ternary,
16818bb183f1SAlex Crichton         )
1682f8771416SJamey Sharp         .operands_in(vec![
1683f8771416SJamey Sharp             Operand::new("c", Any).with_doc("Controlling value to test"),
1684f8771416SJamey Sharp             Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1685f8771416SJamey Sharp             Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1686f8771416SJamey Sharp         ])
1687f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Any)]),
16888bb183f1SAlex Crichton     );
16898bb183f1SAlex Crichton 
1690186effc4SAndrew Brown     ig.push(
1691186effc4SAndrew Brown         Inst::new(
1692186effc4SAndrew Brown             "vany_true",
1693186effc4SAndrew Brown             r#"
1694186effc4SAndrew Brown         Reduce a vector to a scalar boolean.
1695186effc4SAndrew Brown 
1696186effc4SAndrew Brown         Return a scalar boolean true if any lane in ``a`` is non-zero, false otherwise.
1697186effc4SAndrew Brown         "#,
1698186effc4SAndrew Brown             &formats.unary,
1699186effc4SAndrew Brown         )
1700f8771416SJamey Sharp         .operands_in(vec![Operand::new("a", TxN)])
1701f8771416SJamey Sharp         .operands_out(vec![Operand::new("s", i8)]),
1702186effc4SAndrew Brown     );
1703186effc4SAndrew Brown 
1704879ccf87SAndrew Brown     ig.push(
1705879ccf87SAndrew Brown         Inst::new(
1706879ccf87SAndrew Brown             "vall_true",
1707879ccf87SAndrew Brown             r#"
1708879ccf87SAndrew Brown         Reduce a vector to a scalar boolean.
1709879ccf87SAndrew Brown 
1710879ccf87SAndrew Brown         Return a scalar boolean true if all lanes in ``i`` are non-zero, false otherwise.
1711879ccf87SAndrew Brown         "#,
1712879ccf87SAndrew Brown             &formats.unary,
1713879ccf87SAndrew Brown         )
1714f8771416SJamey Sharp         .operands_in(vec![Operand::new("a", TxN)])
1715f8771416SJamey Sharp         .operands_out(vec![Operand::new("s", i8)]),
1716879ccf87SAndrew Brown     );
1717879ccf87SAndrew Brown 
171827029420SJulian Seward     ig.push(
171927029420SJulian Seward         Inst::new(
172027029420SJulian Seward             "vhigh_bits",
172127029420SJulian Seward             r#"
172227029420SJulian Seward         Reduce a vector to a scalar integer.
172327029420SJulian Seward 
172427029420SJulian Seward         Return a scalar integer, consisting of the concatenation of the most significant bit
172527029420SJulian Seward         of each lane of ``a``.
172627029420SJulian Seward         "#,
172727029420SJulian Seward             &formats.unary,
172827029420SJulian Seward         )
1729f8771416SJamey Sharp         .operands_in(vec![Operand::new("a", TxN)])
1730d8db07faSAfonso Bordado         .operands_out(vec![Operand::new("x", NarrowInt)]),
173127029420SJulian Seward     );
173227029420SJulian Seward 
173386430abcSBenjamin Bouvier     ig.push(
173486430abcSBenjamin Bouvier         Inst::new(
173586430abcSBenjamin Bouvier             "icmp",
173686430abcSBenjamin Bouvier             r#"
173786430abcSBenjamin Bouvier         Integer comparison.
173886430abcSBenjamin Bouvier 
173986430abcSBenjamin Bouvier         The condition code determines if the operands are interpreted as signed
174086430abcSBenjamin Bouvier         or unsigned integers.
174186430abcSBenjamin Bouvier 
17429f3c5b96SUjjwal Sharma         | Signed | Unsigned | Condition             |
17439f3c5b96SUjjwal Sharma         |--------|----------|-----------------------|
17449f3c5b96SUjjwal Sharma         | eq     | eq       | Equal                 |
17459f3c5b96SUjjwal Sharma         | ne     | ne       | Not equal             |
17469f3c5b96SUjjwal Sharma         | slt    | ult      | Less than             |
17479f3c5b96SUjjwal Sharma         | sge    | uge      | Greater than or equal |
17489f3c5b96SUjjwal Sharma         | sgt    | ugt      | Greater than          |
17499f3c5b96SUjjwal Sharma         | sle    | ule      | Less than or equal    |
175086430abcSBenjamin Bouvier 
175132a7593cSTrevor Elliott         When this instruction compares integer vectors, it returns a vector of
175232a7593cSTrevor Elliott         lane-wise comparisons.
175391e36f34SKarl Meakin 
175491e36f34SKarl Meakin         When comparing scalars, the result is:
175591e36f34SKarl Meakin             - `1` if the condition holds.
175691e36f34SKarl Meakin             - `0` if the condition does not hold.
175791e36f34SKarl Meakin 
175891e36f34SKarl Meakin         When comparing vectors, the result is:
175991e36f34SKarl Meakin             - `-1` (i.e. all ones) in each lane where the condition holds.
176091e36f34SKarl Meakin             - `0` in each lane where the condition does not hold.
176186430abcSBenjamin Bouvier         "#,
17620243b642SBenjamin Bouvier             &formats.int_compare,
176386430abcSBenjamin Bouvier         )
1764f8771416SJamey Sharp         .operands_in(vec![
1765f8771416SJamey Sharp             Operand::new("Cond", &imm.intcc),
1766f8771416SJamey Sharp             Operand::new("x", Int),
1767f8771416SJamey Sharp             Operand::new("y", Int),
1768f8771416SJamey Sharp         ])
176978dbe93fSTrevor Elliott         .operands_out(vec![Operand::new("a", &Int.as_truthy())]),
177086430abcSBenjamin Bouvier     );
177186430abcSBenjamin Bouvier 
177286430abcSBenjamin Bouvier     ig.push(
177386430abcSBenjamin Bouvier         Inst::new(
177486430abcSBenjamin Bouvier             "icmp_imm",
177586430abcSBenjamin Bouvier             r#"
177686430abcSBenjamin Bouvier         Compare scalar integer to a constant.
177786430abcSBenjamin Bouvier 
1778062ed8f6SBenjamin Bouvier         This is the same as the `icmp` instruction, except one operand is
1779e577a76cSAfonso Bordado         a sign extended 64 bit immediate constant.
178086430abcSBenjamin Bouvier 
1781062ed8f6SBenjamin Bouvier         This instruction can only compare scalars. Use `icmp` for
178286430abcSBenjamin Bouvier         lane-wise vector comparisons.
178386430abcSBenjamin Bouvier         "#,
17840243b642SBenjamin Bouvier             &formats.int_compare_imm,
178586430abcSBenjamin Bouvier         )
1786f8771416SJamey Sharp         .operands_in(vec![
1787f8771416SJamey Sharp             Operand::new("Cond", &imm.intcc),
1788f8771416SJamey Sharp             Operand::new("x", iB),
1789f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
1790f8771416SJamey Sharp         ])
1791f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", i8)]),
179286430abcSBenjamin Bouvier     );
179386430abcSBenjamin Bouvier 
179486430abcSBenjamin Bouvier     ig.push(
179586430abcSBenjamin Bouvier         Inst::new(
179686430abcSBenjamin Bouvier             "iadd",
179786430abcSBenjamin Bouvier             r#"
1798062ed8f6SBenjamin Bouvier         Wrapping integer addition: `a := x + y \pmod{2^B}`.
179986430abcSBenjamin Bouvier 
180086430abcSBenjamin Bouvier         This instruction does not depend on the signed/unsigned interpretation
180186430abcSBenjamin Bouvier         of the operands.
180286430abcSBenjamin Bouvier         "#,
18030243b642SBenjamin Bouvier             &formats.binary,
180486430abcSBenjamin Bouvier         )
1805f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
1806f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
180786430abcSBenjamin Bouvier     );
180886430abcSBenjamin Bouvier 
180986430abcSBenjamin Bouvier     ig.push(
181086430abcSBenjamin Bouvier         Inst::new(
181186430abcSBenjamin Bouvier             "isub",
181286430abcSBenjamin Bouvier             r#"
1813062ed8f6SBenjamin Bouvier         Wrapping integer subtraction: `a := x - y \pmod{2^B}`.
181486430abcSBenjamin Bouvier 
181586430abcSBenjamin Bouvier         This instruction does not depend on the signed/unsigned interpretation
181686430abcSBenjamin Bouvier         of the operands.
181786430abcSBenjamin Bouvier         "#,
18180243b642SBenjamin Bouvier             &formats.binary,
181986430abcSBenjamin Bouvier         )
1820f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
1821f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
182286430abcSBenjamin Bouvier     );
182386430abcSBenjamin Bouvier 
182486430abcSBenjamin Bouvier     ig.push(
182586430abcSBenjamin Bouvier         Inst::new(
1826ba393afdSAndrew Brown             "ineg",
1827ba393afdSAndrew Brown             r#"
1828ba393afdSAndrew Brown         Integer negation: `a := -x \pmod{2^B}`.
1829ba393afdSAndrew Brown         "#,
18300243b642SBenjamin Bouvier             &formats.unary,
1831ba393afdSAndrew Brown         )
1832f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int)])
1833f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
1834ba393afdSAndrew Brown     );
1835ba393afdSAndrew Brown 
1836ba393afdSAndrew Brown     ig.push(
1837ba393afdSAndrew Brown         Inst::new(
183826bdf9c3SAndrew Brown             "iabs",
183926bdf9c3SAndrew Brown             r#"
184026bdf9c3SAndrew Brown         Integer absolute value with wrapping: `a := |x|`.
184126bdf9c3SAndrew Brown         "#,
184226bdf9c3SAndrew Brown             &formats.unary,
184326bdf9c3SAndrew Brown         )
1844f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int)])
1845f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
184626bdf9c3SAndrew Brown     );
184726bdf9c3SAndrew Brown 
184826bdf9c3SAndrew Brown     ig.push(
184926bdf9c3SAndrew Brown         Inst::new(
185086430abcSBenjamin Bouvier             "imul",
185186430abcSBenjamin Bouvier             r#"
1852062ed8f6SBenjamin Bouvier         Wrapping integer multiplication: `a := x y \pmod{2^B}`.
185386430abcSBenjamin Bouvier 
185486430abcSBenjamin Bouvier         This instruction does not depend on the signed/unsigned interpretation
1855630cb3eeSAndrew Brown         of the operands.
185686430abcSBenjamin Bouvier 
185786430abcSBenjamin Bouvier         Polymorphic over all integer types (vector and scalar).
185886430abcSBenjamin Bouvier         "#,
18590243b642SBenjamin Bouvier             &formats.binary,
186086430abcSBenjamin Bouvier         )
1861f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
1862f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
186386430abcSBenjamin Bouvier     );
186486430abcSBenjamin Bouvier 
186586430abcSBenjamin Bouvier     ig.push(
186686430abcSBenjamin Bouvier         Inst::new(
186786430abcSBenjamin Bouvier             "umulhi",
186886430abcSBenjamin Bouvier             r#"
186986430abcSBenjamin Bouvier         Unsigned integer multiplication, producing the high half of a
187086430abcSBenjamin Bouvier         double-length result.
187186430abcSBenjamin Bouvier 
1872562947c6Sdheaton-arm         Polymorphic over all integer types (vector and scalar).
187386430abcSBenjamin Bouvier         "#,
18740243b642SBenjamin Bouvier             &formats.binary,
187586430abcSBenjamin Bouvier         )
1876f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
1877f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
187886430abcSBenjamin Bouvier     );
187986430abcSBenjamin Bouvier 
188086430abcSBenjamin Bouvier     ig.push(
188186430abcSBenjamin Bouvier         Inst::new(
188286430abcSBenjamin Bouvier             "smulhi",
188386430abcSBenjamin Bouvier             r#"
188486430abcSBenjamin Bouvier         Signed integer multiplication, producing the high half of a
188586430abcSBenjamin Bouvier         double-length result.
188686430abcSBenjamin Bouvier 
18872f0ce4c8Sdheaton-arm         Polymorphic over all integer types (vector and scalar).
188886430abcSBenjamin Bouvier         "#,
18890243b642SBenjamin Bouvier             &formats.binary,
189086430abcSBenjamin Bouvier         )
1891f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int), Operand::new("y", Int)])
1892f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
189386430abcSBenjamin Bouvier     );
189486430abcSBenjamin Bouvier 
189598f1ac78SAnton Kirilov     let I16or32 = &TypeVar::new(
189698f1ac78SAnton Kirilov         "I16or32",
18976d9ab206SAfonso Bordado         "A vector integer type with 16- or 32-bit numbers",
189898f1ac78SAnton Kirilov         TypeSetBuilder::new().ints(16..32).simd_lanes(4..8).build(),
189998f1ac78SAnton Kirilov     );
190098f1ac78SAnton Kirilov 
190198f1ac78SAnton Kirilov     ig.push(
190298f1ac78SAnton Kirilov         Inst::new(
190398f1ac78SAnton Kirilov             "sqmul_round_sat",
190498f1ac78SAnton Kirilov             r#"
190598f1ac78SAnton Kirilov         Fixed-point multiplication of numbers in the QN format, where N + 1
190698f1ac78SAnton Kirilov         is the number bitwidth:
19072d1c0abdSJulian Eager         `a := signed_saturate((x * y + (1 << (Q - 1))) >> Q)`
190898f1ac78SAnton Kirilov 
19096d9ab206SAfonso Bordado         Polymorphic over all integer vector types with 16- or 32-bit numbers.
191098f1ac78SAnton Kirilov         "#,
191198f1ac78SAnton Kirilov             &formats.binary,
191298f1ac78SAnton Kirilov         )
1913f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I16or32), Operand::new("y", I16or32)])
1914f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I16or32)]),
191598f1ac78SAnton Kirilov     );
191698f1ac78SAnton Kirilov 
19178bb183f1SAlex Crichton     ig.push(
19188bb183f1SAlex Crichton         Inst::new(
19198bb183f1SAlex Crichton             "x86_pmulhrsw",
19208bb183f1SAlex Crichton             r#"
19218bb183f1SAlex Crichton         A similar instruction to `sqmul_round_sat` except with the semantics
19228bb183f1SAlex Crichton         of x86's `pmulhrsw` instruction.
19238bb183f1SAlex Crichton 
19248bb183f1SAlex Crichton         This is the same as `sqmul_round_sat` except when both input lanes are
19258bb183f1SAlex Crichton         `i16::MIN`.
19268bb183f1SAlex Crichton         "#,
19278bb183f1SAlex Crichton             &formats.binary,
19288bb183f1SAlex Crichton         )
1929f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I16or32), Operand::new("y", I16or32)])
1930f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I16or32)]),
19318bb183f1SAlex Crichton     );
19328bb183f1SAlex Crichton 
19337c5a56b8SChris Fallin     // Integer division and remainder are scalar-only; most
19347c5a56b8SChris Fallin     // hardware does not directly support vector integer division.
19357c5a56b8SChris Fallin 
193686430abcSBenjamin Bouvier     ig.push(
193786430abcSBenjamin Bouvier         Inst::new(
193886430abcSBenjamin Bouvier             "udiv",
193986430abcSBenjamin Bouvier             r#"
1940062ed8f6SBenjamin Bouvier         Unsigned integer division: `a := \lfloor {x \over y} \rfloor`.
194186430abcSBenjamin Bouvier 
194286430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
194386430abcSBenjamin Bouvier         "#,
19440243b642SBenjamin Bouvier             &formats.binary,
194586430abcSBenjamin Bouvier         )
1946f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
1947f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)])
1948b5692db7STrevor Elliott         .can_trap()
1949b5692db7STrevor Elliott         .side_effects_idempotent(),
195086430abcSBenjamin Bouvier     );
195186430abcSBenjamin Bouvier 
195286430abcSBenjamin Bouvier     ig.push(
195386430abcSBenjamin Bouvier         Inst::new(
195486430abcSBenjamin Bouvier             "sdiv",
195586430abcSBenjamin Bouvier             r#"
1956062ed8f6SBenjamin Bouvier         Signed integer division rounded toward zero: `a := sign(xy)
195786430abcSBenjamin Bouvier         \lfloor {|x| \over |y|}\rfloor`.
195886430abcSBenjamin Bouvier 
195986430abcSBenjamin Bouvier         This operation traps if the divisor is zero, or if the result is not
1960062ed8f6SBenjamin Bouvier         representable in `B` bits two's complement. This only happens
1961062ed8f6SBenjamin Bouvier         when `x = -2^{B-1}, y = -1`.
196286430abcSBenjamin Bouvier         "#,
19630243b642SBenjamin Bouvier             &formats.binary,
196486430abcSBenjamin Bouvier         )
1965f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
1966f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)])
1967b5692db7STrevor Elliott         .can_trap()
1968b5692db7STrevor Elliott         .side_effects_idempotent(),
196986430abcSBenjamin Bouvier     );
197086430abcSBenjamin Bouvier 
197186430abcSBenjamin Bouvier     ig.push(
197286430abcSBenjamin Bouvier         Inst::new(
197386430abcSBenjamin Bouvier             "urem",
197486430abcSBenjamin Bouvier             r#"
197586430abcSBenjamin Bouvier         Unsigned integer remainder.
197686430abcSBenjamin Bouvier 
197786430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
197886430abcSBenjamin Bouvier         "#,
19790243b642SBenjamin Bouvier             &formats.binary,
198086430abcSBenjamin Bouvier         )
1981f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
1982f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)])
1983b5692db7STrevor Elliott         .can_trap()
1984b5692db7STrevor Elliott         .side_effects_idempotent(),
198586430abcSBenjamin Bouvier     );
198686430abcSBenjamin Bouvier 
198786430abcSBenjamin Bouvier     ig.push(
198886430abcSBenjamin Bouvier         Inst::new(
198986430abcSBenjamin Bouvier             "srem",
199086430abcSBenjamin Bouvier             r#"
199186430abcSBenjamin Bouvier         Signed integer remainder. The result has the sign of the dividend.
199286430abcSBenjamin Bouvier 
199386430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
199486430abcSBenjamin Bouvier         "#,
19950243b642SBenjamin Bouvier             &formats.binary,
199686430abcSBenjamin Bouvier         )
1997f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
1998f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)])
1999b5692db7STrevor Elliott         .can_trap()
2000b5692db7STrevor Elliott         .side_effects_idempotent(),
200186430abcSBenjamin Bouvier     );
200286430abcSBenjamin Bouvier 
200386430abcSBenjamin Bouvier     ig.push(
200486430abcSBenjamin Bouvier         Inst::new(
200586430abcSBenjamin Bouvier             "iadd_imm",
200686430abcSBenjamin Bouvier             r#"
200786430abcSBenjamin Bouvier         Add immediate integer.
200886430abcSBenjamin Bouvier 
2009e577a76cSAfonso Bordado         Same as `iadd`, but one operand is a sign extended 64 bit immediate constant.
201086430abcSBenjamin Bouvier 
201186430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
201286430abcSBenjamin Bouvier         types.
201386430abcSBenjamin Bouvier         "#,
20140dd77d36SAndrew Brown             &formats.binary_imm64,
201586430abcSBenjamin Bouvier         )
2016f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2017f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
201886430abcSBenjamin Bouvier     );
201986430abcSBenjamin Bouvier 
202086430abcSBenjamin Bouvier     ig.push(
202186430abcSBenjamin Bouvier         Inst::new(
202286430abcSBenjamin Bouvier             "imul_imm",
202386430abcSBenjamin Bouvier             r#"
202486430abcSBenjamin Bouvier         Integer multiplication by immediate constant.
202586430abcSBenjamin Bouvier 
2026e577a76cSAfonso Bordado         Same as `imul`, but one operand is a sign extended 64 bit immediate constant.
2027e577a76cSAfonso Bordado 
202886430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
202986430abcSBenjamin Bouvier         types.
203086430abcSBenjamin Bouvier         "#,
20310dd77d36SAndrew Brown             &formats.binary_imm64,
203286430abcSBenjamin Bouvier         )
2033f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2034f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
203586430abcSBenjamin Bouvier     );
203686430abcSBenjamin Bouvier 
203786430abcSBenjamin Bouvier     ig.push(
203886430abcSBenjamin Bouvier         Inst::new(
203986430abcSBenjamin Bouvier             "udiv_imm",
204086430abcSBenjamin Bouvier             r#"
204186430abcSBenjamin Bouvier         Unsigned integer division by an immediate constant.
204286430abcSBenjamin Bouvier 
2043e577a76cSAfonso Bordado         Same as `udiv`, but one operand is a zero extended 64 bit immediate constant.
2044e577a76cSAfonso Bordado 
204586430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
204686430abcSBenjamin Bouvier         "#,
20470dd77d36SAndrew Brown             &formats.binary_imm64,
204886430abcSBenjamin Bouvier         )
2049f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2050f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
205186430abcSBenjamin Bouvier     );
205286430abcSBenjamin Bouvier 
205386430abcSBenjamin Bouvier     ig.push(
205486430abcSBenjamin Bouvier         Inst::new(
205586430abcSBenjamin Bouvier             "sdiv_imm",
205686430abcSBenjamin Bouvier             r#"
205786430abcSBenjamin Bouvier         Signed integer division by an immediate constant.
205886430abcSBenjamin Bouvier 
2059e577a76cSAfonso Bordado         Same as `sdiv`, but one operand is a sign extended 64 bit immediate constant.
2060e577a76cSAfonso Bordado 
206186430abcSBenjamin Bouvier         This operation traps if the divisor is zero, or if the result is not
2062062ed8f6SBenjamin Bouvier         representable in `B` bits two's complement. This only happens
2063062ed8f6SBenjamin Bouvier         when `x = -2^{B-1}, Y = -1`.
206486430abcSBenjamin Bouvier         "#,
20650dd77d36SAndrew Brown             &formats.binary_imm64,
206686430abcSBenjamin Bouvier         )
2067f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2068f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
206986430abcSBenjamin Bouvier     );
207086430abcSBenjamin Bouvier 
207186430abcSBenjamin Bouvier     ig.push(
207286430abcSBenjamin Bouvier         Inst::new(
207386430abcSBenjamin Bouvier             "urem_imm",
207486430abcSBenjamin Bouvier             r#"
207586430abcSBenjamin Bouvier         Unsigned integer remainder with immediate divisor.
207686430abcSBenjamin Bouvier 
2077e577a76cSAfonso Bordado         Same as `urem`, but one operand is a zero extended 64 bit immediate constant.
2078e577a76cSAfonso Bordado 
207986430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
208086430abcSBenjamin Bouvier         "#,
20810dd77d36SAndrew Brown             &formats.binary_imm64,
208286430abcSBenjamin Bouvier         )
2083f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2084f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
208586430abcSBenjamin Bouvier     );
208686430abcSBenjamin Bouvier 
208786430abcSBenjamin Bouvier     ig.push(
208886430abcSBenjamin Bouvier         Inst::new(
208986430abcSBenjamin Bouvier             "srem_imm",
209086430abcSBenjamin Bouvier             r#"
209186430abcSBenjamin Bouvier         Signed integer remainder with immediate divisor.
209286430abcSBenjamin Bouvier 
2093e577a76cSAfonso Bordado         Same as `srem`, but one operand is a sign extended 64 bit immediate constant.
2094e577a76cSAfonso Bordado 
209586430abcSBenjamin Bouvier         This operation traps if the divisor is zero.
209686430abcSBenjamin Bouvier         "#,
20970dd77d36SAndrew Brown             &formats.binary_imm64,
209886430abcSBenjamin Bouvier         )
2099f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2100f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
210186430abcSBenjamin Bouvier     );
210286430abcSBenjamin Bouvier 
210386430abcSBenjamin Bouvier     ig.push(
210486430abcSBenjamin Bouvier         Inst::new(
210586430abcSBenjamin Bouvier             "irsub_imm",
210686430abcSBenjamin Bouvier             r#"
2107062ed8f6SBenjamin Bouvier         Immediate reverse wrapping subtraction: `a := Y - x \pmod{2^B}`.
210886430abcSBenjamin Bouvier 
2109e577a76cSAfonso Bordado         The immediate operand is a sign extended 64 bit constant.
2110e577a76cSAfonso Bordado 
2111062ed8f6SBenjamin Bouvier         Also works as integer negation when `Y = 0`. Use `iadd_imm`
211286430abcSBenjamin Bouvier         with a negative immediate operand for the reverse immediate
211386430abcSBenjamin Bouvier         subtraction.
211486430abcSBenjamin Bouvier 
211586430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
211686430abcSBenjamin Bouvier         types.
211786430abcSBenjamin Bouvier         "#,
21180dd77d36SAndrew Brown             &formats.binary_imm64,
211986430abcSBenjamin Bouvier         )
2120f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2121f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
212286430abcSBenjamin Bouvier     );
212386430abcSBenjamin Bouvier 
212486430abcSBenjamin Bouvier     ig.push(
212586430abcSBenjamin Bouvier         Inst::new(
2126ff987608SAlex Crichton             "sadd_overflow_cin",
212786430abcSBenjamin Bouvier             r#"
2128ff987608SAlex Crichton         Add signed integers with carry in and overflow out.
212986430abcSBenjamin Bouvier 
2130ff987608SAlex Crichton         Same as `sadd_overflow` with an additional carry input. The `c_in` type
2131ff987608SAlex Crichton         is interpreted as 1 if it's nonzero or 0 if it's zero.
213286430abcSBenjamin Bouvier         "#,
21330243b642SBenjamin Bouvier             &formats.ternary,
213486430abcSBenjamin Bouvier         )
2135f8771416SJamey Sharp         .operands_in(vec![
2136f8771416SJamey Sharp             Operand::new("x", iB),
2137f8771416SJamey Sharp             Operand::new("y", iB),
2138f8771416SJamey Sharp             Operand::new("c_in", i8).with_doc("Input carry flag"),
2139f8771416SJamey Sharp         ])
2140ff987608SAlex Crichton         .operands_out(vec![
2141ff987608SAlex Crichton             Operand::new("a", iB),
2142ff987608SAlex Crichton             Operand::new("c_out", i8).with_doc("Output carry flag"),
2143ff987608SAlex Crichton         ]),
214486430abcSBenjamin Bouvier     );
214586430abcSBenjamin Bouvier 
214686430abcSBenjamin Bouvier     ig.push(
214786430abcSBenjamin Bouvier         Inst::new(
2148ff987608SAlex Crichton             "uadd_overflow_cin",
214986430abcSBenjamin Bouvier             r#"
2150ff987608SAlex Crichton         Add unsigned integers with carry in and overflow out.
215186430abcSBenjamin Bouvier 
2152ff987608SAlex Crichton         Same as `uadd_overflow` with an additional carry input. The `c_in` type
2153ff987608SAlex Crichton         is interpreted as 1 if it's nonzero or 0 if it's zero.
215486430abcSBenjamin Bouvier         "#,
21550243b642SBenjamin Bouvier             &formats.ternary,
215686430abcSBenjamin Bouvier         )
2157f8771416SJamey Sharp         .operands_in(vec![
2158f8771416SJamey Sharp             Operand::new("x", iB),
2159f8771416SJamey Sharp             Operand::new("y", iB),
2160f8771416SJamey Sharp             Operand::new("c_in", i8).with_doc("Input carry flag"),
2161f8771416SJamey Sharp         ])
2162f8771416SJamey Sharp         .operands_out(vec![
2163f8771416SJamey Sharp             Operand::new("a", iB),
2164f8771416SJamey Sharp             Operand::new("c_out", i8).with_doc("Output carry flag"),
2165f8771416SJamey Sharp         ]),
216686430abcSBenjamin Bouvier     );
216786430abcSBenjamin Bouvier 
2168569089e4ST0b1-iOS     {
2169569089e4ST0b1-iOS         let of_out = Operand::new("of", i8).with_doc("Overflow flag");
2170569089e4ST0b1-iOS         ig.push(
2171569089e4ST0b1-iOS             Inst::new(
2172569089e4ST0b1-iOS                 "uadd_overflow",
2173569089e4ST0b1-iOS                 r#"
2174569089e4ST0b1-iOS             Add integers unsigned with overflow out.
2175569089e4ST0b1-iOS             ``of`` is set when the addition overflowed.
2176569089e4ST0b1-iOS             ```text
2177569089e4ST0b1-iOS                 a &= x + y \pmod 2^B \\
2178569089e4ST0b1-iOS                 of &= x+y >= 2^B
2179569089e4ST0b1-iOS             ```
2180569089e4ST0b1-iOS             Polymorphic over all scalar integer types, but does not support vector
2181569089e4ST0b1-iOS             types.
2182569089e4ST0b1-iOS             "#,
2183569089e4ST0b1-iOS                 &formats.binary,
2184569089e4ST0b1-iOS             )
2185569089e4ST0b1-iOS             .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
2186569089e4ST0b1-iOS             .operands_out(vec![Operand::new("a", iB), of_out.clone()]),
2187569089e4ST0b1-iOS         );
2188569089e4ST0b1-iOS 
2189569089e4ST0b1-iOS         ig.push(
2190569089e4ST0b1-iOS             Inst::new(
2191569089e4ST0b1-iOS                 "sadd_overflow",
2192569089e4ST0b1-iOS                 r#"
2193569089e4ST0b1-iOS             Add integers signed with overflow out.
2194569089e4ST0b1-iOS             ``of`` is set when the addition over- or underflowed.
2195569089e4ST0b1-iOS             Polymorphic over all scalar integer types, but does not support vector
2196569089e4ST0b1-iOS             types.
2197569089e4ST0b1-iOS             "#,
2198569089e4ST0b1-iOS                 &formats.binary,
2199569089e4ST0b1-iOS             )
2200569089e4ST0b1-iOS             .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
2201569089e4ST0b1-iOS             .operands_out(vec![Operand::new("a", iB), of_out.clone()]),
2202569089e4ST0b1-iOS         );
2203569089e4ST0b1-iOS 
2204569089e4ST0b1-iOS         ig.push(
2205569089e4ST0b1-iOS             Inst::new(
2206569089e4ST0b1-iOS                 "usub_overflow",
2207569089e4ST0b1-iOS                 r#"
2208569089e4ST0b1-iOS             Subtract integers unsigned with overflow out.
2209569089e4ST0b1-iOS             ``of`` is set when the subtraction underflowed.
2210569089e4ST0b1-iOS             ```text
2211569089e4ST0b1-iOS                 a &= x - y \pmod 2^B \\
2212569089e4ST0b1-iOS                 of &= x - y < 0
2213569089e4ST0b1-iOS             ```
2214569089e4ST0b1-iOS             Polymorphic over all scalar integer types, but does not support vector
2215569089e4ST0b1-iOS             types.
2216569089e4ST0b1-iOS             "#,
2217569089e4ST0b1-iOS                 &formats.binary,
2218569089e4ST0b1-iOS             )
2219569089e4ST0b1-iOS             .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
2220569089e4ST0b1-iOS             .operands_out(vec![Operand::new("a", iB), of_out.clone()]),
2221569089e4ST0b1-iOS         );
2222569089e4ST0b1-iOS 
2223569089e4ST0b1-iOS         ig.push(
2224569089e4ST0b1-iOS             Inst::new(
2225569089e4ST0b1-iOS                 "ssub_overflow",
2226569089e4ST0b1-iOS                 r#"
2227569089e4ST0b1-iOS             Subtract integers signed with overflow out.
2228569089e4ST0b1-iOS             ``of`` is set when the subtraction over- or underflowed.
2229569089e4ST0b1-iOS             Polymorphic over all scalar integer types, but does not support vector
2230569089e4ST0b1-iOS             types.
2231569089e4ST0b1-iOS             "#,
2232569089e4ST0b1-iOS                 &formats.binary,
2233569089e4ST0b1-iOS             )
2234569089e4ST0b1-iOS             .operands_in(vec![Operand::new("x", iB), Operand::new("y", iB)])
2235569089e4ST0b1-iOS             .operands_out(vec![Operand::new("a", iB), of_out.clone()]),
2236569089e4ST0b1-iOS         );
2237569089e4ST0b1-iOS 
2238569089e4ST0b1-iOS         {
2239569089e4ST0b1-iOS             let NarrowScalar = &TypeVar::new(
2240569089e4ST0b1-iOS                 "NarrowScalar",
2241569089e4ST0b1-iOS                 "A scalar integer type up to 64 bits",
2242569089e4ST0b1-iOS                 TypeSetBuilder::new().ints(8..64).build(),
2243569089e4ST0b1-iOS             );
2244569089e4ST0b1-iOS 
2245569089e4ST0b1-iOS             ig.push(
2246569089e4ST0b1-iOS                 Inst::new(
2247569089e4ST0b1-iOS                     "umul_overflow",
2248569089e4ST0b1-iOS                     r#"
2249569089e4ST0b1-iOS                 Multiply integers unsigned with overflow out.
2250569089e4ST0b1-iOS                 ``of`` is set when the multiplication overflowed.
2251569089e4ST0b1-iOS                 ```text
2252569089e4ST0b1-iOS                     a &= x * y \pmod 2^B \\
2253569089e4ST0b1-iOS                     of &= x * y > 2^B
2254569089e4ST0b1-iOS                 ```
2255569089e4ST0b1-iOS                 Polymorphic over all scalar integer types except i128, but does not support vector
2256569089e4ST0b1-iOS                 types.
2257569089e4ST0b1-iOS                 "#,
2258569089e4ST0b1-iOS                     &formats.binary,
2259569089e4ST0b1-iOS                 )
2260569089e4ST0b1-iOS                 .operands_in(vec![
2261569089e4ST0b1-iOS                     Operand::new("x", NarrowScalar),
2262569089e4ST0b1-iOS                     Operand::new("y", NarrowScalar),
2263569089e4ST0b1-iOS                 ])
2264569089e4ST0b1-iOS                 .operands_out(vec![Operand::new("a", NarrowScalar), of_out.clone()]),
2265569089e4ST0b1-iOS             );
2266569089e4ST0b1-iOS 
2267569089e4ST0b1-iOS             ig.push(
2268569089e4ST0b1-iOS                 Inst::new(
2269569089e4ST0b1-iOS                     "smul_overflow",
2270569089e4ST0b1-iOS                     r#"
2271569089e4ST0b1-iOS                 Multiply integers signed with overflow out.
2272569089e4ST0b1-iOS                 ``of`` is set when the multiplication over- or underflowed.
2273569089e4ST0b1-iOS                 Polymorphic over all scalar integer types except i128, but does not support vector
2274569089e4ST0b1-iOS                 types.
2275569089e4ST0b1-iOS                 "#,
2276569089e4ST0b1-iOS                     &formats.binary,
2277569089e4ST0b1-iOS                 )
2278569089e4ST0b1-iOS                 .operands_in(vec![
2279569089e4ST0b1-iOS                     Operand::new("x", NarrowScalar),
2280569089e4ST0b1-iOS                     Operand::new("y", NarrowScalar),
2281569089e4ST0b1-iOS                 ])
2282569089e4ST0b1-iOS                 .operands_out(vec![Operand::new("a", NarrowScalar), of_out.clone()]),
2283569089e4ST0b1-iOS             );
2284569089e4ST0b1-iOS         }
2285569089e4ST0b1-iOS     }
2286569089e4ST0b1-iOS 
228702620441STrevor Elliott     let i32_64 = &TypeVar::new(
228802620441STrevor Elliott         "i32_64",
228902620441STrevor Elliott         "A 32 or 64-bit scalar integer type",
229002620441STrevor Elliott         TypeSetBuilder::new().ints(32..64).build(),
229102620441STrevor Elliott     );
229202620441STrevor Elliott 
229302620441STrevor Elliott     ig.push(
229402620441STrevor Elliott         Inst::new(
229502620441STrevor Elliott             "uadd_overflow_trap",
229602620441STrevor Elliott             r#"
229702620441STrevor Elliott         Unsigned addition of x and y, trapping if the result overflows.
229802620441STrevor Elliott 
229902620441STrevor Elliott         Accepts 32 or 64-bit integers, and does not support vector types.
230002620441STrevor Elliott         "#,
230102620441STrevor Elliott             &formats.int_add_trap,
230202620441STrevor Elliott         )
2303f8771416SJamey Sharp         .operands_in(vec![
2304f8771416SJamey Sharp             Operand::new("x", i32_64),
2305f8771416SJamey Sharp             Operand::new("y", i32_64),
2306f8771416SJamey Sharp             Operand::new("code", &imm.trapcode),
2307f8771416SJamey Sharp         ])
2308f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", i32_64)])
2309b5692db7STrevor Elliott         .can_trap()
2310b5692db7STrevor Elliott         .side_effects_idempotent(),
231102620441STrevor Elliott     );
231202620441STrevor Elliott 
23133418fb6eSUjjwal Sharma     ig.push(
23143418fb6eSUjjwal Sharma         Inst::new(
2315ff987608SAlex Crichton             "ssub_overflow_bin",
231686430abcSBenjamin Bouvier             r#"
2317ff987608SAlex Crichton         Subtract signed integers with borrow in and overflow out.
231886430abcSBenjamin Bouvier 
2319ff987608SAlex Crichton         Same as `ssub_overflow` with an additional borrow input. The `b_in` type
2320ff987608SAlex Crichton         is interpreted as 1 if it's nonzero or 0 if it's zero. The computation
2321ff987608SAlex Crichton         performed here is `x - (y + (b_in != 0))`.
232286430abcSBenjamin Bouvier         "#,
23230243b642SBenjamin Bouvier             &formats.ternary,
232486430abcSBenjamin Bouvier         )
2325f8771416SJamey Sharp         .operands_in(vec![
2326f8771416SJamey Sharp             Operand::new("x", iB),
2327f8771416SJamey Sharp             Operand::new("y", iB),
2328f8771416SJamey Sharp             Operand::new("b_in", i8).with_doc("Input borrow flag"),
2329f8771416SJamey Sharp         ])
2330ff987608SAlex Crichton         .operands_out(vec![
2331ff987608SAlex Crichton             Operand::new("a", iB),
2332ff987608SAlex Crichton             Operand::new("b_out", i8).with_doc("Output borrow flag"),
2333ff987608SAlex Crichton         ]),
233486430abcSBenjamin Bouvier     );
233586430abcSBenjamin Bouvier 
233686430abcSBenjamin Bouvier     ig.push(
233786430abcSBenjamin Bouvier         Inst::new(
2338ff987608SAlex Crichton             "usub_overflow_bin",
233986430abcSBenjamin Bouvier             r#"
2340ff987608SAlex Crichton         Subtract unsigned integers with borrow in and overflow out.
234186430abcSBenjamin Bouvier 
2342ff987608SAlex Crichton         Same as `usub_overflow` with an additional borrow input. The `b_in` type
2343ff987608SAlex Crichton         is interpreted as 1 if it's nonzero or 0 if it's zero. The computation
2344ff987608SAlex Crichton         performed here is `x - (y + (b_in != 0))`.
234586430abcSBenjamin Bouvier         "#,
23460243b642SBenjamin Bouvier             &formats.ternary,
234786430abcSBenjamin Bouvier         )
2348f8771416SJamey Sharp         .operands_in(vec![
2349f8771416SJamey Sharp             Operand::new("x", iB),
2350f8771416SJamey Sharp             Operand::new("y", iB),
2351f8771416SJamey Sharp             Operand::new("b_in", i8).with_doc("Input borrow flag"),
2352f8771416SJamey Sharp         ])
2353f8771416SJamey Sharp         .operands_out(vec![
2354f8771416SJamey Sharp             Operand::new("a", iB),
2355f8771416SJamey Sharp             Operand::new("b_out", i8).with_doc("Output borrow flag"),
2356f8771416SJamey Sharp         ]),
235786430abcSBenjamin Bouvier     );
235886430abcSBenjamin Bouvier 
235960532011SBenjamin Bouvier     let bits = &TypeVar::new(
236086430abcSBenjamin Bouvier         "bits",
236132a7593cSTrevor Elliott         "Any integer, float, or vector type",
236260532011SBenjamin Bouvier         TypeSetBuilder::new()
236386430abcSBenjamin Bouvier             .ints(Interval::All)
236486430abcSBenjamin Bouvier             .floats(Interval::All)
236586430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
236686430abcSBenjamin Bouvier             .includes_scalars(true)
236770f79d23SBenjamin Bouvier             .build(),
236860532011SBenjamin Bouvier     );
236986430abcSBenjamin Bouvier 
237086430abcSBenjamin Bouvier     ig.push(
237186430abcSBenjamin Bouvier         Inst::new(
237286430abcSBenjamin Bouvier             "band",
237386430abcSBenjamin Bouvier             r#"
237486430abcSBenjamin Bouvier         Bitwise and.
237586430abcSBenjamin Bouvier         "#,
23760243b642SBenjamin Bouvier             &formats.binary,
237786430abcSBenjamin Bouvier         )
2378f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2379f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
238086430abcSBenjamin Bouvier     );
238186430abcSBenjamin Bouvier 
238286430abcSBenjamin Bouvier     ig.push(
238386430abcSBenjamin Bouvier         Inst::new(
238486430abcSBenjamin Bouvier             "bor",
238586430abcSBenjamin Bouvier             r#"
238686430abcSBenjamin Bouvier         Bitwise or.
238786430abcSBenjamin Bouvier         "#,
23880243b642SBenjamin Bouvier             &formats.binary,
238986430abcSBenjamin Bouvier         )
2390f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2391f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
239286430abcSBenjamin Bouvier     );
239386430abcSBenjamin Bouvier 
239486430abcSBenjamin Bouvier     ig.push(
239586430abcSBenjamin Bouvier         Inst::new(
239686430abcSBenjamin Bouvier             "bxor",
239786430abcSBenjamin Bouvier             r#"
239886430abcSBenjamin Bouvier         Bitwise xor.
239986430abcSBenjamin Bouvier         "#,
24000243b642SBenjamin Bouvier             &formats.binary,
240186430abcSBenjamin Bouvier         )
2402f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2403f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
240486430abcSBenjamin Bouvier     );
240586430abcSBenjamin Bouvier 
240686430abcSBenjamin Bouvier     ig.push(
240786430abcSBenjamin Bouvier         Inst::new(
240886430abcSBenjamin Bouvier             "bnot",
240986430abcSBenjamin Bouvier             r#"
241086430abcSBenjamin Bouvier         Bitwise not.
241186430abcSBenjamin Bouvier         "#,
24120243b642SBenjamin Bouvier             &formats.unary,
241386430abcSBenjamin Bouvier         )
2414f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits)])
2415f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
241686430abcSBenjamin Bouvier     );
241786430abcSBenjamin Bouvier 
241886430abcSBenjamin Bouvier     ig.push(
241986430abcSBenjamin Bouvier         Inst::new(
242086430abcSBenjamin Bouvier             "band_not",
242186430abcSBenjamin Bouvier             r#"
242286430abcSBenjamin Bouvier         Bitwise and not.
242386430abcSBenjamin Bouvier 
242486430abcSBenjamin Bouvier         Computes `x & ~y`.
242586430abcSBenjamin Bouvier         "#,
24260243b642SBenjamin Bouvier             &formats.binary,
242786430abcSBenjamin Bouvier         )
2428f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2429f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
243086430abcSBenjamin Bouvier     );
243186430abcSBenjamin Bouvier 
243286430abcSBenjamin Bouvier     ig.push(
243386430abcSBenjamin Bouvier         Inst::new(
243486430abcSBenjamin Bouvier             "bor_not",
243586430abcSBenjamin Bouvier             r#"
243686430abcSBenjamin Bouvier         Bitwise or not.
243786430abcSBenjamin Bouvier 
243886430abcSBenjamin Bouvier         Computes `x | ~y`.
243986430abcSBenjamin Bouvier         "#,
24400243b642SBenjamin Bouvier             &formats.binary,
244186430abcSBenjamin Bouvier         )
2442f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2443f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
244486430abcSBenjamin Bouvier     );
244586430abcSBenjamin Bouvier 
244686430abcSBenjamin Bouvier     ig.push(
244786430abcSBenjamin Bouvier         Inst::new(
244886430abcSBenjamin Bouvier             "bxor_not",
244986430abcSBenjamin Bouvier             r#"
245086430abcSBenjamin Bouvier         Bitwise xor not.
245186430abcSBenjamin Bouvier 
245286430abcSBenjamin Bouvier         Computes `x ^ ~y`.
245386430abcSBenjamin Bouvier         "#,
24540243b642SBenjamin Bouvier             &formats.binary,
245586430abcSBenjamin Bouvier         )
2456f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", bits), Operand::new("y", bits)])
2457f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", bits)]),
245886430abcSBenjamin Bouvier     );
245986430abcSBenjamin Bouvier 
246086430abcSBenjamin Bouvier     ig.push(
246186430abcSBenjamin Bouvier         Inst::new(
246286430abcSBenjamin Bouvier             "band_imm",
246386430abcSBenjamin Bouvier             r#"
246486430abcSBenjamin Bouvier         Bitwise and with immediate.
246586430abcSBenjamin Bouvier 
2466e577a76cSAfonso Bordado         Same as `band`, but one operand is a zero extended 64 bit immediate constant.
246786430abcSBenjamin Bouvier 
246886430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
246986430abcSBenjamin Bouvier         types.
247086430abcSBenjamin Bouvier         "#,
24710dd77d36SAndrew Brown             &formats.binary_imm64,
247286430abcSBenjamin Bouvier         )
2473f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2474f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
247586430abcSBenjamin Bouvier     );
247686430abcSBenjamin Bouvier 
247786430abcSBenjamin Bouvier     ig.push(
247886430abcSBenjamin Bouvier         Inst::new(
247986430abcSBenjamin Bouvier             "bor_imm",
248086430abcSBenjamin Bouvier             r#"
248186430abcSBenjamin Bouvier         Bitwise or with immediate.
248286430abcSBenjamin Bouvier 
2483e577a76cSAfonso Bordado         Same as `bor`, but one operand is a zero extended 64 bit immediate constant.
248486430abcSBenjamin Bouvier 
248586430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
248686430abcSBenjamin Bouvier         types.
248786430abcSBenjamin Bouvier         "#,
24880dd77d36SAndrew Brown             &formats.binary_imm64,
248986430abcSBenjamin Bouvier         )
2490f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2491f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
249286430abcSBenjamin Bouvier     );
249386430abcSBenjamin Bouvier 
249486430abcSBenjamin Bouvier     ig.push(
249586430abcSBenjamin Bouvier         Inst::new(
249686430abcSBenjamin Bouvier             "bxor_imm",
249786430abcSBenjamin Bouvier             r#"
249886430abcSBenjamin Bouvier         Bitwise xor with immediate.
249986430abcSBenjamin Bouvier 
2500e577a76cSAfonso Bordado         Same as `bxor`, but one operand is a zero extended 64 bit immediate constant.
250186430abcSBenjamin Bouvier 
250286430abcSBenjamin Bouvier         Polymorphic over all scalar integer types, but does not support vector
250386430abcSBenjamin Bouvier         types.
250486430abcSBenjamin Bouvier         "#,
25050dd77d36SAndrew Brown             &formats.binary_imm64,
250686430abcSBenjamin Bouvier         )
2507f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB), Operand::new("Y", &imm.imm64)])
2508f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
250986430abcSBenjamin Bouvier     );
251086430abcSBenjamin Bouvier 
251186430abcSBenjamin Bouvier     ig.push(
251286430abcSBenjamin Bouvier         Inst::new(
251386430abcSBenjamin Bouvier             "rotl",
251486430abcSBenjamin Bouvier             r#"
251586430abcSBenjamin Bouvier         Rotate left.
251686430abcSBenjamin Bouvier 
251786430abcSBenjamin Bouvier         Rotate the bits in ``x`` by ``y`` places.
251886430abcSBenjamin Bouvier         "#,
25190243b642SBenjamin Bouvier             &formats.binary,
252086430abcSBenjamin Bouvier         )
2521f8771416SJamey Sharp         .operands_in(vec![
2522f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2523f8771416SJamey Sharp             Operand::new("y", iB).with_doc("Number of bits to shift"),
2524f8771416SJamey Sharp         ])
2525f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
252686430abcSBenjamin Bouvier     );
252786430abcSBenjamin Bouvier 
252886430abcSBenjamin Bouvier     ig.push(
252986430abcSBenjamin Bouvier         Inst::new(
253086430abcSBenjamin Bouvier             "rotr",
253186430abcSBenjamin Bouvier             r#"
253286430abcSBenjamin Bouvier         Rotate right.
253386430abcSBenjamin Bouvier 
253486430abcSBenjamin Bouvier         Rotate the bits in ``x`` by ``y`` places.
253586430abcSBenjamin Bouvier         "#,
25360243b642SBenjamin Bouvier             &formats.binary,
253786430abcSBenjamin Bouvier         )
2538f8771416SJamey Sharp         .operands_in(vec![
2539f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2540f8771416SJamey Sharp             Operand::new("y", iB).with_doc("Number of bits to shift"),
2541f8771416SJamey Sharp         ])
2542f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
254386430abcSBenjamin Bouvier     );
254486430abcSBenjamin Bouvier 
254586430abcSBenjamin Bouvier     ig.push(
254686430abcSBenjamin Bouvier         Inst::new(
254786430abcSBenjamin Bouvier             "rotl_imm",
254886430abcSBenjamin Bouvier             r#"
254986430abcSBenjamin Bouvier         Rotate left by immediate.
2550e577a76cSAfonso Bordado 
2551e577a76cSAfonso Bordado         Same as `rotl`, but one operand is a zero extended 64 bit immediate constant.
255286430abcSBenjamin Bouvier         "#,
25530dd77d36SAndrew Brown             &formats.binary_imm64,
255486430abcSBenjamin Bouvier         )
2555f8771416SJamey Sharp         .operands_in(vec![
2556f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2557f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
2558f8771416SJamey Sharp         ])
2559f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
256086430abcSBenjamin Bouvier     );
256186430abcSBenjamin Bouvier 
256286430abcSBenjamin Bouvier     ig.push(
256386430abcSBenjamin Bouvier         Inst::new(
256486430abcSBenjamin Bouvier             "rotr_imm",
256586430abcSBenjamin Bouvier             r#"
256686430abcSBenjamin Bouvier         Rotate right by immediate.
2567e577a76cSAfonso Bordado 
2568e577a76cSAfonso Bordado         Same as `rotr`, but one operand is a zero extended 64 bit immediate constant.
256986430abcSBenjamin Bouvier         "#,
25700dd77d36SAndrew Brown             &formats.binary_imm64,
257186430abcSBenjamin Bouvier         )
2572f8771416SJamey Sharp         .operands_in(vec![
2573f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2574f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
2575f8771416SJamey Sharp         ])
2576f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
257786430abcSBenjamin Bouvier     );
257886430abcSBenjamin Bouvier 
257986430abcSBenjamin Bouvier     ig.push(
258086430abcSBenjamin Bouvier         Inst::new(
258186430abcSBenjamin Bouvier             "ishl",
258286430abcSBenjamin Bouvier             r#"
258386430abcSBenjamin Bouvier         Integer shift left. Shift the bits in ``x`` towards the MSB by ``y``
258486430abcSBenjamin Bouvier         places. Shift in zero bits to the LSB.
258586430abcSBenjamin Bouvier 
258686430abcSBenjamin Bouvier         The shift amount is masked to the size of ``x``.
258786430abcSBenjamin Bouvier 
258886430abcSBenjamin Bouvier         When shifting a B-bits integer type, this instruction computes:
258986430abcSBenjamin Bouvier 
2590bfc14686SBenjamin Bouvier         ```text
2591bfc14686SBenjamin Bouvier             s &:= y \pmod B,
259286430abcSBenjamin Bouvier             a &:= x \cdot 2^s \pmod{2^B}.
2593bfc14686SBenjamin Bouvier         ```
259486430abcSBenjamin Bouvier         "#,
25950243b642SBenjamin Bouvier             &formats.binary,
259686430abcSBenjamin Bouvier         )
2597f8771416SJamey Sharp         .operands_in(vec![
2598f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2599f8771416SJamey Sharp             Operand::new("y", iB).with_doc("Number of bits to shift"),
2600f8771416SJamey Sharp         ])
2601f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
260286430abcSBenjamin Bouvier     );
260386430abcSBenjamin Bouvier 
260486430abcSBenjamin Bouvier     ig.push(
260586430abcSBenjamin Bouvier         Inst::new(
260686430abcSBenjamin Bouvier             "ushr",
260786430abcSBenjamin Bouvier             r#"
260886430abcSBenjamin Bouvier         Unsigned shift right. Shift bits in ``x`` towards the LSB by ``y``
260986430abcSBenjamin Bouvier         places, shifting in zero bits to the MSB. Also called a *logical
261086430abcSBenjamin Bouvier         shift*.
261186430abcSBenjamin Bouvier 
261271d3b638SAlexa VanHattum         The shift amount is masked to the size of ``x``.
261386430abcSBenjamin Bouvier 
261486430abcSBenjamin Bouvier         When shifting a B-bits integer type, this instruction computes:
261586430abcSBenjamin Bouvier 
2616bfc14686SBenjamin Bouvier         ```text
2617bfc14686SBenjamin Bouvier             s &:= y \pmod B,
261886430abcSBenjamin Bouvier             a &:= \lfloor x \cdot 2^{-s} \rfloor.
2619bfc14686SBenjamin Bouvier         ```
262086430abcSBenjamin Bouvier         "#,
26210243b642SBenjamin Bouvier             &formats.binary,
262286430abcSBenjamin Bouvier         )
2623f8771416SJamey Sharp         .operands_in(vec![
2624f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2625f8771416SJamey Sharp             Operand::new("y", iB).with_doc("Number of bits to shift"),
2626f8771416SJamey Sharp         ])
2627f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
262886430abcSBenjamin Bouvier     );
262986430abcSBenjamin Bouvier 
263086430abcSBenjamin Bouvier     ig.push(
263186430abcSBenjamin Bouvier         Inst::new(
263286430abcSBenjamin Bouvier             "sshr",
263386430abcSBenjamin Bouvier             r#"
263486430abcSBenjamin Bouvier         Signed shift right. Shift bits in ``x`` towards the LSB by ``y``
263586430abcSBenjamin Bouvier         places, shifting in sign bits to the MSB. Also called an *arithmetic
263686430abcSBenjamin Bouvier         shift*.
263786430abcSBenjamin Bouvier 
263871d3b638SAlexa VanHattum         The shift amount is masked to the size of ``x``.
263986430abcSBenjamin Bouvier         "#,
26400243b642SBenjamin Bouvier             &formats.binary,
264186430abcSBenjamin Bouvier         )
2642f8771416SJamey Sharp         .operands_in(vec![
2643f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2644f8771416SJamey Sharp             Operand::new("y", iB).with_doc("Number of bits to shift"),
2645f8771416SJamey Sharp         ])
2646f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
264786430abcSBenjamin Bouvier     );
264886430abcSBenjamin Bouvier 
264986430abcSBenjamin Bouvier     ig.push(
265086430abcSBenjamin Bouvier         Inst::new(
265186430abcSBenjamin Bouvier             "ishl_imm",
265286430abcSBenjamin Bouvier             r#"
265386430abcSBenjamin Bouvier         Integer shift left by immediate.
265486430abcSBenjamin Bouvier 
265586430abcSBenjamin Bouvier         The shift amount is masked to the size of ``x``.
265686430abcSBenjamin Bouvier         "#,
26570dd77d36SAndrew Brown             &formats.binary_imm64,
265886430abcSBenjamin Bouvier         )
2659f8771416SJamey Sharp         .operands_in(vec![
2660f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2661f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
2662f8771416SJamey Sharp         ])
2663f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
266486430abcSBenjamin Bouvier     );
266586430abcSBenjamin Bouvier 
266686430abcSBenjamin Bouvier     ig.push(
266786430abcSBenjamin Bouvier         Inst::new(
266886430abcSBenjamin Bouvier             "ushr_imm",
266986430abcSBenjamin Bouvier             r#"
267086430abcSBenjamin Bouvier         Unsigned shift right by immediate.
267186430abcSBenjamin Bouvier 
267271d3b638SAlexa VanHattum         The shift amount is masked to the size of ``x``.
267386430abcSBenjamin Bouvier         "#,
26740dd77d36SAndrew Brown             &formats.binary_imm64,
267586430abcSBenjamin Bouvier         )
2676f8771416SJamey Sharp         .operands_in(vec![
2677f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2678f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
2679f8771416SJamey Sharp         ])
2680f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
268186430abcSBenjamin Bouvier     );
268286430abcSBenjamin Bouvier 
268386430abcSBenjamin Bouvier     ig.push(
268486430abcSBenjamin Bouvier         Inst::new(
268586430abcSBenjamin Bouvier             "sshr_imm",
268686430abcSBenjamin Bouvier             r#"
268786430abcSBenjamin Bouvier         Signed shift right by immediate.
268886430abcSBenjamin Bouvier 
268971d3b638SAlexa VanHattum         The shift amount is masked to the size of ``x``.
269086430abcSBenjamin Bouvier         "#,
26910dd77d36SAndrew Brown             &formats.binary_imm64,
269286430abcSBenjamin Bouvier         )
2693f8771416SJamey Sharp         .operands_in(vec![
2694f8771416SJamey Sharp             Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2695f8771416SJamey Sharp             Operand::new("Y", &imm.imm64),
2696f8771416SJamey Sharp         ])
2697f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
269886430abcSBenjamin Bouvier     );
269986430abcSBenjamin Bouvier 
270086430abcSBenjamin Bouvier     ig.push(
270186430abcSBenjamin Bouvier         Inst::new(
270286430abcSBenjamin Bouvier             "bitrev",
270386430abcSBenjamin Bouvier             r#"
270486430abcSBenjamin Bouvier         Reverse the bits of a integer.
270586430abcSBenjamin Bouvier 
270686430abcSBenjamin Bouvier         Reverses the bits in ``x``.
270786430abcSBenjamin Bouvier         "#,
27080243b642SBenjamin Bouvier             &formats.unary,
270986430abcSBenjamin Bouvier         )
2710f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB)])
2711f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
271286430abcSBenjamin Bouvier     );
271386430abcSBenjamin Bouvier 
271486430abcSBenjamin Bouvier     ig.push(
271586430abcSBenjamin Bouvier         Inst::new(
271686430abcSBenjamin Bouvier             "clz",
271786430abcSBenjamin Bouvier             r#"
271886430abcSBenjamin Bouvier         Count leading zero bits.
271986430abcSBenjamin Bouvier 
272086430abcSBenjamin Bouvier         Starting from the MSB in ``x``, count the number of zero bits before
272186430abcSBenjamin Bouvier         reaching the first one bit. When ``x`` is zero, returns the size of x
272286430abcSBenjamin Bouvier         in bits.
272386430abcSBenjamin Bouvier         "#,
27240243b642SBenjamin Bouvier             &formats.unary,
272586430abcSBenjamin Bouvier         )
2726f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB)])
2727f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
272886430abcSBenjamin Bouvier     );
272986430abcSBenjamin Bouvier 
273086430abcSBenjamin Bouvier     ig.push(
273186430abcSBenjamin Bouvier         Inst::new(
273286430abcSBenjamin Bouvier             "cls",
273386430abcSBenjamin Bouvier             r#"
273486430abcSBenjamin Bouvier         Count leading sign bits.
273586430abcSBenjamin Bouvier 
273686430abcSBenjamin Bouvier         Starting from the MSB after the sign bit in ``x``, count the number of
273786430abcSBenjamin Bouvier         consecutive bits identical to the sign bit. When ``x`` is 0 or -1,
273886430abcSBenjamin Bouvier         returns one less than the size of x in bits.
273986430abcSBenjamin Bouvier         "#,
27400243b642SBenjamin Bouvier             &formats.unary,
274186430abcSBenjamin Bouvier         )
2742f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB)])
2743f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
274486430abcSBenjamin Bouvier     );
274586430abcSBenjamin Bouvier 
274686430abcSBenjamin Bouvier     ig.push(
274786430abcSBenjamin Bouvier         Inst::new(
274886430abcSBenjamin Bouvier             "ctz",
274986430abcSBenjamin Bouvier             r#"
275086430abcSBenjamin Bouvier         Count trailing zeros.
275186430abcSBenjamin Bouvier 
275286430abcSBenjamin Bouvier         Starting from the LSB in ``x``, count the number of zero bits before
275386430abcSBenjamin Bouvier         reaching the first one bit. When ``x`` is zero, returns the size of x
275486430abcSBenjamin Bouvier         in bits.
275586430abcSBenjamin Bouvier         "#,
27560243b642SBenjamin Bouvier             &formats.unary,
275786430abcSBenjamin Bouvier         )
2758f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iB)])
2759f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iB)]),
276086430abcSBenjamin Bouvier     );
276186430abcSBenjamin Bouvier 
27624ca9e82bS11evan     ig.push(
27634ca9e82bS11evan         Inst::new(
27644ca9e82bS11evan             "bswap",
27654ca9e82bS11evan             r#"
27664ca9e82bS11evan         Reverse the byte order of an integer.
27674ca9e82bS11evan 
27684ca9e82bS11evan         Reverses the bytes in ``x``.
27694ca9e82bS11evan         "#,
27704ca9e82bS11evan             &formats.unary,
27714ca9e82bS11evan         )
2772f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", iSwappable)])
2773f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", iSwappable)]),
27744ca9e82bS11evan     );
27754ca9e82bS11evan 
277686430abcSBenjamin Bouvier     ig.push(
277786430abcSBenjamin Bouvier         Inst::new(
277886430abcSBenjamin Bouvier             "popcnt",
277986430abcSBenjamin Bouvier             r#"
278086430abcSBenjamin Bouvier         Population count
278186430abcSBenjamin Bouvier 
278286430abcSBenjamin Bouvier         Count the number of one bits in ``x``.
278386430abcSBenjamin Bouvier         "#,
27840243b642SBenjamin Bouvier             &formats.unary,
278586430abcSBenjamin Bouvier         )
2786f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int)])
2787f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", Int)]),
278886430abcSBenjamin Bouvier     );
278986430abcSBenjamin Bouvier 
279060532011SBenjamin Bouvier     let Float = &TypeVar::new(
279160532011SBenjamin Bouvier         "Float",
279260532011SBenjamin Bouvier         "A scalar or vector floating point number",
279360532011SBenjamin Bouvier         TypeSetBuilder::new()
279486430abcSBenjamin Bouvier             .floats(Interval::All)
279586430abcSBenjamin Bouvier             .simd_lanes(Interval::All)
27969c43749dSSam Parker             .dynamic_simd_lanes(Interval::All)
279770f79d23SBenjamin Bouvier             .build(),
279860532011SBenjamin Bouvier     );
279986430abcSBenjamin Bouvier 
280086430abcSBenjamin Bouvier     ig.push(
280186430abcSBenjamin Bouvier         Inst::new(
280286430abcSBenjamin Bouvier             "fcmp",
280386430abcSBenjamin Bouvier             r#"
280486430abcSBenjamin Bouvier         Floating point comparison.
280586430abcSBenjamin Bouvier 
280686430abcSBenjamin Bouvier         Two IEEE 754-2008 floating point numbers, `x` and `y`, relate to each
280786430abcSBenjamin Bouvier         other in exactly one of four ways:
280886430abcSBenjamin Bouvier 
280990bfa123SAndrew Brown         ```text
281086430abcSBenjamin Bouvier         == ==========================================
281186430abcSBenjamin Bouvier         UN Unordered when one or both numbers is NaN.
2812062ed8f6SBenjamin Bouvier         EQ When `x = y`. (And `0.0 = -0.0`).
2813062ed8f6SBenjamin Bouvier         LT When `x < y`.
2814062ed8f6SBenjamin Bouvier         GT When `x > y`.
281586430abcSBenjamin Bouvier         == ==========================================
281690bfa123SAndrew Brown         ```
281786430abcSBenjamin Bouvier 
2818062ed8f6SBenjamin Bouvier         The 14 `floatcc` condition codes each correspond to a subset of
281986430abcSBenjamin Bouvier         the four relations, except for the empty set which would always be
282086430abcSBenjamin Bouvier         false, and the full set which would always be true.
282186430abcSBenjamin Bouvier 
282286430abcSBenjamin Bouvier         The condition codes are divided into 7 'ordered' conditions which don't
282386430abcSBenjamin Bouvier         include UN, and 7 unordered conditions which all include UN.
282486430abcSBenjamin Bouvier 
282590bfa123SAndrew Brown         ```text
282686430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
282786430abcSBenjamin Bouvier         |Ordered             |Unordered             |Condition                |
282886430abcSBenjamin Bouvier         +=======+============+=========+============+=========================+
282986430abcSBenjamin Bouvier         |ord    |EQ | LT | GT|uno      |UN          |NaNs absent / present.   |
283086430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
283186430abcSBenjamin Bouvier         |eq     |EQ          |ueq      |UN | EQ     |Equal                    |
283286430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
283386430abcSBenjamin Bouvier         |one    |LT | GT     |ne       |UN | LT | GT|Not equal                |
283486430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
283586430abcSBenjamin Bouvier         |lt     |LT          |ult      |UN | LT     |Less than                |
283686430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
283786430abcSBenjamin Bouvier         |le     |LT | EQ     |ule      |UN | LT | EQ|Less than or equal       |
283886430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
283986430abcSBenjamin Bouvier         |gt     |GT          |ugt      |UN | GT     |Greater than             |
284086430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
284186430abcSBenjamin Bouvier         |ge     |GT | EQ     |uge      |UN | GT | EQ|Greater than or equal    |
284286430abcSBenjamin Bouvier         +-------+------------+---------+------------+-------------------------+
284390bfa123SAndrew Brown         ```
284486430abcSBenjamin Bouvier 
284586430abcSBenjamin Bouvier         The standard C comparison operators, `<, <=, >, >=`, are all ordered,
284686430abcSBenjamin Bouvier         so they are false if either operand is NaN. The C equality operator,
284786430abcSBenjamin Bouvier         `==`, is ordered, and since inequality is defined as the logical
2848062ed8f6SBenjamin Bouvier         inverse it is *unordered*. They map to the `floatcc` condition
284986430abcSBenjamin Bouvier         codes as follows:
285086430abcSBenjamin Bouvier 
285190bfa123SAndrew Brown         ```text
285286430abcSBenjamin Bouvier         ==== ====== ============
285386430abcSBenjamin Bouvier         C    `Cond` Subset
285486430abcSBenjamin Bouvier         ==== ====== ============
285586430abcSBenjamin Bouvier         `==` eq     EQ
285686430abcSBenjamin Bouvier         `!=` ne     UN | LT | GT
285786430abcSBenjamin Bouvier         `<`  lt     LT
285886430abcSBenjamin Bouvier         `<=` le     LT | EQ
285986430abcSBenjamin Bouvier         `>`  gt     GT
286086430abcSBenjamin Bouvier         `>=` ge     GT | EQ
286186430abcSBenjamin Bouvier         ==== ====== ============
286290bfa123SAndrew Brown         ```
286386430abcSBenjamin Bouvier 
286486430abcSBenjamin Bouvier         This subset of condition codes also corresponds to the WebAssembly
286586430abcSBenjamin Bouvier         floating point comparisons of the same name.
286686430abcSBenjamin Bouvier 
286786430abcSBenjamin Bouvier         When this instruction compares floating point vectors, it returns a
286832a7593cSTrevor Elliott         vector with the results of lane-wise comparisons.
286991e36f34SKarl Meakin 
287091e36f34SKarl Meakin         When comparing scalars, the result is:
287191e36f34SKarl Meakin             - `1` if the condition holds.
287291e36f34SKarl Meakin             - `0` if the condition does not hold.
287391e36f34SKarl Meakin 
287491e36f34SKarl Meakin         When comparing vectors, the result is:
287591e36f34SKarl Meakin             - `-1` (i.e. all ones) in each lane where the condition holds.
287691e36f34SKarl Meakin             - `0` in each lane where the condition does not hold.
287786430abcSBenjamin Bouvier         "#,
28780243b642SBenjamin Bouvier             &formats.float_compare,
287986430abcSBenjamin Bouvier         )
2880f8771416SJamey Sharp         .operands_in(vec![
2881f8771416SJamey Sharp             Operand::new("Cond", &imm.floatcc),
2882f8771416SJamey Sharp             Operand::new("x", Float),
2883f8771416SJamey Sharp             Operand::new("y", Float),
2884f8771416SJamey Sharp         ])
288578dbe93fSTrevor Elliott         .operands_out(vec![Operand::new("a", &Float.as_truthy())]),
288686430abcSBenjamin Bouvier     );
288786430abcSBenjamin Bouvier 
288886430abcSBenjamin Bouvier     ig.push(
288986430abcSBenjamin Bouvier         Inst::new(
289086430abcSBenjamin Bouvier             "fadd",
289186430abcSBenjamin Bouvier             r#"
289286430abcSBenjamin Bouvier         Floating point addition.
289386430abcSBenjamin Bouvier         "#,
28940243b642SBenjamin Bouvier             &formats.binary,
289586430abcSBenjamin Bouvier         )
2896f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
2897f8771416SJamey Sharp         .operands_out(vec![
289890ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2899f8771416SJamey Sharp         ]),
290086430abcSBenjamin Bouvier     );
290186430abcSBenjamin Bouvier 
290286430abcSBenjamin Bouvier     ig.push(
290386430abcSBenjamin Bouvier         Inst::new(
290486430abcSBenjamin Bouvier             "fsub",
290586430abcSBenjamin Bouvier             r#"
290686430abcSBenjamin Bouvier         Floating point subtraction.
290786430abcSBenjamin Bouvier         "#,
29080243b642SBenjamin Bouvier             &formats.binary,
290986430abcSBenjamin Bouvier         )
2910f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
2911f8771416SJamey Sharp         .operands_out(vec![
291290ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2913f8771416SJamey Sharp         ]),
291486430abcSBenjamin Bouvier     );
291586430abcSBenjamin Bouvier 
291686430abcSBenjamin Bouvier     ig.push(
291786430abcSBenjamin Bouvier         Inst::new(
291886430abcSBenjamin Bouvier             "fmul",
291986430abcSBenjamin Bouvier             r#"
292086430abcSBenjamin Bouvier         Floating point multiplication.
292186430abcSBenjamin Bouvier         "#,
29220243b642SBenjamin Bouvier             &formats.binary,
292386430abcSBenjamin Bouvier         )
2924f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
2925f8771416SJamey Sharp         .operands_out(vec![
292690ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2927f8771416SJamey Sharp         ]),
292886430abcSBenjamin Bouvier     );
292986430abcSBenjamin Bouvier 
293086430abcSBenjamin Bouvier     ig.push(
293186430abcSBenjamin Bouvier         Inst::new(
293286430abcSBenjamin Bouvier             "fdiv",
293386430abcSBenjamin Bouvier             r#"
293486430abcSBenjamin Bouvier         Floating point division.
293586430abcSBenjamin Bouvier 
2936062ed8f6SBenjamin Bouvier         Unlike the integer division instructions ` and
2937062ed8f6SBenjamin Bouvier         `udiv`, this can't trap. Division by zero is infinity or
293886430abcSBenjamin Bouvier         NaN, depending on the dividend.
293986430abcSBenjamin Bouvier         "#,
29400243b642SBenjamin Bouvier             &formats.binary,
294186430abcSBenjamin Bouvier         )
2942f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
2943f8771416SJamey Sharp         .operands_out(vec![
294490ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2945f8771416SJamey Sharp         ]),
294686430abcSBenjamin Bouvier     );
294786430abcSBenjamin Bouvier 
294886430abcSBenjamin Bouvier     ig.push(
294986430abcSBenjamin Bouvier         Inst::new(
295086430abcSBenjamin Bouvier             "sqrt",
295186430abcSBenjamin Bouvier             r#"
295286430abcSBenjamin Bouvier         Floating point square root.
295386430abcSBenjamin Bouvier         "#,
29540243b642SBenjamin Bouvier             &formats.unary,
295586430abcSBenjamin Bouvier         )
2956f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
2957f8771416SJamey Sharp         .operands_out(vec![
295890ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2959f8771416SJamey Sharp         ]),
296086430abcSBenjamin Bouvier     );
296186430abcSBenjamin Bouvier 
296286430abcSBenjamin Bouvier     ig.push(
296386430abcSBenjamin Bouvier         Inst::new(
296486430abcSBenjamin Bouvier             "fma",
296586430abcSBenjamin Bouvier             r#"
296686430abcSBenjamin Bouvier         Floating point fused multiply-and-add.
296786430abcSBenjamin Bouvier 
2968062ed8f6SBenjamin Bouvier         Computes `a := xy+z` without any intermediate rounding of the
296986430abcSBenjamin Bouvier         product.
297086430abcSBenjamin Bouvier         "#,
29710243b642SBenjamin Bouvier             &formats.ternary,
297286430abcSBenjamin Bouvier         )
2973f8771416SJamey Sharp         .operands_in(vec![
2974f8771416SJamey Sharp             Operand::new("x", Float),
2975f8771416SJamey Sharp             Operand::new("y", Float),
2976f8771416SJamey Sharp             Operand::new("z", Float),
2977f8771416SJamey Sharp         ])
2978f8771416SJamey Sharp         .operands_out(vec![
297990ac295eSAlex Crichton             Operand::new("a", Float).with_doc("Result of applying operator to each lane"),
2980f8771416SJamey Sharp         ]),
298186430abcSBenjamin Bouvier     );
298286430abcSBenjamin Bouvier 
298386430abcSBenjamin Bouvier     ig.push(
298486430abcSBenjamin Bouvier         Inst::new(
298586430abcSBenjamin Bouvier             "fneg",
298686430abcSBenjamin Bouvier             r#"
298786430abcSBenjamin Bouvier         Floating point negation.
298886430abcSBenjamin Bouvier 
298986430abcSBenjamin Bouvier         Note that this is a pure bitwise operation.
299086430abcSBenjamin Bouvier         "#,
29910243b642SBenjamin Bouvier             &formats.unary,
299286430abcSBenjamin Bouvier         )
2993f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
2994f8771416SJamey Sharp         .operands_out(vec![
299590ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` with its sign bit inverted"),
2996f8771416SJamey Sharp         ]),
299786430abcSBenjamin Bouvier     );
299886430abcSBenjamin Bouvier 
299986430abcSBenjamin Bouvier     ig.push(
300086430abcSBenjamin Bouvier         Inst::new(
300186430abcSBenjamin Bouvier             "fabs",
300286430abcSBenjamin Bouvier             r#"
300386430abcSBenjamin Bouvier         Floating point absolute value.
300486430abcSBenjamin Bouvier 
300586430abcSBenjamin Bouvier         Note that this is a pure bitwise operation.
300686430abcSBenjamin Bouvier         "#,
30070243b642SBenjamin Bouvier             &formats.unary,
300886430abcSBenjamin Bouvier         )
3009f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3010f8771416SJamey Sharp         .operands_out(vec![
301190ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` with its sign bit cleared"),
3012f8771416SJamey Sharp         ]),
301386430abcSBenjamin Bouvier     );
301486430abcSBenjamin Bouvier 
301586430abcSBenjamin Bouvier     ig.push(
301686430abcSBenjamin Bouvier         Inst::new(
301786430abcSBenjamin Bouvier             "fcopysign",
301886430abcSBenjamin Bouvier             r#"
301986430abcSBenjamin Bouvier         Floating point copy sign.
302086430abcSBenjamin Bouvier 
302186430abcSBenjamin Bouvier         Note that this is a pure bitwise operation. The sign bit from ``y`` is
302286430abcSBenjamin Bouvier         copied to the sign bit of ``x``.
302386430abcSBenjamin Bouvier         "#,
30240243b642SBenjamin Bouvier             &formats.binary,
302586430abcSBenjamin Bouvier         )
3026f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
3027f8771416SJamey Sharp         .operands_out(vec![
302890ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` with its sign bit changed to that of ``y``"),
3029f8771416SJamey Sharp         ]),
303086430abcSBenjamin Bouvier     );
303186430abcSBenjamin Bouvier 
303286430abcSBenjamin Bouvier     ig.push(
303386430abcSBenjamin Bouvier         Inst::new(
303486430abcSBenjamin Bouvier             "fmin",
303586430abcSBenjamin Bouvier             r#"
3036a1b39276SAnton Kirilov         Floating point minimum, propagating NaNs using the WebAssembly rules.
303786430abcSBenjamin Bouvier 
3038a1b39276SAnton Kirilov         If either operand is NaN, this returns NaN with an unspecified sign. Furthermore, if
3039a1b39276SAnton Kirilov         each input NaN consists of a mantissa whose most significant bit is 1 and the rest is
3040a1b39276SAnton Kirilov         0, then the output has the same form. Otherwise, the output mantissa's most significant
3041a1b39276SAnton Kirilov         bit is 1 and the rest is unspecified.
304286430abcSBenjamin Bouvier         "#,
30430243b642SBenjamin Bouvier             &formats.binary,
304486430abcSBenjamin Bouvier         )
3045f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
3046f8771416SJamey Sharp         .operands_out(vec![
304790ac295eSAlex Crichton             Operand::new("a", Float).with_doc("The smaller of ``x`` and ``y``"),
3048f8771416SJamey Sharp         ]),
304986430abcSBenjamin Bouvier     );
305086430abcSBenjamin Bouvier 
3051c15d9bd6SJulian Seward     ig.push(
3052c15d9bd6SJulian Seward         Inst::new(
305386430abcSBenjamin Bouvier             "fmax",
305486430abcSBenjamin Bouvier             r#"
3055a1b39276SAnton Kirilov         Floating point maximum, propagating NaNs using the WebAssembly rules.
305686430abcSBenjamin Bouvier 
3057a1b39276SAnton Kirilov         If either operand is NaN, this returns NaN with an unspecified sign. Furthermore, if
3058a1b39276SAnton Kirilov         each input NaN consists of a mantissa whose most significant bit is 1 and the rest is
3059a1b39276SAnton Kirilov         0, then the output has the same form. Otherwise, the output mantissa's most significant
3060a1b39276SAnton Kirilov         bit is 1 and the rest is unspecified.
306186430abcSBenjamin Bouvier         "#,
30620243b642SBenjamin Bouvier             &formats.binary,
306386430abcSBenjamin Bouvier         )
3064f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float), Operand::new("y", Float)])
3065f8771416SJamey Sharp         .operands_out(vec![
306690ac295eSAlex Crichton             Operand::new("a", Float).with_doc("The larger of ``x`` and ``y``"),
3067f8771416SJamey Sharp         ]),
306886430abcSBenjamin Bouvier     );
306986430abcSBenjamin Bouvier 
3070c15d9bd6SJulian Seward     ig.push(
3071c15d9bd6SJulian Seward         Inst::new(
307286430abcSBenjamin Bouvier             "ceil",
307386430abcSBenjamin Bouvier             r#"
307486430abcSBenjamin Bouvier         Round floating point round to integral, towards positive infinity.
307586430abcSBenjamin Bouvier         "#,
30760243b642SBenjamin Bouvier             &formats.unary,
307786430abcSBenjamin Bouvier         )
3078f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3079f8771416SJamey Sharp         .operands_out(vec![
308090ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` rounded to integral value"),
3081f8771416SJamey Sharp         ]),
308286430abcSBenjamin Bouvier     );
308386430abcSBenjamin Bouvier 
308486430abcSBenjamin Bouvier     ig.push(
308586430abcSBenjamin Bouvier         Inst::new(
308686430abcSBenjamin Bouvier             "floor",
308786430abcSBenjamin Bouvier             r#"
308886430abcSBenjamin Bouvier         Round floating point round to integral, towards negative infinity.
308986430abcSBenjamin Bouvier         "#,
30900243b642SBenjamin Bouvier             &formats.unary,
309186430abcSBenjamin Bouvier         )
3092f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3093f8771416SJamey Sharp         .operands_out(vec![
309490ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` rounded to integral value"),
3095f8771416SJamey Sharp         ]),
309686430abcSBenjamin Bouvier     );
309786430abcSBenjamin Bouvier 
309886430abcSBenjamin Bouvier     ig.push(
309986430abcSBenjamin Bouvier         Inst::new(
310086430abcSBenjamin Bouvier             "trunc",
310186430abcSBenjamin Bouvier             r#"
310286430abcSBenjamin Bouvier         Round floating point round to integral, towards zero.
310386430abcSBenjamin Bouvier         "#,
31040243b642SBenjamin Bouvier             &formats.unary,
310586430abcSBenjamin Bouvier         )
3106f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3107f8771416SJamey Sharp         .operands_out(vec![
310890ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` rounded to integral value"),
3109f8771416SJamey Sharp         ]),
311086430abcSBenjamin Bouvier     );
311186430abcSBenjamin Bouvier 
311286430abcSBenjamin Bouvier     ig.push(
311386430abcSBenjamin Bouvier         Inst::new(
311486430abcSBenjamin Bouvier             "nearest",
311586430abcSBenjamin Bouvier             r#"
311686430abcSBenjamin Bouvier         Round floating point round to integral, towards nearest with ties to
311786430abcSBenjamin Bouvier         even.
311886430abcSBenjamin Bouvier         "#,
31190243b642SBenjamin Bouvier             &formats.unary,
312086430abcSBenjamin Bouvier         )
3121f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3122f8771416SJamey Sharp         .operands_out(vec![
312390ac295eSAlex Crichton             Operand::new("a", Float).with_doc("``x`` rounded to integral value"),
3124f8771416SJamey Sharp         ]),
312586430abcSBenjamin Bouvier     );
312686430abcSBenjamin Bouvier 
312719257f80SCarmen Kwan     ig.push(
312819257f80SCarmen Kwan         Inst::new(
312986430abcSBenjamin Bouvier             "bitcast",
313086430abcSBenjamin Bouvier             r#"
313186430abcSBenjamin Bouvier         Reinterpret the bits in `x` as a different type.
313286430abcSBenjamin Bouvier 
313386430abcSBenjamin Bouvier         The input and output types must be storable to memory and of the same
313486430abcSBenjamin Bouvier         size. A bitcast is equivalent to storing one type and loading the other
31353e5938e6SUlrich Weigand         type from the same address, both using the specified MemFlags.
31363e5938e6SUlrich Weigand 
31373e5938e6SUlrich Weigand         Note that this operation only supports the `big` or `little` MemFlags.
31383e5938e6SUlrich Weigand         The specified byte order only affects the result in the case where
31393e5938e6SUlrich Weigand         input and output types differ in lane count/size.  In this case, the
31403e5938e6SUlrich Weigand         operation is only valid if a byte order specifier is provided.
314161772e97SAndrew Brown         "#,
31423e5938e6SUlrich Weigand             &formats.load_no_offset,
314361772e97SAndrew Brown         )
3144f8771416SJamey Sharp         .operands_in(vec![
3145f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
3146f8771416SJamey Sharp             Operand::new("x", Mem),
3147f8771416SJamey Sharp         ])
3148f8771416SJamey Sharp         .operands_out(vec![
314990ac295eSAlex Crichton             Operand::new("a", MemTo).with_doc("Bits of `x` reinterpreted"),
3150f8771416SJamey Sharp         ]),
315161772e97SAndrew Brown     );
315261772e97SAndrew Brown 
31535f0e5567SAndrew Brown     ig.push(
31545f0e5567SAndrew Brown         Inst::new(
31555f0e5567SAndrew Brown             "scalar_to_vector",
31565f0e5567SAndrew Brown             r#"
3157dd9bfcefSJulian Seward             Copies a scalar value to a vector value.  The scalar is copied into the
3158dd9bfcefSJulian Seward             least significant lane of the vector, and all other lanes will be zero.
31595f0e5567SAndrew Brown             "#,
31600243b642SBenjamin Bouvier             &formats.unary,
31615f0e5567SAndrew Brown         )
3162f8771416SJamey Sharp         .operands_in(vec![
316390ac295eSAlex Crichton             Operand::new("s", &TxN.lane_of()).with_doc("A scalar value"),
3164f8771416SJamey Sharp         ])
3165f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", TxN).with_doc("A vector value")]),
31665f0e5567SAndrew Brown     );
31675f0e5567SAndrew Brown 
316832a7593cSTrevor Elliott     let Truthy = &TypeVar::new(
316932a7593cSTrevor Elliott         "Truthy",
3170b44f67b6STrevor Elliott         "A scalar whose values are truthy",
3171b44f67b6STrevor Elliott         TypeSetBuilder::new().ints(Interval::All).build(),
317238ecd374SAfonso Bordado     );
317387007c58SAfonso Bordado     let IntTo = &TypeVar::new(
317487007c58SAfonso Bordado         "IntTo",
3175b44f67b6STrevor Elliott         "An integer type",
3176b44f67b6STrevor Elliott         TypeSetBuilder::new().ints(Interval::All).build(),
317787007c58SAfonso Bordado     );
317887007c58SAfonso Bordado 
317986430abcSBenjamin Bouvier     ig.push(
318086430abcSBenjamin Bouvier         Inst::new(
318186430abcSBenjamin Bouvier             "bmask",
318286430abcSBenjamin Bouvier             r#"
318386430abcSBenjamin Bouvier         Convert `x` to an integer mask.
318486430abcSBenjamin Bouvier 
3185b44f67b6STrevor Elliott         Non-zero maps to all 1s and zero maps to all 0s.
318686430abcSBenjamin Bouvier         "#,
31870243b642SBenjamin Bouvier             &formats.unary,
318886430abcSBenjamin Bouvier         )
3189f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Truthy)])
3190f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)]),
319186430abcSBenjamin Bouvier     );
319286430abcSBenjamin Bouvier 
319360532011SBenjamin Bouvier     let Int = &TypeVar::new(
319460532011SBenjamin Bouvier         "Int",
3195919604b8SAfonso Bordado         "A scalar integer type",
3196919604b8SAfonso Bordado         TypeSetBuilder::new().ints(Interval::All).build(),
319760532011SBenjamin Bouvier     );
319886430abcSBenjamin Bouvier 
319986430abcSBenjamin Bouvier     ig.push(
320086430abcSBenjamin Bouvier         Inst::new(
320186430abcSBenjamin Bouvier             "ireduce",
320286430abcSBenjamin Bouvier             r#"
3203919604b8SAfonso Bordado         Convert `x` to a smaller integer type by discarding
3204919604b8SAfonso Bordado         the most significant bits.
320586430abcSBenjamin Bouvier 
3206919604b8SAfonso Bordado         This is the same as reducing modulo `2^n`.
320786430abcSBenjamin Bouvier         "#,
32080243b642SBenjamin Bouvier             &formats.unary,
320986430abcSBenjamin Bouvier         )
321090ac295eSAlex Crichton         .operands_in(vec![
321190ac295eSAlex Crichton             Operand::new("x", &Int.wider())
321290ac295eSAlex Crichton                 .with_doc("A scalar integer type, wider than the controlling type"),
321390ac295eSAlex Crichton         ])
3214f5ad74e5STrevor Elliott         .operands_out(vec![Operand::new("a", Int)]),
321586430abcSBenjamin Bouvier     );
321686430abcSBenjamin Bouvier 
3217330f02aaSAnton Kirilov     let I16or32or64xN = &TypeVar::new(
3218330f02aaSAnton Kirilov         "I16or32or64xN",
3219330f02aaSAnton Kirilov         "A SIMD vector type containing integer lanes 16, 32, or 64 bits wide",
322065e6de23SAndrew Brown         TypeSetBuilder::new()
3221330f02aaSAnton Kirilov             .ints(16..64)
3222330f02aaSAnton Kirilov             .simd_lanes(2..8)
32239c43749dSSam Parker             .dynamic_simd_lanes(2..8)
322465e6de23SAndrew Brown             .includes_scalars(false)
322565e6de23SAndrew Brown             .build(),
322665e6de23SAndrew Brown     );
322765e6de23SAndrew Brown 
322865e6de23SAndrew Brown     ig.push(
322965e6de23SAndrew Brown         Inst::new(
323065e6de23SAndrew Brown             "snarrow",
323165e6de23SAndrew Brown             r#"
323265e6de23SAndrew Brown         Combine `x` and `y` into a vector with twice the lanes but half the integer width while
323365e6de23SAndrew Brown         saturating overflowing values to the signed maximum and minimum.
323465e6de23SAndrew Brown 
323565e6de23SAndrew Brown         The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
323665e6de23SAndrew Brown         and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
323765e6de23SAndrew Brown         returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
323865e6de23SAndrew Brown             "#,
323965e6de23SAndrew Brown             &formats.binary,
324065e6de23SAndrew Brown         )
3241f8771416SJamey Sharp         .operands_in(vec![
3242f8771416SJamey Sharp             Operand::new("x", I16or32or64xN),
3243f8771416SJamey Sharp             Operand::new("y", I16or32or64xN),
3244f8771416SJamey Sharp         ])
3245f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I16or32or64xN.split_lanes())]),
324665e6de23SAndrew Brown     );
324765e6de23SAndrew Brown 
3248057c93b6SAndrew Brown     ig.push(
3249057c93b6SAndrew Brown         Inst::new(
3250057c93b6SAndrew Brown             "unarrow",
3251057c93b6SAndrew Brown             r#"
3252057c93b6SAndrew Brown         Combine `x` and `y` into a vector with twice the lanes but half the integer width while
3253057c93b6SAndrew Brown         saturating overflowing values to the unsigned maximum and minimum.
3254057c93b6SAndrew Brown 
3255057c93b6SAndrew Brown         Note that all input lanes are considered signed: any negative lanes will overflow and be
3256057c93b6SAndrew Brown         replaced with the unsigned minimum, `0x00`.
3257057c93b6SAndrew Brown 
3258057c93b6SAndrew Brown         The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
3259057c93b6SAndrew Brown         and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
3260057c93b6SAndrew Brown         returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
3261057c93b6SAndrew Brown             "#,
3262057c93b6SAndrew Brown             &formats.binary,
3263057c93b6SAndrew Brown         )
3264f8771416SJamey Sharp         .operands_in(vec![
3265f8771416SJamey Sharp             Operand::new("x", I16or32or64xN),
3266f8771416SJamey Sharp             Operand::new("y", I16or32or64xN),
3267f8771416SJamey Sharp         ])
3268f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I16or32or64xN.split_lanes())]),
3269057c93b6SAndrew Brown     );
3270057c93b6SAndrew Brown 
3271330f02aaSAnton Kirilov     ig.push(
3272330f02aaSAnton Kirilov         Inst::new(
3273330f02aaSAnton Kirilov             "uunarrow",
3274330f02aaSAnton Kirilov             r#"
3275330f02aaSAnton Kirilov         Combine `x` and `y` into a vector with twice the lanes but half the integer width while
3276330f02aaSAnton Kirilov         saturating overflowing values to the unsigned maximum and minimum.
3277330f02aaSAnton Kirilov 
327883c3bc5bSdheaton-arm         Note that all input lanes are considered unsigned: any negative values will be interpreted as unsigned, overflowing and being replaced with the unsigned maximum.
3279330f02aaSAnton Kirilov 
3280330f02aaSAnton Kirilov         The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
3281330f02aaSAnton Kirilov         and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
3282330f02aaSAnton Kirilov         returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
3283330f02aaSAnton Kirilov             "#,
3284330f02aaSAnton Kirilov             &formats.binary,
3285330f02aaSAnton Kirilov         )
3286f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I16or32or64xN), Operand::new("y", I16or32or64xN)])
3287f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I16or32or64xN.split_lanes())]),
3288330f02aaSAnton Kirilov     );
3289330f02aaSAnton Kirilov 
32905e8a8fe5SAnton Kirilov     let I8or16or32xN = &TypeVar::new(
32915e8a8fe5SAnton Kirilov         "I8or16or32xN",
32925e8a8fe5SAnton Kirilov         "A SIMD vector type containing integer lanes 8, 16, or 32 bits wide.",
3293c8ddf8a3SAndrew Brown         TypeSetBuilder::new()
32945e8a8fe5SAnton Kirilov             .ints(8..32)
32953ef89b77SDamian Heaton             .simd_lanes(2..16)
32963ef89b77SDamian Heaton             .dynamic_simd_lanes(2..16)
3297c8ddf8a3SAndrew Brown             .includes_scalars(false)
3298c8ddf8a3SAndrew Brown             .build(),
3299c8ddf8a3SAndrew Brown     );
3300c8ddf8a3SAndrew Brown 
3301c8ddf8a3SAndrew Brown     ig.push(
3302c8ddf8a3SAndrew Brown         Inst::new(
3303c8ddf8a3SAndrew Brown             "swiden_low",
3304c8ddf8a3SAndrew Brown             r#"
3305c8ddf8a3SAndrew Brown         Widen the low lanes of `x` using signed extension.
3306c8ddf8a3SAndrew Brown 
3307c8ddf8a3SAndrew Brown         This will double the lane width and halve the number of lanes.
3308c8ddf8a3SAndrew Brown             "#,
3309c8ddf8a3SAndrew Brown             &formats.unary,
3310c8ddf8a3SAndrew Brown         )
3311f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I8or16or32xN)])
3312f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I8or16or32xN.merge_lanes())]),
3313c8ddf8a3SAndrew Brown     );
3314c8ddf8a3SAndrew Brown 
3315c8ddf8a3SAndrew Brown     ig.push(
3316c8ddf8a3SAndrew Brown         Inst::new(
3317c8ddf8a3SAndrew Brown             "swiden_high",
3318c8ddf8a3SAndrew Brown             r#"
3319c8ddf8a3SAndrew Brown         Widen the high lanes of `x` using signed extension.
3320c8ddf8a3SAndrew Brown 
3321c8ddf8a3SAndrew Brown         This will double the lane width and halve the number of lanes.
3322c8ddf8a3SAndrew Brown             "#,
3323c8ddf8a3SAndrew Brown             &formats.unary,
3324c8ddf8a3SAndrew Brown         )
3325f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I8or16or32xN)])
3326f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I8or16or32xN.merge_lanes())]),
3327c8ddf8a3SAndrew Brown     );
3328c8ddf8a3SAndrew Brown 
3329c8ddf8a3SAndrew Brown     ig.push(
3330c8ddf8a3SAndrew Brown         Inst::new(
3331c8ddf8a3SAndrew Brown             "uwiden_low",
3332c8ddf8a3SAndrew Brown             r#"
3333c8ddf8a3SAndrew Brown         Widen the low lanes of `x` using unsigned extension.
3334c8ddf8a3SAndrew Brown 
3335c8ddf8a3SAndrew Brown         This will double the lane width and halve the number of lanes.
3336c8ddf8a3SAndrew Brown             "#,
3337c8ddf8a3SAndrew Brown             &formats.unary,
3338c8ddf8a3SAndrew Brown         )
3339f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I8or16or32xN)])
3340f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I8or16or32xN.merge_lanes())]),
3341c8ddf8a3SAndrew Brown     );
3342c8ddf8a3SAndrew Brown 
3343c8ddf8a3SAndrew Brown     ig.push(
3344c8ddf8a3SAndrew Brown         Inst::new(
3345c8ddf8a3SAndrew Brown             "uwiden_high",
3346c8ddf8a3SAndrew Brown             r#"
3347e519fca6SJohnnie Birch             Widen the high lanes of `x` using unsigned extension.
3348e373ddfeSJohnnie Birch 
3349e373ddfeSJohnnie Birch             This will double the lane width and halve the number of lanes.
3350e373ddfeSJohnnie Birch             "#,
3351e373ddfeSJohnnie Birch             &formats.unary,
3352e373ddfeSJohnnie Birch         )
3353f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I8or16or32xN)])
3354f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", &I8or16or32xN.merge_lanes())]),
3355e373ddfeSJohnnie Birch     );
3356e373ddfeSJohnnie Birch 
3357e373ddfeSJohnnie Birch     ig.push(
3358e373ddfeSJohnnie Birch         Inst::new(
3359e519fca6SJohnnie Birch             "iadd_pairwise",
3360e373ddfeSJohnnie Birch             r#"
3361e519fca6SJohnnie Birch         Does lane-wise integer pairwise addition on two operands, putting the
3362e519fca6SJohnnie Birch         combined results into a single vector result. Here a pair refers to adjacent
3363e519fca6SJohnnie Birch         lanes in a vector, i.e. i*2 + (i*2+1) for i == num_lanes/2. The first operand
3364e519fca6SJohnnie Birch         pairwise add results will make up the low half of the resulting vector while
3365e519fca6SJohnnie Birch         the second operand pairwise add results will make up the upper half of the
3366e519fca6SJohnnie Birch         resulting vector.
3367c8ddf8a3SAndrew Brown             "#,
3368e519fca6SJohnnie Birch             &formats.binary,
3369c8ddf8a3SAndrew Brown         )
3370f8771416SJamey Sharp         .operands_in(vec![
3371f8771416SJamey Sharp             Operand::new("x", I8or16or32xN),
3372f8771416SJamey Sharp             Operand::new("y", I8or16or32xN),
3373f8771416SJamey Sharp         ])
3374f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I8or16or32xN)]),
3375c8ddf8a3SAndrew Brown     );
3376c8ddf8a3SAndrew Brown 
33778bb183f1SAlex Crichton     let I8x16 = &TypeVar::new(
33788bb183f1SAlex Crichton         "I8x16",
33798bb183f1SAlex Crichton         "A SIMD vector type consisting of 16 lanes of 8-bit integers",
33808bb183f1SAlex Crichton         TypeSetBuilder::new()
33818bb183f1SAlex Crichton             .ints(8..8)
33828bb183f1SAlex Crichton             .simd_lanes(16..16)
33838bb183f1SAlex Crichton             .includes_scalars(false)
33848bb183f1SAlex Crichton             .build(),
33858bb183f1SAlex Crichton     );
33868bb183f1SAlex Crichton 
33878bb183f1SAlex Crichton     ig.push(
33888bb183f1SAlex Crichton         Inst::new(
33898bb183f1SAlex Crichton             "x86_pmaddubsw",
33908bb183f1SAlex Crichton             r#"
33918bb183f1SAlex Crichton         An instruction with equivalent semantics to `pmaddubsw` on x86.
33928bb183f1SAlex Crichton 
33938bb183f1SAlex Crichton         This instruction will take signed bytes from the first argument and
33948bb183f1SAlex Crichton         multiply them against unsigned bytes in the second argument. Adjacent
33958bb183f1SAlex Crichton         pairs are then added, with saturating, to a 16-bit value and are packed
33968bb183f1SAlex Crichton         into the result.
33978bb183f1SAlex Crichton             "#,
33988bb183f1SAlex Crichton             &formats.binary,
33998bb183f1SAlex Crichton         )
3400f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", I8x16), Operand::new("y", I8x16)])
3401f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", I16x8)]),
34028bb183f1SAlex Crichton     );
34038bb183f1SAlex Crichton 
340486430abcSBenjamin Bouvier     ig.push(
340586430abcSBenjamin Bouvier         Inst::new(
340686430abcSBenjamin Bouvier             "uextend",
340786430abcSBenjamin Bouvier             r#"
340886430abcSBenjamin Bouvier         Convert `x` to a larger integer type by zero-extending.
340986430abcSBenjamin Bouvier 
341086430abcSBenjamin Bouvier         Each lane in `x` is converted to a larger integer type by adding
341186430abcSBenjamin Bouvier         zeroes. The result has the same numerical value as `x` when both are
341286430abcSBenjamin Bouvier         interpreted as unsigned integers.
341386430abcSBenjamin Bouvier 
341486430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input,
341586430abcSBenjamin Bouvier         and each lane must not have fewer bits that the input lanes. If the
341686430abcSBenjamin Bouvier         input and output types are the same, this is a no-op.
341786430abcSBenjamin Bouvier         "#,
34180243b642SBenjamin Bouvier             &formats.unary,
341986430abcSBenjamin Bouvier         )
3420f5ad74e5STrevor Elliott         .operands_in(vec![Operand::new("x", &Int.narrower()).with_doc(
3421f5ad74e5STrevor Elliott             "A scalar integer type, narrower than the controlling type",
3422f5ad74e5STrevor Elliott         )])
3423f5ad74e5STrevor Elliott         .operands_out(vec![Operand::new("a", Int)]),
342486430abcSBenjamin Bouvier     );
342586430abcSBenjamin Bouvier 
342686430abcSBenjamin Bouvier     ig.push(
342786430abcSBenjamin Bouvier         Inst::new(
342886430abcSBenjamin Bouvier             "sextend",
342986430abcSBenjamin Bouvier             r#"
343086430abcSBenjamin Bouvier         Convert `x` to a larger integer type by sign-extending.
343186430abcSBenjamin Bouvier 
343286430abcSBenjamin Bouvier         Each lane in `x` is converted to a larger integer type by replicating
343386430abcSBenjamin Bouvier         the sign bit. The result has the same numerical value as `x` when both
343486430abcSBenjamin Bouvier         are interpreted as signed integers.
343586430abcSBenjamin Bouvier 
343686430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input,
343786430abcSBenjamin Bouvier         and each lane must not have fewer bits that the input lanes. If the
343886430abcSBenjamin Bouvier         input and output types are the same, this is a no-op.
343986430abcSBenjamin Bouvier         "#,
34400243b642SBenjamin Bouvier             &formats.unary,
344186430abcSBenjamin Bouvier         )
3442f5ad74e5STrevor Elliott         .operands_in(vec![Operand::new("x", &Int.narrower()).with_doc(
3443f5ad74e5STrevor Elliott             "A scalar integer type, narrower than the controlling type",
3444f5ad74e5STrevor Elliott         )])
3445f5ad74e5STrevor Elliott         .operands_out(vec![Operand::new("a", Int)]),
344686430abcSBenjamin Bouvier     );
344770925701STrevor Elliott 
3448188f7120STrevor Elliott     let FloatScalar = &TypeVar::new(
3449188f7120STrevor Elliott         "FloatScalar",
3450188f7120STrevor Elliott         "A scalar only floating point number",
3451188f7120STrevor Elliott         TypeSetBuilder::new().floats(Interval::All).build(),
3452188f7120STrevor Elliott     );
3453188f7120STrevor Elliott 
345486430abcSBenjamin Bouvier     ig.push(
345586430abcSBenjamin Bouvier         Inst::new(
345686430abcSBenjamin Bouvier             "fpromote",
345786430abcSBenjamin Bouvier             r#"
345886430abcSBenjamin Bouvier         Convert `x` to a larger floating point format.
345986430abcSBenjamin Bouvier 
346086430abcSBenjamin Bouvier         Each lane in `x` is converted to the destination floating point format.
346186430abcSBenjamin Bouvier         This is an exact operation.
346286430abcSBenjamin Bouvier 
346386430abcSBenjamin Bouvier         Cranelift currently only supports two floating point formats
3464062ed8f6SBenjamin Bouvier         - `f32` and `f64`. This may change in the future.
346586430abcSBenjamin Bouvier 
346686430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input,
3467a793648eSAfonso Bordado         and the result lanes must not have fewer bits than the input lanes.
346886430abcSBenjamin Bouvier         "#,
34690243b642SBenjamin Bouvier             &formats.unary,
347086430abcSBenjamin Bouvier         )
3471f5ad74e5STrevor Elliott         .operands_in(vec![Operand::new("x", &FloatScalar.narrower()).with_doc(
3472f5ad74e5STrevor Elliott             "A scalar only floating point number, narrower than the controlling type",
3473f5ad74e5STrevor Elliott         )])
3474f5ad74e5STrevor Elliott         .operands_out(vec![Operand::new("a", FloatScalar)]),
347586430abcSBenjamin Bouvier     );
347686430abcSBenjamin Bouvier 
347786430abcSBenjamin Bouvier     ig.push(
347886430abcSBenjamin Bouvier         Inst::new(
347986430abcSBenjamin Bouvier             "fdemote",
348086430abcSBenjamin Bouvier             r#"
348186430abcSBenjamin Bouvier         Convert `x` to a smaller floating point format.
348286430abcSBenjamin Bouvier 
348386430abcSBenjamin Bouvier         Each lane in `x` is converted to the destination floating point format
348486430abcSBenjamin Bouvier         by rounding to nearest, ties to even.
348586430abcSBenjamin Bouvier 
348686430abcSBenjamin Bouvier         Cranelift currently only supports two floating point formats
3487062ed8f6SBenjamin Bouvier         - `f32` and `f64`. This may change in the future.
348886430abcSBenjamin Bouvier 
348986430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input,
3490a793648eSAfonso Bordado         and the result lanes must not have more bits than the input lanes.
349186430abcSBenjamin Bouvier         "#,
34920243b642SBenjamin Bouvier             &formats.unary,
349386430abcSBenjamin Bouvier         )
3494f5ad74e5STrevor Elliott         .operands_in(vec![Operand::new("x", &FloatScalar.wider()).with_doc(
3495f5ad74e5STrevor Elliott             "A scalar only floating point number, wider than the controlling type",
3496f5ad74e5STrevor Elliott         )])
3497f5ad74e5STrevor Elliott         .operands_out(vec![Operand::new("a", FloatScalar)]),
349886430abcSBenjamin Bouvier     );
349986430abcSBenjamin Bouvier 
35001770880eSJohnnie Birch     let F64x2 = &TypeVar::new(
35011770880eSJohnnie Birch         "F64x2",
35021770880eSJohnnie Birch         "A SIMD vector type consisting of 2 lanes of 64-bit floats",
35031770880eSJohnnie Birch         TypeSetBuilder::new()
35041770880eSJohnnie Birch             .floats(64..64)
35051770880eSJohnnie Birch             .simd_lanes(2..2)
35061770880eSJohnnie Birch             .includes_scalars(false)
35071770880eSJohnnie Birch             .build(),
35081770880eSJohnnie Birch     );
35091770880eSJohnnie Birch     let F32x4 = &TypeVar::new(
35101770880eSJohnnie Birch         "F32x4",
35111770880eSJohnnie Birch         "A SIMD vector type consisting of 4 lanes of 32-bit floats",
35121770880eSJohnnie Birch         TypeSetBuilder::new()
35131770880eSJohnnie Birch             .floats(32..32)
35141770880eSJohnnie Birch             .simd_lanes(4..4)
35151770880eSJohnnie Birch             .includes_scalars(false)
35161770880eSJohnnie Birch             .build(),
35171770880eSJohnnie Birch     );
35181770880eSJohnnie Birch 
35191770880eSJohnnie Birch     ig.push(
35201770880eSJohnnie Birch         Inst::new(
35211770880eSJohnnie Birch             "fvdemote",
35221770880eSJohnnie Birch             r#"
35231770880eSJohnnie Birch                 Convert `x` to a smaller floating point format.
35241770880eSJohnnie Birch 
35251770880eSJohnnie Birch                 Each lane in `x` is converted to the destination floating point format
35261770880eSJohnnie Birch                 by rounding to nearest, ties to even.
35271770880eSJohnnie Birch 
35281770880eSJohnnie Birch                 Cranelift currently only supports two floating point formats
35291770880eSJohnnie Birch                 - `f32` and `f64`. This may change in the future.
35301770880eSJohnnie Birch 
35311770880eSJohnnie Birch                 Fvdemote differs from fdemote in that with fvdemote it targets vectors.
35321770880eSJohnnie Birch                 Fvdemote is constrained to having the input type being F64x2 and the result
35331770880eSJohnnie Birch                 type being F32x4. The result lane that was the upper half of the input lane
35341770880eSJohnnie Birch                 is initialized to zero.
35351770880eSJohnnie Birch                 "#,
35361770880eSJohnnie Birch             &formats.unary,
35371770880eSJohnnie Birch         )
3538f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", F64x2)])
3539f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", F32x4)]),
35401770880eSJohnnie Birch     );
35411770880eSJohnnie Birch 
35421770880eSJohnnie Birch     ig.push(
35431770880eSJohnnie Birch         Inst::new(
35441770880eSJohnnie Birch             "fvpromote_low",
35451770880eSJohnnie Birch             r#"
35461770880eSJohnnie Birch         Converts packed single precision floating point to packed double precision floating point.
35471770880eSJohnnie Birch 
35481770880eSJohnnie Birch         Considering only the lower half of the register, the low lanes in `x` are interpreted as
35491770880eSJohnnie Birch         single precision floats that are then converted to a double precision floats.
35501770880eSJohnnie Birch 
35511770880eSJohnnie Birch         The result type will have half the number of vector lanes as the input. Fvpromote_low is
35521770880eSJohnnie Birch         constrained to input F32x4 with a result type of F64x2.
35531770880eSJohnnie Birch         "#,
35541770880eSJohnnie Birch             &formats.unary,
35551770880eSJohnnie Birch         )
3556f8771416SJamey Sharp         .operands_in(vec![Operand::new("a", F32x4)])
3557f8771416SJamey Sharp         .operands_out(vec![Operand::new("x", F64x2)]),
35581770880eSJohnnie Birch     );
35591770880eSJohnnie Birch 
35607d482345STrevor Elliott     let IntTo = &TypeVar::new(
35617d482345STrevor Elliott         "IntTo",
35627d482345STrevor Elliott         "An scalar only integer type",
35637d482345STrevor Elliott         TypeSetBuilder::new().ints(Interval::All).build(),
35647d482345STrevor Elliott     );
356586430abcSBenjamin Bouvier 
356686430abcSBenjamin Bouvier     ig.push(
356786430abcSBenjamin Bouvier         Inst::new(
356886430abcSBenjamin Bouvier             "fcvt_to_uint",
356986430abcSBenjamin Bouvier             r#"
35706368c6b1SJohnnie Birch         Converts floating point scalars to unsigned integer.
357186430abcSBenjamin Bouvier 
35726368c6b1SJohnnie Birch         Only operates on `x` if it is a scalar. If `x` is NaN or if
35736368c6b1SJohnnie Birch         the unsigned integral value cannot be represented in the result
35746368c6b1SJohnnie Birch         type, this instruction traps.
357586430abcSBenjamin Bouvier 
357686430abcSBenjamin Bouvier         "#,
35770243b642SBenjamin Bouvier             &formats.unary,
357886430abcSBenjamin Bouvier         )
3579f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", FloatScalar)])
3580f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)])
3581b5692db7STrevor Elliott         .can_trap()
3582b5692db7STrevor Elliott         .side_effects_idempotent(),
358386430abcSBenjamin Bouvier     );
358486430abcSBenjamin Bouvier 
358586430abcSBenjamin Bouvier     ig.push(
358686430abcSBenjamin Bouvier         Inst::new(
35876368c6b1SJohnnie Birch             "fcvt_to_sint",
35886368c6b1SJohnnie Birch             r#"
35896368c6b1SJohnnie Birch         Converts floating point scalars to signed integer.
35906368c6b1SJohnnie Birch 
35916368c6b1SJohnnie Birch         Only operates on `x` if it is a scalar. If `x` is NaN or if
35926368c6b1SJohnnie Birch         the unsigned integral value cannot be represented in the result
35936368c6b1SJohnnie Birch         type, this instruction traps.
35946368c6b1SJohnnie Birch 
35956368c6b1SJohnnie Birch         "#,
35966368c6b1SJohnnie Birch             &formats.unary,
35976368c6b1SJohnnie Birch         )
3598f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", FloatScalar)])
3599f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)])
3600b5692db7STrevor Elliott         .can_trap()
3601b5692db7STrevor Elliott         .side_effects_idempotent(),
36026368c6b1SJohnnie Birch     );
36036368c6b1SJohnnie Birch 
36047d482345STrevor Elliott     let IntTo = &TypeVar::new(
36057d482345STrevor Elliott         "IntTo",
36067d482345STrevor Elliott         "A larger integer type with the same number of lanes",
36077d482345STrevor Elliott         TypeSetBuilder::new()
36087d482345STrevor Elliott             .ints(Interval::All)
36097d482345STrevor Elliott             .simd_lanes(Interval::All)
36107d482345STrevor Elliott             .build(),
36117d482345STrevor Elliott     );
36127d482345STrevor Elliott 
36136368c6b1SJohnnie Birch     ig.push(
36146368c6b1SJohnnie Birch         Inst::new(
361586430abcSBenjamin Bouvier             "fcvt_to_uint_sat",
361686430abcSBenjamin Bouvier             r#"
361786430abcSBenjamin Bouvier         Convert floating point to unsigned integer as fcvt_to_uint does, but
361886430abcSBenjamin Bouvier         saturates the input instead of trapping. NaN and negative values are
361986430abcSBenjamin Bouvier         converted to 0.
362086430abcSBenjamin Bouvier         "#,
36210243b642SBenjamin Bouvier             &formats.unary,
362286430abcSBenjamin Bouvier         )
3623f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3624f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)]),
362586430abcSBenjamin Bouvier     );
362686430abcSBenjamin Bouvier 
362786430abcSBenjamin Bouvier     ig.push(
362886430abcSBenjamin Bouvier         Inst::new(
362986430abcSBenjamin Bouvier             "fcvt_to_sint_sat",
363086430abcSBenjamin Bouvier             r#"
363186430abcSBenjamin Bouvier         Convert floating point to signed integer as fcvt_to_sint does, but
363286430abcSBenjamin Bouvier         saturates the input instead of trapping. NaN values are converted to 0.
363386430abcSBenjamin Bouvier         "#,
36340243b642SBenjamin Bouvier             &formats.unary,
363586430abcSBenjamin Bouvier         )
3636f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3637f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)]),
363886430abcSBenjamin Bouvier     );
363986430abcSBenjamin Bouvier 
36408bb183f1SAlex Crichton     ig.push(
36418bb183f1SAlex Crichton         Inst::new(
36428bb183f1SAlex Crichton             "x86_cvtt2dq",
36438bb183f1SAlex Crichton             r#"
36448bb183f1SAlex Crichton         A float-to-integer conversion instruction for vectors-of-floats which
36458bb183f1SAlex Crichton         has the same semantics as `cvttp{s,d}2dq` on x86. This specifically
36468bb183f1SAlex Crichton         returns `INT_MIN` for NaN or out-of-bounds lanes.
36478bb183f1SAlex Crichton         "#,
36488bb183f1SAlex Crichton             &formats.unary,
36498bb183f1SAlex Crichton         )
3650f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Float)])
3651f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", IntTo)]),
36528bb183f1SAlex Crichton     );
36538bb183f1SAlex Crichton 
3654919604b8SAfonso Bordado     let Int = &TypeVar::new(
3655919604b8SAfonso Bordado         "Int",
3656919604b8SAfonso Bordado         "A scalar or vector integer type",
3657919604b8SAfonso Bordado         TypeSetBuilder::new()
3658919604b8SAfonso Bordado             .ints(Interval::All)
3659919604b8SAfonso Bordado             .simd_lanes(Interval::All)
3660919604b8SAfonso Bordado             .build(),
3661919604b8SAfonso Bordado     );
366286430abcSBenjamin Bouvier 
3663188f7120STrevor Elliott     let FloatTo = &TypeVar::new(
3664188f7120STrevor Elliott         "FloatTo",
3665188f7120STrevor Elliott         "A scalar or vector floating point number",
3666188f7120STrevor Elliott         TypeSetBuilder::new()
3667188f7120STrevor Elliott             .floats(Interval::All)
3668188f7120STrevor Elliott             .simd_lanes(Interval::All)
3669188f7120STrevor Elliott             .build(),
3670188f7120STrevor Elliott     );
3671188f7120STrevor Elliott 
367286430abcSBenjamin Bouvier     ig.push(
367386430abcSBenjamin Bouvier         Inst::new(
367486430abcSBenjamin Bouvier             "fcvt_from_uint",
367586430abcSBenjamin Bouvier             r#"
367686430abcSBenjamin Bouvier         Convert unsigned integer to floating point.
367786430abcSBenjamin Bouvier 
367886430abcSBenjamin Bouvier         Each lane in `x` is interpreted as an unsigned integer and converted to
367986430abcSBenjamin Bouvier         floating point using round to nearest, ties to even.
368086430abcSBenjamin Bouvier 
368186430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input.
368286430abcSBenjamin Bouvier         "#,
36830243b642SBenjamin Bouvier             &formats.unary,
368486430abcSBenjamin Bouvier         )
3685f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int)])
3686f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", FloatTo)]),
368786430abcSBenjamin Bouvier     );
368886430abcSBenjamin Bouvier 
368986430abcSBenjamin Bouvier     ig.push(
369086430abcSBenjamin Bouvier         Inst::new(
369186430abcSBenjamin Bouvier             "fcvt_from_sint",
369286430abcSBenjamin Bouvier             r#"
369386430abcSBenjamin Bouvier         Convert signed integer to floating point.
369486430abcSBenjamin Bouvier 
369586430abcSBenjamin Bouvier         Each lane in `x` is interpreted as a signed integer and converted to
369686430abcSBenjamin Bouvier         floating point using round to nearest, ties to even.
369786430abcSBenjamin Bouvier 
369886430abcSBenjamin Bouvier         The result type must have the same number of vector lanes as the input.
369986430abcSBenjamin Bouvier         "#,
37000243b642SBenjamin Bouvier             &formats.unary,
370186430abcSBenjamin Bouvier         )
3702f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", Int)])
3703f8771416SJamey Sharp         .operands_out(vec![Operand::new("a", FloatTo)]),
370486430abcSBenjamin Bouvier     );
370586430abcSBenjamin Bouvier 
370660532011SBenjamin Bouvier     let WideInt = &TypeVar::new(
370760532011SBenjamin Bouvier         "WideInt",
3708861220c4STrevor Elliott         "An integer type of width `i16` upwards",
3709861220c4STrevor Elliott         TypeSetBuilder::new().ints(16..128).build(),
371060532011SBenjamin Bouvier     );
371186430abcSBenjamin Bouvier 
371286430abcSBenjamin Bouvier     ig.push(
371386430abcSBenjamin Bouvier         Inst::new(
371486430abcSBenjamin Bouvier             "isplit",
371586430abcSBenjamin Bouvier             r#"
371686430abcSBenjamin Bouvier         Split an integer into low and high parts.
371786430abcSBenjamin Bouvier 
371886430abcSBenjamin Bouvier         Vectors of integers are split lane-wise, so the results have the same
371986430abcSBenjamin Bouvier         number of lanes as the input, but the lanes are half the size.
372086430abcSBenjamin Bouvier 
372186430abcSBenjamin Bouvier         Returns the low half of `x` and the high half of `x` as two independent
372286430abcSBenjamin Bouvier         values.
372386430abcSBenjamin Bouvier         "#,
37240243b642SBenjamin Bouvier             &formats.unary,
372586430abcSBenjamin Bouvier         )
3726f8771416SJamey Sharp         .operands_in(vec![Operand::new("x", WideInt)])
3727f8771416SJamey Sharp         .operands_out(vec![
3728f8771416SJamey Sharp             Operand::new("lo", &WideInt.half_width()).with_doc("The low bits of `x`"),
3729f8771416SJamey Sharp             Operand::new("hi", &WideInt.half_width()).with_doc("The high bits of `x`"),
3730f8771416SJamey Sharp         ]),
373186430abcSBenjamin Bouvier     );
373286430abcSBenjamin Bouvier 
373386430abcSBenjamin Bouvier     ig.push(
373486430abcSBenjamin Bouvier         Inst::new(
373586430abcSBenjamin Bouvier             "iconcat",
373686430abcSBenjamin Bouvier             r#"
373786430abcSBenjamin Bouvier         Concatenate low and high bits to form a larger integer type.
373886430abcSBenjamin Bouvier 
373986430abcSBenjamin Bouvier         Vectors of integers are concatenated lane-wise such that the result has
374086430abcSBenjamin Bouvier         the same number of lanes as the inputs, but the lanes are twice the
374186430abcSBenjamin Bouvier         size.
374286430abcSBenjamin Bouvier         "#,
37430243b642SBenjamin Bouvier             &formats.binary,
374486430abcSBenjamin Bouvier         )
3745f8771416SJamey Sharp         .operands_in(vec![
3746f8771416SJamey Sharp             Operand::new("lo", NarrowInt),
3747f8771416SJamey Sharp             Operand::new("hi", NarrowInt),
3748f8771416SJamey Sharp         ])
374990ac295eSAlex Crichton         .operands_out(vec![
375090ac295eSAlex Crichton             Operand::new("a", &NarrowInt.double_width())
375190ac295eSAlex Crichton                 .with_doc("The concatenation of `lo` and `hi`"),
375290ac295eSAlex Crichton         ]),
375386430abcSBenjamin Bouvier     );
375486430abcSBenjamin Bouvier 
375525e31739SJulian Seward     // Instructions relating to atomic memory accesses and fences
375625e31739SJulian Seward     let AtomicMem = &TypeVar::new(
375725e31739SJulian Seward         "AtomicMem",
375825e31739SJulian Seward         "Any type that can be stored in memory, which can be used in an atomic operation",
37593036e795Sbeetrees         TypeSetBuilder::new().ints(8..128).build(),
376025e31739SJulian Seward     );
376125e31739SJulian Seward 
376225e31739SJulian Seward     ig.push(
376325e31739SJulian Seward         Inst::new(
376425e31739SJulian Seward             "atomic_rmw",
376525e31739SJulian Seward             r#"
376625e31739SJulian Seward         Atomically read-modify-write memory at `p`, with second operand `x`.  The old value is
37673036e795Sbeetrees         returned.  `p` has the type of the target word size, and `x` may be any integer type; note
37683036e795Sbeetrees         that some targets require specific target features to be enabled in order to support 128-bit
37693036e795Sbeetrees         integer atomics.  The type of the returned value is the same as the type of `x`.  This
37703036e795Sbeetrees         operation is sequentially consistent and creates happens-before edges that order normal
37713036e795Sbeetrees         (non-atomic) loads and stores.
377225e31739SJulian Seward         "#,
377325e31739SJulian Seward             &formats.atomic_rmw,
377425e31739SJulian Seward         )
3775f8771416SJamey Sharp         .operands_in(vec![
3776f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
3777f8771416SJamey Sharp             Operand::new("AtomicRmwOp", &imm.atomic_rmw_op),
3778f8771416SJamey Sharp             Operand::new("p", iAddr),
3779f8771416SJamey Sharp             Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3780f8771416SJamey Sharp         ])
3781f8771416SJamey Sharp         .operands_out(vec![
378290ac295eSAlex Crichton             Operand::new("a", AtomicMem).with_doc("Value atomically loaded"),
3783f8771416SJamey Sharp         ])
3784b5692db7STrevor Elliott         .can_load()
3785b5692db7STrevor Elliott         .can_store()
3786b5692db7STrevor Elliott         .other_side_effects(),
378725e31739SJulian Seward     );
378825e31739SJulian Seward 
378925e31739SJulian Seward     ig.push(
379025e31739SJulian Seward         Inst::new(
379125e31739SJulian Seward             "atomic_cas",
379225e31739SJulian Seward             r#"
379325e31739SJulian Seward         Perform an atomic compare-and-swap operation on memory at `p`, with expected value `e`,
379425e31739SJulian Seward         storing `x` if the value at `p` equals `e`.  The old value at `p` is returned,
379525e31739SJulian Seward         regardless of whether the operation succeeds or fails.  `p` has the type of the target
37963036e795Sbeetrees         word size, and `x` and `e` must have the same type and the same size, which may be any
37973036e795Sbeetrees         integer type; note that some targets require specific target features to be enabled in order
37983036e795Sbeetrees         to support 128-bit integer atomics.  The type of the returned value is the same as the type
37993036e795Sbeetrees         of `x` and `e`.  This operation is sequentially consistent and creates happens-before edges
38003036e795Sbeetrees         that order normal (non-atomic) loads and stores.
380125e31739SJulian Seward         "#,
380225e31739SJulian Seward             &formats.atomic_cas,
380325e31739SJulian Seward         )
3804f8771416SJamey Sharp         .operands_in(vec![
3805f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
3806f8771416SJamey Sharp             Operand::new("p", iAddr),
3807f8771416SJamey Sharp             Operand::new("e", AtomicMem).with_doc("Expected value in CAS"),
3808f8771416SJamey Sharp             Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3809f8771416SJamey Sharp         ])
3810f8771416SJamey Sharp         .operands_out(vec![
381190ac295eSAlex Crichton             Operand::new("a", AtomicMem).with_doc("Value atomically loaded"),
3812f8771416SJamey Sharp         ])
3813b5692db7STrevor Elliott         .can_load()
3814b5692db7STrevor Elliott         .can_store()
3815b5692db7STrevor Elliott         .other_side_effects(),
381625e31739SJulian Seward     );
381725e31739SJulian Seward 
381825e31739SJulian Seward     ig.push(
381925e31739SJulian Seward         Inst::new(
382025e31739SJulian Seward             "atomic_load",
382125e31739SJulian Seward             r#"
382225e31739SJulian Seward         Atomically load from memory at `p`.
382325e31739SJulian Seward 
382425e31739SJulian Seward         This is a polymorphic instruction that can load any value type which has a memory
38253036e795Sbeetrees         representation.  It can only be used for integer types; note that some targets require
38263036e795Sbeetrees         specific target features to be enabled in order to support 128-bit integer atomics. This
38273036e795Sbeetrees         operation is sequentially consistent and creates happens-before edges that order normal
38283036e795Sbeetrees         (non-atomic) loads and stores.
382925e31739SJulian Seward         "#,
383025e31739SJulian Seward             &formats.load_no_offset,
383125e31739SJulian Seward         )
3832f8771416SJamey Sharp         .operands_in(vec![
3833f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
3834f8771416SJamey Sharp             Operand::new("p", iAddr),
3835f8771416SJamey Sharp         ])
3836f8771416SJamey Sharp         .operands_out(vec![
383790ac295eSAlex Crichton             Operand::new("a", AtomicMem).with_doc("Value atomically loaded"),
3838f8771416SJamey Sharp         ])
3839b5692db7STrevor Elliott         .can_load()
3840b5692db7STrevor Elliott         .other_side_effects(),
384125e31739SJulian Seward     );
384225e31739SJulian Seward 
384325e31739SJulian Seward     ig.push(
384425e31739SJulian Seward         Inst::new(
384525e31739SJulian Seward             "atomic_store",
384625e31739SJulian Seward             r#"
384725e31739SJulian Seward         Atomically store `x` to memory at `p`.
384825e31739SJulian Seward 
384925e31739SJulian Seward         This is a polymorphic instruction that can store any value type with a memory
38503036e795Sbeetrees         representation.  It can only be used for integer types; note that some targets require
38513036e795Sbeetrees         specific target features to be enabled in order to support 128-bit integer atomics This
38523036e795Sbeetrees         operation is sequentially consistent and creates happens-before edges that order normal
38533036e795Sbeetrees         (non-atomic) loads and stores.
385425e31739SJulian Seward         "#,
385525e31739SJulian Seward             &formats.store_no_offset,
385625e31739SJulian Seward         )
3857f8771416SJamey Sharp         .operands_in(vec![
3858f8771416SJamey Sharp             Operand::new("MemFlags", &imm.memflags),
3859f8771416SJamey Sharp             Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3860f8771416SJamey Sharp             Operand::new("p", iAddr),
3861f8771416SJamey Sharp         ])
3862b5692db7STrevor Elliott         .can_store()
3863b5692db7STrevor Elliott         .other_side_effects(),
386425e31739SJulian Seward     );
386525e31739SJulian Seward 
386625e31739SJulian Seward     ig.push(
386725e31739SJulian Seward         Inst::new(
386825e31739SJulian Seward             "fence",
386925e31739SJulian Seward             r#"
387025e31739SJulian Seward         A memory fence.  This must provide ordering to ensure that, at a minimum, neither loads
387125e31739SJulian Seward         nor stores of any kind may move forwards or backwards across the fence.  This operation
387225e31739SJulian Seward         is sequentially consistent.
387325e31739SJulian Seward         "#,
387425e31739SJulian Seward             &formats.nullary,
387525e31739SJulian Seward         )
3876b5692db7STrevor Elliott         .other_side_effects(),
387725e31739SJulian Seward     );
38789c43749dSSam Parker 
38799c43749dSSam Parker     let TxN = &TypeVar::new(
38809c43749dSSam Parker         "TxN",
38819c43749dSSam Parker         "A dynamic vector type",
38829c43749dSSam Parker         TypeSetBuilder::new()
38839c43749dSSam Parker             .ints(Interval::All)
38849c43749dSSam Parker             .floats(Interval::All)
38859c43749dSSam Parker             .dynamic_simd_lanes(Interval::All)
38869c43749dSSam Parker             .build(),
38879c43749dSSam Parker     );
38889c43749dSSam Parker 
38899c43749dSSam Parker     ig.push(
38909c43749dSSam Parker         Inst::new(
38919c43749dSSam Parker             "extract_vector",
38929c43749dSSam Parker             r#"
38939c43749dSSam Parker         Return a fixed length sub vector, extracted from a dynamic vector.
38949c43749dSSam Parker         "#,
38959c43749dSSam Parker             &formats.binary_imm8,
38969c43749dSSam Parker         )
3897f8771416SJamey Sharp         .operands_in(vec![
3898f8771416SJamey Sharp             Operand::new("x", TxN).with_doc("The dynamic vector to extract from"),
3899f8771416SJamey Sharp             Operand::new("y", &imm.uimm8).with_doc("128-bit vector index"),
3900f8771416SJamey Sharp         ])
3901f8771416SJamey Sharp         .operands_out(vec![
390290ac295eSAlex Crichton             Operand::new("a", &TxN.dynamic_to_vector()).with_doc("New fixed vector"),
3903f8771416SJamey Sharp         ]),
39049c43749dSSam Parker     );
3905a3d6e407SChris Fallin 
3906a3d6e407SChris Fallin     ig.push(
3907a3d6e407SChris Fallin         Inst::new(
3908a3d6e407SChris Fallin             "sequence_point",
3909a3d6e407SChris Fallin             r#"
3910a3d6e407SChris Fallin          A compiler barrier that acts as an immovable marker from IR input to machine-code output.
3911a3d6e407SChris Fallin 
3912a3d6e407SChris Fallin          This "sequence point" can have debug tags attached to it, and these tags will be
3913a3d6e407SChris Fallin          noted in the output `MachBuffer`.
3914a3d6e407SChris Fallin 
3915a3d6e407SChris Fallin          It prevents motion of any other side-effects across this boundary.
3916a3d6e407SChris Fallin          "#,
3917a3d6e407SChris Fallin             &formats.nullary,
3918a3d6e407SChris Fallin         )
3919a3d6e407SChris Fallin         .other_side_effects(),
3920a3d6e407SChris Fallin     );
392186430abcSBenjamin Bouvier }
3922