// File: occivink[P]pyct/monocypher.cpp
// Function: mod_l(unsigned char*, unsigned int const*)
static void mod_l(u8 reduced[32], const u32 x[16])
{
    static const u32 r[9] = {0x0a2c131b,0xed9ce5a3,0x086329a7,0x2106215d,
                             0xffffffeb,0xffffffff,0xffffffff,0xffffffff,0xf,};
    // xr = x * r
    u32 xr[25] = {0};
    FOR (i, 0, 9) {
        u64 carry = 0;
        FOR (j, 0, 16) {
            carry  += xr[i+j] + (u64)r[i] * x[j];
            xr[i+j] = (u32)carry;
            carry >>= 32;
        }
        xr[i+16] = (u32)carry;
    }
    // xr = floor(xr / 2^512) * L
    // Since the result is guaranteed to be below 2*L,
    // it is enough to only compute the first 256 bits.
    // The division is performed by saying xr[i+16]. (16 * 32 = 512)
    ZERO(xr, 8);
    FOR (i, 0, 8) {
        u64 carry = 0;
        FOR (j, 0, 8-i) {
            carry   += xr[i+j] + (u64)xr[i+16] * L[j];
            xr[i+j] = (u32)carry;
            carry >>= 32;
        }
    }
    // xr = x - xr
    u64 carry = 1;
    FOR (i, 0, 8) {
        carry  += (u64)x[i] + (~xr[i] & 0xffffffff);
        xr[i]   = (u32)carry;
        carry >>= 32;
    }
    // Final reduction modulo L (conditional subtraction)
    remove_l(xr, xr);
    store32_le_buf(reduced, xr, 8);

    WIPE_BUFFER(xr);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x80(%rbp), %rdi
xorl %esi, %esi
movl $0x64, %edx
callq 0x3160
movq $0x0, -0x88(%rbp)
cmpq $0x9, -0x88(%rbp)
jae 0x11e25
movq $0x0, -0x90(%rbp)
movq $0x0, -0x98(%rbp)
cmpq $0x10, -0x98(%rbp)
jae 0x11dfa
movq -0x88(%rbp), %rax
addq -0x98(%rbp), %rax
movl -0x80(%rbp,%rax,4), %eax
movq -0x88(%rbp), %rdx
leaq 0xb1c0(%rip), %rcx      # 0x1cf50
movl (%rcx,%rdx,4), %ecx
movq -0x10(%rbp), %rdx
movq -0x98(%rbp), %rsi
movl (%rdx,%rsi,4), %edx
imulq %rdx, %rcx
addq %rcx, %rax
addq -0x90(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movl %eax, %ecx
movq -0x88(%rbp), %rax
addq -0x98(%rbp), %rax
movl %ecx, -0x80(%rbp,%rax,4)
movq -0x90(%rbp), %rax
shrq $0x20, %rax
movq %rax, -0x90(%rbp)
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
jmp 0x11d62
movq -0x90(%rbp), %rax
movl %eax, %ecx
movq -0x88(%rbp), %rax
movl %ecx, -0x40(%rbp,%rax,4)
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x88(%rbp)
jmp 0x11d3e
movq $0x0, -0xa0(%rbp)
cmpq $0x8, -0xa0(%rbp)
jae 0x11e5d
movq -0xa0(%rbp), %rax
movl $0x0, -0x80(%rbp,%rax,4)
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0x11e30
movq $0x0, -0xa8(%rbp)
cmpq $0x8, -0xa8(%rbp)
jae 0x11f48
movq $0x0, -0xb0(%rbp)
movq $0x0, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
movl $0x8, %ecx
subq -0xa8(%rbp), %rcx
cmpq %rcx, %rax
jae 0x11f2f
movq -0xa8(%rbp), %rax
addq -0xb8(%rbp), %rax
movl -0x80(%rbp,%rax,4), %eax
movq -0xa8(%rbp), %rcx
movl -0x40(%rbp,%rcx,4), %ecx
movq -0xb8(%rbp), %rsi
leaq 0xac0d(%rip), %rdx      # 0x1cae0
movl (%rdx,%rsi,4), %edx
imulq %rdx, %rcx
addq %rcx, %rax
addq -0xb0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movl %eax, %ecx
movq -0xa8(%rbp), %rax
addq -0xb8(%rbp), %rax
movl %ecx, -0x80(%rbp,%rax,4)
movq -0xb0(%rbp), %rax
shrq $0x20, %rax
movq %rax, -0xb0(%rbp)
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb8(%rbp)
jmp 0x11e8c
jmp 0x11f31
movq -0xa8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa8(%rbp)
jmp 0x11e68
movq $0x1, -0xc0(%rbp)
movq $0x0, -0xc8(%rbp)
cmpq $0x8, -0xc8(%rbp)
jae 0x11fd4
movq -0x10(%rbp), %rax
movq -0xc8(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movq -0xc8(%rbp), %rcx
movl -0x80(%rbp,%rcx,4), %ecx
xorl $-0x1, %ecx
andl $-0x1, %ecx
movl %ecx, %ecx
addq %rcx, %rax
addq -0xc0(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movl %eax, %ecx
movq -0xc8(%rbp), %rax
movl %ecx, -0x80(%rbp,%rax,4)
movq -0xc0(%rbp), %rax
shrq $0x20, %rax
movq %rax, -0xc0(%rbp)
movq -0xc8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xc8(%rbp)
jmp 0x11f5e
leaq -0x80(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x13340
movq -0x8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movl $0x8, %edx
callq 0x3ef0
leaq -0x80(%rbp), %rdi
movl $0x64, %esi
callq 0x3890
addq $0xd0, %rsp
popq %rbp
retq
nopw (%rax,%rax)