// File: jmbjorndalen[P]Malbolge-gen/mbolge-gen.cpp
// Function: MBSearch::getMem(unsigned short)
unsigned short MBSearch::getMem(unsigned short addr)
{
    if (addr >= MAX_TRIT)
    { 
	//std::cerr << "MBSearch::getMem called with addr " << addr << " with is outside legal bounds\n";
	throw ILLEGAL_ADDR_EXCEPTION; // program made an illegal reference, which will not fare well with the original interpreter, so abort this branch
    }
    if (addr >= maxAllowedProgLen) 
	throw MAX_APLEN_EXCEPTION;
    
    if (addr > highestAddrRead)
	highestAddrRead = addr; 
    
    MBMemory::iterator pos = mem.find(addr); 
    if (pos != mem.end())
	return pos->second;  // already have it

    // Reading a new memory location that has never been visited before. 
    // First, check whether we have branched out too deeply before omitting chars
    ++odepth; 
    if (odepth > MAX_OSEARCH)
	throw BRANCH_DEPTH_EXCEPTION; 

    // Simply fill in the first possible OP, then store this object on the stack, allowing the main loop to 
    // pick it up again and modify it later (restarting the object with the next possible instruction). 
    curNewMem = addr;         // keep track of addr, so main loop can modify this instruction
    curNewOP  = 0;            // we're currently using the first one
    orig[addr] = mem[addr]  = encode_op(MalbolgeOps[curNewOP], addr);
    ++nFetches;

    // Store a copy of this one on the stack
    globalStack.push(new MBSearch(*this));     // default copy constructor is ok

    return mem[addr];
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movw %si, %ax
movq %rdi, -0x10(%rbp)
movw %ax, -0x12(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x58(%rbp)
movzwl -0x12(%rbp), %eax
cmpl $0xe6a9, %eax           # imm = 0xE6A9
jl 0x404819
movl $0x4, %edi
callq 0x4096b0
movq %rax, %rdi
movl $0x2b, (%rdi)
leaq 0x1ea1a0(%rip), %rsi    # 0x5ee9b0
xorl %eax, %eax
movl %eax, %edx
callq 0x40a700
movzwl -0x12(%rbp), %eax
cmpl 0x1f190d(%rip), %eax    # 0x5f6130
jl 0x404848
movl $0x4, %edi
callq 0x4096b0
movq %rax, %rdi
movl $0x2c, (%rdi)
leaq 0x1ea171(%rip), %rsi    # 0x5ee9b0
xorl %eax, %eax
movl %eax, %edx
callq 0x40a700
movq -0x58(%rbp), %rcx
movzwl -0x12(%rbp), %eax
cmpl 0x78(%rcx), %eax
jle 0x404860
movq -0x58(%rbp), %rax
movzwl -0x12(%rbp), %ecx
movl %ecx, 0x78(%rax)
movq -0x58(%rbp), %rdi
addq $0x18, %rdi
movzwl -0x12(%rbp), %eax
movl %eax, -0x24(%rbp)
leaq -0x24(%rbp), %rsi
callq 0x405c50
movq -0x58(%rbp), %rdi
movq %rax, -0x20(%rbp)
addq $0x18, %rdi
callq 0x405cb0
movq %rax, -0x30(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x405c80
testb $0x1, %al
jne 0x4048a0
jmp 0x4048b5
leaq -0x20(%rbp), %rdi
callq 0x405ce0
movl 0x4(%rax), %eax
movw %ax, -0x2(%rbp)
jmp 0x4049d7
movq -0x58(%rbp), %rax
movl 0x14(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x14(%rax)
cmpl $0xa, 0x14(%rax)
jle 0x4048eb
movl $0x4, %edi
callq 0x4096b0
movq %rax, %rdi
movl $0x2a, (%rdi)
leaq 0x1ea0ce(%rip), %rsi    # 0x5ee9b0
xorl %eax, %eax
movl %eax, %edx
callq 0x40a700
movq -0x58(%rbp), %rax
movzwl -0x12(%rbp), %ecx
movl %ecx, 0xc(%rax)
movl $0x0, 0x10(%rax)
movslq 0x10(%rax), %rcx
leaq 0x1f1838(%rip), %rax    # 0x5f6140
movzwl (%rax,%rcx,2), %edi
movzwl -0x12(%rbp), %esi
callq 0x4049f0
movq -0x58(%rbp), %rdi
movzwl %ax, %eax
movl %eax, -0x64(%rbp)
addq $0x18, %rdi
movzwl -0x12(%rbp), %eax
movl %eax, -0x34(%rbp)
leaq -0x34(%rbp), %rsi
callq 0x405d00
movl -0x64(%rbp), %ecx
movq -0x58(%rbp), %rdi
movl %ecx, (%rax)
addq $0x48, %rdi
movzwl -0x12(%rbp), %eax
movl %eax, -0x38(%rbp)
leaq -0x38(%rbp), %rsi
callq 0x405d00
movl -0x64(%rbp), %edx
movq %rax, %rcx
movq -0x58(%rbp), %rax
movl %edx, (%rcx)
movl 0x8(%rax), %ecx
incl %ecx
movl %ecx, 0x8(%rax)
movl $0xa8, %edi
callq 0x40a800
movq -0x58(%rbp), %rsi
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x60(%rbp)
callq 0x405e10
jmp 0x404983
movq -0x60(%rbp), %rax
movq %rax, -0x40(%rbp)
leaq 0x1f3be6(%rip), %rdi    # 0x5f8578
leaq -0x40(%rbp), %rsi
callq 0x405de0
movq -0x58(%rbp), %rdi
addq $0x18, %rdi
movzwl -0x12(%rbp), %eax
movl %eax, -0x50(%rbp)
leaq -0x50(%rbp), %rsi
callq 0x405d00
movl (%rax), %eax
movw %ax, -0x2(%rbp)
jmp 0x4049d7
movq -0x60(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl $0xa8, %esi
callq 0x4093d0
jmp 0x4049e1
movw -0x2(%rbp), %ax
addq $0x70, %rsp
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x4b4f90
nopw (%rax,%rax)