[WASM] Add div, sdiv, mod, smod, exp, lt, sar, addmod, mulmod, signextend

This commit is contained in:
rodiazet 2020-01-28 13:32:43 +01:00
parent 0dd398e2ac
commit f1004e712c
10 changed files with 529 additions and 47 deletions

View File

@ -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() }

View File

@ -15,6 +15,11 @@
}
// ----
// Trace:
// INVALID()
// Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000000000008
// 20: 0000000000000000000000000000000000000000000000000000000000000004
// Storage dump:
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000004
// 0000000000000000000000000000000000000000000000000000000000000008: 0000000000000000000000000000000000000000000000000000000000000004

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -17,6 +17,11 @@
}
// ----
// Trace:
// INVALID()
// Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000000000008
// 20: 000000000000000000000000000000000000000000000000000000000000000f
// Storage dump:
// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001
// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000003
// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000000000000000000000f

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -6,6 +6,11 @@
}
// ----
// Trace:
// INVALID()
// Memory dump:
// 0: 0000000000000000000000000000000000000000000000000000000000000003
// 20: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322
// Storage dump:
// 0000000000000000000000000000000000000000000000000000000000000000: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000076
// 0000000000000000000000000000000000000000000000000000000000000002: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// 0000000000000000000000000000000000000000000000000000000000000003: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322