// File: /workspace/github_c_makefile_star2_O0/wuxb45[P]SLB/lib1.c
// Function: rcache_create
struct rcache *
rcache_create(const u64 nr_mb, rcache_match_func match, rcache_hash_func hash_key, rcache_hash_func hash_kv)
{
  debug_assert(ICACHE_ENTRY_NR == 15 || ICACHE_ENTRY_NR == 7);
  debug_assert((sizeof(struct __icache_slot) % 64) == 0);
  debug_assert((sizeof(struct __icache_hist) % 8) == 0);

  if (match == NULL || hash_key == NULL || hash_kv == NULL) {
    return NULL;
  }

  struct rcache * const cache = (typeof(cache))malloc(sizeof(*cache));
  memset(cache, 0, sizeof(*cache));

  for (u64 i = 0; i < KVMAP_HLOCK_NR; i++) {
    spinlock_init(&(cache->hlocks[i]));
  }

  const u64 table_size = nr_mb << 20;
  const u64 nr_slots = table_size / sizeof(cache->table[0]);
  struct __icache_slot * const table = pages_alloc_best(table_size, false, &(cache->slots_alloc_size));
  if (table == NULL) {
    free(cache);
    return NULL;
  }
  debug_assert(nr_slots % KVMAP_HLOCK_NR == 0);
  cache->table = table;
  cache->nr_slots = nr_slots;

  const u64 nr_hists = nr_slots * 16;
  const u64 hists_size = nr_hists * sizeof(cache->hists[0]);
  struct __icache_hist * const hists = pages_alloc_best(hists_size, false, &(cache->hists_alloc_size));
  if (hists == NULL) {
    pages_unmap(table, cache->slots_alloc_size);
    free(cache);
    return NULL;
  }

  cache->nr_hists = nr_hists;
  cache->hists = hists;

  cache->match = match;
  cache->hash_key = hash_key;
  cache->hash_kv = hash_kv;
  return cache;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movl $0x1, %edi
callq 0x7640
movl $0x1, %edi
callq 0x7640
movl $0x1, %edi
callq 0x7640
cmpq $0x0, -0x18(%rbp)
je 0x15dab
cmpq $0x0, -0x20(%rbp)
je 0x15dab
cmpq $0x0, -0x28(%rbp)
jne 0x15db8
movq $0x0, -0x8(%rbp)
jmp 0x15f46
movl $0x10080, %edi          # imm = 0x10080
callq 0x6380
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
xorl %esi, %esi
movl $0x10080, %edx          # imm = 0x10080
callq 0x6200
movq $0x0, -0x38(%rbp)
cmpq $0x400, -0x38(%rbp)     # imm = 0x400
jae 0x15e0a
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq $0x6, %rax
addq %rax, %rdi
callq 0x6e30
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x15dde
movq -0x10(%rbp), %rax
shlq $0x14, %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
shrq $0x6, %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
movq -0x30(%rbp), %rdx
addq $0x10040, %rdx          # imm = 0x10040
xorl %esi, %esi
callq 0x8d40
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x15e59
movq -0x30(%rbp), %rdi
callq 0x6060
movq $0x0, -0x8(%rbp)
jmp 0x15f46
movq -0x48(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
cmpq $0x0, %rax
sete %al
movzbl %al, %edi
andl $0x1, %edi
callq 0x7640
movq -0x50(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10048(%rax)
movq -0x48(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10038(%rax)
movq -0x48(%rbp), %rax
shlq $0x4, %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
shlq $0x4, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rdx
addq $0x10058, %rdx          # imm = 0x10058
xorl %esi, %esi
callq 0x8d40
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
jne 0x15ef3
movq -0x50(%rbp), %rdi
movq -0x30(%rbp), %rax
movq 0x10040(%rax), %rsi
callq 0x8c10
movq -0x30(%rbp), %rdi
callq 0x6060
movq $0x0, -0x8(%rbp)
jmp 0x15f46
movq -0x58(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10050(%rax)
movq -0x68(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10060(%rax)
movq -0x18(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10068(%rax)
movq -0x20(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10070(%rax)
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10078(%rax)
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq