// File: occivink[P]pyct/monocypher.cpp
// Function: crypto_x25519_dirty_fast
void crypto_x25519_dirty_fast(u8 public_key[32], const u8 secret_key[32])
{
    // Compute clean scalar multiplication
    u8 scalar[32];
    ge pk;
    COPY(scalar, secret_key, 32);
    trim_scalar(scalar);
    ge_scalarmult_base(&pk, scalar);

    // Compute low order point
    fe t1, t2;
    select_lop(t1, lop_x, sqrtm1, secret_key[0]);
    select_lop(t2, lop_y, fe_one, secret_key[0] + 2);
    ge_precomp low_order_point;
    fe_add(low_order_point.Yp, t2, t1);
    fe_sub(low_order_point.Ym, t2, t1);
    fe_mul(low_order_point.T2, t2, t1);
    fe_mul(low_order_point.T2, low_order_point.T2, D2);

    // Add low order point to the public key
    ge_madd(&pk, &pk, &low_order_point, t1, t2);

    // Convert to Montgomery u coordinate (we ignore the sign)
    fe_add(t1, pk.Z, pk.Y);
    fe_sub(t2, pk.Z, pk.Y);
    fe_invert(t2, t2);
    fe_mul(t1, t1, t2);

    fe_tobytes(public_key, t1);

    WIPE_BUFFER(t1);    WIPE_CTX(&pk);
    WIPE_BUFFER(t2);    WIPE_CTX(&low_order_point);
    WIPE_BUFFER(scalar);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0xd8(%rbp)
cmpq $0x20, -0xd8(%rbp)
jae 0xfbd5
movq -0x10(%rbp), %rax
movq -0xd8(%rbp), %rcx
movb (%rax,%rcx), %cl
movq -0xd8(%rbp), %rax
movb %cl, -0x30(%rbp,%rax)
movq -0xd8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd8(%rbp)
jmp 0xfb9e
leaq -0x30(%rbp), %rdi
callq 0xd6e0
leaq -0x30(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0xdb40
leaq -0x100(%rbp), %rdi
movq -0x10(%rbp), %rax
leaq 0xc520(%rip), %rsi      # 0x1c120
leaq 0xc549(%rip), %rdx      # 0x1c150
movzbl (%rax), %ecx
callq 0xfdb0
leaq -0x130(%rbp), %rdi
movq -0x10(%rbp), %rax
movzbl (%rax), %eax
addl $0x2, %eax
leaq 0xc559(%rip), %rsi      # 0x1c180
leaq 0xd292(%rip), %rdx      # 0x1cec0
movzbl %al, %ecx
callq 0xfdb0
leaq -0x1a8(%rbp), %rdi
leaq -0x130(%rbp), %rsi
leaq -0x100(%rbp), %rdx
callq 0xeb00
leaq -0x1a8(%rbp), %rdi
addq $0x28, %rdi
leaq -0x130(%rbp), %rsi
leaq -0x100(%rbp), %rdx
callq 0xeb50
leaq -0x1a8(%rbp), %rdi
addq $0x50, %rdi
leaq -0x130(%rbp), %rsi
leaq -0x100(%rbp), %rdx
callq 0xec00
leaq -0x1a8(%rbp), %rdi
addq $0x50, %rdi
leaq -0x1a8(%rbp), %rsi
addq $0x50, %rsi
leaq 0xc507(%rip), %rdx      # 0x1c1b0
callq 0xec00
leaq -0x100(%rbp), %rcx
leaq -0x130(%rbp), %r8
leaq -0xd0(%rbp), %rsi
leaq -0x1a8(%rbp), %rdx
movq %rsi, %rdi
callq 0xfe40
leaq -0x100(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
addq $0x50, %rsi
leaq -0xd0(%rbp), %rdx
addq $0x28, %rdx
callq 0xeb00
leaq -0x130(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
addq $0x50, %rsi
leaq -0xd0(%rbp), %rdx
addq $0x28, %rdx
callq 0xeb50
leaq -0x130(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0xeba0
leaq -0x100(%rbp), %rdi
leaq -0x100(%rbp), %rsi
leaq -0x130(%rbp), %rdx
callq 0xec00
movq -0x8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0xf800
leaq -0x100(%rbp), %rdi
movl $0x28, %esi
callq 0x3890
leaq -0xd0(%rbp), %rdi
movl $0xa0, %esi
callq 0x3890
leaq -0x130(%rbp), %rdi
movl $0x28, %esi
callq 0x3890
leaq -0x1a8(%rbp), %rdi
movl $0x78, %esi
callq 0x3890
leaq -0x30(%rbp), %rdi
movl $0x20, %esi
callq 0x3890
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
nop