2023-03-21 10:56:25 -07:00
|
|
|
// Arithmetic on integers represented with 128-bit limbs.
|
|
|
|
|
// These integers are represented in LITTLE-ENDIAN form.
|
2023-03-07 15:15:20 -08:00
|
|
|
// All integers must be under a given length bound, and are padded with leading zeroes.
|
|
|
|
|
|
|
|
|
|
// Stores b ^ e % m in output_loc, leaving b, e, and m unchanged.
|
|
|
|
|
// b, e, and m must have the same length.
|
|
|
|
|
// output_loc must have size length and be initialized with zeroes; scratch_1 must have size length.
|
2023-02-21 17:04:25 -08:00
|
|
|
// All of scratch_2..scratch_5 must have size 2 * length and be initialized with zeroes.
|
2023-03-07 15:15:20 -08:00
|
|
|
global modexp_bignum:
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1 (=scratch_1), s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
// We store the repeated-squares accumulator x_i in scratch_1, starting with x_0 := b.
|
|
|
|
|
DUP1
|
|
|
|
|
DUP3
|
|
|
|
|
DUP8
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: s1, b_loc, len, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%memcpy_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
// We store the accumulated output value x_i in output_loc, starting with x_0=1.
|
|
|
|
|
PUSH 1
|
|
|
|
|
DUP6
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: out_loc, 1, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%mstore_kernel_general
|
|
|
|
|
|
|
|
|
|
modexp_loop:
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
// y := e % 2
|
|
|
|
|
DUP3
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: e_loc, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%mload_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: e_first, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%mod_const(2)
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: y = e_first % 2 = e % 2, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
ISZERO
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: y == 0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jumpi(modexp_y_0)
|
|
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// if y == 1, modular-multiply output_loc by scratch_1, using scratch_2..scratch_4 as scratch space, and store in scratch_5.
|
2023-03-07 15:15:20 -08:00
|
|
|
PUSH modexp_mul_return
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP10
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP10
|
|
|
|
|
DUP10
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP14
|
|
|
|
|
DUP9
|
|
|
|
|
DUP12
|
|
|
|
|
DUP12
|
|
|
|
|
DUP9
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, out_loc, s1, m_loc, s5, s2, s3, s4, modexp_mul_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jump(modmul_bignum)
|
|
|
|
|
modexp_mul_return:
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// Copy scratch_5 to output_loc.
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP1
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP11
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP7
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: out_loc, s5, len, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%memcpy_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// Zero out scratch_2..scratch_5.
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP1
|
2023-02-21 17:04:25 -08:00
|
|
|
%mul_const(8)
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP8
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: s2, 8 * len, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%clear_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
modexp_y_0:
|
|
|
|
|
// if y == 0, do nothing
|
|
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// Modular-square repeated-squares accumulator x_i (in scratch_1), using scratch_2..scratch_4 as scratch space, and store in scratch_5.
|
2023-03-07 15:15:20 -08:00
|
|
|
PUSH modexp_square_return
|
|
|
|
|
DUP10
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP10
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP10
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP14
|
|
|
|
|
DUP9
|
|
|
|
|
DUP12
|
|
|
|
|
DUP1
|
|
|
|
|
DUP9
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, s1, s1, m_loc, s5, s2, s3, s4, modexp_square_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jump(modmul_bignum)
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
modexp_square_return:
|
2023-02-21 17:04:25 -08:00
|
|
|
// Copy scratch_5 to scratch_1.
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP1
|
2023-02-21 17:04:25 -08:00
|
|
|
DUP11
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP8
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: s1, s5, len, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%memcpy_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// Zero out scratch_2..scratch_5.
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP1
|
2023-02-21 17:04:25 -08:00
|
|
|
%mul_const(8)
|
2023-03-07 15:15:20 -08:00
|
|
|
DUP8
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: s2, 8 * len, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%clear_kernel_general
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
2023-02-21 17:04:25 -08:00
|
|
|
// e //= 2 (with shr_bignum)
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
PUSH modexp_shr_return
|
|
|
|
|
DUP4
|
|
|
|
|
DUP3
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, e_loc, modexp_shr_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jump(shr_bignum)
|
|
|
|
|
modexp_shr_return:
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
|
|
|
|
|
// check if e == 0 (with iszero_bignum)
|
|
|
|
|
PUSH modexp_iszero_return
|
|
|
|
|
DUP4
|
|
|
|
|
DUP3
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: len, e_loc, modexp_iszero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jump(iszero_bignum)
|
|
|
|
|
modexp_iszero_return:
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: e == 0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
ISZERO
|
2023-03-21 10:56:25 -07:00
|
|
|
// stack: e != 0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-03-07 15:15:20 -08:00
|
|
|
%jumpi(modexp_loop)
|
2023-03-21 10:56:25 -07:00
|
|
|
// end of modexp_loop
|
|
|
|
|
// stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest
|
2023-02-21 17:04:25 -08:00
|
|
|
%rep 10
|
2023-03-07 15:15:20 -08:00
|
|
|
POP
|
|
|
|
|
%endrep
|
|
|
|
|
// stack: retdest
|
|
|
|
|
JUMP
|
|
|
|
|
|
|
|
|
|
|