|
@ -605,23 +605,32 @@ depends on the runtime environment. |
|
|
Operations |
|
|
Operations |
|
|
========== |
|
|
========== |
|
|
|
|
|
|
|
|
|
|
|
The remaining instruction set is mostly arithmetic. |
|
|
|
|
|
|
|
|
|
|
|
A few instructions have variants that take immediate operands (e.g., |
|
|
|
|
|
:inst:`and` / :inst:`and_imm`), but in general an instruction is required to |
|
|
|
|
|
load a constant into an SSA value. |
|
|
|
|
|
|
|
|
Special operations |
|
|
.. inst:: a = iconst N |
|
|
------------------ |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = iconst n |
|
|
|
|
|
|
|
|
|
|
|
Integer constant. |
|
|
Integer constant. |
|
|
|
|
|
|
|
|
.. inst:: a = fconst n |
|
|
Create a scalar integer SSA value with an immediate constant value, or an |
|
|
|
|
|
integer vector where all the lanes have the same value. |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = fconst N |
|
|
|
|
|
|
|
|
Floating point constant. |
|
|
Floating point constant. |
|
|
|
|
|
|
|
|
.. inst:: a = vconst n |
|
|
Create a :type:`f32` or :type:`f64` SSA value with an immediate constant |
|
|
|
|
|
value, or a floating point vector where all the lanes have the same value. |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = vconst N |
|
|
|
|
|
|
|
|
Vector constant (floating point or integer). |
|
|
Vector constant (floating point or integer). |
|
|
|
|
|
|
|
|
|
|
|
Create a SIMD vector value where the lanes don't have to be identical. |
|
|
|
|
|
|
|
|
.. inst:: a = select c, x, y |
|
|
.. inst:: a = select c, x, y |
|
|
|
|
|
|
|
|
Conditional select. |
|
|
Conditional select. |
|
@ -680,12 +689,13 @@ Vector operations |
|
|
Integer operations |
|
|
Integer operations |
|
|
------------------ |
|
|
------------------ |
|
|
|
|
|
|
|
|
.. inst:: a = icmp cond, x, y |
|
|
.. inst:: a = icmp Cond, x, y |
|
|
|
|
|
|
|
|
Integer comparison. |
|
|
Integer comparison. |
|
|
|
|
|
|
|
|
:param cond: Condition code determining how ``x`` and ``y`` are compared. |
|
|
:arg Cond: Condition code determining how ``x`` and ``y`` are compared. |
|
|
:param x, y: Integer scalar or vector values of the same type. |
|
|
:arg x: First value to compare. |
|
|
|
|
|
:arg y: Second value to compare. |
|
|
:rtype: :type:`bool` or :type:`boolxN` with the same number of lanes as |
|
|
:rtype: :type:`bool` or :type:`boolxN` with the same number of lanes as |
|
|
``x`` and ``y``. |
|
|
``x`` and ``y``. |
|
|
|
|
|
|
|
@ -708,29 +718,59 @@ Integer operations |
|
|
Wrapping integer addition: :math:`a := x + y \pmod{2^B}`. This instruction |
|
|
Wrapping integer addition: :math:`a := x + y \pmod{2^B}`. This instruction |
|
|
does not depend on the signed/unsigned interpretation of the operands. |
|
|
does not depend on the signed/unsigned interpretation of the operands. |
|
|
|
|
|
|
|
|
|
|
|
Polymorphic over all integer types (vector and scalar). |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = iadd_imm x, Imm |
|
|
|
|
|
|
|
|
|
|
|
Add immediate integer. |
|
|
|
|
|
|
|
|
|
|
|
Same as :inst:`iadd`, but one operand is an immediate constant. |
|
|
|
|
|
|
|
|
|
|
|
:arg iN x: Dynamic addend. |
|
|
|
|
|
:arg Imm: Immediate addend. |
|
|
|
|
|
|
|
|
|
|
|
Polymorphic over all scalar integer types. |
|
|
|
|
|
|
|
|
.. inst:: a = isub x, y |
|
|
.. inst:: a = isub x, y |
|
|
|
|
|
|
|
|
Wrapping integer subtraction: :math:`a := x - y \pmod{2^B}`. This |
|
|
Wrapping integer subtraction: :math:`a := x - y \pmod{2^B}`. This |
|
|
instruction does not depend on the signed/unsigned interpretation of the |
|
|
instruction does not depend on the signed/unsigned interpretation of the |
|
|
operands. |
|
|
operands. |
|
|
|
|
|
|
|
|
.. todo:: Overflow arithmetic |
|
|
Polymorphic over all integer types (vector and scalar). |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = isub_imm Imm, x |
|
|
|
|
|
|
|
|
|
|
|
Immediate subtraction. |
|
|
|
|
|
|
|
|
|
|
|
Also works as integer negation when :math:`Imm = 0`. Use :inst:`iadd_imm` with a |
|
|
|
|
|
negative immediate operand for the reverse immediate subtraction. |
|
|
|
|
|
|
|
|
|
|
|
:arg Imm: Immediate minuend. |
|
|
|
|
|
:arg iN x: Dynamic subtrahend. |
|
|
|
|
|
|
|
|
|
|
|
Polymorphic over all scalar integer types. |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: Integer overflow arithmetic |
|
|
|
|
|
|
|
|
Add instructions for add with carry out / carry in and so on. Enough to |
|
|
Add instructions for add with carry out / carry in and so on. Enough to |
|
|
implement larger integer types efficiently. It should also be possible to |
|
|
implement larger integer types efficiently. It should also be possible to |
|
|
legalize :type:`i64` arithmetic to terms of :type:`i32` operations. |
|
|
legalize :type:`i64` arithmetic to terms of :type:`i32` operations. |
|
|
|
|
|
|
|
|
.. inst:: a = ineg x |
|
|
|
|
|
|
|
|
|
|
|
Wrapping integer negation: :math:`a := -x \pmod{2^B}`. This instruction does |
|
|
|
|
|
not depend on the signed/unsigned interpretation of the operand. |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = imul x, y |
|
|
.. inst:: a = imul x, y |
|
|
|
|
|
|
|
|
Wrapping integer multiplication: :math:`a := x y \pmod{2^B}`. This |
|
|
Wrapping integer multiplication: :math:`a := x y \pmod{2^B}`. This |
|
|
instruction does not depend on the signed/unsigned interpretation of the |
|
|
instruction does not depend on the signed/unsigned interpretation of the |
|
|
operands. |
|
|
operands. |
|
|
|
|
|
|
|
|
|
|
|
Polymorphic over all integer types (vector and scalar). |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = imul_imm x, Imm |
|
|
|
|
|
|
|
|
|
|
|
Integer multiplication by immediate constant. |
|
|
|
|
|
|
|
|
|
|
|
Polymorphic over all scalar integer types. |
|
|
|
|
|
|
|
|
.. todo:: Larger multiplication results. |
|
|
.. todo:: Larger multiplication results. |
|
|
|
|
|
|
|
|
For example, ``smulx`` which multiplies :type:`i32` operands to produce a |
|
|
For example, ``smulx`` which multiplies :type:`i32` operands to produce a |
|
@ -741,10 +781,11 @@ Integer operations |
|
|
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`. This |
|
|
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`. This |
|
|
operation traps if the divisor is zero. |
|
|
operation traps if the divisor is zero. |
|
|
|
|
|
|
|
|
.. todo:: |
|
|
.. inst:: a = udiv_imm x, Imm |
|
|
Add a ``udiv_imm`` variant with an immediate divisor greater than 1. |
|
|
|
|
|
This is useful for pattern-matching divide-by-constant, and this |
|
|
Unsigned integer division by an immediate constant. |
|
|
instruction would be non-trapping. |
|
|
|
|
|
|
|
|
This instruction never traps because a divisor of zero is not allowed. |
|
|
|
|
|
|
|
|
.. inst:: a = sdiv x, y |
|
|
.. inst:: a = sdiv x, y |
|
|
|
|
|
|
|
@ -753,37 +794,52 @@ Integer operations |
|
|
the result is not representable in :math:`B` bits two's complement. This only |
|
|
the result is not representable in :math:`B` bits two's complement. This only |
|
|
happens when :math:`x = -2^{B-1}, y = -1`. |
|
|
happens when :math:`x = -2^{B-1}, y = -1`. |
|
|
|
|
|
|
|
|
.. todo:: |
|
|
.. inst:: a = sdiv_imm x, Imm |
|
|
Add a ``sdiv_imm`` variant with an immediate non-zero divisor. This is |
|
|
|
|
|
useful for pattern-matching divide-by-constant, and this instruction |
|
|
Signed integer division by an immediate constant. |
|
|
would be non-trapping. Don't allow divisors 0, 1, or -1. |
|
|
|
|
|
|
|
|
This instruction never traps because a divisor of -1 or 0 is not allowed. |
|
|
|
|
|
|
|
|
.. inst:: a = urem x, y |
|
|
.. inst:: a = urem x, y |
|
|
|
|
|
|
|
|
Unsigned integer remainder. This operation traps if the divisor is zero. |
|
|
Unsigned integer remainder. |
|
|
|
|
|
|
|
|
|
|
|
This operation traps if the divisor is zero. |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = urem_imm x, Imm |
|
|
|
|
|
|
|
|
.. todo:: |
|
|
Unsigned integer remainder with immediate divisor. |
|
|
Add a ``urem_imm`` non-trapping variant. |
|
|
|
|
|
|
|
|
This instruction never traps because a divisor of zero is not allowed. |
|
|
|
|
|
|
|
|
.. inst:: a = srem x, y |
|
|
.. inst:: a = srem x, y |
|
|
|
|
|
|
|
|
Signed integer remainder. This operation traps if the divisor is zero. |
|
|
Signed integer remainder. |
|
|
|
|
|
|
|
|
|
|
|
This operation traps if the divisor is zero. |
|
|
|
|
|
|
|
|
|
|
|
.. todo:: Integer remainder vs modulus. |
|
|
|
|
|
|
|
|
.. todo:: |
|
|
|
|
|
Clarify whether the result has the sign of the divisor or the dividend. |
|
|
Clarify whether the result has the sign of the divisor or the dividend. |
|
|
Should we add a ``smod`` instruction for the case where the result has |
|
|
Should we add a ``smod`` instruction for the case where the result has |
|
|
the same sign as the divisor? |
|
|
the same sign as the divisor? |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = srem_imm x, Imm |
|
|
|
|
|
|
|
|
|
|
|
Signed integer remainder with immediate divisor. |
|
|
|
|
|
|
|
|
|
|
|
This instruction never traps because a divisor of 0 or -1 is not allowed. |
|
|
|
|
|
|
|
|
.. todo:: Minimum / maximum. |
|
|
.. todo:: Minimum / maximum. |
|
|
|
|
|
|
|
|
NEON has ``smin``, ``smax``, ``umin``, and ``umax`` instructions. We should |
|
|
NEON has ``smin``, ``smax``, ``umin``, and ``umax`` instructions. We should |
|
|
replicate those for both scalar and vector integer types. Even if the |
|
|
replicate those for both scalar and vector integer types. Even if the |
|
|
target ISA doesn't have scalar operations, these are good pattern mtching |
|
|
target ISA doesn't have scalar operations, these are good pattern matching |
|
|
targets. |
|
|
targets. |
|
|
|
|
|
|
|
|
.. todo:: Saturating arithmetic. |
|
|
.. todo:: Saturating arithmetic. |
|
|
|
|
|
|
|
|
Mostly for SIMD use, but again these are good paterns to contract. |
|
|
Mostly for SIMD use, but again these are good patterns for contraction. |
|
|
Something like ``usatadd``, ``usatsub``, ``ssatadd``, and ``ssatsub`` is a |
|
|
Something like ``usatadd``, ``usatsub``, ``ssatadd``, and ``ssatsub`` is a |
|
|
good start. |
|
|
good start. |
|
|
|
|
|
|
|
@ -825,9 +881,9 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Rotate the bits in ``x`` by ``y`` places. |
|
|
Rotate the bits in ``x`` by ``y`` places. |
|
|
|
|
|
|
|
|
:param x: Integer value to be rotated. |
|
|
:arg T x: Integer value to be rotated. |
|
|
:param y: Number of bits to shift. Any integer type, not necessarily the |
|
|
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily |
|
|
same type as ``x``. |
|
|
the same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
|
|
|
|
|
|
.. inst:: a = rotr x, y |
|
|
.. inst:: a = rotr x, y |
|
@ -836,9 +892,9 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Rotate the bits in ``x`` by ``y`` places. |
|
|
Rotate the bits in ``x`` by ``y`` places. |
|
|
|
|
|
|
|
|
:param x: Integer value to be rotated. |
|
|
:arg T x: Integer value to be rotated. |
|
|
:param y: Number of bits to shift. Any integer type, not necessarily the |
|
|
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily |
|
|
same type as ``x``. |
|
|
the same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
|
|
|
|
|
|
.. inst:: a = ishl x, y |
|
|
.. inst:: a = ishl x, y |
|
@ -848,9 +904,9 @@ Bitwise operations |
|
|
|
|
|
|
|
|
The shift amount is masked to the size of ``x``. |
|
|
The shift amount is masked to the size of ``x``. |
|
|
|
|
|
|
|
|
:param x: Integer value to be shifted. |
|
|
:arg T x: Integer value to be shifted. |
|
|
:param y: Number of bits to shift. Any integer type, not necessarily the |
|
|
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily |
|
|
same type as ``x``. |
|
|
the same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
|
|
|
|
|
|
When shifting a B-bits integer type, this instruction computes: |
|
|
When shifting a B-bits integer type, this instruction computes: |
|
@ -868,9 +924,9 @@ Bitwise operations |
|
|
|
|
|
|
|
|
The shift amount is masked to the size of the register. |
|
|
The shift amount is masked to the size of the register. |
|
|
|
|
|
|
|
|
:param x: Integer value to be shifted. |
|
|
:arg T x: Integer value to be shifted. |
|
|
:param y: Number of bits to shift. Can be any integer type, not necessarily |
|
|
:arg iN y: Number of bits to shift. Can be any scalar integer type, not |
|
|
the same type as ``x``. |
|
|
necessarily the same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
|
|
|
|
|
|
When shifting a B-bits integer type, this instruction computes: |
|
|
When shifting a B-bits integer type, this instruction computes: |
|
@ -888,9 +944,9 @@ Bitwise operations |
|
|
|
|
|
|
|
|
The shift amount is masked to the size of the register. |
|
|
The shift amount is masked to the size of the register. |
|
|
|
|
|
|
|
|
:param x: Integer value to be shifted. |
|
|
:arg T x: Integer value to be shifted. |
|
|
:param y: Number of bits to shift. Can be any integer type, not necessarily |
|
|
:arg iN y: Number of bits to shift. Can be any scalar integer type, not |
|
|
the same type as ``x``. |
|
|
necessarily the same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
:rtype: Same type as ``x``. |
|
|
|
|
|
|
|
|
.. todo:: Add ``sshr_imm`` variant with an immediate ``y``. |
|
|
.. todo:: Add ``sshr_imm`` variant with an immediate ``y``. |
|
@ -899,7 +955,7 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Count leading zero bits. |
|
|
Count leading zero bits. |
|
|
|
|
|
|
|
|
:param x: Integer value. |
|
|
:arg x: Integer value. |
|
|
:rtype: :type:`i8` |
|
|
:rtype: :type:`i8` |
|
|
|
|
|
|
|
|
Starting from the MSB in ``x``, count the number of zero bits before |
|
|
Starting from the MSB in ``x``, count the number of zero bits before |
|
@ -910,7 +966,7 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Count leading sign bits. |
|
|
Count leading sign bits. |
|
|
|
|
|
|
|
|
:param x: Integer value. |
|
|
:arg x: Integer value. |
|
|
:rtype: :type:`i8` |
|
|
:rtype: :type:`i8` |
|
|
|
|
|
|
|
|
Starting from the MSB after the sign bit in ``x``, count the number of |
|
|
Starting from the MSB after the sign bit in ``x``, count the number of |
|
@ -921,7 +977,7 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Count trailing zeros. |
|
|
Count trailing zeros. |
|
|
|
|
|
|
|
|
:param x: Integer value. |
|
|
:arg x: Integer value. |
|
|
:rtype: :type:`i8` |
|
|
:rtype: :type:`i8` |
|
|
|
|
|
|
|
|
Starting from the LSB in ``x``, count the number of zero bits before |
|
|
Starting from the LSB in ``x``, count the number of zero bits before |
|
@ -932,7 +988,7 @@ Bitwise operations |
|
|
|
|
|
|
|
|
Population count |
|
|
Population count |
|
|
|
|
|
|
|
|
:param x: Integer value. |
|
|
:arg x: Integer value. |
|
|
:rtype: :type:`i8` |
|
|
:rtype: :type:`i8` |
|
|
|
|
|
|
|
|
Count the number of one bits in ``x``. |
|
|
Count the number of one bits in ``x``. |
|
@ -941,12 +997,14 @@ Bitwise operations |
|
|
Floating point operations |
|
|
Floating point operations |
|
|
------------------------- |
|
|
------------------------- |
|
|
|
|
|
|
|
|
.. inst:: a = fcmp cond, x, y |
|
|
These operations generally follow IEEE 754-2008 semantics. |
|
|
|
|
|
|
|
|
|
|
|
.. inst:: a = fcmp Cond, x, y |
|
|
|
|
|
|
|
|
Floating point comparison. |
|
|
Floating point comparison. |
|
|
|
|
|
|
|
|
:param cond: Condition code determining how ``x`` and ``y`` are compared. |
|
|
:arg Cond: Condition code determining how ``x`` and ``y`` are compared. |
|
|
:param x, y: Floating point scalar or vector values of the same type. |
|
|
:arg x,y: Floating point scalar or vector values of the same type. |
|
|
:rtype: :type:`bool` or :type:`boolxN` with the same number of lanes as |
|
|
:rtype: :type:`bool` or :type:`boolxN` with the same number of lanes as |
|
|
``x`` and ``y``. |
|
|
``x`` and ``y``. |
|
|
|
|
|
|
|
@ -978,7 +1036,7 @@ Floating point operations |
|
|
|
|
|
|
|
|
Floating point negation. |
|
|
Floating point negation. |
|
|
|
|
|
|
|
|
:returns: ``x`` with its sign bit inverted. |
|
|
:result: ``x`` with its sign bit inverted. |
|
|
|
|
|
|
|
|
Note that this is a pure bitwise operation. |
|
|
Note that this is a pure bitwise operation. |
|
|
|
|
|
|
|
@ -986,7 +1044,7 @@ Floating point operations |
|
|
|
|
|
|
|
|
Floating point absolute value. |
|
|
Floating point absolute value. |
|
|
|
|
|
|
|
|
:returns: ``x`` with its sign bit cleared. |
|
|
:result: ``x`` with its sign bit cleared. |
|
|
|
|
|
|
|
|
Note that this is a pure bitwise operation. |
|
|
Note that this is a pure bitwise operation. |
|
|
|
|
|
|
|
@ -994,18 +1052,19 @@ Floating point operations |
|
|
|
|
|
|
|
|
Floating point copy sign. |
|
|
Floating point copy sign. |
|
|
|
|
|
|
|
|
:returns: ``x`` with its sign changed to that of ``y``. |
|
|
:result: ``x`` with its sign changed to that of ``y``. |
|
|
|
|
|
|
|
|
Note that this is a pure bitwise operation. The sign bit from ``y`` is |
|
|
Note that this is a pure bitwise operation. The sign bit from ``y`` is |
|
|
copied to the sign bit of ``x``. |
|
|
copied to the sign bit of ``x``. |
|
|
|
|
|
|
|
|
.. inst:: fmul x, y |
|
|
.. inst:: a = fmul x, y |
|
|
.. inst:: fdiv x, y |
|
|
.. inst:: a = fdiv x, y |
|
|
.. inst:: fmin x, y |
|
|
.. inst:: a = fmin x, y |
|
|
.. inst:: fminnum x, y |
|
|
.. inst:: a = fminnum x, y |
|
|
.. inst:: fmax x, y |
|
|
.. inst:: a = fmax x, y |
|
|
.. inst:: fmaxnum x, y |
|
|
.. inst:: a = fmaxnum x, y |
|
|
.. inst:: ceil x |
|
|
|
|
|
|
|
|
.. inst:: a = ceil x |
|
|
|
|
|
|
|
|
Round floating point round to integral, towards positive infinity. |
|
|
Round floating point round to integral, towards positive infinity. |
|
|
|
|
|
|
|
@ -1053,6 +1112,7 @@ Conversion operations |
|
|
.. inst:: a = cvt_utof x |
|
|
.. inst:: a = cvt_utof x |
|
|
.. inst:: a = cvt_stof x |
|
|
.. inst:: a = cvt_stof x |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Glossary |
|
|
Glossary |
|
|
======== |
|
|
======== |
|
|
|
|
|
|
|
|