{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}

-- |
-- Module: EVM.Opcode.Internal
-- Copyright: 2018 Simon Shine
-- Maintainer: Simon Shine <shreddedglory@gmail.com>
-- License: MIT
--
-- This module exposes the 'Opcode'' abstract type.

module EVM.Opcode.Internal where

import Prelude hiding (LT, EQ, GT)

import           Control.Monad (void)
import           Data.Bits (shift)
import           Data.DoubleWord (Word256)
import           Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.List as List
import           Data.Word (Word8)

-- | An 'Opcode'' is an Ethereum VM Opcode with parameterised jumps.
--
-- For a plain opcode using the basic EVM stack-based jumps, use 'Opcode'
-- instead.
--
-- This type is used for defining and translating from annotated opcodes, e.g.
-- with labelled jumps.
data Opcode' j
  -- 0s: Stop and Arithmetic Operations
  = STOP              -- ^ 0x00
  | ADD               -- ^ 0x01
  | MUL               -- ^ 0x02
  | SUB               -- ^ 0x03
  | DIV               -- ^ 0x04
  | SDIV              -- ^ 0x05
  | MOD               -- ^ 0x06
  | SMOD              -- ^ 0x07
  | ADDMOD            -- ^ 0x08
  | MULMOD            -- ^ 0x09
  | EXP               -- ^ 0x0a
  | SIGNEXTEND        -- ^ 0x0b

  -- 10s: Comparison & Bitwise Logic Operations
  | LT                -- ^ 0x10
  | GT                -- ^ 0x11
  | SLT               -- ^ 0x12
  | SGT               -- ^ 0x13
  | EQ                -- ^ 0x14
  | ISZERO            -- ^ 0x15
  | AND               -- ^ 0x16
  | OR                -- ^ 0x17
  | XOR               -- ^ 0x18
  | NOT               -- ^ 0x19
  | BYTE              -- ^ 0x1a
  | SHL               -- ^ 0x1b, https://eips.ethereum.org/EIPS/eip-145
  | SHR               -- ^ 0x1c, https://eips.ethereum.org/EIPS/eip-145
  | SAR               -- ^ 0x1d, https://eips.ethereum.org/EIPS/eip-145

  -- 20s: SHA3
  | SHA3              -- ^ 0x20

  -- 30s: Environmental Information
  | ADDRESS           -- ^ 0x30
  | BALANCE           -- ^ 0x31
  | ORIGIN            -- ^ 0x32
  | CALLER            -- ^ 0x33
  | CALLVALUE         -- ^ 0x34
  | CALLDATALOAD      -- ^ 0x35
  | CALLDATASIZE      -- ^ 0x36
  | CALLDATACOPY      -- ^ 0x37
  | CODESIZE          -- ^ 0x38
  | CODECOPY          -- ^ 0x39
  | GASPRICE          -- ^ 0x3a
  | EXTCODESIZE       -- ^ 0x3b
  | EXTCODECOPY       -- ^ 0x3c
  | RETURNDATASIZE    -- ^ 0x3d, https://eips.ethereum.org/EIPS/eip-211
  | RETURNDATACOPY    -- ^ 0x3e, https://eips.ethereum.org/EIPS/eip-211
  | EXTCODEHASH       -- ^ 0x3f, https://eips.ethereum.org/EIPS/eip-1052

  -- 40s: Block Information
  | BLOCKHASH         -- ^ 0x40
  | COINBASE          -- ^ 0x41
  | TIMESTAMP         -- ^ 0x42
  | NUMBER            -- ^ 0x43
  | DIFFICULTY        -- ^ 0x44
  | GASLIMIT          -- ^ 0x45
  | CHAINID           -- ^ 0x46, https://eips.ethereum.org/EIPS/eip-1344
  | SELFBALANCE       -- ^ 0x47, https://eips.ethereum.org/EIPS/eip-1884

  -- 50s: Stack, Memory, Storage and Flow Operations
  | POP               -- ^ 0x50
  | MLOAD             -- ^ 0x51
  | MSTORE            -- ^ 0x52
  | MSTORE8           -- ^ 0x53
  | SLOAD             -- ^ 0x54
  | SSTORE            -- ^ 0x55
  | JUMP j            -- ^ 0x56
  | JUMPI j           -- ^ 0x57
  | PC                -- ^ 0x58
  | MSIZE             -- ^ 0x59
  | GAS               -- ^ 0x5a
  | JUMPDEST j        -- ^ 0x5b

  -- 60s & 70s: Push Operations
  | PUSH !Word256     -- ^ 0x60 - 0x7f (PUSH1 - PUSH32)
  | DUP !Ord16         -- ^ 0x80 - 0x8f ('DUP1' - 'DUP16')
  | SWAP !Ord16        -- ^ 0x90 - 0x9f ('SWAP1' - 'SWAP16')

  -- a0s: Logging Operations
  | LOG !Ord5         -- ^ 0xa0 - 0xa4 ('LOG0' - 'LOG4')

  -- f0s: System Operations
  | CREATE            -- ^ 0xf0
  | CALL              -- ^ 0xf1
  | CALLCODE          -- ^ 0xf2
  | RETURN            -- ^ 0xf3
  | DELEGATECALL      -- ^ 0xf4, https://eips.ethereum.org/EIPS/eip-7
  | CREATE2           -- ^ 0xf5, https://eips.ethereum.org/EIPS/eip-1014
  | STATICCALL        -- ^ 0xfa
  | REVERT            -- ^ 0xfd, https://eips.ethereum.org/EIPS/eip-140
  | INVALID           -- ^ 0xfe, https://eips.ethereum.org/EIPS/eip-141
  | SELFDESTRUCT      -- ^ 0xff, https://eips.ethereum.org/EIPS/eip-6
  deriving (Opcode' j -> Opcode' j -> Bool
(Opcode' j -> Opcode' j -> Bool)
-> (Opcode' j -> Opcode' j -> Bool) -> Eq (Opcode' j)
forall j. Eq j => Opcode' j -> Opcode' j -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Opcode' j -> Opcode' j -> Bool
$c/= :: forall j. Eq j => Opcode' j -> Opcode' j -> Bool
== :: Opcode' j -> Opcode' j -> Bool
$c== :: forall j. Eq j => Opcode' j -> Opcode' j -> Bool
Eq, Eq (Opcode' j)
Eq (Opcode' j)
-> (Opcode' j -> Opcode' j -> Ordering)
-> (Opcode' j -> Opcode' j -> Bool)
-> (Opcode' j -> Opcode' j -> Bool)
-> (Opcode' j -> Opcode' j -> Bool)
-> (Opcode' j -> Opcode' j -> Bool)
-> (Opcode' j -> Opcode' j -> Opcode' j)
-> (Opcode' j -> Opcode' j -> Opcode' j)
-> Ord (Opcode' j)
Opcode' j -> Opcode' j -> Bool
Opcode' j -> Opcode' j -> Ordering
Opcode' j -> Opcode' j -> Opcode' j
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall j. Ord j => Eq (Opcode' j)
forall j. Ord j => Opcode' j -> Opcode' j -> Bool
forall j. Ord j => Opcode' j -> Opcode' j -> Ordering
forall j. Ord j => Opcode' j -> Opcode' j -> Opcode' j
min :: Opcode' j -> Opcode' j -> Opcode' j
$cmin :: forall j. Ord j => Opcode' j -> Opcode' j -> Opcode' j
max :: Opcode' j -> Opcode' j -> Opcode' j
$cmax :: forall j. Ord j => Opcode' j -> Opcode' j -> Opcode' j
>= :: Opcode' j -> Opcode' j -> Bool
$c>= :: forall j. Ord j => Opcode' j -> Opcode' j -> Bool
> :: Opcode' j -> Opcode' j -> Bool
$c> :: forall j. Ord j => Opcode' j -> Opcode' j -> Bool
<= :: Opcode' j -> Opcode' j -> Bool
$c<= :: forall j. Ord j => Opcode' j -> Opcode' j -> Bool
< :: Opcode' j -> Opcode' j -> Bool
$c< :: forall j. Ord j => Opcode' j -> Opcode' j -> Bool
compare :: Opcode' j -> Opcode' j -> Ordering
$ccompare :: forall j. Ord j => Opcode' j -> Opcode' j -> Ordering
$cp1Ord :: forall j. Ord j => Eq (Opcode' j)
Ord, a -> Opcode' b -> Opcode' a
(a -> b) -> Opcode' a -> Opcode' b
(forall a b. (a -> b) -> Opcode' a -> Opcode' b)
-> (forall a b. a -> Opcode' b -> Opcode' a) -> Functor Opcode'
forall a b. a -> Opcode' b -> Opcode' a
forall a b. (a -> b) -> Opcode' a -> Opcode' b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Opcode' b -> Opcode' a
$c<$ :: forall a b. a -> Opcode' b -> Opcode' a
fmap :: (a -> b) -> Opcode' a -> Opcode' b
$cfmap :: forall a b. (a -> b) -> Opcode' a -> Opcode' b
Functor)

-- | Convert any @'Opcode'' a@ into an @'Opcode'' ()@.
concrete :: Opcode' a -> Opcode' ()
concrete :: Opcode' a -> Opcode' ()
concrete = Opcode' a -> Opcode' ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void

-- | Extract the @a@ from a @'JUMP' a@ or a @'JUMPI' a@.
jumpAnnot :: Opcode' a -> Maybe a
jumpAnnot :: Opcode' a -> Maybe a
jumpAnnot = \case
  JUMP a
a -> a -> Maybe a
forall a. a -> Maybe a
Just a
a
  JUMPI a
a -> a -> Maybe a
forall a. a -> Maybe a
Just a
a
  Opcode' a
_ -> Maybe a
forall a. Maybe a
Nothing

-- | Extract the @a@ from a @'JUMPDEST' a@.
jumpdestAnnot :: Opcode' a -> Maybe a
jumpdestAnnot :: Opcode' a -> Maybe a
jumpdestAnnot = \case
  JUMPDEST a
a -> a -> Maybe a
forall a. a -> Maybe a
Just a
a
  Opcode' a
_ -> Maybe a
forall a. Maybe a
Nothing

-- | Convert an 'Ord5' or an 'Ord16' to a 'Word8'.
toWord8 :: Enum e => e -> Word8
toWord8 :: e -> Word8
toWord8 = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (e -> Int) -> e -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Int
forall a. Enum a => a -> Int
fromEnum

-- | Convert a 'Word8' to an 'Ord5' or an 'Ord16'.
fromWord8 :: Enum e => Word8 -> e
fromWord8 :: Word8 -> e
fromWord8 = Int -> e
forall a. Enum a => Int -> a
toEnum (Int -> e) -> (Word8 -> Int) -> Word8 -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- | Convenience type of cardinality 5 for 'LOG'.
data Ord5
  = Ord5_0
  | Ord5_1
  | Ord5_2
  | Ord5_3
  | Ord5_4
  deriving (Ord5 -> Ord5 -> Bool
(Ord5 -> Ord5 -> Bool) -> (Ord5 -> Ord5 -> Bool) -> Eq Ord5
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ord5 -> Ord5 -> Bool
$c/= :: Ord5 -> Ord5 -> Bool
== :: Ord5 -> Ord5 -> Bool
$c== :: Ord5 -> Ord5 -> Bool
Eq, Eq Ord5
Eq Ord5
-> (Ord5 -> Ord5 -> Ordering)
-> (Ord5 -> Ord5 -> Bool)
-> (Ord5 -> Ord5 -> Bool)
-> (Ord5 -> Ord5 -> Bool)
-> (Ord5 -> Ord5 -> Bool)
-> (Ord5 -> Ord5 -> Ord5)
-> (Ord5 -> Ord5 -> Ord5)
-> Ord Ord5
Ord5 -> Ord5 -> Bool
Ord5 -> Ord5 -> Ordering
Ord5 -> Ord5 -> Ord5
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Ord5 -> Ord5 -> Ord5
$cmin :: Ord5 -> Ord5 -> Ord5
max :: Ord5 -> Ord5 -> Ord5
$cmax :: Ord5 -> Ord5 -> Ord5
>= :: Ord5 -> Ord5 -> Bool
$c>= :: Ord5 -> Ord5 -> Bool
> :: Ord5 -> Ord5 -> Bool
$c> :: Ord5 -> Ord5 -> Bool
<= :: Ord5 -> Ord5 -> Bool
$c<= :: Ord5 -> Ord5 -> Bool
< :: Ord5 -> Ord5 -> Bool
$c< :: Ord5 -> Ord5 -> Bool
compare :: Ord5 -> Ord5 -> Ordering
$ccompare :: Ord5 -> Ord5 -> Ordering
$cp1Ord :: Eq Ord5
Ord, Int -> Ord5
Ord5 -> Int
Ord5 -> [Ord5]
Ord5 -> Ord5
Ord5 -> Ord5 -> [Ord5]
Ord5 -> Ord5 -> Ord5 -> [Ord5]
(Ord5 -> Ord5)
-> (Ord5 -> Ord5)
-> (Int -> Ord5)
-> (Ord5 -> Int)
-> (Ord5 -> [Ord5])
-> (Ord5 -> Ord5 -> [Ord5])
-> (Ord5 -> Ord5 -> [Ord5])
-> (Ord5 -> Ord5 -> Ord5 -> [Ord5])
-> Enum Ord5
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Ord5 -> Ord5 -> Ord5 -> [Ord5]
$cenumFromThenTo :: Ord5 -> Ord5 -> Ord5 -> [Ord5]
enumFromTo :: Ord5 -> Ord5 -> [Ord5]
$cenumFromTo :: Ord5 -> Ord5 -> [Ord5]
enumFromThen :: Ord5 -> Ord5 -> [Ord5]
$cenumFromThen :: Ord5 -> Ord5 -> [Ord5]
enumFrom :: Ord5 -> [Ord5]
$cenumFrom :: Ord5 -> [Ord5]
fromEnum :: Ord5 -> Int
$cfromEnum :: Ord5 -> Int
toEnum :: Int -> Ord5
$ctoEnum :: Int -> Ord5
pred :: Ord5 -> Ord5
$cpred :: Ord5 -> Ord5
succ :: Ord5 -> Ord5
$csucc :: Ord5 -> Ord5
Enum, Ord5
Ord5 -> Ord5 -> Bounded Ord5
forall a. a -> a -> Bounded a
maxBound :: Ord5
$cmaxBound :: Ord5
minBound :: Ord5
$cminBound :: Ord5
Bounded)

-- | Convenience type of cardinality 16 for 'DUP' and 'SWAP'.
data Ord16
  = Ord16_1
  | Ord16_2
  | Ord16_3
  | Ord16_4
  | Ord16_5
  | Ord16_6
  | Ord16_7
  | Ord16_8
  | Ord16_9
  | Ord16_10
  | Ord16_11
  | Ord16_12
  | Ord16_13
  | Ord16_14
  | Ord16_15
  | Ord16_16
  deriving (Ord16 -> Ord16 -> Bool
(Ord16 -> Ord16 -> Bool) -> (Ord16 -> Ord16 -> Bool) -> Eq Ord16
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ord16 -> Ord16 -> Bool
$c/= :: Ord16 -> Ord16 -> Bool
== :: Ord16 -> Ord16 -> Bool
$c== :: Ord16 -> Ord16 -> Bool
Eq, Eq Ord16
Eq Ord16
-> (Ord16 -> Ord16 -> Ordering)
-> (Ord16 -> Ord16 -> Bool)
-> (Ord16 -> Ord16 -> Bool)
-> (Ord16 -> Ord16 -> Bool)
-> (Ord16 -> Ord16 -> Bool)
-> (Ord16 -> Ord16 -> Ord16)
-> (Ord16 -> Ord16 -> Ord16)
-> Ord Ord16
Ord16 -> Ord16 -> Bool
Ord16 -> Ord16 -> Ordering
Ord16 -> Ord16 -> Ord16
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Ord16 -> Ord16 -> Ord16
$cmin :: Ord16 -> Ord16 -> Ord16
max :: Ord16 -> Ord16 -> Ord16
$cmax :: Ord16 -> Ord16 -> Ord16
>= :: Ord16 -> Ord16 -> Bool
$c>= :: Ord16 -> Ord16 -> Bool
> :: Ord16 -> Ord16 -> Bool
$c> :: Ord16 -> Ord16 -> Bool
<= :: Ord16 -> Ord16 -> Bool
$c<= :: Ord16 -> Ord16 -> Bool
< :: Ord16 -> Ord16 -> Bool
$c< :: Ord16 -> Ord16 -> Bool
compare :: Ord16 -> Ord16 -> Ordering
$ccompare :: Ord16 -> Ord16 -> Ordering
$cp1Ord :: Eq Ord16
Ord, Int -> Ord16
Ord16 -> Int
Ord16 -> [Ord16]
Ord16 -> Ord16
Ord16 -> Ord16 -> [Ord16]
Ord16 -> Ord16 -> Ord16 -> [Ord16]
(Ord16 -> Ord16)
-> (Ord16 -> Ord16)
-> (Int -> Ord16)
-> (Ord16 -> Int)
-> (Ord16 -> [Ord16])
-> (Ord16 -> Ord16 -> [Ord16])
-> (Ord16 -> Ord16 -> [Ord16])
-> (Ord16 -> Ord16 -> Ord16 -> [Ord16])
-> Enum Ord16
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Ord16 -> Ord16 -> Ord16 -> [Ord16]
$cenumFromThenTo :: Ord16 -> Ord16 -> Ord16 -> [Ord16]
enumFromTo :: Ord16 -> Ord16 -> [Ord16]
$cenumFromTo :: Ord16 -> Ord16 -> [Ord16]
enumFromThen :: Ord16 -> Ord16 -> [Ord16]
$cenumFromThen :: Ord16 -> Ord16 -> [Ord16]
enumFrom :: Ord16 -> [Ord16]
$cenumFrom :: Ord16 -> [Ord16]
fromEnum :: Ord16 -> Int
$cfromEnum :: Ord16 -> Int
toEnum :: Int -> Ord16
$ctoEnum :: Int -> Ord16
pred :: Ord16 -> Ord16
$cpred :: Ord16 -> Ord16
succ :: Ord16 -> Ord16
$csucc :: Ord16 -> Ord16
Enum, Ord16
Ord16 -> Ord16 -> Bounded Ord16
forall a. a -> a -> Bounded a
maxBound :: Ord16
$cmaxBound :: Ord16
minBound :: Ord16
$cminBound :: Ord16
Bounded)

-- | An 'OpcodeSpec' for a given 'Opcode' contains the numeric encoding of the
-- opcode, the number of items that this opcode removes from the stack (α),
-- and the number of items added to the stack (δ). These values are documented
-- in the Ethereum Yellow Paper.
--
-- Examples of 'OpcodeSpec's:
--
-- > --         Hex  α δ
-- > OpcodeSpec 0x01 2 1 "add"
-- > OpcodeSpec 0x60 0 1 "push1 255"
-- > OpcodeSpec 0x61 0 1 "push2 256"
data OpcodeSpec = OpcodeSpec
  { OpcodeSpec -> Word8
opcodeEncoding :: !Word8 -- ^ Numeric encoding of opcode
  , OpcodeSpec -> Word8
opcodeAlpha    :: !Word8 -- ^ Number of items opcode places on stack (α)
  , OpcodeSpec -> Word8
opcodeDelta    :: !Word8 -- ^ Number of items opcode removes from stack (δ)
  , OpcodeSpec -> Text
opcodeName     :: !Text  -- ^ Printable name for opcode, e.g. @"add"@
  } deriving (OpcodeSpec -> OpcodeSpec -> Bool
(OpcodeSpec -> OpcodeSpec -> Bool)
-> (OpcodeSpec -> OpcodeSpec -> Bool) -> Eq OpcodeSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OpcodeSpec -> OpcodeSpec -> Bool
$c/= :: OpcodeSpec -> OpcodeSpec -> Bool
== :: OpcodeSpec -> OpcodeSpec -> Bool
$c== :: OpcodeSpec -> OpcodeSpec -> Bool
Eq, Int -> OpcodeSpec -> ShowS
[OpcodeSpec] -> ShowS
OpcodeSpec -> String
(Int -> OpcodeSpec -> ShowS)
-> (OpcodeSpec -> String)
-> ([OpcodeSpec] -> ShowS)
-> Show OpcodeSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OpcodeSpec] -> ShowS
$cshowList :: [OpcodeSpec] -> ShowS
show :: OpcodeSpec -> String
$cshow :: OpcodeSpec -> String
showsPrec :: Int -> OpcodeSpec -> ShowS
$cshowsPrec :: Int -> OpcodeSpec -> ShowS
Show)

-- | Given an 'Opcode'', produce its 'OpcodeSpec'.
--
-- For 'DUP', 'SWAP' and 'LOG' this depends on the specific variant, and for
-- 'PUSH' it depends on the size of the constant being pushed.
opcodeSpec :: Opcode' j -> OpcodeSpec
opcodeSpec :: Opcode' j -> OpcodeSpec
opcodeSpec Opcode' j
opcode = case Opcode' j
opcode of
  -- 0s: Stop and Arithmetic Operations
  --                   Hex  α δ
  Opcode' j
STOP       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x00 Word8
0 Word8
0 Text
"stop"
  Opcode' j
ADD        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x01 Word8
2 Word8
1 Text
"add"
  Opcode' j
MUL        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x02 Word8
2 Word8
1 Text
"mul"
  Opcode' j
SUB        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x03 Word8
2 Word8
1 Text
"sub"
  Opcode' j
DIV        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x04 Word8
2 Word8
1 Text
"div"
  Opcode' j
SDIV       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x05 Word8
2 Word8
1 Text
"sdiv"
  Opcode' j
MOD        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x06 Word8
2 Word8
1 Text
"mod"
  Opcode' j
SMOD       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x07 Word8
2 Word8
1 Text
"smod"
  Opcode' j
ADDMOD     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x08 Word8
3 Word8
1 Text
"addmod"
  Opcode' j
MULMOD     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x09 Word8
3 Word8
1 Text
"mulmod"
  Opcode' j
EXP        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x0a Word8
2 Word8
1 Text
"exp"
  Opcode' j
SIGNEXTEND -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x0b Word8
2 Word8
1 Text
"signextend"

  -- 10s: Comparison & Bitwise Logic Operations
  --                Hex  α δ
  Opcode' j
LT         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x10 Word8
2 Word8
1 Text
"lt"
  Opcode' j
GT         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x11 Word8
2 Word8
1 Text
"gt"
  Opcode' j
SLT        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x12 Word8
2 Word8
1 Text
"slt"
  Opcode' j
SGT        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x13 Word8
2 Word8
1 Text
"sgt"
  Opcode' j
EQ         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x14 Word8
2 Word8
1 Text
"eq"
  Opcode' j
ISZERO     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x15 Word8
1 Word8
1 Text
"iszero"
  Opcode' j
AND        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x16 Word8
2 Word8
1 Text
"and"
  Opcode' j
OR         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x17 Word8
2 Word8
1 Text
"or"
  Opcode' j
XOR        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x18 Word8
2 Word8
1 Text
"xor"
  Opcode' j
NOT        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x19 Word8
1 Word8
1 Text
"not"
  Opcode' j
BYTE       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x1a Word8
2 Word8
1 Text
"byte"
  Opcode' j
SHL        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x1b Word8
2 Word8
1 Text
"shl"
  Opcode' j
SHR        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x1c Word8
2 Word8
1 Text
"shr"
  Opcode' j
SAR        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x1d Word8
2 Word8
1 Text
"sar"

  -- 20s: SHA3
  --               Hex  α δ
  Opcode' j
SHA3       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x20 Word8
2 Word8
1 Text
"sha3"

  -- 30s: Environmental Information
  --     Opcode            Hex  α δ
  Opcode' j
ADDRESS        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x30 Word8
0 Word8
1 Text
"address"
  Opcode' j
BALANCE        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x31 Word8
1 Word8
1 Text
"balance"
  Opcode' j
ORIGIN         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x32 Word8
0 Word8
1 Text
"origin"
  Opcode' j
CALLER         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x33 Word8
0 Word8
1 Text
"caller"
  Opcode' j
CALLVALUE      -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x34 Word8
0 Word8
1 Text
"callvalue"
  Opcode' j
CALLDATALOAD   -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x35 Word8
1 Word8
1 Text
"calldataload"
  Opcode' j
CALLDATASIZE   -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x36 Word8
0 Word8
1 Text
"calldatasize"
  Opcode' j
CALLDATACOPY   -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x37 Word8
3 Word8
0 Text
"calldatacopy"
  Opcode' j
CODESIZE       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x38 Word8
0 Word8
1 Text
"codesize"
  Opcode' j
CODECOPY       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x39 Word8
3 Word8
0 Text
"codecopy"
  Opcode' j
GASPRICE       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3a Word8
0 Word8
1 Text
"gasprice"
  Opcode' j
EXTCODESIZE    -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3b Word8
1 Word8
1 Text
"extcodesize"
  Opcode' j
EXTCODECOPY    -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3c Word8
4 Word8
0 Text
"extcodecopy"
  Opcode' j
RETURNDATASIZE -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3d Word8
0 Word8
1 Text
"returndatasize"
  Opcode' j
RETURNDATACOPY -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3e Word8
3 Word8
0 Text
"returndatacopy"
  Opcode' j
EXTCODEHASH    -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x3f Word8
1 Word8
1 Text
"extcodehash"

  -- 40s: Block Information
  --                    Hex  α δ
  Opcode' j
BLOCKHASH      -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x40 Word8
1 Word8
1 Text
"blockhash"
  Opcode' j
COINBASE       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x41 Word8
0 Word8
1 Text
"coinbase"
  Opcode' j
TIMESTAMP      -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x42 Word8
0 Word8
1 Text
"timestamp"
  Opcode' j
NUMBER         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x43 Word8
0 Word8
1 Text
"number"
  Opcode' j
DIFFICULTY     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x44 Word8
0 Word8
1 Text
"difficulty"
  Opcode' j
GASLIMIT       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x45 Word8
0 Word8
1 Text
"gaslimit"
  Opcode' j
CHAINID        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x46 Word8
0 Word8
1 Text
"chainid"
  Opcode' j
SELFBALANCE    -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x47 Word8
0 Word8
1 Text
"selfbalance"

  -- 50s: Stack, Memory, Storage and Flow Operations
  --                    Hex  α δ
  Opcode' j
POP            -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x50 Word8
1 Word8
0 Text
"pop"
  Opcode' j
MLOAD          -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x51 Word8
1 Word8
1 Text
"mload"
  Opcode' j
MSTORE         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x52 Word8
2 Word8
0 Text
"mstore"
  Opcode' j
MSTORE8        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x53 Word8
2 Word8
0 Text
"mstore8"
  Opcode' j
SLOAD          -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x54 Word8
1 Word8
1 Text
"sload"
  Opcode' j
SSTORE         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x55 Word8
2 Word8
0 Text
"sstore"
  JUMP{}         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x56 Word8
1 Word8
0 Text
"jump"
  JUMPI{}        -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x57 Word8
2 Word8
0 Text
"jumpi"
  Opcode' j
PC             -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x58 Word8
0 Word8
1 Text
"pc"
  Opcode' j
MSIZE          -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x59 Word8
0 Word8
1 Text
"msize"
  Opcode' j
GAS            -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x5a Word8
0 Word8
1 Text
"gas"
  JUMPDEST{}     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0x5b Word8
0 Word8
0 Text
"jumpdest"

  -- 60s & 70s: Push Operations
  PUSH Word256
n ->
    let (Word8
pushHex, [Word8]
pushConst) = Word256 -> (Word8, [Word8])
push' Word256
n
    in OpcodeSpec :: Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec { opcodeEncoding :: Word8
opcodeEncoding = Word8
pushHex
                  , opcodeAlpha :: Word8
opcodeAlpha    = Word8
0
                  , opcodeDelta :: Word8
opcodeDelta    = Word8
1
                  , opcodeName :: Text
opcodeName     = [Text] -> Text
Text.concat
                    [ Text
"push"
                    , String -> Text
Text.pack (Int -> String
forall a. Show a => a -> String
show ([Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
List.length [Word8]
pushConst))
                    , Text
" "
                    , String -> Text
Text.pack (Word256 -> String
forall a. Show a => a -> String
show Word256
n) ]
                  }

  -- 80s: Duplication Operations (DUP)
  DUP Ord16
i ->
    let wi :: Word8
wi = Ord16 -> Word8
forall e. Enum e => e -> Word8
toWord8 Ord16
i
    in OpcodeSpec :: Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec { opcodeEncoding :: Word8
opcodeEncoding = Word8
0x80 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
wi
                  , opcodeAlpha :: Word8
opcodeAlpha    = Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1
                  , opcodeDelta :: Word8
opcodeDelta    = Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
2
                  , opcodeName :: Text
opcodeName     = Text
"dup" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (Word8 -> String
forall a. Show a => a -> String
show (Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1))
                  }

  -- 90s: Exchange operations (SWAP)
  SWAP Ord16
i ->
    let wi :: Word8
wi = Ord16 -> Word8
forall e. Enum e => e -> Word8
toWord8 Ord16
i
    in OpcodeSpec :: Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec { opcodeEncoding :: Word8
opcodeEncoding = Word8
0x90 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
wi
                  , opcodeAlpha :: Word8
opcodeAlpha    = Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1
                  , opcodeDelta :: Word8
opcodeDelta    = Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1
                  , opcodeName :: Text
opcodeName     = Text
"swap" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (Word8 -> String
forall a. Show a => a -> String
show (Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1))
                  }

  -- a0s: Logging Operations (LOG)
  LOG Ord5
i ->
    let wi :: Word8
wi = Ord5 -> Word8
forall e. Enum e => e -> Word8
toWord8 Ord5
i
    in OpcodeSpec :: Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec { opcodeEncoding :: Word8
opcodeEncoding = Word8
0xa0 Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
wi
                  , opcodeAlpha :: Word8
opcodeAlpha    = Word8
wi Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
2
                  , opcodeDelta :: Word8
opcodeDelta    = Word8
0
                  , opcodeName :: Text
opcodeName     = Text
"log" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (Word8 -> String
forall a. Show a => a -> String
show Word8
wi)
                  }

  -- f0s: System Operations
  --                      Hex  α δ
  Opcode' j
CREATE       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf0 Word8
3 Word8
1 Text
"create"
  Opcode' j
CALL         -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf1 Word8
7 Word8
1 Text
"call"
  Opcode' j
CALLCODE     -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf2 Word8
7 Word8
1 Text
"callcode"
  Opcode' j
RETURN       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf3 Word8
2 Word8
0 Text
"return"
  Opcode' j
DELEGATECALL -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf4 Word8
6 Word8
1 Text
"delegatecall"
  Opcode' j
CREATE2      -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xf5 Word8
4 Word8
1 Text
"create2"
  Opcode' j
STATICCALL   -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xfa Word8
6 Word8
1 Text
"staticcall"
  Opcode' j
REVERT       -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xfd Word8
2 Word8
0 Text
"revert"
  Opcode' j
INVALID      -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xfe Word8
0 Word8
0 Text
"invalid" -- α, δ are ∅
  Opcode' j
SELFDESTRUCT -> Word8 -> Word8 -> Word8 -> Text -> OpcodeSpec
OpcodeSpec Word8
0xff Word8
1 Word8
0 Text
"selfdestruct"

instance {-# OVERLAPPABLE #-} Show a => Show (Opcode' a) where
  show :: Opcode' a -> String
show Opcode' a
opcode = Opcode' () -> String
forall a. Show a => a -> String
show (Opcode' a -> Opcode' ()
forall a. Opcode' a -> Opcode' ()
concrete Opcode' a
opcode) String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Opcode' a -> String
forall a. Show a => Opcode' a -> String
showParam Opcode' a
opcode
    where
      showParam :: Opcode' a -> String
showParam (JUMP a
a) = String
" " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
a
      showParam (JUMPI a
a) = String
" " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
a
      showParam (JUMPDEST a
a) = String
" " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
a
      showParam Opcode' a
_opcode = String
""

-- | Convert the constant argument of a 'PUSH' to the opcode encoding
-- (0x60--0x7f) and its constant split into 'Word8' segments.
push' :: Word256 -> (Word8, [Word8])
push' :: Word256 -> (Word8, [Word8])
push' Word256
i | Word256
i Word256 -> Word256 -> Bool
forall a. Ord a => a -> a -> Bool
< Word256
256 = (Word8
0x60, [Word256 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word256
i])
push' Word256
i = (Word8
opcode Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
1, [Word8]
arg [Word8] -> [Word8] -> [Word8]
forall a. Semigroup a => a -> a -> a
<> [Word256 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word256
i])
  where (Word8
opcode, [Word8]
arg) = Word256 -> (Word8, [Word8])
push' (Word256
i Word256 -> Int -> Word256
forall a. Bits a => a -> Int -> a
`shift` (-Int
8))

-- | Use 'DUP1' instead of @'DUP' 'Ord16_1'@.
pattern DUP1 :: forall j. Opcode' j
pattern $bDUP1 :: Opcode' j
$mDUP1 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP1 = DUP Ord16_1

-- | Use 'DUP2' instead of @'DUP' 'Ord16_2'@.
pattern DUP2 :: forall j. Opcode' j
pattern $bDUP2 :: Opcode' j
$mDUP2 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP2 = DUP Ord16_2

-- | Use 'DUP3' instead of @'DUP' 'Ord16_3'@.
pattern DUP3 :: forall j. Opcode' j
pattern $bDUP3 :: Opcode' j
$mDUP3 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP3 = DUP Ord16_3

-- | Use 'DUP4' instead of @'DUP' 'Ord16_4'@.
pattern DUP4 :: forall j. Opcode' j
pattern $bDUP4 :: Opcode' j
$mDUP4 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP4 = DUP Ord16_4

-- | Use 'DUP5' instead of @'DUP' 'Ord16_5'@.
pattern DUP5 :: forall j. Opcode' j
pattern $bDUP5 :: Opcode' j
$mDUP5 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP5 = DUP Ord16_5

-- | Use 'DUP6' instead of @'DUP' 'Ord16_6'@.
pattern DUP6 :: forall j. Opcode' j
pattern $bDUP6 :: Opcode' j
$mDUP6 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP6 = DUP Ord16_6

-- | Use 'DUP7' instead of @'DUP' 'Ord16_7'@.
pattern DUP7 :: forall j. Opcode' j
pattern $bDUP7 :: Opcode' j
$mDUP7 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP7 = DUP Ord16_7

-- | Use 'DUP8' instead of @'DUP' 'Ord16_8'@.
pattern DUP8 :: forall j. Opcode' j
pattern $bDUP8 :: Opcode' j
$mDUP8 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP8 = DUP Ord16_8

-- | Use 'DUP9' instead of @'DUP' 'Ord16_9'@.
pattern DUP9 :: forall j. Opcode' j
pattern $bDUP9 :: Opcode' j
$mDUP9 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP9 = DUP Ord16_9

-- | Use 'DUP10' instead of @'DUP' 'Ord16_10'@.
pattern DUP10 :: forall j. Opcode' j
pattern $bDUP10 :: Opcode' j
$mDUP10 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP10 = DUP Ord16_10

-- | Use 'DUP11' instead of @'DUP' 'Ord16_11'@.
pattern DUP11 :: forall j. Opcode' j
pattern $bDUP11 :: Opcode' j
$mDUP11 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP11 = DUP Ord16_11

-- | Use 'DUP12' instead of @'DUP' 'Ord16_12'@.
pattern DUP12 :: forall j. Opcode' j
pattern $bDUP12 :: Opcode' j
$mDUP12 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP12 = DUP Ord16_12

-- | Use 'DUP13' instead of @'DUP' 'Ord16_13'@.
pattern DUP13 :: forall j. Opcode' j
pattern $bDUP13 :: Opcode' j
$mDUP13 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP13 = DUP Ord16_13

-- | Use 'DUP14' instead of @'DUP' 'Ord16_14'@.
pattern DUP14 :: forall j. Opcode' j
pattern $bDUP14 :: Opcode' j
$mDUP14 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP14 = DUP Ord16_14

-- | Use 'DUP15' instead of @'DUP' 'Ord16_15'@.
pattern DUP15 :: forall j. Opcode' j
pattern $bDUP15 :: Opcode' j
$mDUP15 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP15 = DUP Ord16_15

-- | Use 'DUP16' instead of @'DUP' 'Ord16_16'@.
pattern DUP16 :: forall j. Opcode' j
pattern $bDUP16 :: Opcode' j
$mDUP16 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
DUP16 = DUP Ord16_16

-- | Use 'SWAP1' instead of @'SWAP' 'Ord16_1'@, etc.
pattern SWAP1 :: forall j. Opcode' j
pattern $bSWAP1 :: Opcode' j
$mSWAP1 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP1 = SWAP Ord16_1

-- | Use 'SWAP2' instead of @'SWAP' 'Ord16_2'@, etc.
pattern SWAP2 :: forall j. Opcode' j
pattern $bSWAP2 :: Opcode' j
$mSWAP2 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP2 = SWAP Ord16_2

-- | Use 'SWAP3' instead of @'SWAP' 'Ord16_3'@, etc.
pattern SWAP3 :: forall j. Opcode' j
pattern $bSWAP3 :: Opcode' j
$mSWAP3 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP3 = SWAP Ord16_3

-- | Use 'SWAP4' instead of @'SWAP' 'Ord16_4'@, etc.
pattern SWAP4 :: forall j. Opcode' j
pattern $bSWAP4 :: Opcode' j
$mSWAP4 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP4 = SWAP Ord16_4

-- | Use 'SWAP5' instead of @'SWAP' 'Ord16_5'@, etc.
pattern SWAP5 :: forall j. Opcode' j
pattern $bSWAP5 :: Opcode' j
$mSWAP5 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP5 = SWAP Ord16_5

-- | Use 'SWAP6' instead of @'SWAP' 'Ord16_6'@, etc.
pattern SWAP6 :: forall j. Opcode' j
pattern $bSWAP6 :: Opcode' j
$mSWAP6 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP6 = SWAP Ord16_6

-- | Use 'SWAP7' instead of @'SWAP' 'Ord16_7'@, etc.
pattern SWAP7 :: forall j. Opcode' j
pattern $bSWAP7 :: Opcode' j
$mSWAP7 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP7 = SWAP Ord16_7

-- | Use 'SWAP8' instead of @'SWAP' 'Ord16_8'@, etc.
pattern SWAP8 :: forall j. Opcode' j
pattern $bSWAP8 :: Opcode' j
$mSWAP8 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP8 = SWAP Ord16_8

-- | Use 'SWAP9' instead of @'SWAP' 'Ord16_9'@, etc.
pattern SWAP9 :: forall j. Opcode' j
pattern $bSWAP9 :: Opcode' j
$mSWAP9 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP9 = SWAP Ord16_9

-- | Use 'SWAP10' instead of @'SWAP' 'Ord16_10'@, etc.
pattern SWAP10 :: forall j. Opcode' j
pattern $bSWAP10 :: Opcode' j
$mSWAP10 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP10 = SWAP Ord16_10

-- | Use 'SWAP11' instead of @'SWAP' 'Ord16_11'@, etc.
pattern SWAP11 :: forall j. Opcode' j
pattern $bSWAP11 :: Opcode' j
$mSWAP11 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP11 = SWAP Ord16_11

-- | Use 'SWAP12' instead of @'SWAP' 'Ord16_12'@, etc.
pattern SWAP12 :: forall j. Opcode' j
pattern $bSWAP12 :: Opcode' j
$mSWAP12 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP12 = SWAP Ord16_12

-- | Use 'SWAP13' instead of @'SWAP' 'Ord16_13'@, etc.
pattern SWAP13 :: forall j. Opcode' j
pattern $bSWAP13 :: Opcode' j
$mSWAP13 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP13 = SWAP Ord16_13

-- | Use 'SWAP14' instead of @'SWAP' 'Ord16_14'@, etc.
pattern SWAP14 :: forall j. Opcode' j
pattern $bSWAP14 :: Opcode' j
$mSWAP14 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP14 = SWAP Ord16_14

-- | Use 'SWAP15' instead of @'SWAP' 'Ord16_15'@, etc.
pattern SWAP15 :: forall j. Opcode' j
pattern $bSWAP15 :: Opcode' j
$mSWAP15 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP15 = SWAP Ord16_15

-- | Use 'SWAP16' instead of @'SWAP' 'Ord16_16'@, etc.
pattern SWAP16 :: forall j. Opcode' j
pattern $bSWAP16 :: Opcode' j
$mSWAP16 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
SWAP16 = SWAP Ord16_16

-- | Use 'LOG0' instead of @'LOG' 'Ord5_0'@.
pattern LOG0 :: forall j. Opcode' j
pattern $bLOG0 :: Opcode' j
$mLOG0 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
LOG0 = LOG Ord5_0

-- | Use 'LOG1' instead of @'LOG' 'Ord5_1'@.
pattern LOG1 :: forall j. Opcode' j
pattern $bLOG1 :: Opcode' j
$mLOG1 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
LOG1 = LOG Ord5_1

-- | Use 'LOG2' instead of @'LOG' 'Ord5_2'@.
pattern LOG2 :: forall j. Opcode' j
pattern $bLOG2 :: Opcode' j
$mLOG2 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
LOG2 = LOG Ord5_2

-- | Use 'LOG3' instead of @'LOG' 'Ord5_3'@.
pattern LOG3 :: forall j. Opcode' j
pattern $bLOG3 :: Opcode' j
$mLOG3 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
LOG3 = LOG Ord5_3

-- | Use 'LOG4' instead of @'LOG' 'Ord5_4'@.
pattern LOG4 :: forall j. Opcode' j
pattern $bLOG4 :: Opcode' j
$mLOG4 :: forall r j. Opcode' j -> (Void# -> r) -> (Void# -> r) -> r
LOG4 = LOG Ord5_4