Move instruction definitions into meta.
Use the meta language to define instructions, just insert 'autoinst' references in langref.
This commit is contained in:
@@ -625,7 +625,7 @@ Operations
|
|||||||
The remaining instruction set is mostly arithmetic.
|
The remaining instruction set is mostly arithmetic.
|
||||||
|
|
||||||
A few instructions have variants that take immediate operands (e.g.,
|
A few instructions have variants that take immediate operands (e.g.,
|
||||||
:inst:`and` / :inst:`and_imm`), but in general an instruction is required to
|
:inst:`band` / :inst:`band_imm`), but in general an instruction is required to
|
||||||
load a constant into an SSA value.
|
load a constant into an SSA value.
|
||||||
|
|
||||||
.. inst:: a = iconst N
|
.. inst:: a = iconst N
|
||||||
@@ -747,43 +747,10 @@ Integer operations
|
|||||||
sle ule Less than or equal
|
sle ule Less than or equal
|
||||||
====== ======== =========
|
====== ======== =========
|
||||||
|
|
||||||
.. inst:: a = iadd x, y
|
.. autoinst:: iadd
|
||||||
|
.. autoinst:: iadd_imm
|
||||||
Wrapping integer addition: :math:`a := x + y \pmod{2^B}`. This instruction
|
.. autoinst:: isub
|
||||||
does not depend on the signed/unsigned interpretation of the operands.
|
.. autoinst:: isub_imm
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
Wrapping integer subtraction: :math:`a := x - y \pmod{2^B}`. This
|
|
||||||
instruction does not depend on the signed/unsigned interpretation of the
|
|
||||||
operands.
|
|
||||||
|
|
||||||
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
|
.. todo:: Integer overflow arithmetic
|
||||||
|
|
||||||
@@ -791,78 +758,22 @@ Integer operations
|
|||||||
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 = imul x, y
|
.. autoinst:: imul
|
||||||
|
.. autoinst:: imul_imm
|
||||||
Wrapping integer multiplication: :math:`a := x y \pmod{2^B}`. This
|
|
||||||
instruction does not depend on the signed/unsigned interpretation of the
|
|
||||||
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
|
||||||
:type:`i64` result. Alternatively, ``smulhi`` and ``smullo`` pairs.
|
:type:`i64` result. Alternatively, ``smulhi`` and ``smullo`` pairs.
|
||||||
|
|
||||||
.. inst:: a = udiv x, y
|
.. autoinst:: udiv
|
||||||
|
.. autoinst:: udiv_imm
|
||||||
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`. This
|
.. autoinst:: sdiv
|
||||||
operation traps if the divisor is zero.
|
.. autoinst:: sdiv_imm
|
||||||
|
.. autoinst:: urem
|
||||||
.. inst:: a = udiv_imm x, Imm
|
.. autoinst:: urem_imm
|
||||||
|
.. autoinst:: srem
|
||||||
Unsigned integer division by an immediate constant.
|
.. autoinst:: srem_imm
|
||||||
|
|
||||||
This instruction never traps because a divisor of zero is not allowed.
|
|
||||||
|
|
||||||
.. inst:: a = sdiv x, y
|
|
||||||
|
|
||||||
Signed integer division rounded toward zero: :math:`a := sign(xy) \lfloor
|
|
||||||
{|x| \over |y|}\rfloor`. This operation traps if the divisor is zero, or if
|
|
||||||
the result is not representable in :math:`B` bits two's complement. This only
|
|
||||||
happens when :math:`x = -2^{B-1}, y = -1`.
|
|
||||||
|
|
||||||
.. inst:: a = sdiv_imm x, Imm
|
|
||||||
|
|
||||||
Signed integer division by an immediate constant.
|
|
||||||
|
|
||||||
This instruction never traps because a divisor of -1 or 0 is not allowed.
|
|
||||||
|
|
||||||
.. inst:: a = urem x, y
|
|
||||||
|
|
||||||
Unsigned integer remainder.
|
|
||||||
|
|
||||||
This operation traps if the divisor is zero.
|
|
||||||
|
|
||||||
.. inst:: a = urem_imm x, Imm
|
|
||||||
|
|
||||||
Unsigned integer remainder with immediate divisor.
|
|
||||||
|
|
||||||
This instruction never traps because a divisor of zero is not allowed.
|
|
||||||
|
|
||||||
.. inst:: a = srem x, y
|
|
||||||
|
|
||||||
Signed integer remainder.
|
|
||||||
|
|
||||||
This operation traps if the divisor is zero.
|
|
||||||
|
|
||||||
.. todo:: Integer remainder vs modulus.
|
|
||||||
|
|
||||||
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
|
|
||||||
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.
|
||||||
|
|
||||||
@@ -880,153 +791,41 @@ Integer operations
|
|||||||
Bitwise operations
|
Bitwise operations
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
.. inst:: a = and x, y
|
The bitwise operations and operate on any value type: Integers, floating point
|
||||||
|
numbers, and booleans. When operating on integer or floating point types, the
|
||||||
|
bitwise operations are working on the binary representation of the values. When
|
||||||
|
operating on boolean values, the bitwise operations work as logical operators.
|
||||||
|
|
||||||
Bitwise and.
|
.. autoinst:: band
|
||||||
|
.. autoinst:: bor
|
||||||
:rtype: bool, iB, iBxN, fBxN?
|
.. autoinst:: bxor
|
||||||
|
.. autoinst:: bnot
|
||||||
.. inst:: a = or x, y
|
|
||||||
|
|
||||||
Bitwise or.
|
|
||||||
|
|
||||||
:rtype: bool, iB, iBxN, fBxN?
|
|
||||||
|
|
||||||
.. inst:: a = xor x, y
|
|
||||||
|
|
||||||
Bitwise xor.
|
|
||||||
|
|
||||||
:rtype: bool, iB, iBxN, fBxN?
|
|
||||||
|
|
||||||
.. inst:: a = not x
|
|
||||||
|
|
||||||
Bitwise not.
|
|
||||||
|
|
||||||
:rtype: bool, iB, iBxN, fBxN?
|
|
||||||
|
|
||||||
.. todo:: Redundant bitwise operators.
|
.. todo:: Redundant bitwise operators.
|
||||||
|
|
||||||
ARM has instructions like ``bic(x,y) = x & ~y``, ``orn(x,y) = x | ~y``, and
|
ARM has instructions like ``bic(x,y) = x & ~y``, ``orn(x,y) = x | ~y``, and
|
||||||
``eon(x,y) = x ^ ~y``.
|
``eon(x,y) = x ^ ~y``.
|
||||||
|
|
||||||
.. inst:: a = rotl x, y
|
The shift and rotate operations only work on integer types (scalar and vector).
|
||||||
|
The shift amount does not have to be the same type as the value being shifted.
|
||||||
|
Only the low `B` bits of the shift amount is significant.
|
||||||
|
|
||||||
Rotate left.
|
When operating on an integer vector type, the shift amount is still a scalar
|
||||||
|
type, and all the lanes are shifted the same amount. The shift amount is masked
|
||||||
|
to the number of bits in a *lane*, not the full size of the vector type.
|
||||||
|
|
||||||
Rotate the bits in ``x`` by ``y`` places.
|
.. autoinst:: rotl
|
||||||
|
.. autoinst:: rotr
|
||||||
|
.. autoinst:: ishl
|
||||||
|
.. autoinst:: ushr
|
||||||
|
.. autoinst:: sshr
|
||||||
|
|
||||||
:arg T x: Integer value to be rotated.
|
The bit-counting instructions below are scalar only.
|
||||||
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily
|
|
||||||
the same type as ``x``.
|
|
||||||
:rtype: Same type as ``x``.
|
|
||||||
|
|
||||||
.. inst:: a = rotr x, y
|
|
||||||
|
|
||||||
Rotate right.
|
|
||||||
|
|
||||||
Rotate the bits in ``x`` by ``y`` places.
|
|
||||||
|
|
||||||
:arg T x: Integer value to be rotated.
|
|
||||||
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily
|
|
||||||
the same type as ``x``.
|
|
||||||
:rtype: Same type as ``x``.
|
|
||||||
|
|
||||||
.. inst:: a = ishl x, y
|
|
||||||
|
|
||||||
Integer shift left. Shift the bits in ``x`` towards the MSB by ``y``
|
|
||||||
places. Shift in zero bits to the LSB.
|
|
||||||
|
|
||||||
The shift amount is masked to the size of ``x``.
|
|
||||||
|
|
||||||
:arg T x: Integer value to be shifted.
|
|
||||||
:arg iN y: Number of bits to shift. Any scalar integer type, not necessarily
|
|
||||||
the same type as ``x``.
|
|
||||||
:rtype: Same type as ``x``.
|
|
||||||
|
|
||||||
When shifting a B-bits integer type, this instruction computes:
|
|
||||||
|
|
||||||
.. math::
|
|
||||||
s &:= y \pmod B, \\
|
|
||||||
a &:= x \cdot 2^s \pmod{2^B}.
|
|
||||||
|
|
||||||
.. todo:: Add ``ishl_imm`` variant with an immediate ``y``.
|
|
||||||
|
|
||||||
.. inst:: a = ushr x, y
|
|
||||||
|
|
||||||
Unsigned shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
|
||||||
shifting in zero bits to the MSB. Also called a *logical shift*.
|
|
||||||
|
|
||||||
The shift amount is masked to the size of the register.
|
|
||||||
|
|
||||||
:arg T x: Integer value to be shifted.
|
|
||||||
:arg iN y: Number of bits to shift. Can be any scalar integer type, not
|
|
||||||
necessarily the same type as ``x``.
|
|
||||||
:rtype: Same type as ``x``.
|
|
||||||
|
|
||||||
When shifting a B-bits integer type, this instruction computes:
|
|
||||||
|
|
||||||
.. math::
|
|
||||||
s &:= y \pmod B, \\
|
|
||||||
a &:= \lfloor x \cdot 2^{-s} \rfloor.
|
|
||||||
|
|
||||||
.. todo:: Add ``ushr_imm`` variant with an immediate ``y``.
|
|
||||||
|
|
||||||
.. inst:: a = sshr x, y
|
|
||||||
|
|
||||||
Signed shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
|
||||||
shifting in sign bits to the MSB. Also called an *arithmetic shift*.
|
|
||||||
|
|
||||||
The shift amount is masked to the size of the register.
|
|
||||||
|
|
||||||
:arg T x: Integer value to be shifted.
|
|
||||||
:arg iN y: Number of bits to shift. Can be any scalar integer type, not
|
|
||||||
necessarily the same type as ``x``.
|
|
||||||
:rtype: Same type as ``x``.
|
|
||||||
|
|
||||||
.. todo:: Add ``sshr_imm`` variant with an immediate ``y``.
|
|
||||||
|
|
||||||
.. inst:: a = clz x
|
|
||||||
|
|
||||||
Count leading zero bits.
|
|
||||||
|
|
||||||
:arg x: Integer value.
|
|
||||||
:rtype: :type:`i8`
|
|
||||||
|
|
||||||
Starting from the MSB in ``x``, count the number of zero bits before
|
|
||||||
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
|
||||||
bits.
|
|
||||||
|
|
||||||
.. inst:: a = cls x
|
|
||||||
|
|
||||||
Count leading sign bits.
|
|
||||||
|
|
||||||
:arg x: Integer value.
|
|
||||||
:rtype: :type:`i8`
|
|
||||||
|
|
||||||
Starting from the MSB after the sign bit in ``x``, count the number of
|
|
||||||
consecutive bits identical to the sign bit. When ``x`` is 0 or -1, returns
|
|
||||||
one less than the size of x in bits.
|
|
||||||
|
|
||||||
.. inst:: a = ctz x
|
|
||||||
|
|
||||||
Count trailing zeros.
|
|
||||||
|
|
||||||
:arg x: Integer value.
|
|
||||||
:rtype: :type:`i8`
|
|
||||||
|
|
||||||
Starting from the LSB in ``x``, count the number of zero bits before
|
|
||||||
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
|
||||||
bits.
|
|
||||||
|
|
||||||
.. inst:: a = popcnt x
|
|
||||||
|
|
||||||
Population count
|
|
||||||
|
|
||||||
:arg x: Integer value.
|
|
||||||
:rtype: :type:`i8`
|
|
||||||
|
|
||||||
Count the number of one bits in ``x``.
|
|
||||||
|
|
||||||
|
.. autoinst:: clz
|
||||||
|
.. autoinst:: cls
|
||||||
|
.. autoinst:: ctz
|
||||||
|
.. autoinst:: popcnt
|
||||||
|
|
||||||
Floating point operations
|
Floating point operations
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
275
meta/cretonne/base.py
Normal file
275
meta/cretonne/base.py
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
"""
|
||||||
|
Cretonne base instruction set.
|
||||||
|
|
||||||
|
This module defines the basic Cretonne instruction set that all targets support.
|
||||||
|
"""
|
||||||
|
from . import TypeVar, Operand, Instruction
|
||||||
|
from types import i8
|
||||||
|
from immediates import imm64
|
||||||
|
|
||||||
|
Int = TypeVar('Int', 'A scalar or vector integer type')
|
||||||
|
iB = TypeVar('iB', 'A scalar integer type')
|
||||||
|
|
||||||
|
a = Operand('a', Int)
|
||||||
|
x = Operand('x', Int)
|
||||||
|
y = Operand('y', Int)
|
||||||
|
|
||||||
|
iadd = Instruction('iadd', r"""
|
||||||
|
Wrapping integer addition: :math:`a := x + y \pmod{2^B}`.
|
||||||
|
|
||||||
|
This instruction does not depend on the signed/unsigned interpretation of
|
||||||
|
the operands.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
isub = Instruction('isub', r"""
|
||||||
|
Wrapping integer subtraction: :math:`a := x - y \pmod{2^B}`.
|
||||||
|
|
||||||
|
This instruction does not depend on the signed/unsigned interpretation of
|
||||||
|
the operands.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
imul = Instruction('imul', r"""
|
||||||
|
Wrapping integer multiplication: :math:`a := x y \pmod{2^B}`.
|
||||||
|
|
||||||
|
This instruction does not depend on the signed/unsigned interpretation of
|
||||||
|
the
|
||||||
|
operands.
|
||||||
|
|
||||||
|
Polymorphic over all integer types (vector and scalar).
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
udiv = Instruction('udiv', r"""
|
||||||
|
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`.
|
||||||
|
|
||||||
|
This operation traps if the divisor is zero.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
sdiv = Instruction('sdiv', r"""
|
||||||
|
Signed integer division rounded toward zero: :math:`a := sign(xy) \lfloor
|
||||||
|
{|x| \over |y|}\rfloor`.
|
||||||
|
|
||||||
|
This operation traps if the divisor is zero, or if the result is not
|
||||||
|
representable in :math:`B` bits two's complement. This only happens when
|
||||||
|
:math:`x = -2^{B-1}, y = -1`.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
urem = Instruction('urem', """
|
||||||
|
Unsigned integer remainder.
|
||||||
|
|
||||||
|
This operation traps if the divisor is zero.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
srem = Instruction('srem', """
|
||||||
|
Signed integer remainder.
|
||||||
|
|
||||||
|
This operation traps if the divisor is zero.
|
||||||
|
|
||||||
|
.. todo:: Integer remainder vs modulus.
|
||||||
|
|
||||||
|
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
|
||||||
|
the same sign as the divisor?
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
a = Operand('a', iB)
|
||||||
|
x = Operand('x', iB)
|
||||||
|
Y = Operand('Y', imm64)
|
||||||
|
|
||||||
|
iadd_imm = Instruction('iadd_imm', """
|
||||||
|
Add immediate integer.
|
||||||
|
|
||||||
|
Same as :inst:`iadd`, but one operand is an immediate constant.
|
||||||
|
|
||||||
|
Polymorphic over all scalar integer types, but does not support vector
|
||||||
|
types.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
imul_imm = Instruction('imul_imm', """
|
||||||
|
Integer multiplication by immediate constant.
|
||||||
|
|
||||||
|
Polymorphic over all scalar integer types.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
udiv_imm = Instruction('udiv_imm', """
|
||||||
|
Unsigned integer division by an immediate constant.
|
||||||
|
|
||||||
|
This instruction never traps because a divisor of zero is not allowed.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
sdiv_imm = Instruction('sdiv_imm', """
|
||||||
|
Signed integer division by an immediate constant.
|
||||||
|
|
||||||
|
This instruction never traps because a divisor of -1 or 0 is not allowed.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
urem_imm = Instruction('urem_imm', """
|
||||||
|
Unsigned integer remainder with immediate divisor.
|
||||||
|
|
||||||
|
This instruction never traps because a divisor of zero is not allowed.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
srem_imm = Instruction('srem_imm', """
|
||||||
|
Signed integer remainder with immediate divisor.
|
||||||
|
|
||||||
|
This instruction never traps because a divisor of 0 or -1 is not allowed.
|
||||||
|
""",
|
||||||
|
ins=(x,Y), outs=a)
|
||||||
|
|
||||||
|
# Swap x and y for isub_imm.
|
||||||
|
X = Operand('X', imm64)
|
||||||
|
y = Operand('y', iB)
|
||||||
|
|
||||||
|
isub_imm = Instruction('isub_imm', """
|
||||||
|
Immediate wrapping subtraction: :math:`a := X - y \pmod{2^B}`.
|
||||||
|
|
||||||
|
Also works as integer negation when :math:`X = 0`. Use :inst:`iadd_imm` with a
|
||||||
|
negative immediate operand for the reverse immediate subtraction.
|
||||||
|
|
||||||
|
Polymorphic over all scalar integer types, but does not support vector
|
||||||
|
types.
|
||||||
|
""",
|
||||||
|
ins=(X,y), outs=a)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bitwise operations.
|
||||||
|
#
|
||||||
|
|
||||||
|
# TODO: Which types should permit boolean operations? Any reason to restrict?
|
||||||
|
bits = TypeVar('bits', 'Any integer, float, or boolean scalar or vector type')
|
||||||
|
x = Operand('x', bits)
|
||||||
|
y = Operand('y', bits)
|
||||||
|
a = Operand('a', bits)
|
||||||
|
|
||||||
|
band = Instruction('band', """
|
||||||
|
Bitwise and.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
bor = Instruction('bor', """
|
||||||
|
Bitwise or.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
bxor = Instruction('bxor', """
|
||||||
|
Bitwise xor.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
bnot = Instruction('bnot', """
|
||||||
|
Bitwise not.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
# Shift/rotate.
|
||||||
|
x = Operand('x', Int, doc='Scalar or vector value to shift')
|
||||||
|
y = Operand('y', iB, doc='Number of bits to shift')
|
||||||
|
a = Operand('a', Int)
|
||||||
|
|
||||||
|
rotl = Instruction('rotl', r"""
|
||||||
|
Rotate left.
|
||||||
|
|
||||||
|
Rotate the bits in ``x`` by ``y`` places.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
rotr = Instruction('rotr', r"""
|
||||||
|
Rotate right.
|
||||||
|
|
||||||
|
Rotate the bits in ``x`` by ``y`` places.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
ishl = Instruction('ishl', r"""
|
||||||
|
Integer shift left. Shift the bits in ``x`` towards the MSB by ``y``
|
||||||
|
places. Shift in zero bits to the LSB.
|
||||||
|
|
||||||
|
The shift amount is masked to the size of ``x``.
|
||||||
|
|
||||||
|
When shifting a B-bits integer type, this instruction computes:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
s &:= y \pmod B, \\
|
||||||
|
a &:= x \cdot 2^s \pmod{2^B}.
|
||||||
|
|
||||||
|
.. todo:: Add ``ishl_imm`` variant with an immediate ``y``.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
ushr = Instruction('ushr', r"""
|
||||||
|
Unsigned shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
||||||
|
shifting in zero bits to the MSB. Also called a *logical shift*.
|
||||||
|
|
||||||
|
The shift amount is masked to the size of the register.
|
||||||
|
|
||||||
|
When shifting a B-bits integer type, this instruction computes:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
s &:= y \pmod B, \\
|
||||||
|
a &:= \lfloor x \cdot 2^{-s} \rfloor.
|
||||||
|
|
||||||
|
.. todo:: Add ``ushr_imm`` variant with an immediate ``y``.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
sshr = Instruction('sshr', r"""
|
||||||
|
Signed shift right. Shift bits in ``x`` towards the LSB by ``y`` places,
|
||||||
|
shifting in sign bits to the MSB. Also called an *arithmetic shift*.
|
||||||
|
|
||||||
|
The shift amount is masked to the size of the register.
|
||||||
|
|
||||||
|
.. todo:: Add ``sshr_imm`` variant with an immediate ``y``.
|
||||||
|
""",
|
||||||
|
ins=(x,y), outs=a)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bit counting.
|
||||||
|
#
|
||||||
|
|
||||||
|
x = Operand('x', iB)
|
||||||
|
a = Operand('a', i8)
|
||||||
|
|
||||||
|
clz = Instruction('clz', r"""
|
||||||
|
Count leading zero bits.
|
||||||
|
|
||||||
|
Starting from the MSB in ``x``, count the number of zero bits before
|
||||||
|
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
||||||
|
bits.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
cls = Instruction('cls', r"""
|
||||||
|
Count leading sign bits.
|
||||||
|
|
||||||
|
Starting from the MSB after the sign bit in ``x``, count the number of
|
||||||
|
consecutive bits identical to the sign bit. When ``x`` is 0 or -1, returns
|
||||||
|
one less than the size of x in bits.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
ctz = Instruction('ctz', r"""
|
||||||
|
Count trailing zeros.
|
||||||
|
|
||||||
|
Starting from the LSB in ``x``, count the number of zero bits before
|
||||||
|
reaching the first one bit. When ``x`` is zero, returns the size of x in
|
||||||
|
bits.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
popcnt = Instruction('popcnt', r"""
|
||||||
|
Population count
|
||||||
|
|
||||||
|
Count the number of one bits in ``x``.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
Reference in New Issue
Block a user