// File: jmbjorndalen[P]Malbolge-gen/mbolge-gen.cpp
// Function: MBSearch::doExec()
int MBSearch::doExec()
{
    const long long MAX_ITERS = 100000000LL; 
    long long iters; 
    try
    { 
	for (iters = 0; iters < MAX_ITERS; iters++) // Guard againt infinite loops
	{ 
	    switch(iStage) { 
	    case STAGE_IFETCH:    // instruction fetch
		 instr = getMem(Rc); 
		// Check for infinity: trying to execute values outside the 94-range causes an infinite loop!
		if (instr < 33 || instr > 126) 
		    return RES_INFINITE_LOOP; 
		break; 
	    case STAGE_EXEC:      // execute given instruction
		// Decode op to NOP or one of the 8 ops. 
		switch (decode_op(instr, Rc))
		{
		case OP_READ_DATA:  // read data register from current 
		    Rd = getMem(Rd);
		    break;
		case OP_READ_IP:  // jump to addr 
		    Rc = getMem(Rd);
		    break;
		case OP_ROT_RIGHT:  // rotate right 1, lstrit=> mstrit (3**9 = 19683)
		{
		    unsigned short t = getMem(Rd); 
		    Ra = t / 3 + t % 3 * 19683;
		    storeMem(Rd, Ra);
		    break; 
		}
		case OP_TERNARY:  // run ternary operator on two values
		    Ra = op(Ra, getMem(Rd));
		    storeMem(Rd, Ra);
		    break;
		case OP_WRITE:  // output accumulator as a character
		{
		    // Checks whether this is a 'good' character, otherwise abort!
		    odepth = 0; 
		    char c = (char) Ra; 
		    if ((output.length() >= TARGET.length()) ||  // too long string
			(c != TARGET[output.length()]))          // wrong character
			return RES_WRITE_MISMATCH; 
		    output += c; 
		    break;
		}
		case OP_READ:  // We don't allow input from stdin in the program
		    return RES_TRIED_INPUT; 
		case OP_TERMINATE:  // terminate program
		    return RES_OK;
		case OP_NOP:
		default: // Unspecified operatins correspond to NOPs in the original interpreter
		    break;  
		}
		break; 
	    case STAGE_MODMEM:   { // modify location of memory that the Rc register currently points at
		// Modify op at position. Note that all chars in xlat2 are in the legal range for ops: 33..126
		// So, an OP will always be translated into an OP (either a NOP or the other 8 ops)
		int addr = getMem(Rc); 
		if (addr < 33 || (addr > (95+33)))
		{ 
		    // Pruning search paths that result in accesses out of bounds for xlat2
		    // NB: This happens very often when we search for programs, so we need to explicitly prune these
		    // paths as they will not execute correctly if we try them with the interpreter.
		    return RES_ERROR; 
		}
		storeMem(Rc, xlat2[addr - 33]);	
		break; 
	    }
	    case STAGE_MODINC:    // modulo increment instruction and data pointer
		Rc = modInc(Rc, MAX_TRIT); 
		Rd = modInc(Rd, MAX_TRIT); 
		break; 
	    default:
		std::cerr << "ERROR, interpreter interpreter with illegal stage " << iStage << std::endl; 
		exit(-1);
	    } 
	    iStage = (InterpreterStage) modInc(iStage, STAGE_NUMSTAGES); 
	}
    }
    catch (MB_Exception e)
    {
	switch (e) { 
	case BRANCH_DEPTH_EXCEPTION:
	case MAX_APLEN_EXCEPTION:
	    return RES_BRANCH_DEPTH;
	default:
	    return RES_ERROR;
	}
    }
    return RES_MAX_ITERS;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x48(%rbp)
movq $0x5f5e100, -0x18(%rbp) # imm = 0x5F5E100
movq $0x0, -0x20(%rbp)
cmpq $0x5f5e100, -0x20(%rbp) # imm = 0x5F5E100
jge 0x404f46
movq -0x48(%rbp), %rax
movl 0x7c(%rax), %eax
movq %rax, -0x50(%rbp)
subq $0x3, %rax
ja 0x404eb8
movq -0x50(%rbp), %rax
leaq 0x1814ab(%rip), %rcx    # 0x586010
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x48(%rbp), %rdi
movzwl 0x2(%rdi), %esi
callq 0x4047d0
movw %ax, -0x52(%rbp)
jmp 0x404b81
movq -0x48(%rbp), %rax
movw -0x52(%rbp), %cx
movw %cx, 0x80(%rax)
movzwl 0x80(%rax), %eax
cmpl $0x21, %eax
jl 0x404bac
movq -0x48(%rbp), %rax
movzwl 0x80(%rax), %eax
cmpl $0x7e, %eax
jle 0x404c04
movl $0x1, -0x4(%rbp)
jmp 0x404f74
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x404f80
movq -0x28(%rbp), %rdi
callq 0x409810
movl (%rax), %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
movl %eax, -0x58(%rbp)
subl $0x2a, %eax
je 0x404f48
jmp 0x404bf3
movl -0x58(%rbp), %eax
subl $0x2c, %eax
je 0x404f48
jmp 0x404f58
jmp 0x404f0f
movq -0x48(%rbp), %rax
movzwl 0x80(%rax), %edi
movzwl 0x2(%rax), %esi
callq 0x404f90
movw %ax, -0x5a(%rbp)
jmp 0x404c23
movw -0x5a(%rbp), %ax
movzwl %ax, %eax
addl $-0x6, %eax
movl %eax, %ecx
movq %rcx, -0x68(%rbp)
subl $0x4e, %eax
ja 0x404dfb
movq -0x68(%rbp), %rax
leaq 0x1813d9(%rip), %rcx    # 0x586020
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x48(%rbp), %rdi
movzwl 0x4(%rdi), %esi
callq 0x4047d0
movw %ax, -0x6a(%rbp)
jmp 0x404c63
movq -0x48(%rbp), %rax
movw -0x6a(%rbp), %cx
movw %cx, 0x4(%rax)
jmp 0x404dfd
movq -0x48(%rbp), %rdi
movzwl 0x4(%rdi), %esi
callq 0x4047d0
movw %ax, -0x6c(%rbp)
jmp 0x404c87
movq -0x48(%rbp), %rax
movw -0x6c(%rbp), %cx
movw %cx, 0x2(%rax)
jmp 0x404dfd
movq -0x48(%rbp), %rdi
movzwl 0x4(%rdi), %esi
callq 0x4047d0
movw %ax, -0x6e(%rbp)
jmp 0x404cab
movq -0x48(%rbp), %rdi
movw -0x6e(%rbp), %ax
movw %ax, -0x2e(%rbp)
movzwl -0x2e(%rbp), %eax
movl %eax, %ecx
imulq $0x55555556, %rax, %rax # imm = 0x55555556
shrq $0x20, %rax
movl %eax, %edx
leal (%rdx,%rdx,2), %edx
subl %edx, %ecx
imull $0x4ce3, %ecx, %ecx     # imm = 0x4CE3
addl %ecx, %eax
movw %ax, (%rdi)
movzwl 0x4(%rdi), %esi
movzwl (%rdi), %edx
callq 0x404a30
jmp 0x404ce8
jmp 0x404dfd
movq -0x48(%rbp), %rdi
movw (%rdi), %ax
movw %ax, -0x72(%rbp)
movzwl 0x4(%rdi), %esi
callq 0x4047d0
movw %ax, -0x70(%rbp)
jmp 0x404d07
movw -0x70(%rbp), %ax
movw -0x72(%rbp), %cx
movzwl %cx, %edi
movzwl %ax, %esi
callq 0x404fc0
movw %ax, -0x74(%rbp)
jmp 0x404d20
movq -0x48(%rbp), %rdi
movw -0x74(%rbp), %ax
movw %ax, (%rdi)
movzwl 0x4(%rdi), %esi
movzwl (%rdi), %edx
callq 0x404a30
jmp 0x404d39
jmp 0x404dfd
movq -0x48(%rbp), %rdi
movl $0x0, 0x14(%rdi)
movw (%rdi), %ax
movb %al, -0x2f(%rbp)
addq $0x88, %rdi
callq 0x483910
movq %rax, -0x80(%rbp)
leaq 0x1f37f2(%rip), %rdi    # 0x5f8558
callq 0x483910
movq %rax, %rcx
movq -0x80(%rbp), %rax
cmpq %rcx, %rax
jae 0x404dbd
movq -0x48(%rbp), %rdi
movsbl -0x2f(%rbp), %eax
movl %eax, -0x8c(%rbp)
addq $0x88, %rdi
callq 0x483910
movq %rax, %rsi
leaq 0x1f37bd(%rip), %rdi    # 0x5f8558
callq 0x483c20
movq %rax, -0x88(%rbp)
jmp 0x404da9
movl -0x8c(%rbp), %eax
movq -0x88(%rbp), %rcx
movsbl (%rcx), %ecx
cmpl %ecx, %eax
je 0x404dc9
movl $0x4, -0x4(%rbp)
jmp 0x404f74
movq -0x48(%rbp), %rdi
movsbl -0x2f(%rbp), %esi
addq $0x88, %rdi
callq 0x483cf0
jmp 0x404ddf
jmp 0x404dfd
movl $0x2, -0x4(%rbp)
jmp 0x404f74
movl $0x0, -0x4(%rbp)
jmp 0x404f74
jmp 0x404dfb
jmp 0x404dfd
jmp 0x404f0f
movq -0x48(%rbp), %rdi
movzwl 0x2(%rdi), %esi
callq 0x4047d0
movw %ax, -0x8e(%rbp)
jmp 0x404e18
movw -0x8e(%rbp), %ax
movzwl %ax, %eax
movl %eax, -0x34(%rbp)
cmpl $0x21, -0x34(%rbp)
jl 0x404e34
cmpl $0x80, -0x34(%rbp)
jle 0x404e40
movl $0x5, -0x4(%rbp)
jmp 0x404f74
movq -0x48(%rbp), %rdi
movzwl 0x2(%rdi), %esi
movl -0x34(%rbp), %eax
addl $-0x21, %eax
cltq
leaq 0x181309(%rip), %rcx    # 0x586160
movsbl (%rax,%rcx), %eax
movzwl %ax, %edx
callq 0x404a30
jmp 0x404e65
jmp 0x404f0f
movq -0x48(%rbp), %rax
movzwl 0x2(%rax), %edi
movl $0xe6a9, %esi           # imm = 0xE6A9
callq 0x405080
movl %eax, -0x94(%rbp)
jmp 0x404e84
movq -0x48(%rbp), %rax
movl -0x94(%rbp), %ecx
movw %cx, 0x2(%rax)
movzwl 0x4(%rax), %edi
movl $0xe6a9, %esi           # imm = 0xE6A9
callq 0x405080
movl %eax, -0x98(%rbp)
jmp 0x404ea8
movq -0x48(%rbp), %rax
movl -0x98(%rbp), %ecx
movw %cx, 0x4(%rax)
jmp 0x404f0f
movq $0x5f9420, %rdi         # imm = 0x5F9420
leaq 0x1813fc(%rip), %rsi    # 0x5862c2
callq 0x4737e0
movq %rax, -0xa0(%rbp)
jmp 0x404ed4
movq -0xa0(%rbp), %rdi
movq -0x48(%rbp), %rax
movl 0x7c(%rax), %esi
callq 0x473b80
movq %rax, -0xa8(%rbp)
jmp 0x404ef0
movq -0xa8(%rbp), %rdi
movq $0x4730c0, %rsi         # imm = 0x4730C0
callq 0x4722d0
jmp 0x404f05
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x4d0840
movq -0x48(%rbp), %rax
movl 0x7c(%rax), %edi
movl $0x4, %esi
callq 0x405080
movl %eax, -0xac(%rbp)
jmp 0x404f28
movq -0x48(%rbp), %rax
movl -0xac(%rbp), %ecx
movl %ecx, 0x7c(%rax)
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x404b37
jmp 0x404f6d
movl $0x6, -0x4(%rbp)
movl $0x1, -0x3c(%rbp)
jmp 0x404f66
movl $0x5, -0x4(%rbp)
movl $0x1, -0x3c(%rbp)
callq 0x409880
jmp 0x404f74
movl $0x3, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x4b4f90
nopl (%rax)