// File: CMU-SAFARI[P]ramulator/src/Cache.cpp
// Function: ramulator::Cache::invalidate(long)
std::pair<long, bool> Cache::invalidate(long addr) {
  long delay = latency_each[int(level)];
  bool dirty = false;

  auto& lines = get_lines(addr);
  if (lines.size() == 0) {
    // The line of this address doesn't exist.
    return make_pair(0, false);
  }
  auto line = find_if(lines.begin(), lines.end(),
      [addr, this](Line l){return (l.tag == get_tag(addr));});

  // If the line is in this level cache, then erase it from
  // the buffer.
  if (line != lines.end()) {
    assert(!line->lock);
    debug("invalidate %lx @ level %d", addr, int(level));
    lines.erase(line);
  } else {
    // If it's not in current level, then no need to go up.
    return make_pair(delay, false);
  }

  if (higher_cache.size()) {
    long max_delay = delay;
    for (auto hc : higher_cache) {
      auto result = hc->invalidate(addr);
      if (result.second) {
        max_delay = max(max_delay, delay + result.first * 2);
      } else {
        max_delay = max(max_delay, delay + result.first);
      }
      dirty = dirty || line->dirty || result.second;
    }
    delay = max_delay;
  } else {
    dirty = line->dirty;
  }
  return make_pair(delay, dirty);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0x18(%rbp)
movq %rsi, -0x20(%rbp)
movq -0x18(%rbp), %rdi
movq %rdi, -0x110(%rbp)
movslq 0x5f0(%rdi), %rax
movslq 0x624(%rdi,%rax,4), %rax
movq %rax, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
movq -0x20(%rbp), %rsi
callq 0x1800e0
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x180860
cmpq $0x0, %rax
jne 0x17e237
movl $0x0, -0x44(%rbp)
movb $0x0, -0x45(%rbp)
leaq -0x44(%rbp), %rdi
leaq -0x45(%rbp), %rsi
callq 0x180890
movl %eax, %ecx
movl %ecx, -0x40(%rbp)
shrq $0x20, %rax
movb %al, -0x3c(%rbp)
leaq -0x10(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x1808c0
jmp 0x17e519
movq -0x38(%rbp), %rdi
callq 0x180800
movq %rax, -0x58(%rbp)
movq -0x38(%rbp), %rdi
callq 0x180690
movq %rax, %rcx
movq -0x110(%rbp), %rax
movq %rcx, -0x60(%rbp)
movq -0x20(%rbp), %rcx
movq %rcx, -0x70(%rbp)
movq %rax, -0x68(%rbp)
movq -0x58(%rbp), %rdi
movq -0x60(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq -0x68(%rbp), %rcx
callq 0x17e530
movq %rax, -0x50(%rbp)
movq -0x38(%rbp), %rdi
callq 0x180690
movq %rax, -0x78(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x180830
testb $0x1, %al
jne 0x17e2a0
jmp 0x17e306
leaq -0x50(%rbp), %rdi
callq 0x180300
movb 0x10(%rax), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x17e2b4
jmp 0x17e2b6
jmp 0x17e2d5
leaq 0xdcd86(%rip), %rdi     # 0x25b043
leaq 0xdca67(%rip), %rsi     # 0x25ad2b
movl $0xe6, %edx
leaq 0xdcd7f(%rip), %rcx     # 0x25b04f
callq 0xc280
movq -0x38(%rbp), %rax
movq %rax, -0x118(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x1803c0
movq -0x118(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x180370
movq %rax, -0x88(%rbp)
jmp 0x17e343
movb $0x0, -0x89(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x89(%rbp), %rsi
callq 0x1808f0
movb %dl, -0x98(%rbp)
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0x10(%rbp)
movb -0x98(%rbp), %al
movb %al, -0x8(%rbp)
jmp 0x17e519
movq -0x110(%rbp), %rdi
addq $0x640, %rdi            # imm = 0x640
callq 0x180920
cmpq $0x0, %rax
je 0x17e4da
movq -0x110(%rbp), %rax
movq -0x28(%rbp), %rcx
movq %rcx, -0xa8(%rbp)
addq $0x640, %rax            # imm = 0x640
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x180940
movq %rax, -0xb8(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x180970
movq %rax, -0xc0(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x1809a0
testb $0x1, %al
jne 0x17e3c1
jmp 0x17e4cd
leaq -0xb8(%rbp), %rdi
callq 0x1809e0
movq (%rax), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x17e1b0
movb %dl, -0xe0(%rbp)
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0xd8(%rbp)
movb -0xe0(%rbp), %al
movb %al, -0xd0(%rbp)
testb $0x1, -0xd0(%rbp)
je 0x17e44e
movq -0x28(%rbp), %rax
movq -0xd8(%rbp), %rcx
shlq %rcx
addq %rcx, %rax
movq %rax, -0xf0(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x45510
movq (%rax), %rax
movq %rax, -0xa8(%rbp)
jmp 0x17e47d
movq -0x28(%rbp), %rax
addq -0xd8(%rbp), %rax
movq %rax, -0xf8(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x45510
movq (%rax), %rax
movq %rax, -0xa8(%rbp)
movb $0x1, %al
testb $0x1, -0x29(%rbp)
movb %al, -0x119(%rbp)
jne 0x17e4b1
leaq -0x50(%rbp), %rdi
callq 0x180300
movq %rax, %rcx
movb $0x1, %al
testb $0x1, 0x11(%rcx)
movb %al, -0x119(%rbp)
jne 0x17e4b1
movb -0xd0(%rbp), %al
movb %al, -0x119(%rbp)
movb -0x119(%rbp), %al
andb $0x1, %al
movb %al, -0x29(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x180a00
jmp 0x17e3a5
movq -0xa8(%rbp), %rax
movq %rax, -0x28(%rbp)
jmp 0x17e4eb
leaq -0x50(%rbp), %rdi
callq 0x180300
movb 0x11(%rax), %al
andb $0x1, %al
movb %al, -0x29(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x29(%rbp), %rsi
callq 0x180a20
movb %dl, -0x100(%rbp)
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0x10(%rbp)
movb -0x100(%rbp), %al
movb %al, -0x8(%rbp)
movq -0x10(%rbp), %rax
movb -0x8(%rbp), %dl
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
nopl (%rax)