// File: /workspace/github_cpp_makefile_star2_O3/martinferianc[P]CPUSimulator-EIE2/src/test_mips.cpp
// Function: main
int main(){
  mips_test_begin_suite();
  vector<test> instructions;
  mips_error err;

  //Test #1 if the cpu was created correctly
  mips_mem_h mem = mips_mem_create_ram(4096);
  mips_cpu_h cpu = mips_cpu_create(mem);
  int testId = mips_test_begin_test("<INTERNAL>");
  if (cpu!=0){
    mips_test_end_test(testId, true, "CPU Created");
  } else{
    mips_test_end_test(testId, false, "CPU Creation error");
    mips_test_end_suite();
  }
  //ENDTEST

  //Test #2 writing to register 0
  testId = mips_test_begin_test("<INTERNAL>");
  err = mips_cpu_set_register(cpu, 0, 1);
  uint32_t *r0 = new uint32_t;
  mips_cpu_get_register(cpu, 0, r0);
  if ((err!=mips_Success) || (*r0==0))
    mips_test_end_test(testId, true, "R[0] unchanged");
  else
    mips_test_end_test(testId, false, "R[0] changed");
  delete r0;
  //ENDTEST

  //Test #3 checking if registers are 0
  testId = mips_test_begin_test("<INTERNAL>");
  uint32_t *v = new uint32_t;
  for (int i = 0; i < 32; ++i){
    mips_cpu_get_register(cpu,i,v);
    if (v!=0)
    break;
  }
  if (v!=0)
    mips_test_end_test(testId, true, "Registers are zero");
  else
    mips_test_end_test(testId, false, "Registers are non-zero");
  *v=0;
  //ENDTEST


  //Test #4 Accessing invalid index
  testId = mips_test_begin_test("<INTERNAL>");
  err = mips_cpu_get_register(cpu, 32, v);
  if (err!=mips_Success)
    mips_test_end_test(testId, true, "Register could not be loaded");
  else
    mips_test_end_test(testId, false, "Register index error");
  //ENDTEST

  //Test #5 Test the CPU RESET
  testId = mips_test_begin_test("<INTERNAL>");
  mips_cpu_reset(cpu);
  for (int i = 0; i < 32; ++i){
    mips_cpu_get_register(cpu,i,v);
    if (v!=0)
    break;
  }
  if (v!=0)
    mips_test_end_test(testId, true, "Registers are zero");
  else
    mips_test_end_test(testId, false, "Registers are non-zero");
  delete v;

  //////////TEST SUITE//////////////////
  //ALWAYS R1(result), R2, R3(operands)

  //mips_cpu_set_debug_level(cpu, 2, NULL);

  err = load_instructions(instructions);
  err = load_memory(mem, instructions);
  if (err!=mips_Success){
    cout<<"!   (Error) Instructions could not be loaded from the file please check mips_cpu_instructions.txt"<<endl;
    mips_test_end_suite();
    mips_cpu_free(cpu);
    mips_mem_free(mem);
    return 0;
  }

  int skip_count = 0; //To skip the SKIP parts
  for (uint32_t i = 0; i < instructions.size(); ++i){
    uint32_t *pc = new uint32_t;
    mips_cpu_get_pc(cpu,pc);
    if (instructions[i].instruction_code==0){ //In case the CPU tries to execute the skip
      if (*pc==i*4)
        mips_cpu_set_pc(cpu,*pc+4);
      skip_count++;
      continue;
    }
    uint32_t regs_before [32];
    uint32_t regs_after [32];

    bool success = false;
    int testId = mips_test_begin_test(instructions[i].instruction_name.c_str());

    mips_cpu_set_register(cpu, 2, instructions[i].instruction_r1);
    mips_cpu_set_register(cpu, 3, instructions[i].instruction_r2);
    load_registers(regs_before, cpu);

    err = mips_cpu_step(cpu);
    load_registers(regs_after, cpu);

    mips_cpu_get_pc(cpu,pc);
    switch(instructions[i].instruction_name[0]){
      case 'B':
        //Branch should be taken, expected result == 1, pc changed in the next instruction
        if ((*pc==(i+1)*4) && (instructions[i].instruction_result==1) && (err==mips_Success)){
          if (instructions[i].instruction_name.length() > 4) {
            if(regs_after[31] != (i+2)*4)
            break;
          }
          err = mips_cpu_step(cpu); //Step to the instruction from where branch is performed
          if (err!=mips_Success)
            break;

          mips_cpu_get_pc(cpu,pc);
          if ((*pc==(i+3)*4) && (err==mips_Success)) //Branches always by 2
            success = true;

          break;
        }
        //Branch should not be taken, expected result == 0, pc = pc + 4
        if ((*pc==(i+1)*4) && (instructions[i].instruction_result==0) && (err==mips_Success)){

          err = mips_cpu_step(cpu); //Step to the instruction from where branch is performed
          if (err!=mips_Success)
            break;

          mips_cpu_get_pc(cpu,pc);

          if ((*pc==(i+2)*4) && (err==mips_Success))
            success = true;

          break;
          }

      case '<':
        if (err!=mips_Success)
          success = true;
        break;

      case 'J':
        if ((*pc==(i+1)*4) && (err==mips_Success)){
          if (instructions[i].instruction_name.length() >= 3) {
            if(regs_after[31] != (i+2)*4)
            break;
          }
          err = mips_cpu_step(cpu);
          if (err!=mips_Success)
            break;

          err = mips_cpu_get_pc(cpu,pc);
          if ((*pc==(i+3)*4) && (err==mips_Success))
            success = true;

          break;
        }
      break;
      default:

      //Test all other instructions
      if (regs_after[1] == instructions[i].instruction_result)
        success = true;

    }
    if (success){
      mips_test_end_test(testId, true, instructions[i].instruction_name.c_str());
      if (err==mips_ExceptionArithmeticOverflow)
        mips_cpu_set_pc(cpu, *pc + 4);

      switch (instructions[i].instruction_name[0]) {
        case '<':
          //Manually adjust the PC because the instruction resulted in an error
          mips_cpu_set_pc(cpu, *pc + 4);
          break;

        case 'B':
          if (instructions[i].instruction_result==1) {
            i=i+2;
            skip_count=skip_count+2;
          } else {
            i=i+1;
            skip_count=skip_count+1;
          }
          break;

        case 'J':
          i=i+2;
          skip_count=skip_count+2;
          break;
      }
    } else {
      cout<<"-----------------------------------------------------------------------"<<endl;
      cout<<"| Test: "<<i+1-skip_count<<"| To memory: "<<instructions[i].str()<<"|"<<endl;
      cout<<"-----------------------REGISTERS BEFORE-------------------------------"<<endl;
      print_registers(regs_before);
      cout<<endl<<"----------------------REGISTERS AFTER---------------------------"<<endl;
      print_registers(regs_after);
      mips_cpu_get_pc(cpu,pc);
      mips_test_end_test(testId, false, instructions[i].instruction_name.c_str());
      switch (instructions[i].instruction_name[0]) {
        case '<':
          cout<<endl<<"!   (Error) Instruction should have not been executed: Instruction is invalid!"<<endl;
          if (err != mips_Success)
            mips_cpu_set_pc(cpu, *pc + 4);
        break;

        case 'B':
          if (instructions[i].instruction_result==1){
            if (instructions[i].instruction_name.length() > 4) {
              if(regs_after[31] != (i+2)*4)
                cout<<endl<<"!   (Error) PC + 8 not in R[31]:"<<regs_after[31]<<" PC Awaited: "<<(i+3)*4<<endl;
            }
            cout<<endl<<"!   (Error) PC: "<<*pc<<" PC Awaited: "<<(i+3)*4<<endl;
          }else{
            cout<<endl<<"!   (Error) PC: "<<*pc<<" PC Awaited: "<<(i+1)*4<<endl;
          }
          mips_cpu_set_pc(cpu, (i+3)*4);
          i=i+2;
          skip_count=skip_count+2;
        break;

        case 'J':
          cout<<endl<<"!   (Error) PC: "<<*pc<<" PC Awaited: "<<(i+2)*4<<endl;
          mips_cpu_set_pc(cpu, (i+3)*4);
          i=i+2;
          skip_count=skip_count+2;
        break;

        default:
          cout<<endl<<"!   (Error) Got:"<<regs_after[1]<<" Actual Result: "<<instructions[i].instruction_result<<endl;
          if (err != mips_Success)
            mips_cpu_set_pc(cpu, *pc + 4);
        break;
      }
      cout<<"!    Going to the next memory location PC + 4:"<<endl;
      cout<<"-----------------------------------------------------"<<endl;

      delete pc;
    }
  }
  //////////END TEST SUITE//////////////////
  mips_test_end_suite();
  mips_cpu_free(cpu);
  mips_mem_free(mem);
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x188, %rsp            # imm = 0x188
callq 0x377c
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
movl $0x1000, %edi           # imm = 0x1000
callq 0x4a94
movq %rax, 0x60(%rsp)
movq %rax, 0x38(%rsp)
movq %rax, %rdi
callq 0x4ba4
movq %rax, (%rsp)
leaq 0x1e6f(%rip), %rdi      # 0xa4fb
callq 0x382f
cmpq $0x0, (%rsp)
je 0x86ad
leaq 0x2657(%rip), %rdx      # 0xacf6
movl %eax, %edi
movl $0x1, %esi
callq 0x39a6
jmp 0x86c2
leaq 0x264e(%rip), %rdx      # 0xad02
movl %eax, %edi
xorl %esi, %esi
callq 0x39a6
callq 0x3a2e
leaq 0x1e32(%rip), %rdi      # 0xa4fb
callq 0x382f
movl %eax, %ebx
movq (%rsp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x4c51
movl %eax, %ebp
movl $0x4, %edi
callq 0x31d0
movq %rax, %r15
movq (%rsp), %rdi
xorl %esi, %esi
movq %rax, %rdx
callq 0x4c31
testl %ebp, %ebp
je 0x870f
leaq 0x260d(%rip), %rdx      # 0xad15
movl $0x1, %esi
jmp 0x871e
cmpl $0x0, (%r15)
je 0x8701
leaq 0x2608(%rip), %rdx      # 0xad24
xorl %esi, %esi
movl %ebx, %edi
callq 0x39a6
movl $0x4, %esi
movq %r15, %rdi
callq 0x31e0
leaq 0x1dc2(%rip), %rdi      # 0xa4fb
callq 0x382f
movl %eax, %ebp
movl $0x4, %edi
callq 0x31d0
movq %rax, %rbx
movq (%rsp), %rdi
xorl %esi, %esi
movq %rax, %rdx
callq 0x4c31
leaq 0x25cf(%rip), %rdx      # 0xad31
movl %ebp, %edi
movl $0x1, %esi
callq 0x39a6
movl $0x0, (%rbx)
leaq 0x1d80(%rip), %rdi      # 0xa4fb
callq 0x382f
movl %eax, %ebp
movq (%rsp), %rdi
movl $0x20, %esi
movq %rbx, %rdx
callq 0x4c31
xorl %esi, %esi
testl %eax, %eax
setne %sil
leaq 0x25a2(%rip), %rax      # 0xad44
leaq 0x25b8(%rip), %rdx      # 0xad61
cmovneq %rax, %rdx
movl %ebp, %edi
callq 0x39a6
leaq 0x1d40(%rip), %rdi      # 0xa4fb
callq 0x382f
movl %eax, %ebp
movq (%rsp), %rdi
callq 0x4bf3
movq (%rsp), %rdi
xorl %esi, %esi
movq %rbx, %rdx
callq 0x4c31
leaq 0x2551(%rip), %rdx      # 0xad31
movl %ebp, %edi
movl $0x1, %esi
callq 0x39a6
movl $0x4, %esi
movq %rbx, %rdi
callq 0x31e0
leaq 0x10(%rsp), %rdi
callq 0x80bc
leaq 0x68(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x936c
leaq 0x60(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x847a
movl %eax, %ebx
leaq 0x68(%rsp), %rdi
callq 0x9404
testl %ebx, %ebx
je 0x8894
movq 0x6790(%rip), %rbx      # 0xefc8
leaq 0x2537(%rip), %rsi      # 0xad76
movl $0x61, %edx
movq %rbx, %rdi
callq 0x3210
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x675e(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
callq 0x3a2e
movq (%rsp), %rdi
callq 0x5222
movq 0x38(%rsp), %rdi
callq 0x4b86
jmp 0x9291
movq 0x18(%rsp), %rax
cmpq 0x10(%rsp), %rax
je 0x9279
xorl %r14d, %r14d
movl $0x0, 0xc(%rsp)
movl $0x4, %edi
callq 0x31d0
movq %rax, %rbp
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x4c89
movq 0x10(%rsp), %rax
imulq $0x38, %r14, %r12
cmpl $0x0, (%rax,%r12)
je 0x89ec
addq %r12, %rax
movq 0x8(%rax), %rdi
callq 0x382f
movl %eax, 0x34(%rsp)
movq 0x10(%rsp), %rax
movl 0x2c(%rax,%r12), %edx
movq (%rsp), %rdi
movl $0x2, %esi
callq 0x4c51
movq 0x10(%rsp), %rax
movl 0x30(%rax,%r12), %edx
movq (%rsp), %rdi
movl $0x3, %esi
callq 0x4c51
leaq 0x100(%rsp), %rdi
movq (%rsp), %rsi
callq 0x85e8
movq (%rsp), %rdi
callq 0x4c9b
movl %eax, %ebx
leaq 0x80(%rsp), %rdi
movq (%rsp), %rsi
callq 0x85e8
movq (%rsp), %rdi
movq %rbp, %rsi
callq 0x4c89
movq 0x10(%rsp), %rax
movq 0x8(%rax,%r12), %rcx
movzbl (%rcx), %ecx
cmpl $0x3c, %ecx
je 0x8ab2
addq %r12, %rax
cmpl $0x42, %ecx
je 0x8a0e
cmpl $0x4a, %ecx
jne 0x8a70
leal 0x4(,%r14,4), %ecx
xorl (%rbp), %ecx
orl %ebx, %ecx
jne 0x8b23
leal (,%r14,4), %r15d
cmpq $0x3, 0x10(%rax)
jb 0x89b3
leal 0x8(%r15), %eax
cmpl %eax, 0xfc(%rsp)
jne 0x8b21
movq (%rsp), %rdi
callq 0x4c9b
movl %eax, %ebx
testl %eax, %eax
jne 0x8b23
movq (%rsp), %rdi
movq %rbp, %rsi
callq 0x4c89
addl $0xc, %r15d
xorl (%rbp), %r15d
xorl %ebx, %ebx
orl %eax, %r15d
je 0x8ab6
movl %eax, %ebx
jmp 0x8b23
leal (,%r14,4), %esi
cmpl %esi, (%rbp)
jne 0x8a05
addl $0x4, %esi
movq (%rsp), %rdi
callq 0x4c73
incl 0xc(%rsp)
jmp 0x9247
leal 0x4(,%r14,4), %ecx
cmpl %ecx, (%rbp)
jne 0x8ab2
leal (,%r14,4), %r15d
movl 0x28(%rax), %ecx
movl %ecx, %edx
xorl $0x1, %edx
orl %ebx, %edx
jne 0x8a81
cmpq $0x5, 0x10(%rax)
jb 0x8a4b
leal 0x8(%r15), %eax
cmpl %eax, 0xfc(%rsp)
jne 0x8b21
movq (%rsp), %rdi
callq 0x4c9b
movl %eax, %ebx
testl %eax, %eax
jne 0x8b23
movq (%rsp), %rdi
movq %rbp, %rsi
callq 0x4c89
addl $0xc, %r15d
jmp 0x8aa8
movl 0x84(%rsp), %ecx
cmpl 0x28(%rax), %ecx
je 0x8ab6
jmp 0x8b23
orl %ebx, %ecx
jne 0x8ab2
movq (%rsp), %rdi
callq 0x4c9b
movl %eax, %ebx
testl %eax, %eax
jne 0x8b23
movq (%rsp), %rdi
movq %rbp, %rsi
callq 0x4c89
addl $0x8, %r15d
xorl %ebx, %ebx
cmpl %r15d, (%rbp)
je 0x8ab6
jmp 0x8b23
testl %ebx, %ebx
je 0x8b21
movq 0x10(%rsp), %rax
movq 0x8(%rax,%r12), %rdx
movl 0x34(%rsp), %edi
movl $0x1, %esi
callq 0x39a6
cmpl $0x2006, %ebx           # imm = 0x2006
jne 0x8ae5
movl (%rbp), %esi
addl $0x4, %esi
movq (%rsp), %rdi
callq 0x4c73
movq 0x10(%rsp), %rax
movq 0x8(%rax,%r12), %rcx
movzbl (%rcx), %ecx
cmpl $0x4a, %ecx
je 0x90d8
cmpl $0x42, %ecx
je 0x90cb
cmpl $0x3c, %ecx
jne 0x9247
movl (%rbp), %esi
addl $0x4, %esi
movq (%rsp), %rdi
callq 0x4c73
jmp 0x9247
xorl %ebx, %ebx
movl $0x47, %edx
movq 0x6499(%rip), %rdi      # 0xefc8
leaq 0x22a2(%rip), %rsi      # 0xadd8
callq 0x3210
movq 0x6486(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x6468(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movl $0x8, %edx
movq 0x644f(%rip), %rdi      # 0xefc8
leaq 0x22a0(%rip), %rsi      # 0xae20
callq 0x3210
leal 0x1(%r14), %r15d
movl %r15d, %esi
subl 0xc(%rsp), %esi
movq 0x6431(%rip), %rdi      # 0xefc8
callq 0x3120
movq %rax, %r13
movl $0xd, %edx
movq %rax, %rdi
leaq 0x227b(%rip), %rsi      # 0xae29
callq 0x3210
movq 0x10(%rsp), %rsi
addq %r12, %rsi
leaq 0x40(%rsp), %rdi
callq 0x9462
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rdx
movq %r13, %rdi
callq 0x3210
movq %rax, %r13
movl $0x1, %edx
movq %rax, %rdi
leaq 0x224e(%rip), %rsi      # 0xae37
callq 0x3210
movq (%r13), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %r13, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x8c32
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x31e0
movl $0x46, %edx
movq 0x638a(%rip), %rdi      # 0xefc8
leaq 0x21f4(%rip), %rsi      # 0xae39
callq 0x3210
movq 0x6377(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x6359(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
leaq 0x100(%rsp), %rdi
callq 0x84f1
movq 0x6338(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x631a(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %r13
movl $0x40, %edx
movq %rax, %rdi
leaq 0x21b3(%rip), %rsi      # 0xae80
callq 0x3210
movq (%r13), %rax
movq -0x18(%rax), %rdi
addq %r13, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %r13, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
leaq 0x80(%rsp), %rdi
callq 0x84f1
movq (%rsp), %rdi
movq %rbp, %rsi
callq 0x4c89
movq 0x10(%rsp), %rax
movq 0x8(%rax,%r12), %rdx
movl 0x34(%rsp), %edi
xorl %esi, %esi
callq 0x39a6
movq 0x10(%rsp), %rax
movq 0x8(%rax,%r12), %rcx
movzbl (%rcx), %ecx
cmpl $0x3c, %ecx
je 0x8f8f
cmpl $0x42, %ecx
je 0x8e0b
cmpl $0x4a, %ecx
jne 0x9004
movq 0x6271(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x6253(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %rbx
movl $0x10, %edx
movq %rax, %rdi
leaq 0x21ab(%rip), %rsi      # 0xaf3f
callq 0x3210
movl (%rbp), %esi
movq %rbx, %rdi
callq 0x3120
movq %rax, %rbx
movl $0xd, %edx
movq %rax, %rdi
leaq 0x217b(%rip), %rsi      # 0xaf31
callq 0x3210
leal 0x8(,%r14,4), %esi
movq %rbx, %rdi
callq 0x3120
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
leal 0xc(,%r14,4), %esi
movq (%rsp), %rdi
callq 0x4c73
jmp 0x919d
addq %r12, %rax
cmpl $0x1, 0x28(%rax)
jne 0x90e6
cmpq $0x5, 0x10(%rax)
jb 0x8ee2
movl 0xfc(%rsp), %ebx
leal 0x8(,%r14,4), %eax
cmpl %eax, %ebx
je 0x8ee2
movq 0x6187(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x6169(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %r15
movl $0x20, %edx
movq %rax, %rdi
leaq 0x2092(%rip), %rsi      # 0xaf10
callq 0x3210
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3120
movq %rax, %rbx
movl $0xd, %edx
movq %rax, %rdi
leaq 0x2091(%rip), %rsi      # 0xaf31
callq 0x3210
leal (,%r14,4), %esi
addl $0xc, %esi
movq %rbx, %rdi
callq 0x3120
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq 0x60df(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x60c1(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %rbx
movl $0x10, %edx
movq %rax, %rdi
leaq 0x2019(%rip), %rsi      # 0xaf3f
callq 0x3210
movl (%rbp), %esi
movq %rbx, %rdi
callq 0x3120
movq %rax, %r15
movl $0xd, %edx
movq %rax, %rdi
leaq 0x1fe9(%rip), %rsi      # 0xaf31
callq 0x3210
leal 0xc(,%r14,4), %ebx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3120
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %r15, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
jmp 0x9192
movq 0x6032(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x6014(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %r15
movl $0x4e, %edx
movq %rax, %rdi
leaq 0x1eee(%rip), %rsi      # 0xaec1
callq 0x3210
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %r15, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
jmp 0x90af
movq 0x5fbd(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x5f9f(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %r15
movl $0x10, %edx
movq %rax, %rdi
leaq 0x1f08(%rip), %rsi      # 0xaf50
callq 0x3210
movl 0x84(%rsp), %esi
movq %r15, %rdi
callq 0x3120
movq %rax, %r15
movl $0x10, %edx
movq %rax, %rdi
leaq 0x1ef3(%rip), %rsi      # 0xaf61
callq 0x3210
movq 0x10(%rsp), %rax
movl 0x28(%rax,%r12), %esi
movq %r15, %rdi
callq 0x3120
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %r15, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
testl %ebx, %ebx
je 0x91a6
movl (%rbp), %esi
addl $0x4, %esi
movq (%rsp), %rdi
callq 0x4c73
jmp 0x91a6
addq %r12, %rax
cmpl $0x1, 0x28(%rax)
jne 0x9271
addl $0x2, %r14d
addl $0x2, 0xc(%rsp)
jmp 0x9247
movq 0x5edb(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x5ebd(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movq %rax, %rbx
movl $0x10, %edx
movq %rax, %rdi
leaq 0x1e15(%rip), %rsi      # 0xaf3f
callq 0x3210
movl (%rbp), %esi
movq %rbx, %rdi
callq 0x3120
movq %rax, %rbx
movl $0xd, %edx
movq %rax, %rdi
leaq 0x1de5(%rip), %rsi      # 0xaf31
callq 0x3210
shll $0x2, %r15d
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3120
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3130
leal 0xc(,%r14,4), %ebx
movq (%rsp), %rdi
movl %ebx, %esi
callq 0x4c73
addl $0x2, %r14d
addl $0x2, 0xc(%rsp)
movl $0x2e, %edx
movq 0x5e16(%rip), %rdi      # 0xefc8
leaq 0x1db9(%rip), %rsi      # 0xaf72
callq 0x3210
movq 0x5e03(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x5de5(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movl $0x35, %edx
movq 0x5dcc(%rip), %rdi      # 0xefc8
leaq 0x1be7(%rip), %rsi      # 0xadea
callq 0x3210
movq 0x5db9(%rip), %rcx      # 0xefc8
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x31c0
movsbl %al, %esi
movq 0x5d9b(%rip), %rdi      # 0xefc8
callq 0x3040
movq %rax, %rdi
callq 0x3130
movl $0x4, %esi
movq %rbp, %rdi
callq 0x31e0
movq 0x18(%rsp), %rax
subq 0x10(%rsp), %rax
incl %r14d
sarq $0x3, %rax
movabsq $0x6db6db6db6db6db7, %rcx # imm = 0x6DB6DB6DB6DB6DB7
imulq %rcx, %rax
cmpq %r14, %rax
ja 0x88af
jmp 0x9279
incl %r14d
jmp 0x8a05
callq 0x3a2e
movq (%rsp), %rdi
callq 0x5222
movq 0x38(%rsp), %rdi
callq 0x4b86
leaq 0x10(%rsp), %rdi
callq 0x9404
xorl %eax, %eax
addq $0x188, %rsp            # imm = 0x188
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x9404
jmp 0x92f6
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
jmp 0x92f3
movq %rax, %rbx
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x92f6
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x31e0
jmp 0x92f6
jmp 0x92f3
jmp 0x92f3
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x9404
movq %rbx, %rdi
callq 0x3330