diff --git a/libyul/backends/wasm/EVMToEwasmTranslator.cpp b/libyul/backends/wasm/EVMToEwasmTranslator.cpp index 7f01253c9..004f29092 100644 --- a/libyul/backends/wasm/EVMToEwasmTranslator.cpp +++ b/libyul/backends/wasm/EVMToEwasmTranslator.cpp @@ -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() } diff --git a/test/libyul/ewasmTranslationTests/arithmetic_addmod.yul b/test/libyul/ewasmTranslationTests/arithmetic_addmod.yul index c1d43a731..40b84764e 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_addmod.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_addmod.yul @@ -15,6 +15,11 @@ } // ---- // Trace: -// INVALID() // Memory dump: +// 0: 0000000000000000000000000000000000000000000000000000000000000008 +// 20: 0000000000000000000000000000000000000000000000000000000000000004 // Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000001 +// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001 +// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000004 +// 0000000000000000000000000000000000000000000000000000000000000008: 0000000000000000000000000000000000000000000000000000000000000004 diff --git a/test/libyul/ewasmTranslationTests/arithmetic_div.yul b/test/libyul/ewasmTranslationTests/arithmetic_div.yul index 3d97f464c..f32c244a9 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_div.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_div.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/arithmetic_exp.yul b/test/libyul/ewasmTranslationTests/arithmetic_exp.yul index 328ac9c3b..6428e7343 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_exp.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_exp.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/arithmetic_mod.yul b/test/libyul/ewasmTranslationTests/arithmetic_mod.yul index 4aa5c6997..38cc808bf 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_mod.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_mod.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul b/test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul index 094723ae0..ef6efafd4 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_mulmod.yul @@ -17,6 +17,11 @@ } // ---- // Trace: -// INVALID() // Memory dump: +// 0: 0000000000000000000000000000000000000000000000000000000000000008 +// 20: 000000000000000000000000000000000000000000000000000000000000000f // Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000003: 0000000000000000000000000000000000000000000000000000000000000001 +// 0000000000000000000000000000000000000000000000000000000000000004: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +// 0000000000000000000000000000000000000000000000000000000000000007: 0000000000000000000000000000000000000000000000000000000000000003 +// 0000000000000000000000000000000000000000000000000000000000000008: 000000000000000000000000000000000000000000000000000000000000000f diff --git a/test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul b/test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul index fd4364185..0cefb3405 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_sdiv.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/arithmetic_smod.yul b/test/libyul/ewasmTranslationTests/arithmetic_smod.yul index 97983a463..cffb8f73d 100644 --- a/test/libyul/ewasmTranslationTests/arithmetic_smod.yul +++ b/test/libyul/ewasmTranslationTests/arithmetic_smod.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/shifts.yul b/test/libyul/ewasmTranslationTests/shifts.yul index c3e9b6036..cf900dae2 100644 --- a/test/libyul/ewasmTranslationTests/shifts.yul +++ b/test/libyul/ewasmTranslationTests/shifts.yul @@ -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 diff --git a/test/libyul/ewasmTranslationTests/signextend.yul b/test/libyul/ewasmTranslationTests/signextend.yul index 4b5433219..f39d5926b 100644 --- a/test/libyul/ewasmTranslationTests/signextend.yul +++ b/test/libyul/ewasmTranslationTests/signextend.yul @@ -6,6 +6,11 @@ } // ---- // Trace: -// INVALID() // Memory dump: +// 0: 0000000000000000000000000000000000000000000000000000000000000003 +// 20: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322 // Storage dump: +// 0000000000000000000000000000000000000000000000000000000000000000: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86 +// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000076 +// 0000000000000000000000000000000000000000000000000000000000000002: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +// 0000000000000000000000000000000000000000000000000000000000000003: ffffffffffffffffffffffffffffffffffffffffffffffffffffff8844553322