// File: /workspace/github_cpp_makefile_star2_O2/marxn[P]pupp/3rdparty/gmp/mpn/toom4_sqr.c
// Function: _gmpn_toom4_sqr
void
mpn_toom4_sqr (mp_ptr pp,
	       mp_srcptr ap, mp_size_t an,
	       mp_ptr scratch)
{
  mp_size_t n, s;
  mp_limb_t cy;

#define a0  ap
#define a1  (ap + n)
#define a2  (ap + 2*n)
#define a3  (ap + 3*n)

  n = (an + 3) >> 2;

  s = an - 3 * n;

  ASSERT (0 < s && s <= n);

  /* NOTE: The multiplications to v2, vm2, vh and vm1 overwrites the
   * following limb, so these must be computed in order, and we need a
   * one limb gap to tp. */
#define v0    pp				/* 2n */
#define v1    (pp + 2 * n)			/* 2n+1 */
#define vinf  (pp + 6 * n)			/* s+t */
#define v2    scratch				/* 2n+1 */
#define vm2   (scratch + 2 * n + 1)		/* 2n+1 */
#define vh    (scratch + 4 * n + 2)		/* 2n+1 */
#define vm1   (scratch + 6 * n + 3)		/* 2n+1 */
#define tp (scratch + 8*n + 5)

  /* No overlap with v1 */
#define apx   pp				/* n+1 */
#define amx   (pp + 4*n + 2)			/* n+1 */

  /* Total scratch need: 8*n + 5 + scratch for recursive calls. This
     gives roughly 32 n/3 + log term. */

  /* Compute apx = a0 + 2 a1 + 4 a2 + 8 a3 and amx = a0 - 2 a1 + 4 a2 - 8 a3.  */
  mpn_toom_eval_dgr3_pm2 (apx, amx, ap, n, s, tp);

  TOOM4_SQR_REC (v2, apx, n + 1, tp);	/* v2,  2n+1 limbs */
  TOOM4_SQR_REC (vm2, amx, n + 1, tp);	/* vm2,  2n+1 limbs */

  /* Compute apx = 8 a0 + 4 a1 + 2 a2 + a3 = (((2*a0 + a1) * 2 + a2) * 2 + a3 */
#if HAVE_NATIVE_mpn_addlsh1_n
  cy = mpn_addlsh1_n (apx, a1, a0, n);
  cy = 2*cy + mpn_addlsh1_n (apx, a2, apx, n);
  if (s < n)
    {
      mp_limb_t cy2;
      cy2 = mpn_addlsh1_n (apx, a3, apx, s);
      apx[n] = 2*cy + mpn_lshift (apx + s, apx + s, n - s, 1);
      MPN_INCR_U (apx + s, n+1-s, cy2);
    }
  else
    apx[n] = 2*cy + mpn_addlsh1_n (apx, a3, apx, n);
#else
  cy = mpn_lshift (apx, a0, n, 1);
  cy += mpn_add_n (apx, apx, a1, n);
  cy = 2*cy + mpn_lshift (apx, apx, n, 1);
  cy += mpn_add_n (apx, apx, a2, n);
  cy = 2*cy + mpn_lshift (apx, apx, n, 1);
  apx[n] = cy + mpn_add (apx, apx, n, a3, s);
#endif

  ASSERT (apx[n] < 15);

  TOOM4_SQR_REC (vh, apx, n + 1, tp);	/* vh,  2n+1 limbs */

  /* Compute apx = a0 + a1 + a2 + a3 and amx = a0 - a1 + a2 - a3.  */
  mpn_toom_eval_dgr3_pm1 (apx, amx, ap, n, s, tp);

  TOOM4_SQR_REC (v1, apx, n + 1, tp);	/* v1,  2n+1 limbs */
  TOOM4_SQR_REC (vm1, amx, n + 1, tp);	/* vm1,  2n+1 limbs */

  TOOM4_SQR_REC (v0, a0, n, tp);
  TOOM4_SQR_REC (vinf, a3, s, tp);	/* vinf, 2s limbs */

  mpn_toom_interpolate_7pts (pp, n, (enum toom7_flags) 0, vm2, vm1, v2, vh, 2*s, tp);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rcx, %r14
movq %rcx, 0x8(%rsp)
movq %rdx, %r13
movq %rsi, %rdx
movq %rsi, (%rsp)
movq %rdi, %r15
leaq 0x3(%r13), %rsi
movq %rsi, %r12
sarq $0x2, %r12
leaq (%r12,%r12,2), %rcx
movq %rcx, 0x20(%rsp)
subq %rcx, %r13
andq $-0x4, %rsi
movq %rsi, 0x18(%rsp)
leaq (%rdi,%rsi,8), %rsi
addq $0x10, %rsi
movq %rsi, 0x28(%rsp)
movq %r12, %rax
shlq $0x6, %rax
leaq (%r14,%rax), %rbx
addq $0x28, %rbx
movq %r12, %rcx
movq %r13, %r8
movq %rbx, %r9
callq 0x226f4
leaq 0x1(%r12), %rbp
movq %r14, %rdi
movq %r15, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
callq 0x220b0
leaq (%r12,%r12), %rax
movq %rax, 0x10(%rsp)
movq %r12, %r14
shlq $0x4, %r14
movq 0x8(%rsp), %rax
leaq (%rax,%r14), %rdi
addq $0x8, %rdi
movq %rdi, 0x48(%rsp)
movq 0x28(%rsp), %rsi
movq %rbp, 0x40(%rsp)
movq %rbp, %rdx
movq %rbx, 0x50(%rsp)
movq %rbx, %rcx
callq 0x220b0
movq (%rsp), %rbx
leaq (%rbx,%r12,8), %rsi
movq %r15, %rdi
movq %rbx, %rdx
movq %r12, %rcx
callq 0x291c0
movq %rax, %rbp
addq %rbx, %r14
movq %r15, %rdi
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
callq 0x291c0
leaq (%rax,%rbp,2), %rbx
movq %r12, %r14
movq %r13, 0x30(%rsp)
subq %r13, %r14
jle 0x2252a
movq (%rsp), %rax
movq 0x20(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
movq %r15, %rdi
movq %r15, %rdx
movq %rbx, %r13
movq 0x30(%rsp), %rbx
movq %rbx, %rcx
callq 0x291c0
movq %rax, 0x38(%rsp)
leaq (%r15,%rbx,8), %rbp
pushq $0x1
popq %rcx
movq %rbp, %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0x181a0
leaq (%rax,%r13,2), %rax
movq %rax, (%r15,%r12,8)
movq 0x38(%rsp), %rax
addq %rax, (%rbp)
jae 0x22528
addq $0x1, 0x8(%rbp)
leaq 0x8(%rbp), %rbp
jb 0x2251d
jmp 0x2254d
movq (%rsp), %rax
movq 0x20(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
movq %r15, %rdi
movq %r15, %rdx
movq %r12, %rcx
callq 0x291c0
leaq (%rax,%rbx,2), %rax
movq %rax, (%r15,%r12,8)
movq 0x18(%rsp), %rax
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,8), %rdi
addq $0x10, %rdi
movq %rdi, 0x18(%rsp)
movq %r15, %rsi
movq 0x40(%rsp), %r13
movq %r13, %rdx
movq 0x50(%rsp), %r14
movq %r14, %rcx
callq 0x220b0
movq %r15, %rdi
movq 0x28(%rsp), %rsi
movq (%rsp), %rdx
movq %r12, %rcx
movq 0x30(%rsp), %rbx
movq %rbx, %r8
movq %r14, %r9
callq 0x22648
movq 0x10(%rsp), %rax
leaq (%r15,%rax,8), %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %r14, %rcx
callq 0x220b0
imulq $0x30, %r12, %rbp
movq 0x8(%rsp), %rax
leaq (%rax,%rbp), %rdi
addq $0x18, %rdi
movq %rdi, 0x10(%rsp)
movq 0x28(%rsp), %rsi
movq %r13, %rdx
movq %r14, %rcx
callq 0x220b0
movq %r15, %rdi
movq (%rsp), %r13
movq %r13, %rsi
movq %r12, %rdx
movq %r14, %rcx
callq 0x220b0
addq %r15, %rbp
movq 0x20(%rsp), %rax
leaq (,%rax,8), %rsi
addq %r13, %rsi
movq %rbp, %rdi
movq %rbx, %rdx
movq %r14, %rcx
callq 0x220b0
addq %rbx, %rbx
subq $0x8, %rsp
movq %r15, %rdi
movq %r12, %rsi
xorl %edx, %edx
movq 0x50(%rsp), %rcx
movq 0x18(%rsp), %r8
movq 0x10(%rsp), %r9
pushq %r14
pushq %rbx
pushq 0x30(%rsp)
callq 0x23460
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop