// File: /workspace/github_c_makefile_star2_O0/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
subq $0x230, %rsp            # imm = 0x230
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x2, -0x8(%rbp)
jge 0x3329
leaq 0x6cee(%rip), %rdi      # 0xa004
movb $0x0, %al
callq 0x30d0
movl $0x1, -0x4(%rbp)
jmp 0x3541
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x20(%rbp), %rsi
leaq -0x24(%rbp), %rdx
callq 0x3550
cmpl $0x0, %eax
jne 0x3378
movq -0x18(%rbp), %rsi
leaq 0x6cbd(%rip), %rdi      # 0xa022
movb $0x0, %al
callq 0x30d0
movl $0x1, -0x4(%rbp)
jmp 0x3541
movq -0x20(%rbp), %rax
movq %rax, -0x50(%rbp)
movq $0x1fffffff, -0x48(%rbp) # imm = 0x1FFFFFFF
movslq -0x24(%rbp), %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x1ac(%rbp)
movl $0x0, -0x1a4(%rbp)
movl $0x700000f0, -0x64(%rbp) # imm = 0x700000F0
movl $0x40001, -0x58(%rbp)   # imm = 0x40001
movl $0x1, -0x54(%rbp)
movb $0x0, %al
callq 0x78e0
leaq -0x1f8(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x8800
leaq -0x1f8(%rbp), %rdi
movl $0x6072, %esi           # imm = 0x6072
callq 0x7d00
movq %rax, -0x200(%rbp)
cmpq $0x0, -0x200(%rbp)
jne 0x340f
leaq 0x6c39(%rip), %rdi      # 0xa035
movb $0x0, %al
callq 0x30d0
movl $0x1, -0x4(%rbp)
jmp 0x3541
jmp 0x3411
movq -0x200(%rbp), %rdi
callq 0x8000
cmpl $0x0, -0x54(%rbp)
jne 0x3425
jmp 0x3411
movl -0x1ac(%rbp), %esi
leaq 0x6c20(%rip), %rdi      # 0xa052
movb $0x0, %al
callq 0x30d0
movq -0x20(%rbp), %rax
movl -0x1ac(%rbp), %ecx
movw (%rax,%rcx), %ax
movw %ax, -0x21a(%rbp)
cmpw $0x0, -0x21a(%rbp)
jne 0x34df
movl -0x1ac(%rbp), %eax
movl %eax, %esi
leaq -0x1b0(%rbp), %rdi
callq 0x8cc0
movq %rax, -0x228(%rbp)
cmpq $0x0, -0x228(%rbp)
je 0x3483
jmp 0x34a2
leaq 0x6bd1(%rip), %rdi      # 0xa05b
leaq 0x6bcd(%rip), %rsi      # 0xa05e
movl $0x58, %edx
leaq 0x6bcb(%rip), %rcx      # 0xa068
callq 0x30f0
movq -0x228(%rbp), %rax
cmpl $0x0, 0x8(%rax)
je 0x34c2
movq -0x228(%rbp), %rsi
leaq -0x1b0(%rbp), %rdi
callq 0x8d60
movq -0x200(%rbp), %rdi
movl $0x5, %esi
callq 0x7f10
movl $0x0, -0x54(%rbp)
jmp 0x3411
leaq -0x218(%rbp), %rsi
movzwl -0x21a(%rbp), %edi
callq 0x7c20
cmpl $0x0, %eax
jne 0x3515
movzwl -0x21a(%rbp), %esi
leaq 0x6b7a(%rip), %rdi      # 0xa07f
movb $0x0, %al
callq 0x30d0
movl $0x1, -0x4(%rbp)
jmp 0x3541
movq -0x218(%rbp), %rax
leaq -0x1b0(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq *0x10(%rax)
movl -0x1ac(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x1ac(%rbp)
jmp 0x3411
movl -0x4(%rbp), %eax
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
nopl (%rax)