mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[WASM] Add div, sdiv, mod, smod, exp, lt, sar, addmod, mulmod, signextend
This commit is contained in:
parent
0dd398e2ac
commit
f1004e712c
@ -52,6 +52,12 @@ static string const polyfill{R"({
|
||||
function or_bool(a, b, c, d) -> r {
|
||||
r := i64.or(i64.or(a, b), i64.or(c, d))
|
||||
}
|
||||
function or_bool_320(a, b, c, d, e) -> r {
|
||||
r := i64.or(or_bool(a, b, c, d), e)
|
||||
}
|
||||
function or_bool_512(a, b, c, d, e, f, g, h) -> r {
|
||||
r := i64.or(or_bool(a, b, c, d), or_bool(e, f, g, h))
|
||||
}
|
||||
// returns a + y + c plus carry value on 64 bit values.
|
||||
// c should be at most 1
|
||||
function add_carry(x, y, c) -> r, r_c {
|
||||
@ -80,6 +86,27 @@ function sub(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
function sub320(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> r1, r2, r3, r4, r5 {
|
||||
// x - y = x + (~y + 1)
|
||||
let carry
|
||||
r5, carry := add_carry(x5, bit_negate(y5), 1)
|
||||
r4, carry := add_carry(x4, bit_negate(y4), carry)
|
||||
r3, carry := add_carry(x3, bit_negate(y3), carry)
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
function sub512(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// x - y = x + (~y + 1)
|
||||
let carry
|
||||
r8, carry := add_carry(x8, bit_negate(y8), 1)
|
||||
r7, carry := add_carry(x7, bit_negate(y7), carry)
|
||||
r6, carry := add_carry(x6, bit_negate(y6), carry)
|
||||
r5, carry := add_carry(x5, bit_negate(y5), carry)
|
||||
r4, carry := add_carry(x4, bit_negate(y4), carry)
|
||||
r3, carry := add_carry(x3, bit_negate(y3), carry)
|
||||
r2, carry := add_carry(x2, bit_negate(y2), carry)
|
||||
r1, carry := add_carry(x1, bit_negate(y1), carry)
|
||||
}
|
||||
function split(x) -> hi, lo {
|
||||
hi := i64.shr_u(x, 32)
|
||||
lo := i64.and(x, 0xffffffff)
|
||||
@ -124,36 +151,317 @@ function mul_128x128_256(x1, x2, y1, y2) -> r1, r2, r3, r4 {
|
||||
|
||||
r1 := i64.add(i64.add(ah, carry1), carry2)
|
||||
}
|
||||
// Multiplies two 256 bit values resulting in a 512 bit
|
||||
// value split into eight 64 bit values.
|
||||
function mul_256x256_512(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
let a1, a2, a3, a4 := mul_128x128_256(x1, x2, y1, y2)
|
||||
let b1, b2, b3, b4 := mul_128x128_256(x1, x2, y3, y4)
|
||||
let c1, c2, c3, c4 := mul_128x128_256(x3, x4, y1, y2)
|
||||
let d1, d2, d3, d4 := mul_128x128_256(x3, x4, y3, y4)
|
||||
|
||||
r8 := d4
|
||||
r7 := d3
|
||||
|
||||
let carry1, carry2
|
||||
let t1, t2
|
||||
|
||||
r6, carry1 := add_carry(b4, c4, 0)
|
||||
r6, carry2 := add_carry(r6, d2, 0)
|
||||
|
||||
r5, carry1 := add_carry(b3, c3, carry1)
|
||||
r5, carry2 := add_carry(r5, d1, carry2)
|
||||
|
||||
r4, carry1 := add_carry(a4, b2, carry1)
|
||||
r4, carry2 := add_carry(r4, c2, carry2)
|
||||
|
||||
r3, carry1 := add_carry(a3, b1, carry1)
|
||||
r3, carry2 := add_carry(r3, c1, carry2)
|
||||
|
||||
r2, carry1 := add_carry(a2, carry1, carry2)
|
||||
r1 := i64.add(a1, carry1)
|
||||
}
|
||||
function mul(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO it would actually suffice to have mul_128x128_128 for the first two.
|
||||
let b1, b2, b3, b4 := mul_128x128_256(x3, x4, y1, y2)
|
||||
let c1, c2, c3, c4 := mul_128x128_256(x1, x2, y3, y4)
|
||||
let d1, d2, d3, d4 := mul_128x128_256(x3, x4, y3, y4)
|
||||
let d1, d2, d3, d4 := mul_128x128_256(x3, x4, y3, y4)
|
||||
r4 := d4
|
||||
r3 := d3
|
||||
let t1, t2
|
||||
t1, t2, r1, r2 := add(0, 0, b3, b4, 0, 0, c3, c4)
|
||||
t1, t2, r1, r2 := add(0, 0, r1, r2, 0, 0, d1, d2)
|
||||
}
|
||||
function shl_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.shl(x4, amount)
|
||||
}
|
||||
function shr_internal(amount, x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
// amount < 64
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, amount)
|
||||
}
|
||||
function shl320_internal(amount, x1, x2, x3, x4, x5) -> r1, r2, r3, r4, r5 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shl(x4, amount), i64.shr_u(x5, i64.sub(64, amount)))
|
||||
r5 := i64.shl(x5, 1)
|
||||
}
|
||||
function shr320_internal(amount, x1, x2, x3, x4, x5) -> r1, r2, r3, r4, r5 {
|
||||
// amount < 64
|
||||
r5 := i64.add(i64.shr_u(x5, amount), i64.shl(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, 1)
|
||||
}
|
||||
function shl512_internal(amount, x1, x2, x3, x4, x5, x6, x7, x8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// amount < 64
|
||||
r1 := i64.add(i64.shl(x1, amount), i64.shr_u(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shl(x2, amount), i64.shr_u(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shl(x3, amount), i64.shr_u(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shl(x4, amount), i64.shr_u(x5, i64.sub(64, amount)))
|
||||
r5 := i64.add(i64.shl(x5, amount), i64.shr_u(x6, i64.sub(64, amount)))
|
||||
r6 := i64.add(i64.shl(x6, amount), i64.shr_u(x7, i64.sub(64, amount)))
|
||||
r7 := i64.add(i64.shl(x7, amount), i64.shr_u(x8, i64.sub(64, amount)))
|
||||
r8 := i64.shl(x8, amount)
|
||||
}
|
||||
function shr512_internal(amount, x1, x2, x3, x4, x5, x6, x7, x8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// amount < 64
|
||||
r8 := i64.add(i64.shr_u(x8, amount), i64.shl(x7, i64.sub(64, amount)))
|
||||
r7 := i64.add(i64.shr_u(x7, amount), i64.shl(x6, i64.sub(64, amount)))
|
||||
r6 := i64.add(i64.shr_u(x6, amount), i64.shl(x5, i64.sub(64, amount)))
|
||||
r5 := i64.add(i64.shr_u(x5, amount), i64.shl(x4, i64.sub(64, amount)))
|
||||
r4 := i64.add(i64.shr_u(x4, amount), i64.shl(x3, i64.sub(64, amount)))
|
||||
r3 := i64.add(i64.shr_u(x3, amount), i64.shl(x2, i64.sub(64, amount)))
|
||||
r2 := i64.add(i64.shr_u(x2, amount), i64.shl(x1, i64.sub(64, amount)))
|
||||
r1 := i64.shr_u(x1, amount)
|
||||
}
|
||||
function div(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
r4 := i64.div_u(x4, y4)
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/DIV.wast
|
||||
if iszero256(y1, y2, y3, y4) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
for {} 1 {} {
|
||||
if i64.or(i64.eqz(i64.clz(y1)), gte_256x256_64(y1, y2, y3, y4, x1, x2, x3, x4)) {
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4 := shl_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shl_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
for {} or_bool(m1, m2, m3, m4) {} {
|
||||
if gte_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) {
|
||||
x1, x2, x3, x4 := sub(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shr_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
}
|
||||
function sdiv(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
unreachable()
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/SDIV.wast
|
||||
|
||||
let sign := i64.shr_u(i64.xor(x1, y1), 63)
|
||||
|
||||
if i64.eqz(i64.clz(x1)) {
|
||||
x1, x2, x3, x4 := xor(
|
||||
x1, x2, x3, x4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
x1, x2, x3, x4 := add(x1, x2, x3, x4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
if i64.eqz(i64.clz(y1)) {
|
||||
y1, y2, y3, y4 := xor(
|
||||
y1, y2, y3, y4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
y1, y2, y3, y4 := add(y1, y2, y3, y4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
r1, r2, r3, r4 := div(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
|
||||
if sign {
|
||||
r1, r2, r3, r4 := xor(
|
||||
r1, r2, r3, r4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
function mod(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
r4 := i64.rem_u(x4, y4)
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/MOD.wast
|
||||
if iszero256(y1, y2, y3, y4) {
|
||||
leave
|
||||
}
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
for {} 1 {} {
|
||||
if i64.or(i64.eqz(i64.clz(y1)), gte_256x256_64(y1, y2, y3, y4, r1, r2, r3, r4)) {
|
||||
break
|
||||
}
|
||||
|
||||
y1, y2, y3, y4 := shl_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shl_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
|
||||
for {} or_bool(m1, m2, m3, m4) {} {
|
||||
if gte_256x256_64(r1, r2, r3, r4, y1, y2, y3, y4) {
|
||||
r1, r2, r3, r4 := sub(r1, r2, r3, r4, y1, y2, y3, y4)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
m1, m2, m3, m4 := shr_internal(1, m1, m2, m3, m4)
|
||||
}
|
||||
}
|
||||
function mod320(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> r1, r2, r3, r4, r5 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/mod_320.wast
|
||||
if iszero320(y1, y2, y3, y4, y5) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 0
|
||||
let m5 := 1
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
r5 := x5
|
||||
|
||||
for {} 1 {} {
|
||||
if i64.or(i64.eqz(i64.clz(y1)), gte_320x320_64(y1, y2, y3, y4, y5, r1, r2, r3, r4, r5)) {
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4, y5 := shl320_internal(1, y1, y2, y3, y4, y5)
|
||||
m1, m2, m3, m4, m5 := shl320_internal(1, m1, m2, m3, m4, m5)
|
||||
}
|
||||
|
||||
for {} or_bool_320(m1, m2, m3, m4, m5) {} {
|
||||
if gte_320x320_64(r1, r2, r3, r4, r5, y1, y2, y3, y4, y5) {
|
||||
r1, r2, r3, r4, r5 := sub320(r1, r2, r3, r4, r5, y1, y2, y3, y4, y5)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4, y5 := shr320_internal(1, y1, y2, y3, y4, y5)
|
||||
m1, m2, m3, m4, m5 := shr320_internal(1, m1, m2, m3, m4, m5)
|
||||
}
|
||||
}
|
||||
function mod512(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> r1, r2, r3, r4, r5, r6, r7, r8 {
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/mod_512.wast
|
||||
if iszero512(y1, y2, y3, y4, y5, y6, y7, y8) {
|
||||
leave
|
||||
}
|
||||
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 0
|
||||
let m5 := 0
|
||||
let m6 := 0
|
||||
let m7 := 0
|
||||
let m8 := 1
|
||||
|
||||
r1 := x1
|
||||
r2 := x2
|
||||
r3 := x3
|
||||
r4 := x4
|
||||
r5 := x5
|
||||
r6 := x6
|
||||
r7 := x7
|
||||
r8 := x8
|
||||
|
||||
for {} 1 {} {
|
||||
if i64.or(
|
||||
i64.eqz(i64.clz(y1)),
|
||||
gte_512x512_64(y1, y2, y3, y4, y5, y6, y7, y8, r1, r2, r3, r4, r5, r6, r7, r8)
|
||||
)
|
||||
{
|
||||
break
|
||||
}
|
||||
y1, y2, y3, y4, y5, y6, y7, y8 := shl512_internal(1, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
m1, m2, m3, m4, m5, m6, m7, m8 := shl512_internal(1, m1, m2, m3, m4, m5, m6, m7, m8)
|
||||
}
|
||||
|
||||
for {} or_bool_512(m1, m2, m3, m4, m5, m6, m7, m8) {} {
|
||||
if gte_512x512_64(r1, r2, r3, r4, r5, r6, r7, r8, y1, y2, y3, y4, y5, y6, y7, y8) {
|
||||
r1, r2, r3, r4, r5, r6, r7, r8 := sub512(r1, r2, r3, r4, r5, r6, r7, r8, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
}
|
||||
|
||||
y1, y2, y3, y4, y5, y6, y7, y8 := shr512_internal(1, y1, y2, y3, y4, y5, y6, y7, y8)
|
||||
m1, m2, m3, m4, m5, m6, m7, m8 := shr512_internal(1, m1, m2, m3, m4, m5, m6, m7, m8)
|
||||
}
|
||||
}
|
||||
function smod(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
r4 := i64.rem_u(x4, y4)
|
||||
// Based on https://github.com/ewasm/evm2wasm/blob/master/wasm/SMOD.wast
|
||||
let m1 := 0
|
||||
let m2 := 0
|
||||
let m3 := 0
|
||||
let m4 := 1
|
||||
|
||||
let sign := i64.shr_u(x1, 63)
|
||||
|
||||
if i64.eqz(i64.clz(x1)) {
|
||||
x1, x2, x3, x4 := xor(
|
||||
x1, x2, x3, x4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
x1, x2, x3, x4 := add(x1, x2, x3, x4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
if i64.eqz(i64.clz(y1)) {
|
||||
y1, y2, y3, y4 := xor(
|
||||
y1, y2, y3, y4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
y1, y2, y3, y4 := add(y1, y2, y3, y4, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
r1, r2, r3, r4 := mod(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
|
||||
if sign {
|
||||
r1, r2, r3, r4 := xor(
|
||||
r1, r2, r3, r4,
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
r1, r2, r3, r4 := add(r1, r2, r3, r4, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
function exp(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
// TODO implement properly
|
||||
unreachable()
|
||||
r4 := 1
|
||||
for {} or_bool(y1, y2, y3, y4) {} {
|
||||
if i64.and(y4, 1) {
|
||||
r1, r2, r3, r4 := mul(r1, r2, r3, r4, x1, x2, x3, x4)
|
||||
}
|
||||
x1, x2, x3, x4 := mul(x1, x2, x3, x4, x1, x2, x3, x4)
|
||||
y1, y2, y3, y4 := shr_internal(1, y1, y2, y3, y4)
|
||||
}
|
||||
}
|
||||
|
||||
function byte(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
@ -191,8 +499,17 @@ function not(x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
let mask := 0xffffffffffffffff
|
||||
r1, r2, r3, r4 := xor(x1, x2, x3, x4, mask, mask, mask, mask)
|
||||
}
|
||||
function iszero(x1, x2, x3, x4) -> r1, r2, r3, r4 {
|
||||
r4 := i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4)))
|
||||
function iszero(x1, x2, x3, x4) -> r1, r2, r3 ,r4 {
|
||||
r4 := iszero256(x1, x2, x3, x4)
|
||||
}
|
||||
function iszero256(x1, x2, x3, x4) -> r {
|
||||
r := i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4)))
|
||||
}
|
||||
function iszero320(x1, x2, x3, x4, x5) -> r {
|
||||
r := i64.eqz(i64.or(i64.or(i64.or(x1, x2), i64.or(x3, x4)), x5))
|
||||
}
|
||||
function iszero512(x1, x2, x3, x4, x5, x6, x7, x8) -> r {
|
||||
r := i64.and(iszero256(x1, x2, x3, x4), iszero256(x5, x6, x7, x8))
|
||||
}
|
||||
function eq(x1, x2, x3, x4, y1, y2, y3, y4) -> r1, r2, r3, r4 {
|
||||
if i64.eq(x1, y1) {
|
||||
@ -214,27 +531,100 @@ function cmp(a, b) -> r {
|
||||
r := i64.ne(a, b)
|
||||
}
|
||||
}
|
||||
)"
|
||||
// Split long string to make it compilable on msvc
|
||||
// https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2026?view=vs-2019
|
||||
R"(
|
||||
function lt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
function lt_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> z {
|
||||
switch cmp(x1, y1)
|
||||
case 0 {
|
||||
switch cmp(x2, y2)
|
||||
case 0 {
|
||||
switch cmp(x3, y3)
|
||||
case 0 {
|
||||
z4 := i64.lt_u(x4, y4)
|
||||
switch cmp(x4, y4)
|
||||
case 0 {
|
||||
z := i64.lt_u(x5, y5)
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z4 := 0 }
|
||||
default { z4 := 1 }
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z4 := 0 }
|
||||
default { z4 := 1 }
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z4 := 0 }
|
||||
default { z4 := 1 }
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
function lt_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> z {
|
||||
switch cmp(x1, y1)
|
||||
case 0 {
|
||||
switch cmp(x2, y2)
|
||||
case 0 {
|
||||
switch cmp(x3, y3)
|
||||
case 0 {
|
||||
switch cmp(x4, y4)
|
||||
case 0 {
|
||||
switch cmp(x5, y5)
|
||||
case 0 {
|
||||
switch cmp(x6, y6)
|
||||
case 0 {
|
||||
switch cmp(x7, y7)
|
||||
case 0 {
|
||||
z := i64.lt_u(x8, y8)
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
)"
|
||||
// Split long string to make it compilable on msvc
|
||||
// https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2026?view=vs-2019
|
||||
R"(
|
||||
function lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) -> z {
|
||||
switch cmp(x1, y1)
|
||||
case 0 {
|
||||
switch cmp(x2, y2)
|
||||
case 0 {
|
||||
switch cmp(x3, y3)
|
||||
case 0 {
|
||||
z := i64.lt_u(x4, y4)
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
case 1 { z := 0 }
|
||||
default { z := 1 }
|
||||
}
|
||||
function lt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z4 := lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
}
|
||||
function gte_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4) -> z {
|
||||
z := i64.eqz(lt_256x256_64(x1, x2, x3, x4, y1, y2, y3, y4))
|
||||
}
|
||||
function gte_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5) -> z {
|
||||
z := i64.eqz(lt_320x320_64(x1, x2, x3, x4, x5, y1, y2, y3, y4, y5))
|
||||
}
|
||||
function gte_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8) -> z {
|
||||
z := i64.eqz(lt_512x512_64(x1, x2, x3, x4, x5, x6, x7, x8, y1, y2, y3, y4, y5, y6, y7, y8))
|
||||
}
|
||||
function gt(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
z1, z2, z3, z4 := lt(y1, y2, y3, y4, x1, x2, x3, x4)
|
||||
@ -323,20 +713,54 @@ function shr(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
}
|
||||
}
|
||||
function sar(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
if i64.clz(y1) {
|
||||
z1, z2, z3, z4 := shr(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
leave
|
||||
}
|
||||
|
||||
if gte_256x256_64(x1, x2, x3, x4, 0, 0, 0, 256) {
|
||||
z1 := 0xffffffffffffffff
|
||||
z2 := 0xffffffffffffffff
|
||||
z3 := 0xffffffffffffffff
|
||||
z4 := 0xffffffffffffffff
|
||||
}
|
||||
if lt_256x256_64(x1, x2, x3, x4, 0, 0, 0, 256) {
|
||||
y1, y2, y3, y4 := shr(0, 0, 0, x4, y1, y2, y3, y4)
|
||||
z1, z2, z3, z4 := shl(
|
||||
0, 0, 0, i64.sub(256, x4),
|
||||
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff
|
||||
)
|
||||
z1, z2, z3, z4 := or(y1, y2, y3, y4, z1, z2, z3, z4)
|
||||
}
|
||||
}
|
||||
function addmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
let carry
|
||||
z4, carry := add_carry(x4, y4, 0)
|
||||
z3, carry := add_carry(x3, y3, carry)
|
||||
z2, carry := add_carry(x2, y2, carry)
|
||||
z1, carry := add_carry(x1, y1, carry)
|
||||
|
||||
let z0
|
||||
z0, z1, z2, z3, z4 := mod320(carry, z1, z2, z3, z4, 0, m1, m2, m3, m4)
|
||||
}
|
||||
function mulmod(x1, x2, x3, x4, y1, y2, y3, y4, m1, m2, m3, m4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
let r1, r2, r3, r4, r5, r6, r7, r8 := mul_256x256_512(x1, x2, x3, x4, y1, y2, y3, y4)
|
||||
let t1
|
||||
let t2
|
||||
let t3
|
||||
let t4
|
||||
t1, t2, t3, t4, z1, z2, z3, z4 := mod512(r1, r2, r3, r4, r5, r6, r7, r8, 0, 0, 0, 0, m1, m2, m3, m4)
|
||||
}
|
||||
function signextend(x1, x2, x3, x4, y1, y2, y3, y4) -> z1, z2, z3, z4 {
|
||||
// TODO implement
|
||||
unreachable()
|
||||
z1 := y1
|
||||
z2 := y2
|
||||
z3 := y3
|
||||
z4 := y4
|
||||
if lt_256x256_64(x1, x2, x3, x4, 0, 0, 0, 32) {
|
||||
let d := i64.mul(i64.sub(31, x4), 8)
|
||||
z1, z2, z3, z4 := shl(0, 0, 0, d, z1, z2, z3, z4)
|
||||
z1, z2, z3, z4 := sar(0, 0, 0, d, z1, z2, z3, z4)
|
||||
}
|
||||
}
|
||||
function u256_to_u128(x1, x2, x3, x4) -> v1, v2 {
|
||||
if i64.ne(0, i64.or(x1, x2)) { invalid() }
|
||||
|
@ -15,6 +15,11 @@
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000008
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000004
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000004
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 0000000000000000000000000000000000000000000000000000000000000004
|
||||
|
@ -19,5 +19,16 @@
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000d
|
||||
// 20: 0000000000000000555555555555555555555555555555550000000000000000
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000006: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 00000000000000000000000000000000ffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000000ffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 0000000000000000ffffffffffffffffffffffffffffffff0000000000000000
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000000555555555555555555555555555555555555555555555555
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 0000000000000000000000000000000055555555555555555555555555555555
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 0000000000000000000000000000000000000000000000005555555555555555
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000000555555555555555555555555555555550000000000000000
|
||||
|
@ -20,6 +20,21 @@
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000f
|
||||
// 20: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000002: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000006: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: fffffffffffffffffffffffffffffffe00000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 00000000000000000000000000000000fffffffffffffffe0000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 0000000000000000000000000000000100000000000000000000000000000000
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000002ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 00000000000000000000000000000002ffffffffffffffffffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 0000000000000000fffffffffffffffd0000000000000002ffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: ffffffffffffffff000000000000000000000000000000000000000000000000
|
||||
// 000000000000000000000000000000000000000000000000000000000000000f: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
|
@ -19,7 +19,11 @@
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000d
|
||||
// 20: 0000000000000000000000000000000000000aacffffffff8b3c03a314db9000
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000001ffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000000000000000000000000000000000000000000000000000003
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000000000000000000000000000aacffffffff8b3c03a314db9000
|
||||
|
@ -17,6 +17,11 @@
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000008
|
||||
// 20: 000000000000000000000000000000000000000000000000000000000000000f
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000003
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000000000000000000000f
|
||||
|
@ -20,6 +20,14 @@
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000e
|
||||
// 20: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000005: 8000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000007: 7000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000009: 8000000000000000000000000000000000000000000000000000000000000001
|
||||
// 000000000000000000000000000000000000000000000000000000000000000b: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000c: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 000000000000000000000000000000000000000000000000000000000000000e: 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
|
@ -23,7 +23,11 @@
|
||||
// ----
|
||||
// Trace:
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0: 000000000000000000000000000000000000000000000000000000000000000e
|
||||
// 20: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000001ffffffffffffffff
|
||||
// 000000000000000000000000000000000000000000000000000000000000000a: 0000000000000000000000000000000000000000000000000000000000000003
|
||||
// 000000000000000000000000000000000000000000000000000000000000000d: 0000000000000000000000000000000000000aacffffffff8b3c03a314db9000
|
||||
// 000000000000000000000000000000000000000000000000000000000000000e: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
|
||||
|
@ -13,10 +13,11 @@
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
// 20: 0000000000000000000000000000000000101112131415161718191a1b1c1d1e
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000005
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 101112131415161718191a1b1c1d1e1f20000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000101112131415161718191a1b1c1d1e
|
||||
// 0000000000000000000000000000000000000000000000000000000000000002: ffffffffffffffffffffffffffffffffff801112131415161718191a1b1c1d1e
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000004: 0000000000000000000000000000000000701112131415161718191a1b1c1d1e
|
||||
|
@ -6,6 +6,11 @@
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// INVALID()
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000003
|
||||
// 20: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000076
|
||||
// 0000000000000000000000000000000000000000000000000000000000000002: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// 0000000000000000000000000000000000000000000000000000000000000003: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322
|
||||
|
Loading…
Reference in New Issue
Block a user