// File: /workspace/github_c_makefile_star2_O3/ioerror[P]csidh-reference-implementation/bench.c
// Function: main
int main()
{
    clock_t t0, t1, time = 0;
    uint64_t c0, c1, cycles = 0;
    size_t bytes = 0;
    unsigned char *stack;

    private_key priv;
    public_key pub = base;
    (void) pub; /* suppress "unused variable" warning */

    printf("doing %lu iterations of%s%s%s.\n",
        its,
        val ? " validation" : "",
        val && act ? " and" : !val && !act ? " nothing" : "",
        act ? " action" : ""
    );

#ifdef X64
    __asm__ __volatile__ ("mov %%rsp, %0" : "=m"(stack));
#endif
#ifdef A64
    __asm__ __volatile__ ("mov %0, sp\n\t" : "=r"(stack)::);
#endif

    stack -= stacksz;

    for (unsigned long i = 0; i < its; ++i) {

        if (its >= 100 && i % (its / 100) == 0) {
            printf("%2lu%%", 100 * i / its);
            fflush(stdout);
            printf("\r\x1b[K");
        }

        csidh_private(&priv);

#if !defined(__OpenBSD__)
        /* spray stack */
        unsigned char canary;
        randombytes(&canary, 1);
        for (size_t j = 0; j < stacksz; ++j)
            stack[j] = canary;
#endif

        t0 = clock();   /* uses stack, but not too much */
        c0 = rdtsc();

        /**************************************/

        if (val)
            assert(validate(&pub));

        if (act)
            action(&pub, &pub, &priv);

        /**************************************/

        c1 = rdtsc();
        t1 = clock();
        cycles += c1 - c0;
        time += t1 - t0;

#if !defined(__OpenBSD__)
        /* check stack */
        assert(*stack == canary);   /* make sure we sprayed enough */
        for (size_t j = 0; j < stacksz - bytes; ++j)
            if (stack[j] != canary)
                bytes = stacksz - j;
#endif
    }

    printf("iterations: %lu\n", its);
    printf("clock cycles: %" PRIu64 " (%.1lf*10^6)\n", (uint64_t) cycles / its, 1e-6 * cycles / its);
    printf("wall-clock time: %.3lf ms\n", 1000. * time / CLOCKS_PER_SEC / its);
    printf("stack memory usage: %lu b\n", bytes);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
leaq 0x7f0(%rip), %rax       # 0x4280
vmovupd (%rax), %ymm0
vmovups 0x20(%rax), %ymm1
leaq 0x60(%rsp), %rbx
vmovups %ymm1, 0x20(%rbx)
vmovupd %ymm0, (%rbx)
leaq 0xa32(%rip), %rdi       # 0x44e0
leaq 0xa4b(%rip), %rdx       # 0x4500
leaq 0xa50(%rip), %rcx       # 0x450c
leaq 0xa4e(%rip), %r8        # 0x4511
movl $0x3e8, %esi            # imm = 0x3E8
xorl %eax, %eax
vzeroupper
callq 0x1040
movq %rsp, 0x10(%rsp)
addq $-0x8000, 0x10(%rsp)    # imm = 0x8000
leaq 0x3b(%rsp), %r12
xorl %r15d, %r15d
xorl %eax, %eax
xorl %r13d, %r13d
xorl %r14d, %r14d
movq %rax, 0x28(%rsp)
imull $0xffffcccd, %r15d, %eax # imm = 0xFFFFCCCD
rorw %ax
movzwl %ax, %eax
cmpl $0x1999, %eax           # imm = 0x1999
ja 0x3b44
movzwl %r15w, %eax
imull $0xcccd, %eax, %eax     # imm = 0xCCCD
shrl $0x13, %eax
movzwl %ax, %esi
leaq 0x9f9(%rip), %rdi       # 0x4519
xorl %eax, %eax
callq 0x1040
movq 0x24b2(%rip), %rax      # 0x5fe0
movq (%rax), %rdi
callq 0x1070
leaq 0x9e3(%rip), %rdi       # 0x4520
xorl %eax, %eax
callq 0x1040
movq %r15, 0x30(%rsp)
movq %r12, %rdi
callq 0x30b0
movl $0x1, %esi
leaq 0xf(%rsp), %rdi
callq 0x119c
movb 0xf(%rsp), %al
xorl %ecx, %ecx
movq 0x10(%rsp), %rdx
movb %al, (%rdx,%rcx)
incq %rcx
cmpq $0x8000, %rcx           # imm = 0x8000
jne 0x3b66
callq 0x1030
movq %rax, %rbp
rdtsc
movl %edx, %r15d
movl %eax, 0x1c(%rsp)
movq %rbx, %rdi
callq 0x312a
testb %al, %al
je 0x3d10
movq %rbp, 0x20(%rsp)
movq %rbx, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x3555
rdtsc
movl %edx, %r12d
movl %eax, %ebx
callq 0x1030
movq 0x10(%rsp), %rcx
movb (%rcx), %dl
cmpb 0xf(%rsp), %dl
jne 0x3cf1
movl $0x8000, %ebp           # imm = 0x8000
movq 0x28(%rsp), %r8
cmpq $0x8000, %r8            # imm = 0x8000
je 0x3c03
movl $0x8000, %esi           # imm = 0x8000
xorl %edi, %edi
movq %r8, %rbp
cmpb %dl, (%rcx,%rdi)
cmovneq %rsi, %rbp
incq %rdi
movl $0x8000, %r8d           # imm = 0x8000
subq %rbp, %r8
decq %rsi
cmpq %r8, %rdi
jb 0x3be8
negl %r15d
shlq $0x20, %r15
movl 0x1c(%rsp), %ecx
subq %rcx, %r13
movq %r13, %rcx
addq %r15, %rcx
movl %ebx, %edx
shlq $0x20, %r12
addq %rdx, %r12
movq %r12, %r13
addq %rcx, %r13
subq 0x20(%rsp), %r14
addq %rax, %r14
movq 0x30(%rsp), %r15
incq %r15
movq %rbp, %rax
cmpq $0x3e8, %r15            # imm = 0x3E8
leaq 0x60(%rsp), %rbx
leaq 0x3b(%rsp), %r12
jne 0x3af0
leaq 0x901(%rip), %rdi       # 0x4558
movl $0x3e8, %esi            # imm = 0x3E8
xorl %eax, %eax
callq 0x1040
movq %r13, %rdx
shrq $0x3, %rdx
movabsq $0x20c49ba5e353f7cf, %rax # imm = 0x20C49BA5E353F7CF
mulxq %rax, %rsi, %rsi
vcvtusi2sd %r13, %xmm2, %xmm0
shrq $0x4, %rsi
vmulsd 0x825(%rip), %xmm0, %xmm0 # 0x44b0
vdivsd 0x825(%rip), %xmm0, %xmm0 # 0x44b8
leaq 0x8cf(%rip), %rdi       # 0x4569
movb $0x1, %al
callq 0x1040
vcvtsi2sd %r14, %xmm2, %xmm0
vmovsd 0x80a(%rip), %xmm1      # 0x44b8
vmulsd %xmm1, %xmm0, %xmm0
vdivsd 0x806(%rip), %xmm0, %xmm0 # 0x44c0
vdivsd %xmm1, %xmm0, %xmm0
leaq 0x8c4(%rip), %rdi       # 0x4589
movb $0x1, %al
callq 0x1040
leaq 0x8d1(%rip), %rdi       # 0x45a4
movq %rbp, %rsi
xorl %eax, %eax
callq 0x1040
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x84f(%rip), %rdi       # 0x4547
leaq 0x835(%rip), %rsi       # 0x4534
leaq 0x836(%rip), %rcx       # 0x453c
movl $0x78, %edx
callq 0x1050
leaq 0x80e(%rip), %rdi       # 0x4525
leaq 0x816(%rip), %rsi       # 0x4534
leaq 0x817(%rip), %rcx       # 0x453c
movl $0x6a, %edx
callq 0x1050