// File: 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
movq %rsp, %rbp
subq $0x3f0, %rsp            # imm = 0x3F0
movl $0x0, -0x4(%rbp)
callq 0x3740
leaq -0x20(%rbp), %rdi
callq 0xffb0
movl $0x1000, %edi           # imm = 0x1000
callq 0x78f0
movq %rax, -0x1d0(%rbp)
jmp 0xec33
movq -0x1d0(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x7b50
movq %rax, -0x1d8(%rbp)
jmp 0xec50
movq -0x1d8(%rbp), %rax
movq %rax, -0x48(%rbp)
leaq 0x3899(%rip), %rdi      # 0x124fb
callq 0x3850
movl %eax, -0x1dc(%rbp)
jmp 0xec6f
movl -0x1dc(%rbp), %eax
movl %eax, -0x4c(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0xeca8
movl -0x4c(%rbp), %edi
leaq 0x4041(%rip), %rdx      # 0x12cca
movl $0x1, %esi
callq 0x3a70
jmp 0xec95
jmp 0xecc4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0xfe6e
movl -0x4c(%rbp), %edi
leaq 0x4024(%rip), %rdx      # 0x12cd6
xorl %esi, %esi
callq 0x3a70
jmp 0xecbb
callq 0x3be0
jmp 0xecc2
jmp 0xecc4
leaq 0x3830(%rip), %rdi      # 0x124fb
callq 0x3850
movl %eax, -0x1e0(%rbp)
jmp 0xecd8
movl -0x1e0(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq -0x48(%rbp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x7cc0
movl %eax, -0x1e4(%rbp)
jmp 0xecf9
movl -0x1e4(%rbp), %eax
movl %eax, -0x24(%rbp)
movl $0x4, %edi
callq 0x3270
movq %rax, -0x1f0(%rbp)
jmp 0xed15
movq -0x1f0(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rdi
movq -0x58(%rbp), %rdx
xorl %esi, %esi
callq 0x7c70
jmp 0xed31
cmpl $0x0, -0x24(%rbp)
jne 0xed40
movq -0x58(%rbp), %rax
cmpl $0x0, (%rax)
jne 0xed58
movl -0x4c(%rbp), %edi
leaq 0x3f9f(%rip), %rdx      # 0x12ce9
movl $0x1, %esi
callq 0x3a70
jmp 0xed56
jmp 0xed6d
movl -0x4c(%rbp), %edi
leaq 0x3f96(%rip), %rdx      # 0x12cf8
xorl %esi, %esi
callq 0x3a70
jmp 0xed6b
jmp 0xed6d
movq -0x58(%rbp), %rax
movq %rax, -0x1f8(%rbp)
cmpq $0x0, %rax
je 0xed8f
movq -0x1f8(%rbp), %rdi
movl $0x4, %esi
callq 0x3280
leaq 0x3765(%rip), %rdi      # 0x124fb
callq 0x3850
movl %eax, -0x1fc(%rbp)
jmp 0xeda3
movl -0x1fc(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl $0x4, %edi
callq 0x3270
movq %rax, -0x208(%rbp)
jmp 0xedbf
movq -0x208(%rbp), %rax
movq %rax, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
cmpl $0x20, -0x64(%rbp)
jge 0xedff
movq -0x48(%rbp), %rdi
movl -0x64(%rbp), %esi
movq -0x60(%rbp), %rdx
callq 0x7c70
jmp 0xede9
cmpq $0x0, -0x60(%rbp)
je 0xedf2
jmp 0xedff
jmp 0xedf4
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0xedd1
cmpq $0x0, -0x60(%rbp)
je 0xee1e
movl -0x4c(%rbp), %edi
leaq 0x3ef5(%rip), %rdx      # 0x12d05
movl $0x1, %esi
callq 0x3a70
jmp 0xee1c
jmp 0xee33
movl -0x4c(%rbp), %edi
leaq 0x3ef0(%rip), %rdx      # 0x12d18
xorl %esi, %esi
callq 0x3a70
jmp 0xee31
jmp 0xee33
movq -0x60(%rbp), %rax
movl $0x0, (%rax)
leaq 0x36b7(%rip), %rdi      # 0x124fb
callq 0x3850
movl %eax, -0x20c(%rbp)
jmp 0xee51
movl -0x20c(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq -0x48(%rbp), %rdi
movq -0x60(%rbp), %rdx
movl $0x20, %esi
callq 0x7c70
movl %eax, -0x210(%rbp)
jmp 0xee74
movl -0x210(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0xee9b
movl -0x4c(%rbp), %edi
leaq 0x3ea2(%rip), %rdx      # 0x12d2f
movl $0x1, %esi
callq 0x3a70
jmp 0xee99
jmp 0xeeb0
movl -0x4c(%rbp), %edi
leaq 0x3ea7(%rip), %rdx      # 0x12d4c
xorl %esi, %esi
callq 0x3a70
jmp 0xeeae
jmp 0xeeb0
leaq 0x3644(%rip), %rdi      # 0x124fb
callq 0x3850
movl %eax, -0x214(%rbp)
jmp 0xeec4
movl -0x214(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq -0x48(%rbp), %rdi
callq 0x7bf0
jmp 0xeed8
movl $0x0, -0x68(%rbp)
cmpl $0x20, -0x68(%rbp)
jge 0xef0d
movq -0x48(%rbp), %rdi
movl -0x68(%rbp), %esi
movq -0x60(%rbp), %rdx
callq 0x7c70
jmp 0xeef7
cmpq $0x0, -0x60(%rbp)
je 0xef00
jmp 0xef0d
jmp 0xef02
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0xeedf
cmpq $0x0, -0x60(%rbp)
je 0xef2c
movl -0x4c(%rbp), %edi
leaq 0x3de7(%rip), %rdx      # 0x12d05
movl $0x1, %esi
callq 0x3a70
jmp 0xef2a
jmp 0xef41
movl -0x4c(%rbp), %edi
leaq 0x3de2(%rip), %rdx      # 0x12d18
xorl %esi, %esi
callq 0x3a70
jmp 0xef3f
jmp 0xef41
movq -0x60(%rbp), %rax
movq %rax, -0x220(%rbp)
cmpq $0x0, %rax
je 0xef63
movq -0x220(%rbp), %rdi
movl $0x4, %esi
callq 0x3280
leaq -0x20(%rbp), %rdi
callq 0xe690
movl %eax, -0x224(%rbp)
jmp 0xef74
movl -0x224(%rbp), %eax
movl %eax, -0x24(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x20(%rbp), %rsi
callq 0xffd0
jmp 0xef8c
leaq -0x30(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0xea00
movl %eax, -0x228(%rbp)
jmp 0xefa1
movl -0x228(%rbp), %eax
movl %eax, -0x24(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x100c0
cmpl $0x0, -0x24(%rbp)
je 0xf037
movq 0xa008(%rip), %rdi      # 0x18fc8
leaq 0x3d9a(%rip), %rsi      # 0x12d61
callq 0x3260
movq %rax, -0x230(%rbp)
jmp 0xefd5
movq -0x230(%rbp), %rdi
movq 0x9fd5(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xefea
callq 0x3be0
jmp 0xeff1
movq -0x48(%rbp), %rdi
callq 0x8310
jmp 0xeffc
movq -0x30(%rbp), %rdi
callq 0x7b10
jmp 0xf007
movl $0x0, -0x4(%rbp)
movl $0x1, -0x84(%rbp)
jmp 0xfe59
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x100c0
jmp 0xfe6e
movl $0x0, -0x88(%rbp)
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
movq %rax, -0x238(%rbp)
leaq -0x20(%rbp), %rdi
callq 0xff60
movq %rax, %rcx
movq -0x238(%rbp), %rax
cmpq %rcx, %rax
jae 0xfe2b
movl $0x4, %edi
callq 0x3270
movq %rax, -0x240(%rbp)
jmp 0xf087
movq -0x240(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
jmp 0xf0a7
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
cmpl $0x0, (%rax)
jne 0xf100
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf0ec
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
addl $0x4, %esi
callq 0x7d10
jmp 0xf0ea
jmp 0xf0ec
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0xfe17
movb $0x0, -0x1a1(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x3110
movq %rax, %rdi
callq 0x3850
movl %eax, -0x244(%rbp)
jmp 0xf134
movl -0x244(%rbp), %eax
movl %eax, -0x1a8(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x250(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq -0x250(%rbp), %rdi
movl 0x2c(%rax), %edx
movl $0x2, %esi
callq 0x7cc0
jmp 0xf172
movq -0x48(%rbp), %rax
movq %rax, -0x258(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq -0x258(%rbp), %rdi
movl 0x30(%rax), %edx
movl $0x3, %esi
callq 0x7cc0
jmp 0xf1a4
movq -0x48(%rbp), %rsi
leaq -0x120(%rbp), %rdi
callq 0xeb70
jmp 0xf1b6
movq -0x48(%rbp), %rdi
callq 0x7d90
movl %eax, -0x25c(%rbp)
jmp 0xf1c7
movl -0x25c(%rbp), %eax
movl %eax, -0x24(%rbp)
movq -0x48(%rbp), %rsi
leaq -0x1a0(%rbp), %rdi
callq 0xeb70
jmp 0xf1e2
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
jmp 0xf1f4
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3480
movq %rax, -0x268(%rbp)
jmp 0xf21e
movq -0x268(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x26c(%rbp)
subl $0x3c, %eax
je 0xf3d8
jmp 0xf239
movl -0x26c(%rbp), %eax
subl $0x42, %eax
je 0xf25a
jmp 0xf246
movl -0x26c(%rbp), %eax
subl $0x4a, %eax
je 0xf3ea
jmp 0xf4be
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf33e
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
cmpl $0x1, 0x28(%rax)
jne 0xf33e
cmpl $0x0, -0x24(%rbp)
jne 0xf33e
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x33e0
cmpq $0x4, %rax
jbe 0xf2dc
movl -0x124(%rbp), %eax
movl -0x8c(%rbp), %ecx
addl $0x2, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
je 0xf2da
jmp 0xf4f2
jmp 0xf2dc
movq -0x48(%rbp), %rdi
callq 0x7d90
movl %eax, -0x270(%rbp)
jmp 0xf2ed
movl -0x270(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0xf301
jmp 0xf4f2
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
jmp 0xf313
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x3, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf339
cmpl $0x0, -0x24(%rbp)
jne 0xf339
movb $0x1, -0x1a1(%rbp)
jmp 0xf4f2
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf3d6
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
cmpl $0x0, 0x28(%rax)
jne 0xf3d6
cmpl $0x0, -0x24(%rbp)
jne 0xf3d6
movq -0x48(%rbp), %rdi
callq 0x7d90
movl %eax, -0x274(%rbp)
jmp 0xf385
movl -0x274(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0xf399
jmp 0xf4f2
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
jmp 0xf3ab
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x2, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf3d1
cmpl $0x0, -0x24(%rbp)
jne 0xf3d1
movb $0x1, -0x1a1(%rbp)
jmp 0xf4f2
jmp 0xf3d8
cmpl $0x0, -0x24(%rbp)
je 0xf3e5
movb $0x1, -0x1a1(%rbp)
jmp 0xf4f2
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf4bc
cmpl $0x0, -0x24(%rbp)
jne 0xf4bc
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x33e0
cmpq $0x3, %rax
jb 0xf451
movl -0x124(%rbp), %eax
movl -0x8c(%rbp), %ecx
addl $0x2, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
je 0xf44f
jmp 0xf4f2
jmp 0xf451
movq -0x48(%rbp), %rdi
callq 0x7d90
movl %eax, -0x278(%rbp)
jmp 0xf462
movl -0x278(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0xf473
jmp 0xf4f2
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
movl %eax, -0x27c(%rbp)
jmp 0xf48b
movl -0x27c(%rbp), %eax
movl %eax, -0x24(%rbp)
movq -0x98(%rbp), %rax
movl (%rax), %eax
movl -0x8c(%rbp), %ecx
addl $0x3, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
jne 0xf4ba
cmpl $0x0, -0x24(%rbp)
jne 0xf4ba
movb $0x1, -0x1a1(%rbp)
jmp 0xf4f2
jmp 0xf4f2
movl -0x19c(%rbp), %eax
movl %eax, -0x280(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rcx
movl -0x280(%rbp), %eax
cmpl 0x28(%rcx), %eax
jne 0xf4f0
movb $0x1, -0x1a1(%rbp)
jmp 0xf4f2
testb $0x1, -0x1a1(%rbp)
je 0xf650
movl -0x1a8(%rbp), %eax
movl %eax, -0x284(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x3110
movl -0x284(%rbp), %edi
movq %rax, %rdx
movl $0x1, %esi
callq 0x3a70
jmp 0xf53d
cmpl $0x2006, -0x24(%rbp)    # imm = 0x2006
jne 0xf55f
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
addl $0x4, %esi
callq 0x7d10
jmp 0xf55d
jmp 0xf55f
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3480
movq %rax, -0x290(%rbp)
jmp 0xf589
movq -0x290(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x294(%rbp)
subl $0x3c, %eax
je 0xf5bd
jmp 0xf5a0
movl -0x294(%rbp), %eax
subl $0x42, %eax
je 0xf5d6
jmp 0xf5ad
movl -0x294(%rbp), %eax
subl $0x4a, %eax
je 0xf62d
jmp 0xf64b
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
addl $0x4, %esi
callq 0x7d10
jmp 0xf5d4
jmp 0xf64b
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
cmpl $0x1, 0x28(%rax)
jne 0xf60d
movl -0x8c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x8c(%rbp)
movl -0x88(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x88(%rbp)
jmp 0xf62b
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0xf64b
movl -0x8c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x8c(%rbp)
movl -0x88(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x88(%rbp)
jmp 0xfe15
movq 0x9971(%rip), %rdi      # 0x18fc8
leaq 0x3765(%rip), %rsi      # 0x12dc3
callq 0x3260
movq %rax, -0x2a0(%rbp)
jmp 0xf66c
movq -0x2a0(%rbp), %rdi
movq 0x993e(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xf681
movq 0x9940(%rip), %rdi      # 0x18fc8
leaq 0x377c(%rip), %rsi      # 0x12e0b
callq 0x3260
movq %rax, -0x2a8(%rbp)
jmp 0xf69d
movq -0x2a8(%rbp), %rdi
movl -0x8c(%rbp), %esi
movl -0x88(%rbp), %eax
subl %eax, %esi
incl %esi
callq 0x3390
movq %rax, -0x2b0(%rbp)
jmp 0xf6c2
movq -0x2b0(%rbp), %rdi
leaq 0x3744(%rip), %rsi      # 0x12e14
callq 0x3260
movq %rax, -0x2b8(%rbp)
jmp 0xf6de
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x10140
jmp 0xf700
movq -0x2b8(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x3240
movq %rax, -0x2c0(%rbp)
jmp 0xf71c
movq -0x2c0(%rbp), %rdi
leaq 0x36f8(%rip), %rsi      # 0x12e22
callq 0x3260
movq %rax, -0x2c8(%rbp)
jmp 0xf738
movq -0x2c8(%rbp), %rdi
movq 0x9872(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xf74d
leaq -0x1c8(%rbp), %rdi
callq 0x3170
movq 0x9868(%rip), %rdi      # 0x18fc8
leaq 0x36bd(%rip), %rsi      # 0x12e24
callq 0x3260
movq %rax, -0x2d0(%rbp)
jmp 0xf775
movq -0x2d0(%rbp), %rdi
movq 0x9835(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xf78a
leaq -0x120(%rbp), %rdi
callq 0xeaa0
jmp 0xf798
movq 0x9829(%rip), %rdi      # 0x18fc8
movq 0x9812(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x2d8(%rbp)
jmp 0xf7b4
movq -0x2d8(%rbp), %rdi
leaq 0x36a9(%rip), %rsi      # 0x12e6b
callq 0x3260
movq %rax, -0x2e0(%rbp)
jmp 0xf7d0
movq -0x2e0(%rbp), %rdi
movq 0x97da(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xf7e5
leaq -0x1a0(%rbp), %rdi
callq 0xeaa0
jmp 0xf7f3
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rsi
callq 0x7d50
jmp 0xf805
movl -0x1a8(%rbp), %eax
movl %eax, -0x2e4(%rbp)
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x3110
movl -0x2e4(%rbp), %edi
movq %rax, %rdx
xorl %esi, %esi
callq 0x3a70
jmp 0xf840
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3480
movq %rax, -0x2f0(%rbp)
jmp 0xf86a
movq -0x2f0(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x2f4(%rbp)
subl $0x3c, %eax
je 0xf8c3
jmp 0xf881
movl -0x2f4(%rbp), %eax
subl $0x42, %eax
je 0xf934
jmp 0xf892
movl -0x2f4(%rbp), %eax
subl $0x4a, %eax
je 0xfbd6
jmp 0xfcbe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0x3170
jmp 0xfe6e
movq 0x96fe(%rip), %rdi      # 0x18fc8
movq 0x96e7(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x300(%rbp)
jmp 0xf8df
movq -0x300(%rbp), %rdi
leaq 0x35bf(%rip), %rsi      # 0x12eac
callq 0x3260
movq %rax, -0x308(%rbp)
jmp 0xf8fb
movq -0x308(%rbp), %rdi
movq 0x96af(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xf910
cmpl $0x0, -0x24(%rbp)
je 0xf92f
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
addl $0x4, %esi
callq 0x7d10
jmp 0xf92d
jmp 0xf92f
jmp 0xfd8c
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
cmpl $0x1, 0x28(%rax)
jne 0xfaec
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq %rax, %rdi
addq $0x8, %rdi
callq 0x33e0
cmpq $0x4, %rax
jbe 0xfa3c
movl -0x124(%rbp), %eax
movl -0x8c(%rbp), %ecx
addl $0x2, %ecx
shll $0x2, %ecx
cmpl %ecx, %eax
je 0xfa3a
movq 0x9631(%rip), %rdi      # 0x18fc8
movq 0x961a(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x310(%rbp)
jmp 0xf9ac
movq -0x310(%rbp), %rdi
leaq 0x3541(%rip), %rsi      # 0x12efb
callq 0x3260
movq %rax, -0x318(%rbp)
jmp 0xf9c8
movq -0x318(%rbp), %rdi
movl -0x124(%rbp), %esi
callq 0x3390
movq %rax, -0x320(%rbp)
jmp 0xf9e3
movq -0x320(%rbp), %rdi
leaq 0x352b(%rip), %rsi      # 0x12f1c
callq 0x3260
movq %rax, -0x328(%rbp)
jmp 0xf9ff
movq -0x328(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0xc(,%rax,4), %esi
callq 0x3390
movq %rax, -0x330(%rbp)
jmp 0xfa23
movq -0x330(%rbp), %rdi
movq 0x9587(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfa38
jmp 0xfa3a
jmp 0xfa3c
movq 0x9585(%rip), %rdi      # 0x18fc8
movq 0x956e(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x338(%rbp)
jmp 0xfa58
movq -0x338(%rbp), %rdi
leaq 0x34c4(%rip), %rsi      # 0x12f2a
callq 0x3260
movq %rax, -0x340(%rbp)
jmp 0xfa74
movq -0x340(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
callq 0x3390
movq %rax, -0x348(%rbp)
jmp 0xfa92
movq -0x348(%rbp), %rdi
leaq 0x347c(%rip), %rsi      # 0x12f1c
callq 0x3260
movq %rax, -0x350(%rbp)
jmp 0xfaae
movq -0x350(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0xc(,%rax,4), %esi
callq 0x3390
movq %rax, -0x358(%rbp)
jmp 0xfad2
movq -0x358(%rbp), %rdi
movq 0x94d8(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfae7
jmp 0xfb99
movq 0x94d5(%rip), %rdi      # 0x18fc8
movq 0x94be(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x360(%rbp)
jmp 0xfb08
movq -0x360(%rbp), %rdi
leaq 0x3414(%rip), %rsi      # 0x12f2a
callq 0x3260
movq %rax, -0x368(%rbp)
jmp 0xfb24
movq -0x368(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
callq 0x3390
movq %rax, -0x370(%rbp)
jmp 0xfb42
movq -0x370(%rbp), %rdi
leaq 0x33cc(%rip), %rsi      # 0x12f1c
callq 0x3260
movq %rax, -0x378(%rbp)
jmp 0xfb5e
movq -0x378(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0x4(,%rax,4), %esi
callq 0x3390
movq %rax, -0x380(%rbp)
jmp 0xfb82
movq -0x380(%rbp), %rdi
movq 0x9428(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfb97
jmp 0xfb99
movq -0x48(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0xc(,%rax,4), %esi
callq 0x7d10
jmp 0xfbb3
movl -0x8c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x8c(%rbp)
movl -0x88(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x88(%rbp)
jmp 0xfd8c
movq 0x93eb(%rip), %rdi      # 0x18fc8
movq 0x93d4(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x388(%rbp)
jmp 0xfbf2
movq -0x388(%rbp), %rdi
leaq 0x332a(%rip), %rsi      # 0x12f2a
callq 0x3260
movq %rax, -0x390(%rbp)
jmp 0xfc0e
movq -0x390(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
callq 0x3390
movq %rax, -0x398(%rbp)
jmp 0xfc2c
movq -0x398(%rbp), %rdi
leaq 0x32e2(%rip), %rsi      # 0x12f1c
callq 0x3260
movq %rax, -0x3a0(%rbp)
jmp 0xfc48
movq -0x3a0(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0x8(,%rax,4), %esi
callq 0x3390
movq %rax, -0x3a8(%rbp)
jmp 0xfc6c
movq -0x3a8(%rbp), %rdi
movq 0x933e(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfc81
movq -0x48(%rbp), %rdi
movl -0x8c(%rbp), %ecx
movl %ecx, %eax
leal 0xc(,%rax,4), %esi
callq 0x7d10
jmp 0xfc9b
movl -0x8c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x8c(%rbp)
movl -0x88(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x88(%rbp)
jmp 0xfd8c
movq 0x9303(%rip), %rdi      # 0x18fc8
movq 0x92ec(%rip), %rsi      # 0x18fb8
callq 0x32a0
movq %rax, -0x3b0(%rbp)
jmp 0xfcda
movq -0x3b0(%rbp), %rdi
leaq 0x3253(%rip), %rsi      # 0x12f3b
callq 0x3260
movq %rax, -0x3b8(%rbp)
jmp 0xfcf6
movq -0x3b8(%rbp), %rdi
movl -0x19c(%rbp), %esi
callq 0x3390
movq %rax, -0x3c0(%rbp)
jmp 0xfd11
movq -0x3c0(%rbp), %rdi
leaq 0x322d(%rip), %rsi      # 0x12f4c
callq 0x3260
movq %rax, -0x3c8(%rbp)
jmp 0xfd2d
movl -0x8c(%rbp), %eax
movl %eax, %esi
leaq -0x20(%rbp), %rdi
callq 0x10120
movq -0x3c8(%rbp), %rdi
movl 0x28(%rax), %esi
callq 0x3390
movq %rax, -0x3d0(%rbp)
jmp 0xfd56
movq -0x3d0(%rbp), %rdi
movq 0x9254(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfd6b
cmpl $0x0, -0x24(%rbp)
je 0xfd8a
movq -0x48(%rbp), %rdi
movq -0x98(%rbp), %rax
movl (%rax), %esi
addl $0x4, %esi
callq 0x7d10
jmp 0xfd88
jmp 0xfd8a
jmp 0xfd8c
movq 0x9235(%rip), %rdi      # 0x18fc8
leaq 0x31c3(%rip), %rsi      # 0x12f5d
callq 0x3260
movq %rax, -0x3d8(%rbp)
jmp 0xfda8
movq -0x3d8(%rbp), %rdi
movq 0x9202(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfdbd
movq 0x9204(%rip), %rdi      # 0x18fc8
leaq 0x300a(%rip), %rsi      # 0x12dd5
callq 0x3260
movq %rax, -0x3e0(%rbp)
jmp 0xfdd9
movq -0x3e0(%rbp), %rdi
movq 0x91d1(%rip), %rsi      # 0x18fb8
callq 0x32a0
jmp 0xfdee
movq -0x98(%rbp), %rax
movq %rax, -0x3e8(%rbp)
cmpq $0x0, %rax
je 0xfe13
movq -0x3e8(%rbp), %rdi
movl $0x4, %esi
callq 0x3280
jmp 0xfe15
jmp 0xfe17
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0xf04b
callq 0x3be0
jmp 0xfe32
movq -0x48(%rbp), %rdi
callq 0x8310
jmp 0xfe3d
movq -0x30(%rbp), %rdi
callq 0x7b10
jmp 0xfe48
movl $0x0, -0x4(%rbp)
movl $0x1, -0x84(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x100c0
movl -0x4(%rbp), %eax
addq $0x3f0, %rsp            # imm = 0x3F0
popq %rbp
retq
leaq -0x20(%rbp), %rdi
callq 0x100c0
movq -0x38(%rbp), %rdi
callq 0x3440