// File: jstaursky[P]hutch/src/Sleigh/address.cc
// Function: power2Divide(int, unsigned long, unsigned long&, unsigned long&)
int4 power2Divide(int4 n,uint8 divisor,uint8 &q,uint8 &r)

{
  if (divisor == 0) return 2;
  uint8 power = 1;
  if (n < 64) {
    power <<= n;
    q = power / divisor;
    r = power % divisor;
    return 0;
  }
  // Divide numerand and divisor by 2^(n-63) to get approximation of result
  uint8 y = divisor >> (n-64);	// Most of the way on divisor
  if (y == 0) return 1;		// Check if result will be too big
  y >>= 1;			// Divide divisor by final bit
  power <<= 63;
  uint8 max;
  if (y == 0) {
    max = 0;
    max -= 1;			// Could be maximal
    // Check if divisor is a power of 2
    if ((((uint8)1) << (n-64)) == divisor)
      return 1;
  }
  else
    max = power / y + 1;
  uint8 min = power / (y+1);
  if (min != 0)
    min -= 1;
  uint8 fullpower[2];
  fullpower[1] = ((uint8)1)<<(n-64);
  fullpower[0] = 0;
  uint8 mult[2];
  mult[0] = 0;
  mult[1] = 0;
  uint8 tmpq = 0;
  while(max > min+1) {
    tmpq = max + min;
    if (tmpq < min) {
      tmpq = (tmpq>>1) + 0x8000000000000000L;
    }
    else
      tmpq >>= 1;
    mult64to128(mult,divisor,tmpq);
    if (unsignedCompare128(fullpower,mult) < 0)
      max = tmpq-1;
    else
      min = tmpq;
  }
  // min is now our putative quotient
  if (tmpq != min)
    mult64to128(mult,divisor,min);
  unsignedSubtract128(fullpower,mult); // Calculate remainder
  // min might be 1 too small
  if (fullpower[1] != 0 || fullpower[0] >= divisor) {
    q = min + 1;
    r = fullpower[0] - divisor;
  }
  else {
    q = min;
    r = fullpower[0];
  }
  return 0;
}

// Assembly:
subq $0x78, %rsp
movl %edi, 0x70(%rsp)
movq %rsi, 0x68(%rsp)
movq %rdx, 0x60(%rsp)
movq %rcx, 0x58(%rsp)
cmpq $0x0, 0x68(%rsp)
jne 0xe5c2c
movl $0x2, 0x74(%rsp)
jmp 0xe5ec6
movq $0x1, 0x50(%rsp)
cmpl $0x40, 0x70(%rsp)
jge 0xe5c8b
movl 0x70(%rsp), %ecx
movq 0x50(%rsp), %rax
movl %ecx, %ecx
shlq %cl, %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x68(%rsp)
movq %rax, %rcx
movq 0x60(%rsp), %rax
movq %rcx, (%rax)
movq 0x50(%rsp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x68(%rsp)
movq 0x58(%rsp), %rax
movq %rdx, (%rax)
movl $0x0, 0x74(%rsp)
jmp 0xe5ec6
movq 0x68(%rsp), %rax
movl 0x70(%rsp), %ecx
subl $0x40, %ecx
movl %ecx, %ecx
shrq %cl, %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, 0x48(%rsp)
jne 0xe5cb6
movl $0x1, 0x74(%rsp)
jmp 0xe5ec6
movq 0x48(%rsp), %rax
shrq %rax
movq %rax, 0x48(%rsp)
movq 0x50(%rsp), %rax
shlq $0x3f, %rax
movq %rax, 0x50(%rsp)
cmpq $0x0, 0x48(%rsp)
jne 0xe5d19
movq $0x0, 0x40(%rsp)
movq 0x40(%rsp), %rax
subq $0x1, %rax
movq %rax, 0x40(%rsp)
movl 0x70(%rsp), %eax
subl $0x40, %eax
movl %eax, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
cmpq 0x68(%rsp), %rax
jne 0xe5d17
movl $0x1, 0x74(%rsp)
jmp 0xe5ec6
jmp 0xe5d30
movq 0x50(%rsp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x48(%rsp)
addq $0x1, %rax
movq %rax, 0x40(%rsp)
movq 0x50(%rsp), %rax
movq 0x48(%rsp), %rcx
addq $0x1, %rcx
xorl %edx, %edx
divq %rcx
movq %rax, 0x38(%rsp)
cmpq $0x0, 0x38(%rsp)
je 0xe5d5e
movq 0x38(%rsp), %rax
subq $0x1, %rax
movq %rax, 0x38(%rsp)
movl 0x70(%rsp), %eax
subl $0x40, %eax
movl %eax, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
movq $0x0, 0x10(%rsp)
movq $0x0, 0x18(%rsp)
movq $0x0, 0x8(%rsp)
movq 0x40(%rsp), %rax
movq 0x38(%rsp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jbe 0xe5e3c
movq 0x40(%rsp), %rax
addq 0x38(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rax
cmpq 0x38(%rsp), %rax
jae 0xe5de8
movq 0x8(%rsp), %rax
shrq %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
addq %rcx, %rax
movq %rax, 0x8(%rsp)
jmp 0xe5df5
movq 0x8(%rsp), %rax
shrq %rax
movq %rax, 0x8(%rsp)
leaq 0x10(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x8(%rsp), %rdx
callq 0xd3bd0
leaq 0x20(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0xdb000
cmpl $0x0, %eax
jge 0xe5e2d
movq 0x8(%rsp), %rax
subq $0x1, %rax
movq %rax, 0x40(%rsp)
jmp 0xe5e37
movq 0x8(%rsp), %rax
movq %rax, 0x38(%rsp)
jmp 0xe5d9a
movq 0x8(%rsp), %rax
cmpq 0x38(%rsp), %rax
je 0xe5e5c
leaq 0x10(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x38(%rsp), %rdx
callq 0xd3bd0
leaq 0x20(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0xdf0b0
cmpq $0x0, 0x28(%rsp)
jne 0xe5e7f
movq 0x20(%rsp), %rax
cmpq 0x68(%rsp), %rax
jb 0xe5ea4
movq 0x38(%rsp), %rcx
addq $0x1, %rcx
movq 0x60(%rsp), %rax
movq %rcx, (%rax)
movq 0x20(%rsp), %rcx
subq 0x68(%rsp), %rcx
movq 0x58(%rsp), %rax
movq %rcx, (%rax)
jmp 0xe5ebe
movq 0x38(%rsp), %rcx
movq 0x60(%rsp), %rax
movq %rcx, (%rax)
movq 0x20(%rsp), %rcx
movq 0x58(%rsp), %rax
movq %rcx, (%rax)
movl $0x0, 0x74(%rsp)
movl 0x74(%rsp), %eax
addq $0x78, %rsp
retq
nop