// File: baziotis[P]minijava-cpp/alloc.cpp
// Function: allocate(unsigned long, MEM)
void *allocate(size_t n, MEM enum_ar) {
    int ar = (int) enum_ar;
    block_t *ap = arena[ar];
    assert(ap);
    
    n = roundup(n, ALIGN_SIZE);
    if (n > (ap->limit - ap->avail)) {
        ap->next = freeblocks;
        if (ap->next != NULL) {
            do {
                freeblocks = freeblocks->next;
                ap = ap->next;
            } while(n > (ap->limit - ap->avail));
        } else {  // Need to allocate
            size_t sz = sizeof(block_t) + n + roundup(BLOCK_TAIL, ALIGN_SIZE);
            // Set `next` to the new block first so that if this is the first block
            // in the arena `ar`, then first[ar].next will be set to this new block.
            ap->next = (block_t *)malloc(sz);
            ap = ap->next;
            assert(ap && "Insufficient memory");
            ap->limit = (uint8_t*)ap + sz;
        }
        ap->avail = (uint8_t*)(ap + 1);
        ap->next = NULL;
        arena[ar] = ap;
    }
    ap->avail += n;
    void *ret = (void*)(ap->avail - n);
    assert(ret);
    return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x10(%rbp)
movslq -0x10(%rbp), %rcx
leaq 0x21da0(%rip), %rax     # 0x24100
movq (%rax,%rcx,8), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x2371
jmp 0x2390
leaq 0x1a9f8(%rip), %rdi     # 0x1cd70
leaq 0x16c85(%rip), %rsi     # 0x19004
movl $0x41, %edx
leaq 0x16c83(%rip), %rcx     # 0x1900e
callq 0x20d0
movq -0x8(%rbp), %rdi
movl $0x8, %esi
callq 0x2540
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq -0x18(%rbp), %rdx
movq 0x8(%rdx), %rdx
subq %rdx, %rcx
cmpq %rcx, %rax
jbe 0x24db
movq 0x2223f(%rip), %rcx     # 0x24608
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
je 0x2419
jmp 0x23dc
movq 0x22225(%rip), %rax     # 0x24608
movq (%rax), %rax
movq %rax, 0x2221b(%rip)     # 0x24608
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq -0x18(%rbp), %rcx
movq 0x10(%rcx), %rcx
movq -0x18(%rbp), %rdx
movq 0x8(%rdx), %rdx
subq %rdx, %rcx
cmpq %rcx, %rax
ja 0x23dc
jmp 0x24ad
movq -0x8(%rbp), %rax
addq $0x18, %rax
movq %rax, -0x38(%rbp)
movl $0x2800, %edi           # imm = 0x2800
movl $0x8, %esi
callq 0x2540
movq %rax, %rcx
movq -0x38(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
callq 0x2160
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x18(%rbp)
movb %al, -0x29(%rbp)
je 0x2473
movb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x2473
movb -0x29(%rbp), %al
testb $0x1, %al
jne 0x247c
jmp 0x247e
jmp 0x249d
leaq 0x16bb9(%rip), %rdi     # 0x1903e
leaq 0x16b78(%rip), %rsi     # 0x19004
movl $0x51, %edx
leaq 0x16b76(%rip), %rcx     # 0x1900e
callq 0x20d0
movq -0x18(%rbp), %rcx
addq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x18(%rbp), %rcx
addq $0x18, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq $0x0, (%rax)
movq -0x18(%rbp), %rdx
movslq -0x10(%rbp), %rcx
leaq 0x21c29(%rip), %rax     # 0x24100
movq %rdx, (%rax,%rcx,8)
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rax
addq 0x8(%rax), %rcx
movq %rcx, 0x8(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
xorl %ecx, %ecx
subq -0x8(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x2509
jmp 0x2528
leaq 0x16b4a(%rip), %rdi     # 0x1905a
leaq 0x16aed(%rip), %rsi     # 0x19004
movl $0x5a, %edx
leaq 0x16aeb(%rip), %rcx     # 0x1900e
callq 0x20d0
movq -0x28(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)