// File: /workspace/github_c_makefile_star2_O0/GregorR[P]lstg/source/memory.c
// Function: gc_move
static struct object *gc_move(struct mobject *ptr)
{
  struct mobject *old_address = ptr,
    *previous_object = 0,
    *new_address = 0,
    *replacement = 0;
  int             sz;

  while(1)
  {

    /*
     * part 1.  Walking down the tree
     * keep stacking objects to be moved until we find
     * one that we can handle
     */
    for(;;)
    {
      /*
       * SmallInt's are not proper memory pointers,
       * so catch them first.  Their "object pointer"
       * value can be used as-is in the new space.
       */
      if(IS_SMALLINT(old_address))
      {
        replacement = old_address;
        old_address = previous_object;
        break;

        /*
         * If we find a pointer in the current space
         * to the new space (other than indirections) then
         * something is very wrong
         */
      }
      else if((old_address >=
               (struct mobject *) memoryBase)
              && (old_address <= (struct mobject *) memoryTop))
      {
        sysError("GC invariant failure -- address in new space",
                 old_address);

        /*
           else see if not  in old space 
         */
      }
      else if((old_address < (struct mobject *) oldBase) ||
              (old_address > (struct mobject *) oldTop))
      {
        replacement = old_address;
        old_address = previous_object;
        break;

        /*
           else see if already forwarded 
         */
      }
      else if(old_address->size & FLAG_GCDONE)
      {
        if(old_address->size & FLAG_BIN)
        {
          replacement = old_address->data[0];
        }
        else
        {
          sz = SIZE(old_address);
          replacement = old_address->data[sz];
        }
        old_address = previous_object;
        break;

        /*
           else see if binary object 
         */
      }
      else if(old_address->size & FLAG_BIN)
      {
        int             isz;

        isz = SIZE(old_address);
        sz = (isz + BytesPerWord - 1) / BytesPerWord;
        memoryPointer = WORDSDOWN(memoryPointer, sz + 2);
        new_address = (struct mobject *) memoryPointer;
        SETSIZE(new_address, isz);
        new_address->size |= FLAG_BIN;
        while(sz)
        {
          new_address->data[sz] = old_address->data[sz];
          sz--;
        }
        old_address->size |= FLAG_GCDONE;
        new_address->data[0] = previous_object;
        previous_object = old_address;
        old_address = old_address->data[0];
        previous_object->data[0] = new_address;
        /*
           now go chase down class pointer 
         */

        /*
           must be non-binary object 
         */
      }
      else
      {
        sz = SIZE(old_address);
        memoryPointer = WORDSDOWN(memoryPointer, sz + 2);
        new_address = (struct mobject *) memoryPointer;
        SETSIZE(new_address, sz);
        old_address->size |= FLAG_GCDONE;
        new_address->data[sz] = previous_object;
        previous_object = old_address;
        old_address = old_address->data[sz];
        previous_object->data[sz] = new_address;
      }
    }

    /*
     * part 2.  Fix up pointers,
     * move back up tree as long as possible
     * old_address points to an object in the old space,
     * which in turns points to an object in the new space,
     * which holds a pointer that is now to be replaced.
     * the value in replacement is the new value
     */
    for(;;)
    {
      /*
         backed out entirely 
       */
      if(old_address == 0)
      {
        return (struct object *) replacement;
      }

      /*
         case 1, binary or last value 
       */
      if((old_address->size & FLAG_BIN) || (SIZE(old_address) == 0))
      {

        /*
           fix up class pointer 
         */
        new_address = old_address->data[0];
        previous_object = new_address->data[0];
        new_address->data[0] = replacement;
        old_address->data[0] = new_address;
        replacement = new_address;
        old_address = previous_object;
      }
      else
      {
        sz = SIZE(old_address);
        new_address = old_address->data[sz];
        previous_object = new_address->data[sz];
        new_address->data[sz] = replacement;
        sz--;

        /*
         * quick cheat for recovering zero fields
         */
        while(sz && (old_address->data[sz] == 0))
        {
          new_address->data[sz--] = 0;
        }

        SETSIZE(old_address, sz);
        old_address->size |= FLAG_GCDONE;
        new_address->data[sz] = previous_object;
        previous_object = old_address;
        old_address = old_address->data[sz];
        previous_object->data[sz] = new_address;
        break;                  /* go track down this value */
      }
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
jmp 0x629e
movq -0x10(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
je 0x62c1
movq -0x10(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x64e6
movq -0x10(%rbp), %rax
cmpq 0x42744(%rip), %rax     # 0x48a10
jb 0x62f0
movq -0x10(%rbp), %rax
cmpq 0x42757(%rip), %rax     # 0x48a30
ja 0x62f0
movq -0x10(%rbp), %rsi
leaq 0x417d(%rip), %rdi      # 0xa463
callq 0x56d0
jmp 0x64df
movq -0x10(%rbp), %rax
cmpq 0x4272d(%rip), %rax     # 0x48a28
jb 0x630a
movq -0x10(%rbp), %rax
cmpq 0x42730(%rip), %rax     # 0x48a38
jbe 0x631f
movq -0x10(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x64e6
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x6373
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x6349
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x6366
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x2, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x64e6
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x644f
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x2, %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
addl $0x8, %eax
subl $0x1, %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, -0x2c(%rbp)
movq 0x4266c(%rip), %rax     # 0x48a18
movl -0x2c(%rbp), %edx
addl $0x2, %edx
xorl %ecx, %ecx
subl %edx, %ecx
shll $0x3, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x42652(%rip)     # 0x48a18
movq 0x4264b(%rip), %rax     # 0x48a18
movq %rax, -0x20(%rbp)
movl -0x30(%rbp), %ecx
shll $0x2, %ecx
movq -0x20(%rbp), %rax
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
orl $0x2, %ecx
movl %ecx, (%rax)
cmpl $0x0, -0x2c(%rbp)
je 0x6413
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rdx
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x63e8
movq -0x10(%rbp), %rax
movl (%rax), %ecx
orl $0x1, %ecx
movl %ecx, (%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x64d9
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x2, %eax
movl %eax, -0x2c(%rbp)
movq 0x425b6(%rip), %rax     # 0x48a18
movl -0x2c(%rbp), %edx
addl $0x2, %edx
xorl %ecx, %ecx
subl %edx, %ecx
shll $0x3, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x4259c(%rip)     # 0x48a18
movq 0x42595(%rip), %rax     # 0x48a18
movq %rax, -0x20(%rbp)
movl -0x2c(%rbp), %ecx
shll $0x2, %ecx
movq -0x20(%rbp), %rax
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
orl $0x1, %ecx
movl %ecx, (%rax)
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x10(%rbp)
movq -0x20(%rbp), %rdx
movq -0x18(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
jmp 0x64db
jmp 0x64dd
jmp 0x64df
jmp 0x64e1
jmp 0x629e
jmp 0x64e8
cmpq $0x0, -0x10(%rbp)
jne 0x64f9
movq -0x28(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
jne 0x6515
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x2, %eax
cmpl $0x0, %eax
jne 0x655a
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x28(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x663b
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x2, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x18(%rbp)
movq -0x28(%rbp), %rdx
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x2c(%rbp)
movb %al, -0x31(%rbp)
je 0x65c1
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
cmpq $0x0, 0x8(%rax,%rcx,8)
sete %al
movb %al, -0x31(%rbp)
movb -0x31(%rbp), %al
testb $0x1, %al
jne 0x65ca
jmp 0x65e7
movq -0x20(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl %ecx, %edx
addl $-0x1, %edx
movl %edx, -0x2c(%rbp)
movslq %ecx, %rcx
movq $0x0, 0x8(%rax,%rcx,8)
jmp 0x65a2
movl -0x2c(%rbp), %ecx
shll $0x2, %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
orl $0x1, %ecx
movl %ecx, (%rax)
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x10(%rbp)
movq -0x20(%rbp), %rdx
movq -0x18(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
jmp 0x6640
jmp 0x64e8
jmp 0x629c
nopw %cs:(%rax,%rax)