// File: /workspace/github_cpp_makefile_star2_O1/saumya-prakash[P]AssemblerEmulator/Emulator.cpp
// Function: Emulator::execute[abi:cxx11]()
string Emulator::execute()
{   
    if(fault==true)
    {
        return fault_cause;
    }

    if(finished==true)
        return string();

    if(text_size==0)
    {
        finished = true;
        return "No text segment to execute";
    }

    string res = current_state();

    int mach_code = mempory_space[PC];     // get current machine code

    int opcode = (mach_code<<24)>>24;
    int operand = (mach_code & static_cast<int>(0xffffff00)) / 256; // cast required for operations to work correctly work correctly


    ++PC;   // PC incremented to point to next instruction

    check_PC(PC);
    if(PC>pc_upper)
    {   
        fault = true;

        string tmp = faults.find(0)->second;
        fault_cause = tmp + " as upper limit for text segment crossed; no HALT encountered";
        
        return fault_cause;
    }

    switch(opcode)
    {
        case 0:         // ldc value
                B = A;
                A = operand;
                break;
        
        case 1:         // adc value
                A = A + operand;
                break;

        case 2:         // ldl value      // proper checks to be included

                check_memory_access(SP+operand);
                if(fault==true)
                    return fault_cause;

                B = A;
                A = mempory_space[SP+operand];
                break;

        case 3:         // stl value
                check_memory_access(SP+operand);
                if(fault==true)
                    return fault_cause;

                mempory_space[SP+operand] = A;
                A = B;
                break;

        case 4:         // ldnl offset
                check_memory_access(A+operand);
                if(fault==true)
                    return fault_cause;
                
                A = mempory_space[A+operand];
                break;
        
        case 5:         // stnl offset
                check_memory_access(A+operand);
                if(fault==true)
                    return fault_cause;

                mempory_space[A+operand] = B;
                break;

        case 6:         // add
                A = B + A;
                break;

        case 7:         // sub
                A = B - A;
                break;

        case 8:         // shl
                A = B<<A;
                break;
        
        case 9:         // shr
                A = B>>A;
                break;
        
        case 10:        // adj value
                check_SP(SP+operand);
                if(fault==true)
                    return fault_cause;

                SP = SP + operand;
                break;
        
        case 11:        //a2sp
                check_SP(A);
                if(fault==true)
                    return fault_cause;

                SP = A;
                A = B;
                break;
        
        case 12:        // sp2a
                B = A;
                A = SP;
                break;
        
        case 13:        // call offset

                check_PC(PC+operand);
                if(fault==true)
                    return fault_cause;
                
                B = A;
                A = PC;
                PC = PC+operand;
                break;

        case 14:        // return 
                check_PC(A);
                if(fault==true)
                    return fault_cause;
                
                PC = A;
                A = B;
                break;

        case 15:        // brz offset
                if(A==0)
                {   check_PC(PC+operand);
                    if(fault==true)
                        return fault_cause;
                
                    PC = PC+operand;
                }

                break;
        
        case 16:        // brlz offset
                if(A<0)
                {
                    check_PC(PC+operand);
                    if(fault==true)
                        return fault_cause;
                    
                    PC = PC+operand;
                }

                break;

        case 17:        // br offset
                check_PC(PC+operand);
                if(fault==true)
                    return fault_cause;
                
                PC = PC+operand;
                break;
        
        case 18:        // HALT
                finished = true;
                break;
        
        default:    
                fault = true;
                fault_cause = faults.find(7)->second;
                return fault_cause;
                
                break;
    }

    ++instr_cnt; 

    if(instr_cnt==max_instruction_count) // looped back to 0 -> limit crossed
    {
        fault = true;          
                                  // indiacte program took too long to finish
        ostringstream oss;

        oss<<faults.find(6)->second;
        oss<<'\n';
        
        oss<<instr_cnt<<" instructions executed so far\n";

        fault_cause = oss.str();

        return fault_cause;
    }

    return res;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1b8, %rsp            # imm = 0x1B8
movq %rsi, %r14
movq %rdi, %rbx
cmpb $0x1, 0x51(%rsi)
jne 0x47d6
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
movq 0x58(%r14), %rsi
movq 0x60(%r14), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x434c
jmp 0x4d6d
cmpb $0x1, 0x50(%r14)
jne 0x47f5
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
movq $0x0, 0x8(%rbx)
movb $0x0, 0x10(%rbx)
jmp 0x4d6d
cmpl $0x0, 0x48(%r14)
je 0x4853
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0x4e0e
movq 0x30(%r14), %rax
movslq 0x28(%r14), %rcx
movl (%rax,%rcx,4), %ebp
leal 0x1(%rcx), %esi
movl %esi, 0x28(%r14)
movq %r14, %rdi
callq 0x5138
movl 0x28(%r14), %esi
cmpl $0x400, %esi            # imm = 0x400
jb 0x487a
movb $0x1, 0x51(%r14)
movq 0x597d(%rip), %rdx      # 0xa1b8
leaq 0x596e(%rip), %rax      # 0xa1b0
movq %rax, %rcx
testq %rdx, %rdx
je 0x48ad
movq %rdx, %rcx
movq 0x10(%rdx), %rdx
jmp 0x4845
movb $0x1, 0x50(%r14)
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
leaq 0x2c04(%rip), %rsi      # 0x746a
leaq 0x2c17(%rip), %rdx      # 0x7484
movq %rbx, %rdi
callq 0x43dc
jmp 0x4d6d
movsbl %bpl, %eax
cmpl $0x12, %eax
ja 0x4cde
sarl $0x8, %ebp
movl %eax, %eax
leaq 0x2a1d(%rip), %rcx      # 0x72b0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x20(%r14), %eax
movl %eax, 0x24(%r14)
movl %ebp, 0x20(%r14)
jmp 0x4b6a
cmpq %rax, %rcx
je 0x48c1
cmpl $0x0, 0x20(%rcx)
leaq 0x58f3(%rip), %rax      # 0xa1b0
cmoveq %rcx, %rax
leaq 0x50(%rsp), %r12
movq %r12, -0x10(%r12)
movq 0x28(%rax), %rsi
movq 0x30(%rax), %rdx
addq %rsi, %rdx
leaq 0x40(%rsp), %rdi
callq 0x434c
leaq 0x10(%rsp), %r13
movq %r13, -0x10(%r13)
movq 0x40(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq %rsi, %rdx
movq %rsp, %rdi
callq 0x434c
leaq 0x2b80(%rip), %rsi      # 0x7485
movq %rsp, %rdi
callq 0x2290
leaq 0x58(%r14), %rdi
movq %rsp, %r15
movq %r15, %rsi
callq 0x21c0
movq (%r15), %rdi
cmpq %r13, %rdi
je 0x4931
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2190
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
movq 0x58(%r14), %rsi
movq 0x60(%r14), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x434c
movq 0x40(%rsp), %rdi
cmpq %r12, %rdi
je 0x4d52
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x2190
jmp 0x4d52
cmpl $0x0, 0x20(%r14)
jns 0x4b6a
addl %ebp, %esi
movq %r14, %rdi
callq 0x5138
jmp 0x4abb
movl 0x20(%r14), %esi
movq %r14, %rdi
callq 0x5138
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x20(%r14), %eax
movl 0x24(%r14), %ecx
movl %eax, 0x28(%r14)
jmp 0x49fe
movl 0x20(%r14), %esi
movq %r14, %rdi
callq 0x55c6
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x20(%r14), %eax
movl 0x24(%r14), %ecx
movl %eax, 0x2c(%r14)
jmp 0x49fe
movl 0x20(%r14), %esi
addl %ebp, %esi
movq %r14, %rdi
callq 0x533c
cmpb $0x1, 0x51(%r14)
je 0x4d38
movq 0x30(%r14), %rax
movslq 0x20(%r14), %rcx
jmp 0x4a3f
movl 0x20(%r14), %eax
movl 0x2c(%r14), %ecx
movl %eax, 0x24(%r14)
movl %ecx, 0x20(%r14)
jmp 0x4b6a
movl 0x24(%r14), %eax
movb 0x20(%r14), %cl
sarl %cl, %eax
jmp 0x4b66
movl 0x2c(%r14), %esi
addl %ebp, %esi
movq %r14, %rdi
callq 0x533c
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x20(%r14), %eax
movl %eax, 0x24(%r14)
movq 0x30(%r14), %rax
movslq 0x2c(%r14), %rcx
movslq %ebp, %rdx
addq %rcx, %rdx
movl (%rax,%rdx,4), %eax
jmp 0x4b66
cmpl $0x0, 0x20(%r14)
jne 0x4b6a
addl %ebp, %esi
movq %r14, %rdi
callq 0x5138
jmp 0x4abb
movl 0x2c(%r14), %esi
addl %ebp, %esi
movq %r14, %rdi
callq 0x533c
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x20(%r14), %eax
movq 0x30(%r14), %rcx
movslq 0x2c(%r14), %rdx
movslq %ebp, %rsi
addq %rdx, %rsi
movl %eax, (%rcx,%rsi,4)
movl 0x24(%r14), %eax
jmp 0x4b66
movl 0x24(%r14), %eax
subl 0x20(%r14), %eax
jmp 0x4b66
addl %ebp, 0x20(%r14)
jmp 0x4b6a
addl %ebp, %esi
movq %r14, %rdi
callq 0x5138
cmpb $0x1, 0x51(%r14)
je 0x4d38
addl %ebp, 0x28(%r14)
jmp 0x4b6a
movl 0x20(%r14), %esi
addl %ebp, %esi
movq %r14, %rdi
callq 0x533c
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x24(%r14), %eax
movq 0x30(%r14), %rcx
movslq 0x20(%r14), %rdx
movslq %ebp, %rsi
addq %rdx, %rsi
movl %eax, (%rcx,%rsi,4)
jmp 0x4b6a
addl %ebp, %esi
movq %r14, %rdi
callq 0x5138
cmpb $0x1, 0x51(%r14)
je 0x4d38
movl 0x20(%r14), %eax
movl 0x28(%r14), %ecx
movl %eax, 0x24(%r14)
movl %ecx, 0x20(%r14)
addl %ecx, %ebp
movl %ebp, 0x28(%r14)
jmp 0x4b6a
movl 0x24(%r14), %eax
addl %eax, 0x20(%r14)
jmp 0x4b6a
movb $0x1, 0x50(%r14)
jmp 0x4b6a
movl 0x2c(%r14), %esi
addl %ebp, %esi
movq %r14, %rdi
callq 0x55c6
cmpb $0x1, 0x51(%r14)
je 0x4d38
addl %ebp, 0x2c(%r14)
jmp 0x4b6a
movl 0x24(%r14), %eax
movb 0x20(%r14), %cl
shll %cl, %eax
movl %eax, 0x20(%r14)
movq 0x40(%r14), %rax
incq %rax
movq %rax, 0x40(%r14)
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpq %rcx, %rax
jne 0x4c97
movb $0x1, 0x51(%r14)
leaq 0x40(%rsp), %rdi
callq 0x2200
movq 0x561f(%rip), %rdx      # 0xa1b8
leaq 0x5610(%rip), %rax      # 0xa1b0
movq %rax, %rcx
testq %rdx, %rdx
je 0x4bc7
leaq 0x5601(%rip), %rcx      # 0xa1b0
xorl %esi, %esi
cmpl $0x6, 0x20(%rdx)
setb %sil
cmovaeq %rdx, %rcx
movq 0x10(%rdx,%rsi,8), %rdx
testq %rdx, %rdx
jne 0x4baf
cmpq %rax, %rcx
je 0x4bdb
cmpl $0x7, 0x20(%rcx)
leaq 0x55d9(%rip), %rax      # 0xa1b0
cmovbq %rcx, %rax
movq 0x28(%rax), %rsi
movq 0x30(%rax), %rdx
leaq 0x40(%rsp), %rdi
callq 0x21b0
movq %rsp, %rsi
movb $0xa, (%rsi)
leaq 0x40(%rsp), %rdi
movl $0x1, %edx
callq 0x21b0
movq 0x40(%r14), %rsi
leaq 0x40(%rsp), %rdi
callq 0x2100
leaq 0x28ac(%rip), %rsi      # 0x74c3
movl $0x1e, %edx
movq %rax, %rdi
callq 0x21b0
leaq 0x48(%rsp), %rsi
movq %rsp, %rdi
callq 0x2230
leaq 0x58(%r14), %rdi
movq %rsp, %r15
movq %r15, %rsi
callq 0x21c0
movq (%r15), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x4c5a
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2190
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
movq 0x58(%r14), %rsi
movq 0x60(%r14), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x434c
movq 0x534d(%rip), %rsi      # 0x9fc8
leaq 0x40(%rsp), %rdi
callq 0x20d0
leaq 0xb0(%rsp), %rdi
callq 0x20a0
jmp 0x4d52
leaq 0x10(%rbx), %rcx
movq %rcx, (%rbx)
leaq 0x30(%rsp), %rax
movq -0x10(%rax), %rdx
cmpq %rax, %rdx
je 0x4cba
movq %rdx, (%rbx)
movq 0x30(%rsp), %rcx
movq %rcx, 0x10(%rbx)
jmp 0x4cc0
movups (%rax), %xmm0
movups %xmm0, (%rcx)
movq 0x28(%rsp), %rcx
movq %rcx, 0x8(%rbx)
movq %rax, 0x20(%rsp)
movq $0x0, 0x28(%rsp)
movb $0x0, 0x30(%rsp)
jmp 0x4d52
movb $0x1, 0x51(%r14)
movq 0x54ce(%rip), %rcx      # 0xa1b8
leaq 0x54bf(%rip), %rsi      # 0xa1b0
movq %rsi, %rax
testq %rcx, %rcx
je 0x4d17
leaq 0x54b0(%rip), %rax      # 0xa1b0
xorl %edx, %edx
cmpl $0x7, 0x20(%rcx)
setb %dl
cmovaeq %rcx, %rax
movq 0x10(%rcx,%rdx,8), %rcx
testq %rcx, %rcx
jne 0x4d00
cmpq %rsi, %rax
je 0x4d2b
cmpl $0x8, 0x20(%rax)
leaq 0x5489(%rip), %rsi      # 0xa1b0
cmovbq %rax, %rsi
addq $0x28, %rsi
leaq 0x58(%r14), %rdi
callq 0x20e0
leaq 0x10(%rbx), %rax
movq %rax, (%rbx)
movq 0x58(%r14), %rsi
movq 0x60(%r14), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x434c
leaq 0x30(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4d6d
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x2190
movq %rbx, %rax
addq $0x1b8, %rsp            # imm = 0x1B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4de8
jmp 0x4dc5
jmp 0x4dc5
jmp 0x4de8
jmp 0x4da7
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r13, %rdi
je 0x4daa
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x2190
jmp 0x4daa
movq %rax, %rbx
movq 0x40(%rsp), %rdi
cmpq %r12, %rdi
je 0x4deb
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x2190
jmp 0x4deb
jmp 0x4de8
movq %rax, %rbx
movq 0x51f9(%rip), %rsi      # 0x9fc8
leaq 0x40(%rsp), %rdi
callq 0x20d0
leaq 0xb0(%rsp), %rdi
callq 0x20a0
jmp 0x4deb
movq %rax, %rbx
leaq 0x30(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x4e06
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x2190
movq %rbx, %rdi
callq 0x2270