// File: CMU-SAFARI[P]ramulator/src/Cache.cpp
// Function: ramulator::Cache::evict(std::__cxx11::list<ramulator::Cache::Line, std::allocator<ramulator::Cache::Line>>*, std::_List_iterator<ramulator::Cache::Line>)
void Cache::evict(std::list<Line>* lines,
    std::list<Line>::iterator victim) {
  debug("level %d miss evict victim %lx", int(level), victim->addr);
  cache_eviction++;

  long addr = victim->addr;
  long invalidate_time = 0;
  bool dirty = victim->dirty;

  // First invalidate the victim line in higher level.
  if (higher_cache.size()) {
    for (auto hc : higher_cache) {
      auto result = hc->invalidate(addr);
      invalidate_time = max(invalidate_time,
          result.first + (result.second ? latency_each[int(level)] : 0));
      dirty = dirty || result.second || victim->dirty;
    }
  }

  debug("invalidate delay: %ld, dirty: %s", invalidate_time,
      dirty ? "true" : "false");

  if (!is_last_level) {
    // not LLC eviction
    assert(lower_cache != nullptr);
    lower_cache->evictline(addr, dirty);
  } else {
    // LLC eviction
    if (dirty) {
      Request write_req(addr, Request::Type::WRITE);
      cachesys->wait_list.push_back(make_pair(
          cachesys->clk + invalidate_time + latency[int(level)],
          write_req));

      debug("inject one write request to memory system "
          "addr %lx, invalidate time %ld, issue time %ld",
          write_req.addr, invalidate_time,
          cachesys->clk + invalidate_time + latency[int(level)]);
    }
  }

  lines->erase(victim);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdx, -0x8(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x170(%rbp)
addq $0x1c8, %rdi            # imm = 0x1C8
xorl %esi, %esi
callq 0x40970
leaq -0x8(%rbp), %rdi
callq 0x180300
movq (%rax), %rax
movq %rax, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
leaq -0x8(%rbp), %rdi
callq 0x180300
movq -0x170(%rbp), %rdi
movb 0x11(%rax), %al
andb $0x1, %al
movb %al, -0x29(%rbp)
addq $0x640, %rdi            # imm = 0x640
callq 0x180920
cmpq $0x0, %rax
je 0x17e735
movq -0x170(%rbp), %rax
addq $0x640, %rax            # imm = 0x640
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x180940
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x180970
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x1809a0
testb $0x1, %al
jne 0x17e657
jmp 0x17e733
leaq -0x40(%rbp), %rdi
callq 0x1809e0
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x17e1b0
movb %dl, -0x68(%rbp)
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x60(%rbp)
movb -0x68(%rbp), %al
movb %al, -0x58(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x178(%rbp)
testb $0x1, -0x58(%rbp)
je 0x17e6b7
movq -0x170(%rbp), %rax
movslq 0x5f0(%rax), %rcx
movl 0x624(%rax,%rcx,4), %eax
movl %eax, -0x17c(%rbp)
jmp 0x17e6c1
xorl %eax, %eax
movl %eax, -0x17c(%rbp)
jmp 0x17e6c1
movq -0x178(%rbp), %rax
movl -0x17c(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x45510
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movb $0x1, %al
testb $0x1, -0x29(%rbp)
movb %al, -0x17d(%rbp)
jne 0x17e71a
movb $0x1, %al
testb $0x1, -0x58(%rbp)
movb %al, -0x17d(%rbp)
jne 0x17e71a
leaq -0x8(%rbp), %rdi
callq 0x180300
movb 0x11(%rax), %al
movb %al, -0x17d(%rbp)
movb -0x17d(%rbp), %al
andb $0x1, %al
movb %al, -0x29(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x180a00
jmp 0x17e641
jmp 0x17e735
movq -0x170(%rbp), %rax
testb $0x1, 0x661(%rax)
jne 0x17e79b
movq -0x170(%rbp), %rax
cmpq $0x0, 0x658(%rax)
je 0x17e758
jmp 0x17e777
leaq 0xdc929(%rip), %rdi     # 0x25b088
leaq 0xdc5c5(%rip), %rsi     # 0x25ad2b
movl $0x119, %edx            # imm = 0x119
leaq 0xdc92d(%rip), %rcx     # 0x25b09f
callq 0xc280
movq -0x170(%rbp), %rax
movq 0x658(%rax), %rdi
movq -0x20(%rbp), %rsi
movb -0x29(%rbp), %al
andb $0x1, %al
movzbl %al, %edx
callq 0x17df40
jmp 0x17e8a8
testb $0x1, -0x29(%rbp)
je 0x17e8a6
movq -0x20(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
movq %rdi, -0x188(%rbp)
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x180a50
movq -0x170(%rbp), %rdi
addq $0x630, %rdi            # imm = 0x630
movq %rdi, -0x198(%rbp)
callq 0x180090
movq -0x198(%rbp), %rdi
movq %rax, -0x190(%rbp)
callq 0x180090
movq -0x170(%rbp), %rcx
movq -0x188(%rbp), %rdx
movq 0x50(%rax), %rax
movq -0x28(%rbp), %rsi
addq %rsi, %rax
movslq 0x5f0(%rcx), %rsi
movslq 0x618(%rcx,%rsi,4), %rcx
addq %rcx, %rax
movq %rax, -0x148(%rbp)
leaq -0x140(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0x180420
jmp 0x17e837
movq -0x190(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0x1803e0
jmp 0x17e84c
leaq -0x140(%rbp), %rdi
callq 0x180460
leaq -0xd8(%rbp), %rdi
callq 0x36780
jmp 0x17e8a6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x150(%rbp)
movl %eax, -0x154(%rbp)
jmp 0x17e898
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x150(%rbp)
movl %eax, -0x154(%rbp)
leaq -0x140(%rbp), %rdi
callq 0x180460
leaq -0xd8(%rbp), %rdi
callq 0x36780
jmp 0x17e8e6
jmp 0x17e8a8
movq -0x18(%rbp), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x160(%rbp), %rdi
leaq -0x8(%rbp), %rsi
callq 0x1803c0
movq -0x1a0(%rbp), %rdi
movq -0x160(%rbp), %rsi
callq 0x180370
movq %rax, -0x168(%rbp)
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
movq -0x150(%rbp), %rdi
callq 0xc5d0
nopw %cs:(%rax,%rax)