Move instruction definitions into meta.

Use the meta language to define instructions, just insert 'autoinst' references
in langref.
This commit is contained in:
Jakob Stoklund Olesen
2016-03-29 15:22:16 -07:00
parent 20183554a4
commit a2db4b680e
2 changed files with 314 additions and 240 deletions

View File

@@ -625,7 +625,7 @@ 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
:inst:`band` / :inst:`band_imm`), but in general an instruction is required to
load a constant into an SSA value.
.. inst:: a = iconst N
@@ -747,43 +747,10 @@ Integer operations
sle ule Less than or equal
====== ======== =========
.. inst:: a = iadd x, y
Wrapping integer addition: :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 = 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.
.. autoinst:: iadd
.. autoinst:: iadd_imm
.. autoinst:: isub
.. autoinst:: isub_imm
.. todo:: Integer overflow arithmetic
@@ -791,78 +758,22 @@ Integer operations
implement larger integer types efficiently. It should also be possible to
legalize :type:`i64` arithmetic to terms of :type:`i32` operations.
.. inst:: a = imul x, y
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.
.. autoinst:: imul
.. autoinst:: imul_imm
.. todo:: Larger multiplication results.
For example, ``smulx`` which multiplies :type:`i32` operands to produce a
:type:`i64` result. Alternatively, ``smulhi`` and ``smullo`` pairs.
.. inst:: a = udiv x, y
Unsigned integer division: :math:`a := \lfloor {x \over y} \rfloor`. This
operation traps if the divisor is zero.
.. inst:: a = udiv_imm x, Imm
Unsigned integer division by an immediate constant.
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.
.. autoinst:: udiv
.. autoinst:: udiv_imm
.. autoinst:: sdiv
.. autoinst:: sdiv_imm
.. autoinst:: urem
.. autoinst:: urem_imm
.. autoinst:: srem
.. autoinst:: srem_imm
.. todo:: Minimum / maximum.
@@ -880,153 +791,41 @@ Integer 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.
:rtype: bool, iB, iBxN, fBxN?
.. 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?
.. autoinst:: band
.. autoinst:: bor
.. autoinst:: bxor
.. autoinst:: bnot
.. todo:: Redundant bitwise operators.
ARM has instructions like ``bic(x,y) = x & ~y``, ``orn(x,y) = x | ~y``, and
``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.
: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``.
The bit-counting instructions below are scalar only.
.. autoinst:: clz
.. autoinst:: cls
.. autoinst:: ctz
.. autoinst:: popcnt
Floating point operations
-------------------------

275
meta/cretonne/base.py Normal file
View 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)