// File: 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
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x18(%rbp), %rax
addq $0x3, %rax
sarq $0x2, %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
imulq $0x3, -0x28(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x30(%rbp)
jmp 0x4969d
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x10(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x20(%rbp), %r9
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %r9
addq $0x28, %r9
callq 0x49be0
movq -0x20(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
jmp 0x4970e
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x8, %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x28(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x10(%rbp), %rdx
movq -0x28(%rbp), %rcx
callq 0x555c0
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
shlq %rax
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x8(%rbp), %rdx
movq -0x28(%rbp), %rcx
callq 0x555c0
movq %rax, %rcx
movq -0x50(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
cmpq -0x28(%rbp), %rax
jge 0x4986d
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
imulq $0x3, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x8(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x555c0
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
shlq %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x30(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x28(%rbp), %rdx
subq -0x30(%rbp), %rdx
movl $0x1, %ecx
callq 0x37320
movq -0x58(%rbp), %rdx
addq %rax, %rdx
movq -0x8(%rbp), %rax
movq -0x28(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0x8(%rbp), %rax
movq -0x30(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq -0x40(%rbp), %rcx
addq %rcx, (%rax)
jae 0x49863
addq $0x1, 0x8(%rax)
leaq 0x8(%rax), %rax
jb 0x49858
movq %rax, -0x48(%rbp)
jmp 0x49869
jmp 0x4986b
jmp 0x498ac
movq -0x38(%rbp), %rax
shlq %rax
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
imulq $0x3, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x8(%rbp), %rdx
movq -0x28(%rbp), %rcx
callq 0x555c0
movq -0x60(%rbp), %rdx
addq %rax, %rdx
movq -0x8(%rbp), %rax
movq -0x28(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
jmp 0x498ae
jmp 0x498b0
jmp 0x498b2
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x10, %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x10(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x20(%rbp), %r9
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %r9
addq $0x28, %r9
callq 0x49ac0
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
jmp 0x49970
movq -0x20(%rbp), %rdi
imulq $0x6, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
addq $0x18, %rdi
movq -0x8(%rbp), %rsi
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %rsi
addq $0x10, %rsi
movq -0x28(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
jmp 0x499c1
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
jmp 0x499eb
movq -0x8(%rbp), %rdi
imulq $0x6, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
imulq $0x3, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
movq -0x30(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq $0x3, %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x28, %rcx
callq 0x49120
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %rax
shlq %rax
shlq $0x3, %rax
addq %rax, %rcx
addq $0x8, %rcx
movq -0x20(%rbp), %r8
imulq $0x6, -0x28(%rbp), %rax
shlq $0x3, %rax
addq %rax, %r8
addq $0x18, %r8
movq -0x20(%rbp), %r9
movq -0x20(%rbp), %r11
movq -0x28(%rbp), %rax
shlq $0x2, %rax
shlq $0x3, %rax
addq %rax, %r11
addq $0x10, %r11
movq -0x30(%rbp), %r10
shlq %r10
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdx
shlq $0x3, %rdx
shlq $0x3, %rdx
addq %rdx, %rax
addq $0x28, %rax
xorl %edx, %edx
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x4b2d0
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop