// File: luooofan[P]hblzbd_compiler/src/Pass/arm_offset_fixup.cpp
// Function: SPOffsetFixup::Fixup4Func(ArmFunction*)
void SPOffsetFixup::Fixup4Func(ArmFunction *func) {
#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Prune Instruction Start:" << std::endl;
#endif
  // 每一个函数确定了之后 更改push/pop指令 更改add/sub sp sp stack_size指令
  int offset_fixup_diff = func->used_callee_saved_regs.size() * 4 + func->stack_size_;
  bool is_lr_used = func->used_callee_saved_regs.find(ArmReg::lr) != func->used_callee_saved_regs.end();

#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Modify Push Pop Start:" << std::endl;
#endif
  for (auto bb : func->bb_list_) {
    for (auto iter = bb->inst_list_.begin(); iter != bb->inst_list_.end();) {
      if (auto pushpop_inst = dynamic_cast<PushPop *>(*iter)) {
        // pushpop_inst->EmitCode(outfile);
        pushpop_inst->reg_list_.clear();
        Cond cond = pushpop_inst->cond_;
        for (auto reg : func->used_callee_saved_regs) {
          pushpop_inst->reg_list_.push_back(new Reg(reg));
        }
        if (pushpop_inst->opkind_ == PushPop::OpKind::PUSH) {
          if (pushpop_inst->reg_list_.empty()) {
            iter = bb->inst_list_.erase(iter);
            continue;
          }
        } else {
          if (is_lr_used) {  // 把pop lr 改为pop pc
            MyAssert(pushpop_inst->reg_list_.back()->reg_id_ == ArmReg::lr);
            pushpop_inst->reg_list_.back()->reg_id_ = ArmReg::pc;
          }
          if (pushpop_inst->reg_list_.empty()) {
            iter = bb->inst_list_.erase(iter);
          } else {
            ++iter;
          }
          // 此时iter指向原pop指令的下一条指令
          if (!is_lr_used) {  // 不在push中 插入一条 bx lr
            iter = bb->inst_list_.insert(iter, new Branch(false, true, cond, "lr", bb, false));
          }
          continue;
        }
        ++iter;
      } else {
        ++iter;
      }
    }
  }
#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Modify Push Pop End." << std::endl;
#endif

#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Fixup sp_arg Start:" << std::endl;
#endif

  auto merge_ldrpseudo_with_ldr = [&func](std::unordered_set<Instruction *>::iterator it) {
    // 把ldrpseudo和后面的ldr合起来
    for (auto bb : func->bb_list_) {
      for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) {
        if (*inst_it == *it) {
          int imm = 0;
          auto src_inst = dynamic_cast<LdrPseudo *>(*inst_it);
          MyAssert(nullptr != src_inst && src_inst->IsImm());
          imm = src_inst->imm_;
          inst_it = bb->inst_list_.erase(inst_it);
          // inst_it现在指向了ldr vreg sp op2指令 要把op2改为立即数类型
          auto ldr_inst = dynamic_cast<LdrStr *>(*inst_it);
          MyAssert(nullptr != ldr_inst && !ldr_inst->is_offset_imm_ && nullptr != ldr_inst->offset_ &&
                   ldr_inst->rn_->reg_id_ == ArmReg::sp && !ldr_inst->offset_->is_imm_ &&
                   ldr_inst->offset_->reg_->reg_id_ == src_inst->rd_->reg_id_);
          // TODO delete src op2
          ldr_inst->offset_ = new Operand2(imm);
          // *it = ldr_inst;  // 之后sp_arg_fixup中会出现ldr指令
          return;
        }
      }
    }
    MyAssert(0);
  };

  // 针对sp_arg的修复 需要修复栈中高处实参的位置 一定是一条ldr-pseudo指令
  for (auto it = func->sp_arg_fixup_.begin(); it != func->sp_arg_fixup_.end(); ++it) {
    auto src_inst = dynamic_cast<LdrPseudo *>(*it);
    MyAssert(nullptr != src_inst && src_inst->IsImm());
    src_inst->imm_ += offset_fixup_diff;
    if (LdrStr::CheckImm12(src_inst->imm_)) {
      merge_ldrpseudo_with_ldr(it);
    }
  }

  func->sp_arg_fixup_.clear();

#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Fixup sp_arg End." << std::endl;
  std::cout << "Fixup sp Start:" << std::endl;
#endif

  auto convert_imm_inst = [&func](std::unordered_set<Instruction *>::iterator it) {
    // 把mov/mvn转换成ldrpseudo
    for (auto bb : func->bb_list_) {
      for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) {
        if (*inst_it == *it) {
          auto src_inst = dynamic_cast<Move *>(*it);
          MyAssert(nullptr != src_inst && src_inst->op2_->is_imm_);
          inst_it = bb->inst_list_.erase(inst_it);
          int imm = 0;
          if (src_inst->is_mvn_) {
            imm = -src_inst->op2_->imm_num_ - 1;
          } else {
            imm = src_inst->op2_->imm_num_;
          }
          auto pseudo_ldr_inst = new LdrPseudo(Cond::AL, src_inst->rd_, imm, bb);
          inst_it = bb->inst_list_.insert(inst_it, pseudo_ldr_inst);
          // TODO: delete
          // *it = pseudo_ldr_inst;
          return;
        }
      }
    }
    MyAssert(0);
  };

  auto merge_with_addsub = [&func](std::unordered_set<Instruction *>::iterator it) {
    // 把mov/ldrpseudo和后面的addsub sp sp 合起来
    for (auto bb : func->bb_list_) {
      for (auto inst_it = bb->inst_list_.begin(); inst_it != bb->inst_list_.end(); ++inst_it) {
        if (*inst_it == *it) {
          int imm = 0;
          if (auto src_inst = dynamic_cast<Move *>(*it)) {
            MyAssert(src_inst->op2_->is_imm_);
            if (src_inst->is_mvn_) return;
            imm = src_inst->op2_->imm_num_;
          } else if (auto src_inst = dynamic_cast<LdrPseudo *>(*it)) {
            MyAssert(src_inst->IsImm());
            imm = src_inst->imm_;
          } else {
            MyAssert(0);
          }
          inst_it = bb->inst_list_.erase(inst_it);
          // inst_it现在指向了add或sub sp sp op2指令 要把op2改为立即数类型
          auto addsub_inst = dynamic_cast<BinaryInst *>(*inst_it);
          MyAssert(nullptr != addsub_inst && addsub_inst->rd_->reg_id_ == ArmReg::sp &&
                   addsub_inst->rn_->reg_id_ == ArmReg::sp);
          // TODO delete src op2
          addsub_inst->op2_ = new Operand2(imm);
          // *it = addsub_inst;  // 之后sp_fixup中会出现addsub指令
          return;
        }
      }
    }
    MyAssert(0);
  };

  // 针对function prologue和epilogue中sp的修复 原来都是0 可能是mov mvn或者pseudo ldr
  for (auto it = func->sp_fixup_.begin(); it != func->sp_fixup_.end(); ++it) {
    if (auto src_inst = dynamic_cast<Move *>(*it)) {
      MyAssert(src_inst->op2_->is_imm_);
      if (src_inst->is_mvn_) {
        MyAssert(0);
        src_inst->op2_->imm_num_ = -func->stack_size_;
      } else {
        src_inst->op2_->imm_num_ = func->stack_size_;
      }
      if (!Operand2::CheckImm8m(src_inst->op2_->imm_num_)) {
        convert_imm_inst(it);
      } else {
        // 满足op2 可以和后面的add/sub合为一条语句
        merge_with_addsub(it);
      }
    } else if (auto src_inst = dynamic_cast<LdrPseudo *>(*it)) {
      MyAssert(src_inst->IsImm());
      src_inst->imm_ = func->stack_size_;
      if (Operand2::CheckImm8m(src_inst->imm_)) {
        // 满足op2 可以和后面的add/sub合为一条语句
        merge_with_addsub(it);
      }
    } else {
      MyAssert(0);
    }
  }

  func->sp_fixup_.clear();

#ifdef DEBUG_FIXUP_PROCESS
  std::cout << "Fixup sp End." << std::endl;
#endif
}

