// File: /workspace/github_c_makefile_star2_O0/skeeto[P]enchive/src/curve25519-donna.c
// Function: fmonty
static void
fmonty(int64_t *x2, int64_t *z2,  /* output 2Q */
       int64_t *x3, int64_t *z3,  /* output Q + Q' */
       int64_t *x, int64_t *z,    /* input Q */
       int64_t *xprime, int64_t *zprime,  /* input Q' */
       const int64_t *qmqp /* input Q - Q' */)
{
  int64_t origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
        zzprime[19], zzzprime[19], xxxprime[19];

  memcpy(origx, x, 10 * sizeof(int64_t));
  fsum(x, z);
  /* |x[i]| < 2^27 */
  fdifference(z, origx);  /* does x - z */
  /* |z[i]| < 2^27 */

  memcpy(origxprime, xprime, sizeof(int64_t) * 10);
  fsum(xprime, zprime);
  /* |xprime[i]| < 2^27 */
  fdifference(zprime, origxprime);
  /* |zprime[i]| < 2^27 */
  fproduct(xxprime, xprime, z);
  /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be <
   * 2^(27+27) and fproduct adds together, at most, 14 of those products.
   * (Approximating that to 2^58 doesn't work out.) */
  fproduct(zzprime, x, zprime);
  /* |zzprime[i]| < 14*2^54 */
  freduce_degree(xxprime);
  freduce_coefficients(xxprime);
  /* |xxprime[i]| < 2^26 */
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  /* |zzprime[i]| < 2^26 */
  memcpy(origxprime, xxprime, sizeof(int64_t) * 10);
  fsum(xxprime, zzprime);
  /* |xxprime[i]| < 2^27 */
  fdifference(zzprime, origxprime);
  /* |zzprime[i]| < 2^27 */
  fsquare(xxxprime, xxprime);
  /* |xxxprime[i]| < 2^26 */
  fsquare(zzzprime, zzprime);
  /* |zzzprime[i]| < 2^26 */
  fproduct(zzprime, zzzprime, qmqp);
  /* |zzprime[i]| < 14*2^52 */
  freduce_degree(zzprime);
  freduce_coefficients(zzprime);
  /* |zzprime[i]| < 2^26 */
  memcpy(x3, xxxprime, sizeof(int64_t) * 10);
  memcpy(z3, zzprime, sizeof(int64_t) * 10);

  fsquare(xx, x);
  /* |xx[i]| < 2^26 */
  fsquare(zz, z);
  /* |zz[i]| < 2^26 */
  fproduct(x2, xx, zz);
  /* |x2[i]| < 14*2^52 */
  freduce_degree(x2);
  freduce_coefficients(x2);
  /* |x2[i]| < 2^26 */
  fdifference(zz, xx);  /* does zz = xx - zz */
  /* |zz[i]| < 2^27 */
  memset(zzz + 10, 0, sizeof(int64_t) * 9);
  fscalar_product(zzz, zz, 121665);
  /* |zzz[i]| < 2^(27+17) */
  /* No need to call freduce_degree here:
     fscalar_product doesn't increase the degree of its input. */
  freduce_coefficients(zzz);
  /* |zzz[i]| < 2^26 */
  fsum(zzz, xx);
  /* |zzz[i]| < 2^27 */
  fproduct(z2, zz, zzz);
  /* |z2[i]| < 14*2^(26+27) */
  freduce_degree(z2);
  freduce_coefficients(z2);
  /* |z2|i| < 2^26 */
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x530, %rsp            # imm = 0x530
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
leaq -0x80(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x50, %edx
callq 0x2230
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x89c0
movq -0x30(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x8a50
leaq -0xd0(%rbp), %rdi
movq 0x10(%rbp), %rsi
movl $0x50, %edx
callq 0x2230
movq 0x10(%rbp), %rdi
movq 0x18(%rbp), %rsi
callq 0x89c0
movq 0x18(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x8a50
leaq -0x350(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x8aa0
leaq -0x3f0(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq 0x18(%rbp), %rdx
callq 0x8aa0
leaq -0x350(%rbp), %rdi
callq 0x9620
leaq -0x350(%rbp), %rdi
callq 0x98a0
leaq -0x3f0(%rbp), %rdi
callq 0x9620
leaq -0x3f0(%rbp), %rdi
callq 0x98a0
leaq -0xd0(%rbp), %rdi
leaq -0x350(%rbp), %rsi
movl $0x50, %edx
callq 0x2230
leaq -0x350(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
callq 0x89c0
leaq -0x3f0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x8a50
leaq -0x530(%rbp), %rdi
leaq -0x350(%rbp), %rsi
callq 0x9a00
leaq -0x490(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
callq 0x9a00
leaq -0x3f0(%rbp), %rdi
leaq -0x490(%rbp), %rsi
movq 0x20(%rbp), %rdx
callq 0x8aa0
leaq -0x3f0(%rbp), %rdi
callq 0x9620
leaq -0x3f0(%rbp), %rdi
callq 0x98a0
movq -0x18(%rbp), %rdi
leaq -0x530(%rbp), %rsi
movl $0x50, %edx
callq 0x2230
movq -0x20(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
movl $0x50, %edx
callq 0x2230
leaq -0x210(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x9a00
leaq -0x2b0(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x9a00
movq -0x8(%rbp), %rdi
leaq -0x210(%rbp), %rsi
leaq -0x2b0(%rbp), %rdx
callq 0x8aa0
movq -0x8(%rbp), %rdi
callq 0x9620
movq -0x8(%rbp), %rdi
callq 0x98a0
leaq -0x2b0(%rbp), %rdi
leaq -0x210(%rbp), %rsi
callq 0x8a50
leaq -0x170(%rbp), %rdi
addq $0x50, %rdi
xorl %esi, %esi
movl $0x48, %edx
callq 0x2160
leaq -0x170(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
movl $0x1db41, %edx          # imm = 0x1DB41
callq 0x9a60
leaq -0x170(%rbp), %rdi
callq 0x98a0
leaq -0x170(%rbp), %rdi
leaq -0x210(%rbp), %rsi
callq 0x89c0
movq -0x10(%rbp), %rdi
leaq -0x2b0(%rbp), %rsi
leaq -0x170(%rbp), %rdx
callq 0x8aa0
movq -0x10(%rbp), %rdi
callq 0x9620
movq -0x10(%rbp), %rdi
callq 0x98a0
addq $0x530, %rsp            # imm = 0x530
popq %rbp
retq
nop