Native bitwise shifting instructions are introduced, which are more efficient processing wise on the host and are cheaper to use by a contract.
EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing SHL
and SHR
using arithmetic cost each 35 gas, while the proposed instructions take 3 gas.
The following instructions are introduced:
0x1b
: SHL
(shift left)The SHL
instruction (shift left) pops 2 values from the stack, first arg1
and then arg2
, and pushes on the stack arg2
shifted to the left by arg1
number of bits. The result is equal to
(arg2 * 2^arg1) mod 2^256
Notes:
arg2
) is interpreted as an unsigned number.arg1
) is interpreted as an unsigned number.arg1
) is greater or equal 256 the result is 0.PUSH1 2 EXP MUL
.0x1c
: SHR
(logical shift right)The SHR
instruction (logical shift right) pops 2 values from the stack, first arg1
and then arg2
, and pushes on the stack arg2
shifted to the right by arg1
number of bits with zero fill. The result is equal to
floor(arg2 / 2^arg1)
Notes:
arg2
) is interpreted as an unsigned number.arg1
) is interpreted as an unsigned number.arg1
) is greater or equal 256 the result is 0.PUSH1 2 EXP DIV
.0x1d
: SAR
(arithmetic shift right)The SAR
instruction (arithmetic shift right) pops 2 values from the stack, first arg1
and then arg2
, and pushes on the stack arg2
shifted to the right by arg1
number of bits with sign extension. The result is equal to
floor(arg2 / 2^arg1)
Notes:
arg2
) is interpreted as a signed number.arg1
) is interpreted as an unsigned number.arg1
) is greater or equal 256 the result is 0 if arg2
is non-negative or -1 if arg2
is negative.PUSH1 2 EXP SDIV
, since it rounds differently. See SDIV(-1, 2) == 0
, while SAR(-1, 1) == -1
.The cost of the shift instructions is set at verylow
tier (3 gas).
Instruction operands were chosen to fit the more natural use case of shifting a value already on the stack. This means the operand order is swapped compared to most arithmetic instructions.
The newly introduced instructions have no effect on bytecode created in the past.
SHL
(shift left)0x0000000000000000000000000000000000000000000000000000000000000001 ```
0x0000000000000000000000000000000000000000000000000000000000000002 ```
0x8000000000000000000000000000000000000000000000000000000000000000 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe ```
0x8000000000000000000000000000000000000000000000000000000000000000 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x01
SHL
---
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
SHR
(logical shift right)0x0000000000000000000000000000000000000000000000000000000000000001 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0x4000000000000000000000000000000000000000000000000000000000000000 ```
0x0000000000000000000000000000000000000000000000000000000000000001 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0x0000000000000000000000000000000000000000000000000000000000000001 ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
SAR
(arithmetic shift right)0x0000000000000000000000000000000000000000000000000000000000000001 ```
0x0000000000000000000000000000000000000000000000000000000000000000 ```
0xc000000000000000000000000000000000000000000000000000000000000000 ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x4000000000000000000000000000000000000000000000000000000000000000
PUSH 0xfe
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xf8
SAR
---
0x000000000000000000000000000000000000000000000000000000000000007f
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xfe
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xff
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
Client support:
Compiler support:
Sources:
Filled Tests:
Copyright and related rights waived via CC0.