// File: /workspace/github_c_makefile_star2_O0/an4[P]Applied-Security-Mod/modmul.c
// Function: sliding_window_exponentiation
void sliding_window_exponentiation(mpz_t output, mpz_t base, mpz_t exp, mpz_t modulus) {
    const int table_length = 1 << (WINDOW_SIZE - 1);
    mpz_t table[table_length];
    mpz_t square_base;
    mpz_t temp;
    int i;
    int exp_length;
    int l;
    // value in window
    int u;

    mpz_init(temp);
    mpz_init(square_base);

    // T[0] = x
    mpz_init_set(table[0], base);
    // x^2 mod N
    mpz_mul(square_base, base, base);
    mpz_mod(square_base, square_base, modulus);
    // Compute lookup table.
    for(i = 1; i < table_length; i++) {
        mpz_init(table[i]);
        mpz_mul(table[i], table[i-1], square_base);
        mpz_mod(table[i], table[i], modulus);
    }
    // t = 1
    mpz_init_set_ui(output, 1);
    // |y|
    exp_length = mpz_size(exp) * mp_bits_per_limb;
    // |y| - 1
    i = exp_length - 1;
    while(i >= 0) {
        if(!mpz_tstbit(exp, i)) {
            l = i;
            u = 0;
        } else {
            l = ((i - WINDOW_SIZE + 1) > 0) ? (i - WINDOW_SIZE + 1) : 0;
            while(!mpz_tstbit(exp,l)) {
                l++;
            }
            // Set u = exp bits between i and l
            u = binary_to_decimal(exp, i, l);
        }

        // t' = t
        mpz_set(temp, output);
        // t^p
        int p = 1 << (i - l + 1);
        if(p>0) {
            // t = t'^p (mod N)
            mpz_powm_ui(output, temp, p, modulus);
        }
        if(u != 0) {
            // t = t * T[(u-1)/2] mod N
            mpz_mul(output, output, table[(u-1)/2]);
            mpz_mod(output, output, modulus);
        }
        i = l - 1;
    }

    mpz_clear(square_base);
    mpz_clear(temp);
    for(i=0 ; i<table_length; i++) {
        mpz_clear(table[i]);
    }
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
movq %rdi, 0x100(%rsp)
movq %rsi, 0xf8(%rsp)
movq %rdx, 0xf0(%rsp)
movq %rcx, 0xe8(%rsp)
movl $0x8, 0xe4(%rsp)
movq %rsp, %rax
movq %rax, 0xd8(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x4a80
leaq 0xc0(%rsp), %rdi
callq 0x4a80
leaq 0x10(%rsp), %rdi
movq 0xf8(%rsp), %rsi
callq 0x4cc0
leaq 0xc0(%rsp), %rdi
movq 0xf8(%rsp), %rsi
movq 0xf8(%rsp), %rdx
callq 0x4ed0
leaq 0xc0(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
callq 0x4d60
movl $0x1, 0xac(%rsp)
cmpl $0x8, 0xac(%rsp)
jge 0x24f9
movslq 0xac(%rsp), %rax
leaq 0x10(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
callq 0x4a80
movslq 0xac(%rsp), %rax
leaq 0x10(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
movl 0xac(%rsp), %eax
subl $0x1, %eax
cltq
leaq 0x10(%rsp), %rsi
shlq $0x4, %rax
addq %rax, %rsi
leaq 0xc0(%rsp), %rdx
callq 0x4ed0
movslq 0xac(%rsp), %rax
leaq 0x10(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
movslq 0xac(%rsp), %rax
leaq 0x10(%rsp), %rsi
shlq $0x4, %rax
addq %rax, %rsi
movq 0xe8(%rsp), %rdx
callq 0x4d60
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x244e
movq 0x100(%rsp), %rdi
movl $0x1, %esi
callq 0x4d20
movq 0xf0(%rsp), %rdi
callq 0x7110
leaq 0x34c4d(%rip), %rcx     # 0x3716c
movslq (%rcx), %rcx
imulq %rcx, %rax
movl %eax, 0xa8(%rsp)
movl 0xa8(%rsp), %eax
subl $0x1, %eax
movl %eax, 0xac(%rsp)
cmpl $0x0, 0xac(%rsp)
jl 0x26e9
movq 0xf0(%rsp), %rdi
movslq 0xac(%rsp), %rsi
callq 0x80b0
cmpl $0x0, %eax
jne 0x2584
movl 0xac(%rsp), %eax
movl %eax, 0xa4(%rsp)
movl $0x0, 0xa0(%rsp)
jmp 0x2614
movl 0xac(%rsp), %eax
subl $0x4, %eax
addl $0x1, %eax
cmpl $0x0, %eax
jle 0x25a9
movl 0xac(%rsp), %eax
subl $0x4, %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x25b1
xorl %eax, %eax
movl %eax, 0xc(%rsp)
jmp 0x25b1
movl 0xc(%rsp), %eax
movl %eax, 0xa4(%rsp)
movq 0xf0(%rsp), %rdi
movslq 0xa4(%rsp), %rsi
callq 0x80b0
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x25df
jmp 0x25f2
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x25bc
movq 0xf0(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xa4(%rsp), %edx
callq 0x2320
movl %eax, 0xa0(%rsp)
leaq 0xb0(%rsp), %rdi
movq 0x100(%rsp), %rsi
callq 0x7060
movl 0xac(%rsp), %ecx
subl 0xa4(%rsp), %ecx
addl $0x1, %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, 0x9c(%rsp)
cmpl $0x0, 0x9c(%rsp)
jle 0x2677
movq 0x100(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
movslq 0x9c(%rsp), %rdx
movq 0xe8(%rsp), %rcx
callq 0x6820
cmpl $0x0, 0xa0(%rsp)
je 0x26d3
movq 0x100(%rsp), %rdi
movq 0x100(%rsp), %rsi
movl 0xa0(%rsp), %eax
subl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
cltq
leaq 0x10(%rsp), %rdx
shlq $0x4, %rax
addq %rax, %rdx
callq 0x4ed0
movq 0x100(%rsp), %rdi
movq 0x100(%rsp), %rsi
movq 0xe8(%rsp), %rdx
callq 0x4d60
movl 0xa4(%rsp), %eax
subl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x253e
leaq 0xc0(%rsp), %rdi
callq 0x4460
leaq 0xb0(%rsp), %rdi
callq 0x4460
movl $0x0, 0xac(%rsp)
cmpl $0x8, 0xac(%rsp)
jge 0x2744
movslq 0xac(%rsp), %rax
leaq 0x10(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
callq 0x4460
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x270e
movq 0xd8(%rsp), %rax
movq %rax, %rsp
addq $0x108, %rsp            # imm = 0x108
retq
nopw (%rax,%rax)