// File: /workspace/github_c_makefile_star2_O2/inolen[P]gdb_server/example.c
// Function: main
int main(int argc, char **argv) {
  if (argc < 2) {
    printf("usage: example fibonacci.bin\n");
    return EXIT_FAILURE;
  }

  // load sh4 binary
  const char *bin_path = argv[1];
  uint8_t *bin = NULL;
  int bin_size = 0;

  if (!load_bin(bin_path, &bin, &bin_size)) {
    printf("failed to load %s\n", bin_path);
    return EXIT_FAILURE;
  }

  // create sh4 context
  sh4_context_t ctx;
  ctx.physical_base = bin;
  ctx.physical_mask = 0x1fffffff;
  ctx.physical_size = bin_size;
  ctx.pc = 0x0;
  ctx.pr = 0x0;
  ctx.sr = 0x700000f0;
  ctx.fpscr = 0x00040001;
  ctx.running = 1;
  sh4_init_tables();

  // create gdb server
  gdb_target_t target;
  sh4_server_init(&target, &ctx);

  gdb_server_t *sv = gdb_server_create(&target, 24690);
  if (!sv) {
    printf("Failed to create GDB server\n");
    return EXIT_FAILURE;
  }

  // main loop
  sh4_instr_t instr;

  while (1) {
    gdb_server_pump(sv);

    // spin, waiting for the debugger to resume if the cpu isn't running
    if (!ctx.running) {
      continue;
    }

    printf("PC 0x%x\n", ctx.pc);

    uint16_t data = *(uint16_t *)&bin[ctx.pc];

    // invalid opcode, breakpoint hit
    if (!data) {
      breakpoint_t *bp = sh4_server_find_bp(&ctx, ctx.pc);
      assert(bp);

      // auto remove temporary breakpoints
      if (bp->temp) {
        sh4_server_rem_bp(&ctx, bp);
      }

      // let the client know we've stopped
      gdb_server_interrupt(sv, GDB_SIGNAL_TRAP);
      ctx.running = 0;

      continue;
    }

    // valid opcode, decode and execute
    if (!sh4_decode(data, &instr)) {
      printf("Failed to decode 0x%x\n", data);
      return EXIT_FAILURE;
    }

    instr.type->fn(&ctx, &instr);

    // move onto the next instruction
    ctx.pc += 2;
  }

  // cleanup server
  gdb_server_destroy(sv);

  // cleanup sh4 binary
  free_bin(bin);

  return EXIT_SUCCESS;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1e8, %rsp            # imm = 0x1E8
cmpl $0x1, %edi
jg 0x3316
leaq 0x3d6e(%rip), %rdi      # 0x707a
callq 0x3050
jmp 0x34c4
movq 0x8(%rsi), %r14
leaq 0x3d3a(%rip), %rsi      # 0x705b
movq %r14, %rdi
callq 0x31a0
testq %rax, %rax
je 0x34a0
movq %rax, %r15
pushq $0x2
popq %rdx
movq %rax, %rdi
xorl %esi, %esi
callq 0x3170
movq %r15, %rdi
callq 0x3120
movq %rax, %rbx
movq %r15, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x3170
movslq %ebx, %r12
movq %r12, %rdi
callq 0x3150
movq %rax, %rbx
pushq $0x1
popq %rsi
movq %rax, %rdi
movq %r12, %rdx
movq %r15, %rcx
callq 0x3060
movq %rax, %r13
movq %r15, %rdi
callq 0x3080
cmpl %r13d, %r12d
jne 0x3498
leaq -0x1c8(%rbp), %r14
movq %rbx, 0x160(%r14)
movq $0x1fffffff, 0x168(%r14) # imm = 0x1FFFFFFF
movq %r12, 0x170(%r14)
andl $0x0, 0x4(%r14)
andl $0x0, 0xc(%r14)
movl $0x700000f0, 0x14c(%r14) # imm = 0x700000F0
movabsq $0x100040001, %rax      # imm = 0x100040001
movq %rax, 0x158(%r14)
xorl %eax, %eax
callq 0x4e5e
leaq -0x210(%rbp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x5a76
movq %r15, %rdi
movl $0x6072, %esi           # imm = 0x6072
callq 0x5104
testq %rax, %rax
je 0x34d9
movq %rax, %r14
leaq -0x1c8(%rbp), %r12
leaq -0x40(%rbp), %r13
movq %r14, %rdi
callq 0x52c0
cmpl $0x0, -0x6c(%rbp)
je 0x340f
movl -0x1c4(%rbp), %esi
leaq 0x3bed(%rip), %rdi      # 0x7017
xorl %eax, %eax
callq 0x30c0
movl -0x1c4(%rbp), %esi
movzwl (%rbx,%rsi), %r15d
testl %r15d, %r15d
je 0x3466
movl %r15d, %edi
movq %r13, %rsi
callq 0x5097
testl %eax, %eax
je 0x34b3
movq -0x40(%rbp), %rax
movq %r12, %rdi
movq %r13, %rsi
callq *0x10(%rax)
addl $0x2, -0x1c4(%rbp)
jmp 0x340f
movq %r12, %rdi
callq 0x5d28
testq %rax, %rax
je 0x34e5
cmpl $0x0, 0x8(%rax)
je 0x3484
movq %r12, %rdi
movq %rax, %rsi
callq 0x5d70
movq %r14, %rdi
pushq $0x5
popq %rsi
callq 0x520a
andl $0x0, -0x6c(%rbp)
jmp 0x340f
movq %rbx, %rdi
callq 0x3030
leaq 0x3b5d(%rip), %rdi      # 0x7004
movq %r14, %rsi
xorl %eax, %eax
callq 0x30c0
jmp 0x34c4
leaq 0x3b8a(%rip), %rdi      # 0x7044
movl %r15d, %esi
xorl %eax, %eax
callq 0x30c0
pushq $0x1
popq %rax
addq $0x1e8, %rsp            # imm = 0x1E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3b7e(%rip), %rdi      # 0x705e
jmp 0x330c
leaq 0x3b34(%rip), %rdi      # 0x7020
leaq 0x3b30(%rip), %rsi      # 0x7023
leaq 0x3b33(%rip), %rcx      # 0x702d
pushq $0x58
popq %rdx
callq 0x30e0
nop