193 lines
9.7 KiB
NASM
Raw Normal View History

2023-03-07 15:15:20 -08:00
// Arithmetic on little-endian integers represented with 128-bit limbs.
// All integers must be under a given length bound, and are padded with leading zeroes.
// Stores a * b % m in output_loc, leaving a, b, and m unchanged.
// a, b, and m must have the same length.
// Both output_loc and scratch_1 must have size length.
2023-02-17 17:11:58 -08:00
// Both scratch_2 and scratch_3 have size 2 * length and be initialized with zeroes.
2023-03-07 15:15:20 -08:00
global modmul_bignum:
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
// The prover provides x := (a * b) % m, which we store in output_loc.
PUSH 0
2023-02-17 17:11:58 -08:00
// stack: i=0, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
modmul_remainder_loop:
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
PROVER_INPUT(bignum_modmul::remainder)
2023-02-17 17:11:58 -08:00
// stack: PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP7
2023-02-17 17:11:58 -08:00
// stack: output_loc, PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP3
2023-02-17 17:11:58 -08:00
// stack: i, output_loc, PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ADD
2023-02-17 17:11:58 -08:00
// stack: output_loc[i], PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%mstore_kernel_general
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%increment
2023-02-17 17:11:58 -08:00
// stack: i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP2
DUP2
2023-02-17 17:11:58 -08:00
// stack: i+1, length, i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
EQ
2023-02-17 17:11:58 -08:00
// stack: i+1==length, i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ISZERO
2023-02-17 17:11:58 -08:00
// stack: i+1!=length, i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jumpi(modmul_remainder_loop)
modmul_remainder_end:
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
POP
// The prover provides k := (a * b) / m, which we store in scratch_1.
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
PUSH 0
2023-02-17 17:11:58 -08:00
// stack: i=0, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
modmul_quotient_loop:
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
PROVER_INPUT(bignum_modmul::quotient)
2023-02-17 17:11:58 -08:00
// stack: PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP8
2023-02-17 17:11:58 -08:00
// stack: scratch_1, PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP3
2023-02-17 17:11:58 -08:00
// stack: i, scratch_1, PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ADD
2023-02-17 17:11:58 -08:00
// stack: scratch_1[i], PI, i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%mstore_kernel_general
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%increment
2023-02-17 17:11:58 -08:00
// stack: i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP2
DUP2
2023-02-17 17:11:58 -08:00
// stack: i+1, length, i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%neq
2023-02-17 17:11:58 -08:00
// stack: i+1!=length, i+1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jumpi(modmul_quotient_loop)
modmul_quotient_end:
2023-02-17 17:11:58 -08:00
// stack: i, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
POP
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
// Verification step 1: calculate x + k * m.
2023-02-17 17:11:58 -08:00
// Store k * m in scratch_2.
2023-03-07 15:15:20 -08:00
PUSH modmul_return_1
2023-02-17 17:11:58 -08:00
// stack: modmul_return_1, length, a_start_loc, b_start_loc, m_start_loc, output_loc, scratch_1, scratch_2, scratch_3, retdest
%stack (return, len, a, b, m, out, s1, s2) -> (len, s1, m, s2, return, len, a, b, out, s2)
// stack: length, scratch_1, m_start_loc, scratch_2, modmul_return_1, length, a_start_loc, b_start_loc, output_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jump(mul_bignum)
modmul_return_1:
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, output_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
// Add x into k * m (in scratch_2).
PUSH modmul_return_2
2023-02-17 17:11:58 -08:00
// stack: modmul_return_2, length, a_start_loc, b_start_loc, output_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%stack (return, len, a, b, out, s2) -> (len, s2, out, return, len, a, b, s2)
2023-02-17 17:11:58 -08:00
// stack: length, scratch_2, output_loc, modmul_return_2, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jump(add_bignum)
modmul_return_2:
2023-02-17 17:11:58 -08:00
// stack: carry, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ISZERO
%jumpi(no_carry)
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP4
2023-02-17 17:11:58 -08:00
// stack: scratch_2, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP2
2023-02-17 17:11:58 -08:00
// stack: length, scratch_2, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ADD
2023-02-17 17:11:58 -08:00
// stack: cur_loc=scratch_2 + length, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
increment_loop:
2023-02-17 17:11:58 -08:00
// stack: cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP1
%mload_kernel_general
2023-02-17 17:11:58 -08:00
// stack: val, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%increment
2023-02-17 17:11:58 -08:00
// stack: val+1, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP1
2023-02-17 17:11:58 -08:00
// stack: val+1, val+1, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%eq_const(@BIGNUM_LIMB_BASE)
2023-02-17 17:11:58 -08:00
// stack: val+1==limb_base, val+1, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP1
2023-02-17 17:11:58 -08:00
// stack: val+1==limb_base, val+1==limb_base, val+1, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ISZERO
2023-02-17 17:11:58 -08:00
// stack: val+1!=limb_base, val+1==limb_base, val+1, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
SWAP1
SWAP2
2023-02-17 17:11:58 -08:00
// stack: val+1, val+1!=limb_base, val+1==limb_base, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
MUL
2023-02-17 17:11:58 -08:00
// stack: to_write=(val+1)*(val+1!=limb_base), continue=val+1==limb_base, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP3
2023-02-17 17:11:58 -08:00
// stack: cur_loc, to_write, continue, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%mstore_kernel_general
2023-02-17 17:11:58 -08:00
// stack: continue, cur_loc, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
SWAP1
2023-02-17 17:11:58 -08:00
// stack: cur_loc, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%increment
2023-02-17 17:11:58 -08:00
// stack: cur_loc + 1, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP1
2023-02-17 17:11:58 -08:00
// stack: cur_loc + 1, cur_loc + 1, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
DUP8
2023-02-17 17:11:58 -08:00
// stack: scratch_3, cur_loc + 1, cur_loc + 1, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
EQ
2023-02-17 17:11:58 -08:00
// stack: cur_loc + 1 == scratch_3, cur_loc + 1, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
ISZERO
2023-02-17 17:11:58 -08:00
// stack: cur_loc + 1 != scratch_3, cur_loc + 1, continue, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
SWAP1
SWAP2
2023-02-17 17:11:58 -08:00
// stack: continue, cur_loc + 1 != scratch_3, cur_loc + 1, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
MUL
2023-02-17 17:11:58 -08:00
// stack: new_continue=continue*(cur_loc + 1 != scratch_3), cur_loc + 1, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jumpi(increment_loop)
2023-02-17 17:11:58 -08:00
// stack: cur_loc + 1, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
POP
no_carry:
2023-02-17 17:11:58 -08:00
// stack: length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
// Calculate a * b.
2023-02-17 17:11:58 -08:00
// Store a * b in scratch_3.
2023-03-07 15:15:20 -08:00
PUSH modmul_return_3
2023-02-17 17:11:58 -08:00
// stack: modmul_return_3, length, a_start_loc, b_start_loc, scratch_2, scratch_3, retdest
%stack (return, len, a, b, s2, s3) -> (len, a, b, s3, return, len, s2, s3)
// stack: length, a_start_loc, b_start_loc, scratch_3, modmul_return_3, length, scratch_2, scratch_3, retdest
2023-03-07 15:15:20 -08:00
%jump(mul_bignum)
modmul_return_3:
// stack: length, scratch_2, scratch_3, retdest
// Check that x + k * m = a * b.
// Walk through scratch_2 and scratch_3, checking that they are equal.
// stack: n=length, i=scratch_2, j=scratch_3, retdest
modmul_check_loop:
// stack: n, i, j, retdest
%stack (l, idx: 2) -> (idx, l, idx)
// stack: i, j, n, i, j, retdest
%mload_kernel_general
SWAP1
%mload_kernel_general
SWAP1
// stack: mem[i], mem[j], n, i, j, retdest
%assert_eq
// stack: n, i, j, retdest
%decrement
// stack: n-1, i, j, retdest
SWAP1
// stack: i, n-1, j, retdest
%increment
// stack: i+1, n-1, j, retdest
SWAP2
// stack: j, n-1, i+1, retdest
%increment
// stack: j+1, n-1, i+1, retdest
SWAP2
SWAP1
// stack: n-1, i+1, j+1, retdest
DUP1
// stack: n-1, n-1, i+1, j+1, retdest
%jumpi(modmul_check_loop)
modmul_check_end:
// stack: n-1, i+1, j+1, retdest
%pop3
// stack: retdest
JUMP