diff --git a/docs/langref.rst b/docs/langref.rst index 12949ab691..d4b30780b4 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -437,6 +437,26 @@ accesses may trap, or they may work. Sometimes, operating systems catch alignment traps and emulate the misaligned memory access. +Extending loads and truncating stores +------------------------------------- + +Most ISAs provide instructions that load an integer value smaller than a register +and extends it to the width of the register. Similarly, store instructions that +only write the low bits of an integer register are common. + +Cretonne provides extending loads and truncation stores for 8, 16, and 32-bit +memory accesses. + +.. autoinst:: uload8 +.. autoinst:: sload8 +.. autoinst:: istore8 +.. autoinst:: uload16 +.. autoinst:: sload16 +.. autoinst:: istore16 +.. autoinst:: uload32 +.. autoinst:: sload32 +.. autoinst:: istore32 + Local variables --------------- diff --git a/lib/cretonne/meta/base/immediates.py b/lib/cretonne/meta/base/immediates.py index 2f8803e245..8e643bb9ee 100644 --- a/lib/cretonne/meta/base/immediates.py +++ b/lib/cretonne/meta/base/immediates.py @@ -91,7 +91,7 @@ floatcc = ImmediateKind( 'uge': 'UnorderedOrGreaterThanOrEqual', }) -#: Flags for memory operations like :inst:`load` and :inst:`store`. +#: Flags for memory operations like :cton:inst:`load` and :cton:inst:`store`. memflags = ImmediateKind( 'memflags', 'Memory operation flags', diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index 487dca1a89..a7c549ce93 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -231,6 +231,99 @@ store = Instruction( """, ins=(Flags, x, p, Offset)) +iExt8 = TypeVar( + 'iExt8', 'An integer type with more than 8 bits', + ints=(16, 64)) +x = Operand('x', iExt8) +a = Operand('a', iExt8) + +uload8 = Instruction( + 'uload8', r""" + Load 8 bits from memory at ``p + Offset`` and zero-extend. + + This is equivalent to ``load.i8`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +sload8 = Instruction( + 'sload8', r""" + Load 8 bits from memory at ``p + Offset`` and sign-extend. + + This is equivalent to ``load.i8`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +istore8 = Instruction( + 'istore8', r""" + Store the low 8 bits of ``x`` to memory at ``p + Offset``. + + This is equivalent to ``ireduce.i8`` followed by ``store.i8``. + """, + ins=(Flags, x, p, Offset)) + +iExt16 = TypeVar( + 'iExt16', 'An integer type with more than 16 bits', + ints=(32, 64)) +x = Operand('x', iExt16) +a = Operand('a', iExt16) + +uload16 = Instruction( + 'uload16', r""" + Load 16 bits from memory at ``p + Offset`` and zero-extend. + + This is equivalent to ``load.i16`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +sload16 = Instruction( + 'sload16', r""" + Load 16 bits from memory at ``p + Offset`` and sign-extend. + + This is equivalent to ``load.i16`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +istore16 = Instruction( + 'istore16', r""" + Store the low 16 bits of ``x`` to memory at ``p + Offset``. + + This is equivalent to ``ireduce.i16`` followed by ``store.i8``. + """, + ins=(Flags, x, p, Offset)) + +iExt32 = TypeVar( + 'iExt32', 'An integer type with more than 32 bits', + ints=(64, 64)) +x = Operand('x', iExt32) +a = Operand('a', iExt32) + +uload32 = Instruction( + 'uload32', r""" + Load 32 bits from memory at ``p + Offset`` and zero-extend. + + This is equivalent to ``load.i32`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +sload32 = Instruction( + 'sload32', r""" + Load 32 bits from memory at ``p + Offset`` and sign-extend. + + This is equivalent to ``load.i32`` followed by ``uextend``. + """, + ins=(Flags, p, Offset), outs=a) + +istore32 = Instruction( + 'istore32', r""" + Store the low 32 bits of ``x`` to memory at ``p + Offset``. + + This is equivalent to ``ireduce.i32`` followed by ``store.i8``. + """, + ins=(Flags, x, p, Offset)) + +x = Operand('x', Mem, doc='Value to be stored') +a = Operand('a', Mem, doc='Value loaded') + stack_load = Instruction( 'stack_load', r""" Load a value from a stack slot at the constant offset.