// File: donfreiday[P]gb/main.cpp
// Function: disassemble(CPU&, unsigned short&)
void disassemble(CPU& cpu, u16& pc) {
  g_disasm.address = pc;
  g_disasm.opcode = cpu.mmu.memory[pc];
  g_disasm.operandSize = 0;
  g_disasm.operand = 0;

  if (g_disasm.opcode == 0xCB) {
    g_disasm.operandSize = 1;
    g_disasm.operand = cpu.mmu.memory[++pc];
    g_disasm.str = cpu.instructions_CB[g_disasm.operand].disassembly;
  } else if (cpu.instructions[g_disasm.opcode].operandLength == 1) {
    g_disasm.operandSize = 1;
    g_disasm.operand = cpu.mmu.memory[++pc];
    g_disasm.str = cpu.instructions[g_disasm.opcode].disassembly;
  } else if (cpu.instructions[g_disasm.opcode].operandLength == 2) {
    g_disasm.operandSize = 2;
    g_disasm.operand = cpu.mmu.read16(++pc);
    g_disasm.str = cpu.instructions[g_disasm.opcode].disassembly;
    pc++;
  } else {
    ++pc;
    g_disasm.operandSize = 0;
    g_disasm.str = cpu.instructions[g_disasm.opcode].disassembly;
  }

  // Make sure we don't skip over any code entry points
  bool skippedEntry = false;
  for (u16 address : g_disasm.knownEntryPoints) {
    if (pc < address && pc + g_disasm.operandSize > address) {
      skippedEntry = true;
      pc = address;
    }
  }

  // Data sections are mixed in with code. So we need to make sure
  // that we don't skip right over the PC by blindly disassembling
  if (pc < g_cpu.reg.pc && pc + g_disasm.operandSize > g_cpu.reg.pc) {
    pc = g_cpu.reg.pc;
    g_disasm.knownEntryPoints.insert(pc);
    skippedEntry = true;
  }

  if (!skippedEntry) {
    pc += g_disasm.operandSize;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movw (%rax), %ax
movw %ax, 0x3e66a(%rip)      # 0x96f28
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
movl %eax, %esi
callq 0x4f3d0
movb (%rax), %al
movb %al, 0x3e64a(%rip)      # 0x96f2a
movb $0x0, 0x3e647(%rip)     # 0x96f2e
movw $0x0, 0x3e63c(%rip)     # 0x96f2c
movzbl 0x3e633(%rip), %eax     # 0x96f2a
cmpl $0xcb, %eax
jne 0x5895f
movb $0x1, 0x3e629(%rip)     # 0x96f2e
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rcx
movw (%rcx), %ax
addw $0x1, %ax
movw %ax, (%rcx)
movzwl %ax, %eax
movl %eax, %esi
callq 0x4f3d0
movzbl (%rax), %eax
movw %ax, 0x3e5f9(%rip)      # 0x96f2c
movq -0x8(%rbp), %rax
addq $0x12a8, %rax           # imm = 0x12A8
movzwl 0x3e5e8(%rip), %ecx     # 0x96f2c
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
leaq 0x3e5b3(%rip), %rdi     # 0x96f08
callq 0x7340
jmp 0x58aa5
movq -0x8(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movzbl 0x3e5ba(%rip), %ecx     # 0x96f2a
shlq $0x4, %rcx
addq %rcx, %rax
movzbl 0x8(%rax), %eax
cmpl $0x1, %eax
jne 0x589e1
movb $0x1, 0x3e5a7(%rip)     # 0x96f2e
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
addq $0x8, %rdi
movq -0x10(%rbp), %rcx
movw (%rcx), %ax
addw $0x1, %ax
movw %ax, (%rcx)
movzwl %ax, %eax
movl %eax, %esi
callq 0x4f3d0
movzbl (%rax), %eax
movw %ax, 0x3e577(%rip)      # 0x96f2c
movq -0x8(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movzbl 0x3e564(%rip), %ecx     # 0x96f2a
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
leaq 0x3e531(%rip), %rdi     # 0x96f08
callq 0x7340
jmp 0x58aa3
movq -0x8(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movzbl 0x3e538(%rip), %ecx     # 0x96f2a
shlq $0x4, %rcx
addq %rcx, %rax
movzbl 0x8(%rax), %eax
cmpl $0x2, %eax
jne 0x58a65
movb $0x2, 0x3e525(%rip)     # 0x96f2e
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
movq -0x10(%rbp), %rcx
movw (%rcx), %ax
addw $0x1, %ax
movw %ax, (%rcx)
movzwl %ax, %esi
callq 0x4ee20
movw %ax, 0x3e4fe(%rip)      # 0x96f2c
movq -0x8(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movzbl 0x3e4eb(%rip), %ecx     # 0x96f2a
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
leaq 0x3e4b8(%rip), %rdi     # 0x96f08
callq 0x7340
movq -0x10(%rbp), %rax
movw (%rax), %cx
addw $0x1, %cx
movw %cx, (%rax)
jmp 0x58aa1
movq -0x10(%rbp), %rax
movw (%rax), %cx
addw $0x1, %cx
movw %cx, (%rax)
movb $0x0, 0x3e4b4(%rip)     # 0x96f2e
movq -0x8(%rbp), %rax
addq $0x2a8, %rax            # imm = 0x2A8
movzbl 0x3e49f(%rip), %ecx     # 0x96f2a
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rsi
leaq 0x3e46c(%rip), %rdi     # 0x96f08
callq 0x7340
jmp 0x58aa3
jmp 0x58aa5
movb $0x0, -0x11(%rbp)
leaq 0x3e458(%rip), %rax     # 0x96f08
addq $0x28, %rax
movq %rax, -0x20(%rbp)
leaq 0x3e449(%rip), %rdi     # 0x96f08
addq $0x28, %rdi
callq 0x58e50
movq %rax, -0x28(%rbp)
leaq 0x3e435(%rip), %rdi     # 0x96f08
addq $0x28, %rdi
callq 0x58da0
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x58d30
testb $0x1, %al
jne 0x58af3
jmp 0x58b46
leaq -0x28(%rbp), %rdi
callq 0x58e80
movw (%rax), %ax
movw %ax, -0x32(%rbp)
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
movzwl -0x32(%rbp), %ecx
cmpl %ecx, %eax
jge 0x58b39
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
movzbl 0x3e40e(%rip), %ecx     # 0x96f2e
addl %ecx, %eax
movzwl -0x32(%rbp), %ecx
cmpl %ecx, %eax
jle 0x58b39
movb $0x1, -0x11(%rbp)
movw -0x32(%rbp), %cx
movq -0x10(%rbp), %rax
movw %cx, (%rax)
jmp 0x58b3b
leaq -0x28(%rbp), %rdi
callq 0x58ea0
jmp 0x58ae0
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
movzwl 0x2b2ec(%rip), %ecx     # 0x83e40
cmpl %ecx, %eax
jge 0x58ba0
movq -0x10(%rbp), %rax
movzwl (%rax), %eax
movzbl 0x3e3c8(%rip), %ecx     # 0x96f2e
addl %ecx, %eax
movzwl 0x2b2d1(%rip), %ecx     # 0x83e40
cmpl %ecx, %eax
jle 0x58ba0
movw 0x2b2c6(%rip), %cx      # 0x83e40
movq -0x10(%rbp), %rax
movw %cx, (%rax)
movq -0x10(%rbp), %rsi
leaq 0x3e37c(%rip), %rdi     # 0x96f08
addq $0x28, %rdi
callq 0x58ce0
movq %rax, -0x48(%rbp)
movb %dl, -0x40(%rbp)
movb $0x1, -0x11(%rbp)
testb $0x1, -0x11(%rbp)
jne 0x58bb9
movzbl 0x3e381(%rip), %edx     # 0x96f2e
movq -0x10(%rbp), %rax
movzwl (%rax), %ecx
addl %edx, %ecx
movw %cx, (%rax)
addq $0x50, %rsp
popq %rbp
retq
nop