// File: marxn[P]pupp/3rdparty/gmp/mpn/get_str.c
// Function: _gmpn_get_str
size_t
mpn_get_str (unsigned char *str, int base, mp_ptr up, mp_size_t un)
{
  mp_ptr powtab_mem, powtab_mem_ptr;
  mp_limb_t big_base;
  size_t digits_in_base;
  powers_t powtab[GMP_LIMB_BITS];
  int pi;
  mp_size_t n;
  mp_ptr p, t;
  size_t out_len;
  mp_ptr tmp;
  TMP_DECL;

  /* Special case zero, as the code below doesn't handle it.  */
  if (un == 0)
    {
      str[0] = 0;
      return 1;
    }

  if (POW2_P (base))
    {
      /* The base is a power of 2.  Convert from most significant end.  */
      mp_limb_t n1, n0;
      int bits_per_digit = mp_bases[base].big_base;
      int cnt;
      int bit_pos;
      mp_size_t i;
      unsigned char *s = str;
      mp_bitcnt_t bits;

      n1 = up[un - 1];
      count_leading_zeros (cnt, n1);

      /* BIT_POS should be R when input ends in least significant nibble,
	 R + bits_per_digit * n when input ends in nth least significant
	 nibble. */

      bits = (mp_bitcnt_t) GMP_NUMB_BITS * un - cnt + GMP_NAIL_BITS;
      cnt = bits % bits_per_digit;
      if (cnt != 0)
	bits += bits_per_digit - cnt;
      bit_pos = bits - (mp_bitcnt_t) (un - 1) * GMP_NUMB_BITS;

      /* Fast loop for bit output.  */
      i = un - 1;
      for (;;)
	{
	  bit_pos -= bits_per_digit;
	  while (bit_pos >= 0)
	    {
	      *s++ = (n1 >> bit_pos) & ((1 << bits_per_digit) - 1);
	      bit_pos -= bits_per_digit;
	    }
	  i--;
	  if (i < 0)
	    break;
	  n0 = (n1 << -bit_pos) & ((1 << bits_per_digit) - 1);
	  n1 = up[i];
	  bit_pos += GMP_NUMB_BITS;
	  *s++ = n0 | (n1 >> bit_pos);
	}

      return s - str;
    }

  /* General case.  The base is not a power of 2.  */

  if (BELOW_THRESHOLD (un, GET_STR_PRECOMPUTE_THRESHOLD))
    return mpn_sb_get_str (str, (size_t) 0, up, un, base) - str;

  TMP_MARK;

  /* Allocate one large block for the powers of big_base.  */
  powtab_mem = TMP_BALLOC_LIMBS (mpn_dc_get_str_powtab_alloc (un));
  powtab_mem_ptr = powtab_mem;

  /* Compute a table of powers, were the largest power is >= sqrt(U).  */

  big_base = mp_bases[base].big_base;
  digits_in_base = mp_bases[base].chars_per_limb;

  {
    mp_size_t n_pows, xn, pn, exptab[GMP_LIMB_BITS], bexp;
    mp_limb_t cy;
    mp_size_t shift;
    size_t ndig;

    DIGITS_IN_BASE_PER_LIMB (ndig, un, base);
    xn = 1 + ndig / mp_bases[base].chars_per_limb; /* FIXME: scalar integer division */

    n_pows = 0;
    for (pn = xn; pn != 1; pn = (pn + 1) >> 1)
      {
	exptab[n_pows] = pn;
	n_pows++;
      }
    exptab[n_pows] = 1;

    powtab[0].p = &big_base;
    powtab[0].n = 1;
    powtab[0].digits_in_base = digits_in_base;
    powtab[0].base = base;
    powtab[0].shift = 0;

    powtab[1].p = powtab_mem_ptr;  powtab_mem_ptr += 2;
    powtab[1].p[0] = big_base;
    powtab[1].n = 1;
    powtab[1].digits_in_base = digits_in_base;
    powtab[1].base = base;
    powtab[1].shift = 0;

    n = 1;
    p = &big_base;
    bexp = 1;
    shift = 0;
    for (pi = 2; pi < n_pows; pi++)
      {
	t = powtab_mem_ptr;
	powtab_mem_ptr += 2 * n + 2;

	ASSERT_ALWAYS (powtab_mem_ptr < powtab_mem + mpn_dc_get_str_powtab_alloc (un));

	mpn_sqr (t, p, n);

	digits_in_base *= 2;
	n *= 2;  n -= t[n - 1] == 0;
	bexp *= 2;

	if (bexp + 1 < exptab[n_pows - pi])
	  {
	    digits_in_base += mp_bases[base].chars_per_limb;
	    cy = mpn_mul_1 (t, t, n, big_base);
	    t[n] = cy;
	    n += cy != 0;
	    bexp += 1;
	  }
	shift *= 2;
	/* Strip low zero limbs.  */
	while (t[0] == 0)
	  {
	    t++;
	    n--;
	    shift++;
	  }
	p = t;
	powtab[pi].p = p;
	powtab[pi].n = n;
	powtab[pi].digits_in_base = digits_in_base;
	powtab[pi].base = base;
	powtab[pi].shift = shift;
      }

    for (pi = 1; pi < n_pows; pi++)
      {
	t = powtab[pi].p;
	n = powtab[pi].n;
	cy = mpn_mul_1 (t, t, n, big_base);
	t[n] = cy;
	n += cy != 0;
	if (t[0] == 0)
	  {
	    powtab[pi].p = t + 1;
	    n--;
	    powtab[pi].shift++;
	  }
	powtab[pi].n = n;
	powtab[pi].digits_in_base += mp_bases[base].chars_per_limb;
      }

#if 0
    { int i;
      printf ("Computed table values for base=%d, un=%d, xn=%d:\n", base, un, xn);
      for (i = 0; i < n_pows; i++)
	printf ("%2d: %10ld %10ld %11ld %ld\n", i, exptab[n_pows-i], powtab[i].n, powtab[i].digits_in_base, powtab[i].shift);
    }
#endif
  }

  /* Using our precomputed powers, now in powtab[], convert our number.  */
  tmp = TMP_BALLOC_LIMBS (mpn_dc_get_str_itch (un));
  out_len = mpn_dc_get_str (str, 0, up, un, powtab + (pi - 1), tmp) - str;
  TMP_FREE;

  return out_len;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd20, %rsp            # imm = 0xD20
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x5dbd5
movq -0x10(%rbp), %rax
movb $0x0, (%rax)
movq $0x1, -0x8(%rbp)
jmp 0x5e547
movl -0x14(%rbp), %eax
movl -0x14(%rbp), %ecx
subl $0x1, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0x5de20
movslq -0x14(%rbp), %rcx
leaq 0x366c(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x18(%rax), %rax
movl %eax, -0xa9c(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xab8(%rbp)
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rcx
subq $0x1, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xa90(%rbp)
jmp 0x5dc29
jmp 0x5dc2b
movq -0xa90(%rbp), %rax
movq %rax, -0xd20(%rbp)
bsrq -0xd20(%rbp), %rax
movq %rax, -0xac8(%rbp)
movq -0xac8(%rbp), %rax
xorq $0x3f, %rax
movl %eax, -0xaa0(%rbp)
movq -0x28(%rbp), %rax
shlq $0x6, %rax
movslq -0xaa0(%rbp), %rcx
subq %rcx, %rax
addq $0x0, %rax
movq %rax, -0xac0(%rbp)
movq -0xac0(%rbp), %rax
movslq -0xa9c(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, -0xaa0(%rbp)
cmpl $0x0, -0xaa0(%rbp)
je 0x5dcb6
movl -0xa9c(%rbp), %eax
subl -0xaa0(%rbp), %eax
cltq
addq -0xac0(%rbp), %rax
movq %rax, -0xac0(%rbp)
movq -0xac0(%rbp), %rax
movq -0x28(%rbp), %rcx
subq $0x1, %rcx
shlq $0x6, %rcx
subq %rcx, %rax
movl %eax, -0xaa4(%rbp)
movq -0x28(%rbp), %rax
subq $0x1, %rax
movq %rax, -0xab0(%rbp)
movl -0xa9c(%rbp), %ecx
movl -0xaa4(%rbp), %eax
subl %ecx, %eax
movl %eax, -0xaa4(%rbp)
cmpl $0x0, -0xaa4(%rbp)
jl 0x5dd55
movq -0xa90(%rbp), %rax
movl -0xaa4(%rbp), %ecx
shrq %cl, %rax
movl -0xa9c(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
andq %rcx, %rax
movb %al, %cl
movq -0xab8(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0xab8(%rbp)
movb %cl, (%rax)
movl -0xa9c(%rbp), %ecx
movl -0xaa4(%rbp), %eax
subl %ecx, %eax
movl %eax, -0xaa4(%rbp)
jmp 0x5dcf5
movq -0xab0(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0xab0(%rbp)
cmpq $0x0, -0xab0(%rbp)
jge 0x5dd76
jmp 0x5de09
movq -0xa90(%rbp), %rax
xorl %ecx, %ecx
subl -0xaa4(%rbp), %ecx
movl %ecx, %ecx
shlq %cl, %rax
movl -0xa9c(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
andq %rcx, %rax
movq %rax, -0xa98(%rbp)
movq -0x20(%rbp), %rax
movq -0xab0(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xa90(%rbp)
movl -0xaa4(%rbp), %eax
addl $0x40, %eax
movl %eax, -0xaa4(%rbp)
movq -0xa98(%rbp), %rax
movq -0xa90(%rbp), %rdx
movl -0xaa4(%rbp), %ecx
shrq %cl, %rdx
movq %rdx, %rcx
orq %rcx, %rax
movb %al, %cl
movq -0xab8(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0xab8(%rbp)
movb %cl, (%rax)
jmp 0x5dce1
movq -0xab8(%rbp), %rax
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x8(%rbp)
jmp 0x5e547
cmpq $0x1d, -0x28(%rbp)
jge 0x5de50
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
movl -0x14(%rbp), %r8d
xorl %eax, %eax
movl %eax, %esi
callq 0x5e560
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x8(%rbp)
jmp 0x5e547
movq $0x0, -0xa88(%rbp)
movq -0x28(%rbp), %rsi
addq $0x80, %rsi
shlq $0x3, %rsi
leaq -0xa88(%rbp), %rdi
callq 0x56430
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
movslq -0x14(%rbp), %rcx
leaq 0x33d3(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x18(%rax), %rax
movq %rax, -0x40(%rbp)
movslq -0x14(%rbp), %rcx
leaq 0x33b9(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rax
movq %rax, -0x48(%rbp)
movslq -0x14(%rbp), %rcx
leaq 0x33a0(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq -0x28(%rbp), %rcx
shlq $0x6, %rcx
movq %rcx, -0xd18(%rbp)
mulq -0xd18(%rbp)
movq %rax, -0xd10(%rbp)
movq %rdx, -0xd08(%rbp)
movq -0xd08(%rbp), %rax
movq %rax, -0xd00(%rbp)
movq -0xd00(%rbp), %rax
movslq -0x14(%rbp), %rdx
leaq 0x3351(%rip), %rcx      # 0x61260
imulq $0x28, %rdx, %rdx
addq %rdx, %rcx
movslq (%rcx), %rcx
xorl %edx, %edx
divq %rcx
addq $0x1, %rax
movq %rax, -0xad8(%rbp)
movq $0x0, -0xad0(%rbp)
movq -0xad8(%rbp), %rax
movq %rax, -0xae0(%rbp)
cmpq $0x1, -0xae0(%rbp)
je 0x5df8b
movq -0xae0(%rbp), %rcx
movq -0xad0(%rbp), %rax
movq %rcx, -0xce0(%rbp,%rax,8)
movq -0xad0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xad0(%rbp)
movq -0xae0(%rbp), %rax
addq $0x1, %rax
sarq %rax
movq %rax, -0xae0(%rbp)
jmp 0x5df42
movq -0xad0(%rbp), %rax
movq $0x1, -0xce0(%rbp,%rax,8)
leaq -0x40(%rbp), %rax
movq %rax, -0xa50(%rbp)
movq $0x1, -0xa48(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xa38(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0xa30(%rbp)
movq $0x0, -0xa40(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xa28(%rbp)
movq -0x38(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x38(%rbp)
movq -0x40(%rbp), %rcx
movq -0xa28(%rbp), %rax
movq %rcx, (%rax)
movq $0x1, -0xa20(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xa10(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0xa08(%rbp)
movq $0x0, -0xa18(%rbp)
movq $0x1, -0xa60(%rbp)
leaq -0x40(%rbp), %rax
movq %rax, -0xa68(%rbp)
movq $0x1, -0xce8(%rbp)
movq $0x0, -0xcf8(%rbp)
movl $0x2, -0xa54(%rbp)
movslq -0xa54(%rbp), %rax
cmpq -0xad0(%rbp), %rax
jge 0x5e325
movq -0x38(%rbp), %rax
movq %rax, -0xa70(%rbp)
movq -0xa60(%rbp), %rax
shlq %rax
addq $0x2, %rax
shlq $0x3, %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x30(%rbp), %rcx
movq -0x28(%rbp), %rdx
addq $0x80, %rdx
shlq $0x3, %rdx
addq %rdx, %rcx
cmpq %rcx, %rax
setb %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x5e0e3
leaq 0x6b6e(%rip), %rdi      # 0x64c40
movl $0x1e9, %esi            # imm = 0x1E9
leaq 0x6b6c(%rip), %rdx      # 0x64c4a
callq 0x562c0
jmp 0x5e0e5
movq -0xa70(%rbp), %rdi
movq -0xa68(%rbp), %rsi
movq -0xa60(%rbp), %rdx
callq 0x392b0
movq -0x48(%rbp), %rax
shlq %rax
movq %rax, -0x48(%rbp)
movq -0xa60(%rbp), %rax
shlq %rax
movq %rax, -0xa60(%rbp)
movq -0xa70(%rbp), %rax
movq -0xa60(%rbp), %rcx
subq $0x1, %rcx
cmpq $0x0, (%rax,%rcx,8)
sete %al
andb $0x1, %al
movzbl %al, %eax
movslq %eax, %rcx
movq -0xa60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0xa60(%rbp)
movq -0xce8(%rbp), %rax
shlq %rax
movq %rax, -0xce8(%rbp)
movq -0xce8(%rbp), %rax
addq $0x1, %rax
movq -0xad0(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
subq %rdx, %rcx
cmpq -0xce0(%rbp,%rcx,8), %rax
jge 0x5e216
movslq -0x14(%rbp), %rcx
leaq 0x30cc(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rax
addq -0x48(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0xa70(%rbp), %rdi
movq -0xa70(%rbp), %rsi
movq -0xa60(%rbp), %rdx
movq -0x40(%rbp), %rcx
callq 0x37206
movq %rax, -0xcf0(%rbp)
movq -0xcf0(%rbp), %rdx
movq -0xa70(%rbp), %rax
movq -0xa60(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
cmpq $0x0, -0xcf0(%rbp)
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
addq -0xa60(%rbp), %rax
movq %rax, -0xa60(%rbp)
movq -0xce8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xce8(%rbp)
movq -0xcf8(%rbp), %rax
shlq %rax
movq %rax, -0xcf8(%rbp)
movq -0xa70(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x5e26c
movq -0xa70(%rbp), %rax
addq $0x8, %rax
movq %rax, -0xa70(%rbp)
movq -0xa60(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0xa60(%rbp)
movq -0xcf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xcf8(%rbp)
jmp 0x5e227
movq -0xa70(%rbp), %rax
movq %rax, -0xa68(%rbp)
movq -0xa68(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq -0xa60(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq -0x48(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x18(%rax)
movl -0x14(%rbp), %ecx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x20(%rax)
movq -0xcf8(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x10(%rax)
movl -0xa54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa54(%rbp)
jmp 0x5e058
movl $0x1, -0xa54(%rbp)
movslq -0xa54(%rbp), %rax
cmpq -0xad0(%rbp), %rax
jge 0x5e4a9
movslq -0xa54(%rbp), %rcx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq (%rax), %rax
movq %rax, -0xa70(%rbp)
movslq -0xa54(%rbp), %rcx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0xa60(%rbp)
movq -0xa70(%rbp), %rdi
movq -0xa70(%rbp), %rsi
movq -0xa60(%rbp), %rdx
movq -0x40(%rbp), %rcx
callq 0x37206
movq %rax, -0xcf0(%rbp)
movq -0xcf0(%rbp), %rdx
movq -0xa70(%rbp), %rax
movq -0xa60(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
cmpq $0x0, -0xcf0(%rbp)
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
addq -0xa60(%rbp), %rax
movq %rax, -0xa60(%rbp)
movq -0xa70(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x5e443
movq -0xa70(%rbp), %rcx
addq $0x8, %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq -0xa60(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0xa60(%rbp)
movslq -0xa54(%rbp), %rcx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x10(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x10(%rax)
movq -0xa60(%rbp), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movslq -0x14(%rbp), %rcx
leaq 0x2df2(%rip), %rax      # 0x61260
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
movslq -0xa54(%rbp), %rdx
leaq -0xa50(%rbp), %rax
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
addq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
movl -0xa54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa54(%rbp)
jmp 0x5e32f
movq -0x28(%rbp), %rsi
addq $0x40, %rsi
shlq $0x3, %rsi
leaq -0xa88(%rbp), %rdi
callq 0x56430
movq %rax, -0xa80(%rbp)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rdx
movq -0x28(%rbp), %rcx
leaq -0xa50(%rbp), %r8
movl -0xa54(%rbp), %eax
subl $0x1, %eax
cltq
imulq $0x28, %rax, %rax
addq %rax, %r8
movq -0xa80(%rbp), %r9
xorl %eax, %eax
movl %eax, %esi
callq 0x5eb10
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0xa78(%rbp)
cmpq $0x0, -0xa88(%rbp)
setne %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movzbl %al, %eax
cltq
cmpq $0x0, %rax
je 0x5e53a
movq -0xa88(%rbp), %rdi
callq 0x564a0
jmp 0x5e53c
movq -0xa78(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xd20, %rsp            # imm = 0xD20
popq %rbp
retq
nopw %cs:(%rax,%rax)