// File: /workspace/github_c_makefile_star2_O2/LoupVaillant[P]Monocypher-Utils/src/monocypher.c
// Function: ge_scalarmult_base
static void ge_scalarmult_base(ge *p, const u8 scalar[32])
{
    // 5-bits signed comb, from Mike Hamburg's
    // Fast and compact elliptic-curve cryptography (2012)
    static const u8 half_mod_L[32] = { // 1 / 2 modulo L
        0xf7, 0xe9, 0x7a, 0x2e, 0x8d, 0x31, 0x09, 0x2c,
        0x6b, 0xce, 0x7b, 0x51, 0xef, 0x7c, 0x6f, 0x0a,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
    };
    static const u8 half_ones[32] = { // (2^255 - 1) / 2 modulo L
        0x42, 0x9a, 0xa3, 0xba, 0x23, 0xa5, 0xbf, 0xcb,
        0x11, 0x5b, 0x9d, 0xc5, 0x74, 0x95, 0xf3, 0xb6,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07,
    };
    // All bits set form: 1 means 1, 0 means -1
    u8 s_scalar[32];
    mul_add(s_scalar, scalar, half_mod_L, half_ones);

    // Double and add ladder
    fe yp, ym, t2, n2, a, b; // temporaries for addition
    ge dbl;                  // temporary for doublings
    ge_zero(p);
    for (int i = 50; i >= 0; i--) {
        if (i < 50) {
            ge_double(p, p, &dbl);
        }
        fe_1(yp);
        fe_1(ym);
        fe_0(t2);
        u8 teeth =  scalar_bit(s_scalar, i)
            +      (scalar_bit(s_scalar, i +  51) << 1)
            +      (scalar_bit(s_scalar, i + 102) << 2)
            +      (scalar_bit(s_scalar, i + 153) << 3)
            +      (scalar_bit(s_scalar, i + 204) << 4);
        u8 high  = teeth >> 4;
        u8 index = (teeth ^ (high - 1)) & 15;
        FOR (j, 0, 16) {
            i32 select = 1 & (((j ^ index) - 1) >> 8);
            fe_ccopy(yp, comb_Yp[j], select);
            fe_ccopy(ym, comb_Ym[j], select);
            fe_ccopy(t2, comb_T2[j], select);
        }

        fe_neg(n2, t2);
        fe_cswap(t2, n2, high);
        fe_cswap(yp, ym, high);
        ge_madd(p, p, ym, yp, n2, a, b);
    }
    WIPE_CTX(&dbl);
    WIPE_BUFFER(a);  WIPE_BUFFER(yp);  WIPE_BUFFER(t2);
    WIPE_BUFFER(b);  WIPE_BUFFER(ym);  WIPE_BUFFER(n2);
    WIPE_BUFFER(s_scalar);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x208, %rsp            # imm = 0x208
movq %rdi, %rbx
leaq 0x3f2b(%rip), %rdx      # 0x96a0
leaq 0x3f44(%rip), %rcx      # 0x96c0
leaq 0x30(%rsp), %rdi
callq 0x5d3e
movq %rbx, %rdi
callq 0x7565
leaq 0x28(%rbx), %rax
movq %rax, 0x18(%rsp)
leaq 0x50(%rbx), %rax
movq %rax, 0x10(%rsp)
movq %rbx, (%rsp)
leaq 0x78(%rbx), %rax
movq %rax, 0x8(%rsp)
pushq $0x32
popq %rbx
testl %ebx, %ebx
js 0x5a3d
cmpl $0x31, %ebx
ja 0x57d1
movq (%rsp), %rdi
movq %rdi, %rsi
leaq 0x168(%rsp), %rdx
callq 0x758d
leaq 0xb0(%rsp), %rdi
callq 0x4475
leaq 0x80(%rsp), %rdi
callq 0x4475
leaq 0x50(%rsp), %rdi
callq 0x448e
movl %ebx, %eax
shrl $0x3, %eax
movzbl 0x30(%rsp,%rax), %eax
movl %ebx, %ecx
andl $0x7, %ecx
xorl %edx, %edx
btl %ecx, %eax
setb %dl
leal 0x33(%rbx), %ecx
movl %ecx, %eax
shrl $0x3, %eax
movzbl 0x30(%rsp,%rax), %eax
andb $0x7, %cl
shrl %cl, %eax
andl $0x1, %eax
leal (%rdx,%rax,2), %eax
leal 0x66(%rbx), %ecx
movl %ecx, %edx
shrl $0x3, %edx
movzbl 0x30(%rsp,%rdx), %edx
andb $0x7, %cl
shrl %cl, %edx
andl $0x1, %edx
leal (%rax,%rdx,4), %eax
leal 0x99(%rbx), %ecx
movl %ecx, %edx
shrl $0x3, %edx
movzbl 0x30(%rsp,%rdx), %edx
andb $0x7, %cl
shrl %cl, %edx
andl $0x1, %edx
leal (%rax,%rdx,8), %eax
movq %rbx, 0x28(%rsp)
leal 0xcc(%rbx), %ecx
movl %ecx, %edx
shrl $0x3, %edx
movzbl 0x30(%rsp,%rdx), %edx
andl $0x7, %ecx
xorl %esi, %esi
btl %ecx, %edx
setb %sil
movq %rsi, 0x20(%rsp)
leal -0x1(%rsi), %r12d
andl $0xf, %r12d
xorl %eax, %r12d
leaq 0x4351(%rip), %r15      # 0x9be0
leaq 0x40ca(%rip), %rbx      # 0x9960
leaq 0x3e43(%rip), %rbp      # 0x96e0
xorl %r14d, %r14d
cmpq $0x10, %r14
je 0x58fe
movl %r12d, %r13d
xorl %r14d, %r13d
decl %r13d
shrl $0x8, %r13d
andl $0x1, %r13d
leaq 0xb0(%rsp), %rdi
movq %rbp, %rsi
movl %r13d, %edx
callq 0x7680
leaq 0x80(%rsp), %rdi
movq %rbx, %rsi
movl %r13d, %edx
callq 0x7680
leaq 0x50(%rsp), %rdi
movq %r15, %rsi
movl %r13d, %edx
callq 0x7680
incq %r14
addq $0x28, %rbp
addq $0x28, %rbx
addq $0x28, %r15
jmp 0x58a0
leaq 0xe0(%rsp), %r13
movq %r13, %rdi
leaq 0x50(%rsp), %rbx
movq %rbx, %rsi
callq 0x76a4
movq %rbx, %rdi
movq %r13, %rsi
movq 0x20(%rsp), %rbx
movl %ebx, %edx
callq 0x44b4
leaq 0xb0(%rsp), %r15
movq %r15, %rdi
leaq 0x80(%rsp), %r12
movq %r12, %rsi
movl %ebx, %edx
callq 0x44b4
leaq 0x140(%rsp), %rbp
movq %rbp, %rdi
movq 0x18(%rsp), %r14
movq %r14, %rsi
movq (%rsp), %rbx
movq %rbx, %rdx
callq 0x44f2
leaq 0x110(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x44db
movq %rbp, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x4509
movq %r13, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x4509
movq %r14, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x44f2
movq %rbx, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x44db
movq 0x10(%rsp), %r15
movq %r15, %rdi
movq %r15, %rsi
movq %r15, %rdx
callq 0x44f2
movq 0x8(%rsp), %r12
movq %r12, %rdi
movq %r12, %rsi
leaq 0xe0(%rsp), %rdx
callq 0x4509
movq %rbp, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x44f2
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x44db
movq %r12, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x4509
movq %rbx, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x4509
movq %r14, %rdi
movq %r14, %rsi
movq %rbp, %rdx
callq 0x4509
movq %r15, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x4509
movq 0x28(%rsp), %rbx
decl %ebx
jmp 0x57b0
leaq 0x168(%rsp), %rdi
movl $0xa0, %esi
callq 0x1734
leaq 0x140(%rsp), %rdi
pushq $0x28
popq %rbx
movq %rbx, %rsi
callq 0x1734
leaq 0xb0(%rsp), %rdi
movq %rbx, %rsi
callq 0x1734
leaq 0x50(%rsp), %rdi
movq %rbx, %rsi
callq 0x1734
leaq 0x110(%rsp), %rdi
movq %rbx, %rsi
callq 0x1734
leaq 0x80(%rsp), %rdi
movq %rbx, %rsi
callq 0x1734
leaq 0xe0(%rsp), %rdi
movq %rbx, %rsi
callq 0x1734
leaq 0x30(%rsp), %rdi
pushq $0x20
popq %rsi
callq 0x1734
addq $0x208, %rsp            # imm = 0x208
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq