// File: /workspace/github_c_makefile_star2_O1/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 $0x1f8, %rsp            # imm = 0x1F8
cmpl $0x1, %edi
jg 0x3316
leaq 0x3d6e(%rip), %rdi      # 0x707a
callq 0x3060
jmp 0x33c0
movq 0x8(%rsi), %r14
leaq 0x3d3a(%rip), %rsi      # 0x705b
movq %r14, %rdi
callq 0x31a0
movq %rax, %r12
movb $0x1, %al
testq %r12, %r12
je 0x3396
movq %r14, -0x30(%rbp)
movq %r12, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x3170
movq %r12, %rdi
callq 0x3120
movq %rax, %r15
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x3170
movslq %r15d, %r13
movq %r13, %rdi
callq 0x3150
movq %rax, %rbx
movl $0x1, %esi
movq %rax, %rdi
movq %r13, %rdx
movq %r12, %rcx
callq 0x3070
movq %rax, %r14
movq %r12, %rdi
callq 0x3090
cmpl %r14d, %r13d
jne 0x339d
xorl %eax, %eax
movq -0x30(%rbp), %r14
jmp 0x33ab
xorl %ebx, %ebx
xorl %r15d, %r15d
jmp 0x33ab
movq %rbx, %rdi
callq 0x3030
movq -0x30(%rbp), %r14
movb $0x1, %al
testb %al, %al
je 0x33d7
leaq 0x3c4e(%rip), %rdi      # 0x7004
movq %r14, %rsi
xorl %eax, %eax
callq 0x30d0
movl $0x1, %eax
addq $0x1f8, %rsp            # imm = 0x1F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x1d0(%rbp), %r14
movq %rbx, 0x160(%r14)
movq $0x1fffffff, 0x168(%r14) # imm = 0x1FFFFFFF
movslq %r15d, %rax
movq %rax, 0x170(%r14)
xorl %eax, %eax
movl %eax, 0x4(%r14)
movl %eax, 0xc(%r14)
movl $0x700000f0, 0x14c(%r14) # imm = 0x700000F0
movabsq $0x100040001, %rax      # imm = 0x100040001
movq %rax, 0x158(%r14)
xorl %eax, %eax
callq 0x4eb0
leaq -0x218(%rbp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x5d60
movq %r15, %rdi
movl $0x6072, %esi           # imm = 0x6072
callq 0x5140
testq %rax, %rax
je 0x3523
movq %rax, %r14
leaq -0x1d0(%rbp), %r13
leaq -0x48(%rbp), %r15
movl $0x0, -0x30(%rbp)
movq %r14, %rdi
callq 0x534a
cmpl $0x0, -0x74(%rbp)
je 0x3464
movl -0x1cc(%rbp), %esi
leaq 0x3b98(%rip), %rdi      # 0x7017
xorl %eax, %eax
callq 0x30d0
movl -0x1cc(%rbp), %esi
movzwl (%rbx,%rsi), %r12d
testl %r12d, %r12d
je 0x34bd
movl %r12d, %edi
movq %r15, %rsi
callq 0x50d2
testl %eax, %eax
je 0x34f6
movq -0x48(%rbp), %rax
movq %r13, %rdi
movq %r15, %rsi
callq *0x10(%rax)
addl $0x2, -0x1cc(%rbp)
xorl %eax, %eax
jmp 0x3513
movq %r13, %rdi
callq 0x6028
testq %rax, %rax
je 0x352f
cmpl $0x0, 0x8(%rax)
je 0x34db
movq %r13, %rdi
movq %rax, %rsi
callq 0x6057
movq %r14, %rdi
movl $0x5, %esi
callq 0x5271
movl $0x0, -0x74(%rbp)
movl $0x2, %eax
jmp 0x3513
leaq 0x3b47(%rip), %rdi      # 0x7044
movl %r12d, %esi
xorl %eax, %eax
callq 0x30d0
movl $0x1, %eax
movl $0x1, -0x30(%rbp)
testb $0x1, %al
je 0x3464
movl -0x30(%rbp), %eax
jmp 0x33c5
leaq 0x3b34(%rip), %rdi      # 0x705e
jmp 0x330c
leaq 0x3aea(%rip), %rdi      # 0x7020
leaq 0x3ae6(%rip), %rsi      # 0x7023
leaq 0x3ae9(%rip), %rcx      # 0x702d
movl $0x58, %edx
callq 0x30f0
nop