// Assembly:
subq $0x208, %rsp            # imm = 0x208
movq %rdi, 0x200(%rsp)
movq %rsi, 0x1f8(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0xd8, %rdi
callq 0x80a40
shlq $0x2, %rax
movq 0x1f8(%rsp), %rcx
movslq 0x2c(%rcx), %rcx
addq %rcx, %rax
movl %eax, 0x1f4(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0xd8, %rdi
movl $0xe, 0x1e4(%rsp)
leaq 0x1e4(%rsp), %rsi
callq 0x80a70
movq %rax, 0x1e8(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0xd8, %rdi
callq 0x80ab0
movq %rax, 0x1d8(%rsp)
leaq 0x1e8(%rsp), %rdi
leaq 0x1d8(%rsp), %rsi
callq 0x80a50
andb $0x1, %al
movb %al, 0x1f3(%rsp)
movq 0x1f8(%rsp), %rax
addq $0x38, %rax
movq %rax, 0x1d0(%rsp)
movq 0x1d0(%rsp), %rdi
callq 0x10bd0
movq %rax, 0x1c8(%rsp)
movq 0x1d0(%rsp), %rdi
callq 0x10c00
movq %rax, 0x1c0(%rsp)
leaq 0x1c8(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x10c30
testb $0x1, %al
jne 0x7f27a
jmp 0x7f7c7
leaq 0x1c8(%rsp), %rdi
callq 0x10c70
movq (%rax), %rax
movq %rax, 0x1b8(%rsp)
movq 0x1b8(%rsp), %rdi
addq $0x30, %rdi
callq 0xcaa0
movq %rax, 0x1b0(%rsp)
movq 0x1b8(%rsp), %rdi
addq $0x30, %rdi
callq 0xcad0
movq %rax, 0x1a8(%rsp)
leaq 0x1b0(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0xcb00
testb $0x1, %al
jne 0x7f2e2
jmp 0x7f7b3
leaq 0x1b0(%rsp), %rdi
callq 0xf5c0
movq (%rax), %rax
movq %rax, 0x88(%rsp)
cmpq $0x0, %rax
je 0x7f329
movq 0x88(%rsp), %rdi
leaq 0xcb279(%rip), %rsi     # 0x14a588
leaq 0xcb25a(%rip), %rdx     # 0x14a570
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x80(%rsp)
jmp 0x7f335
xorl %eax, %eax
movq %rax, 0x80(%rsp)
jmp 0x7f335
movq 0x80(%rsp), %rax
movq %rax, 0x1a0(%rsp)
cmpq $0x0, 0x1a0(%rsp)
je 0x7f7a1
movq 0x1a0(%rsp), %rdi
addq $0x18, %rdi
callq 0x80ae0
movq 0x1a0(%rsp), %rax
movl 0x10(%rax), %eax
movl %eax, 0x19c(%rsp)
movq 0x1f8(%rsp), %rax
addq $0xd8, %rax
movq %rax, 0x190(%rsp)
movq 0x190(%rsp), %rdi
callq 0x80b00
movq %rax, 0x188(%rsp)
movq 0x190(%rsp), %rdi
callq 0x80ab0
movq %rax, 0x180(%rsp)
leaq 0x188(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x80a50
testb $0x1, %al
jne 0x7f3d5
jmp 0x7f478
leaq 0x188(%rsp), %rdi
callq 0x80b30
movl (%rax), %eax
movl %eax, 0x17c(%rsp)
movq 0x1a0(%rsp), %rax
addq $0x18, %rax
movq %rax, 0x70(%rsp)
movl $0x40, %edi
callq 0x8340
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x78(%rsp)
movl 0x17c(%rsp), %esi
callq 0x77bb0
jmp 0x7f41f
movq 0x70(%rsp), %rdi
movq 0x78(%rsp), %rax
movq %rax, 0x170(%rsp)
leaq 0x170(%rsp), %rsi
callq 0x7d230
leaq 0x188(%rsp), %rdi
callq 0x80b50
jmp 0x7f3b7
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x168(%rsp)
movl %eax, 0x164(%rsp)
movl $0x40, %esi
callq 0x8350
jmp 0x7fd34
movq 0x1a0(%rsp), %rax
cmpl $0x0, 0x14(%rax)
jne 0x7f4f7
movq 0x1a0(%rsp), %rdi
addq $0x18, %rdi
callq 0xcd40
testb $0x1, %al
jne 0x7f49d
jmp 0x7f4f2
movq 0x1b8(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x68(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0xcb80
movq 0x68(%rsp), %rdi
movq 0x150(%rsp), %rsi
callq 0x80b80
movq %rax, 0x158(%rsp)
movq 0x158(%rsp), %rax
movq %rax, 0x1b0(%rsp)
jmp 0x7f2ab
jmp 0x7f792
testb $0x1, 0x1f3(%rsp)
je 0x7f591
movq 0x1a0(%rsp), %rdi
addq $0x18, %rdi
callq 0x7ec20
movq (%rax), %rax
cmpl $0xe, 0x38(%rax)
je 0x7f576
movq 0xccac2(%rip), %rdi     # 0x14bfe8
leaq 0x7abcb(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7e21a(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7be9f(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0x2e, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcca19(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
movq 0x1a0(%rsp), %rdi
addq $0x18, %rdi
callq 0x7ec20
movq (%rax), %rax
movl $0xf, 0x38(%rax)
movq 0x1a0(%rsp), %rdi
addq $0x18, %rdi
callq 0xcd40
testb $0x1, %al
jne 0x7f5a8
jmp 0x7f5fa
movq 0x1b8(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x60(%rsp)
leaq 0x140(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0xcb80
movq 0x60(%rsp), %rdi
movq 0x140(%rsp), %rsi
callq 0x80b80
movq %rax, 0x148(%rsp)
movq 0x148(%rsp), %rax
movq %rax, 0x1b0(%rsp)
jmp 0x7f607
leaq 0x1b0(%rsp), %rdi
callq 0xf8f0
testb $0x1, 0x1f3(%rsp)
jne 0x7f78d
movq 0x1b8(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x40(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0xcb80
movl $0x40, %edi
callq 0x8340
movq %rax, 0x48(%rsp)
movb $0x1, 0x106(%rsp)
movl 0x19c(%rsp), %eax
movl %eax, 0x54(%rsp)
leaq 0x107(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x8680
movq 0x58(%rsp), %rdx
leaq 0x7aae3(%rip), %rsi     # 0xfa15e
leaq 0x108(%rsp), %rdi
callq 0xc570
jmp 0x7f68a
movl 0x54(%rsp), %ecx
movq 0x48(%rsp), %rdi
movq 0x1b8(%rsp), %r9
movq %rsp, %rax
movl $0x0, (%rax)
xorl %esi, %esi
movl $0x1, %edx
leaq 0x108(%rsp), %r8
callq 0x80bf0
jmp 0x7f6ba
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rax
movb $0x0, 0x106(%rsp)
movq %rax, 0x128(%rsp)
movq 0x130(%rsp), %rsi
leaq 0x128(%rsp), %rdx
callq 0xcb40
movq %rax, 0x38(%rsp)
jmp 0x7f6f0
movq 0x38(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rax
movq %rax, 0x1b0(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x8728
leaq 0x107(%rsp), %rdi
callq 0x83c0
jmp 0x7f78d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x168(%rsp)
movl %eax, 0x164(%rsp)
jmp 0x7f760
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x168(%rsp)
movl %eax, 0x164(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x8728
leaq 0x107(%rsp), %rdi
callq 0x83c0
testb $0x1, 0x106(%rsp)
jne 0x7f779
jmp 0x7f788
movq 0x48(%rsp), %rdi
movl $0x40, %esi
callq 0x8350
jmp 0x7fd34
jmp 0x7f2ab
leaq 0x1b0(%rsp), %rdi
callq 0xf8f0
jmp 0x7f7ae
leaq 0x1b0(%rsp), %rdi
callq 0xf8f0
jmp 0x7f2ab
jmp 0x7f7b5
leaq 0x1c8(%rsp), %rdi
callq 0x10c80
jmp 0x7f25c
leaq 0x1f8(%rsp), %rax
movq %rax, 0xf8(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0x68, %rdi
callq 0x80cb0
movq %rax, 0xf0(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0x68, %rdi
callq 0x80d00
movq %rax, 0xe8(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x80ce0
testb $0x1, %al
jne 0x7f827
jmp 0x7f953
leaq 0xf0(%rsp), %rdi
callq 0x80d30
movq (%rax), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0x7f865
movq 0x30(%rsp), %rdi
leaq 0xcad3a(%rip), %rsi     # 0x14a588
leaq 0xcad03(%rip), %rdx     # 0x14a558
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x28(%rsp)
jmp 0x7f86e
xorl %eax, %eax
movq %rax, 0x28(%rsp)
jmp 0x7f86e
movq 0x28(%rsp), %rax
movq %rax, 0xe0(%rsp)
xorl %eax, %eax
cmpq 0xe0(%rsp), %rax
je 0x7f898
movq 0xe0(%rsp), %rdi
callq 0x80d50
testb $0x1, %al
jne 0x7f8ef
movq 0xcc749(%rip), %rdi     # 0x14bfe8
leaq 0x7a852(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7dea1(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7bb26(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0x66, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcc6a0(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
movl 0x1f4(%rsp), %ecx
movq 0xe0(%rsp), %rax
addl 0x40(%rax), %ecx
movl %ecx, 0x40(%rax)
movq 0xe0(%rsp), %rax
movl 0x40(%rax), %edi
callq 0x77b80
testb $0x1, %al
jne 0x7f91a
jmp 0x7f93f
movq 0xf0(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rsi
leaq 0xf8(%rsp), %rdi
callq 0x7fd50
jmp 0x7f941
leaq 0xf0(%rsp), %rdi
callq 0x80d60
jmp 0x7f7f0
movq 0x1f8(%rsp), %rdi
addq $0x68, %rdi
callq 0x80d90
leaq 0x1f8(%rsp), %rax
movq %rax, 0xd0(%rsp)
leaq 0x1f8(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0xa0, %rdi
callq 0x80cb0
movq %rax, 0xc0(%rsp)
movq 0x1f8(%rsp), %rdi
addq $0xa0, %rdi
callq 0x80d00
movq %rax, 0xb8(%rsp)
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x80ce0
testb $0x1, %al
jne 0x7f9da
jmp 0x7fd18
leaq 0xc0(%rsp), %rdi
callq 0x80d30
movq (%rax), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x7fa18
movq 0x20(%rsp), %rdi
leaq 0xcab87(%rip), %rsi     # 0x14a588
leaq 0xcaac0(%rip), %rdx     # 0x14a4c8
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x18(%rsp)
jmp 0x7fa21
xorl %eax, %eax
movq %rax, 0x18(%rsp)
jmp 0x7fa21
movq 0x18(%rsp), %rax
movq %rax, 0xb0(%rsp)
cmpq $0x0, 0xb0(%rsp)
je 0x7fb8d
movq 0xb0(%rsp), %rax
movq 0x20(%rax), %rax
testb $0x1, (%rax)
jne 0x7faa5
movq 0xcc593(%rip), %rdi     # 0x14bfe8
leaq 0x7a69c(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7dceb(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7b970(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0xaf, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcc4ea(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
movq 0xb0(%rsp), %rax
testb $0x1, 0x14(%rax)
je 0x7fb0a
movq 0xcc52e(%rip), %rdi     # 0x14bfe8
leaq 0x7a637(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7dc86(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7b90b(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0xb1, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcc485(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
movq 0x1f8(%rsp), %rax
movl 0x2c(%rax), %ecx
movq 0xb0(%rsp), %rax
movq 0x20(%rax), %rax
movl %ecx, 0x4(%rax)
movq 0xb0(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x4(%rax), %edi
callq 0xa450
testb $0x1, %al
jne 0x7fb63
movq 0xc0(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0xa8(%rsp), %rsi
leaq 0xd0(%rsp), %rdi
callq 0x80160
jmp 0x7fb88
movq 0xc0(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x80510
jmp 0x7fd04
leaq 0xc0(%rsp), %rdi
callq 0x80d30
movq (%rax), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x7fbcb
movq 0x10(%rsp), %rdi
leaq 0xca9d4(%rip), %rsi     # 0x14a588
leaq 0xca99d(%rip), %rdx     # 0x14a558
xorl %eax, %eax
movl %eax, %ecx
callq 0x8410
movq %rax, 0x8(%rsp)
jmp 0x7fbd4
xorl %eax, %eax
movq %rax, 0x8(%rsp)
jmp 0x7fbd4
movq 0x8(%rsp), %rax
movq %rax, 0x98(%rsp)
cmpq $0x0, 0x98(%rsp)
je 0x7fcab
movq 0x98(%rsp), %rdi
callq 0x80d50
testb $0x1, %al
jne 0x7fc58
movq 0xcc3e0(%rip), %rdi     # 0x14bfe8
leaq 0x7a4e9(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7db38(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7b7bd(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0xbd, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcc337(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
movq 0x1f8(%rsp), %rax
movl 0x2c(%rax), %ecx
movq 0x98(%rsp), %rax
movl %ecx, 0x40(%rax)
movq 0x98(%rsp), %rax
movl 0x40(%rax), %edi
callq 0xa450
testb $0x1, %al
jne 0x7fc84
jmp 0x7fca9
movq 0xc0(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x80510
jmp 0x7fd02
movq 0xcc336(%rip), %rdi     # 0x14bfe8
leaq 0x7a43f(%rip), %rsi     # 0xfa0f8
callq 0x8330
movq %rax, %rdi
leaq 0x7da8e(%rip), %rsi     # 0xfd756
callq 0x8330
movq %rax, %rdi
leaq 0x7b713(%rip), %rsi     # 0xfb3ea
callq 0x8330
movq %rax, %rdi
movl $0xc4, %esi
callq 0x8650
movq %rax, %rdi
movq 0xcc28d(%rip), %rsi     # 0x14bf80
callq 0x8380
movl $0xff, %edi
callq 0x8460
jmp 0x7fd04
jmp 0x7fd06
leaq 0xc0(%rsp), %rdi
callq 0x80d60
jmp 0x7f9a0
movq 0x1f8(%rsp), %rdi
addq $0xa0, %rdi
callq 0x80d90
addq $0x208, %rsp            # imm = 0x208
retq
movq 0x168(%rsp), %rdi
callq 0x8670
nopw %cs:(%rax,%rax)