// File: /workspace/github_cpp_makefile_star2_O1/daniel5151[P]mips241/src/cpu.cc
// Function: MIPS::CPU::exec()
void MIPS::CPU::exec() {
  // Get signed values
  int32_t RA_s = static_cast<int32_t>(RA);
  int32_t RB_s = static_cast<int32_t>(RB);
  int16_t imm  = static_cast<int16_t>(IR & 0xFFFF);

  uint32_t opcode = decodeOPcode(IR);

  switch (opcode) {
    /* Arithmetic */
    case OP_ADD:
      RZ = static_cast<uint32_t>(RA_s + RB_s);
      break;
    case OP_SUB:
      RZ = static_cast<uint32_t>(RA_s - RB_s);
      break;
    case OP_SLT:
      RZ = static_cast<uint32_t>(RA_s < RB_s);
      break;
    case OP_SLTU:
      RZ = RA < RB;
      break;
    case OP_MFHI:
      RZ = hi;
      break;
    case OP_MFLO:
      RZ = lo;
      break;
    case OP_MULT:
      lo = (static_cast<int64_t>(RA_s) * static_cast<int64_t>(RB_s));
      hi = (static_cast<int64_t>(RA_s) * static_cast<int64_t>(RB_s)) >> 32;
      break;
    case OP_MULTU:
      lo = (static_cast<uint64_t>(RA) * static_cast<uint64_t>(RB));
      hi = (static_cast<uint64_t>(RA) * static_cast<uint64_t>(RB)) >> 32;
      break;
    case OP_DIV:
      lo = RA_s / RB_s;
      hi = RA_s % RB_s;
      break;
    case OP_DIVU:
      lo = RA / RB;
      hi = RA % RB;
      break;

    /* Jumps and Branches */
    case OP_JR:
      PC = RA;
      break;
    case OP_JALR:
      RZ = PC;
      PC = RA;
      break;
    case OP_BEQ:
      PC += (RA == RB) ? imm * 4 : 0;
      break;
    case OP_BNE:
      PC += (RA != RB) ? imm * 4 : 0;
      break;

    /* Loads and Stores */
    case OP_SW:
      RZ = RA + imm;
      RM = RB;
      break;
    case OP_LW:
      RZ = RA + imm;
      break;

    /* Load Immediate Store */
    case OP_LIS:
      RZ = PC;
      PC += 4;
      break;

    default:
      error("Invalid opcode");
      break;
  }

  stage = S_MEMORY;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x20, %rsp
movq %rdi, %rbx
movl 0x88(%rdi), %edx
movl 0xa4(%rdi), %eax
movl 0xa8(%rdi), %ecx
cmpl $0x4000000, %edx        # imm = 0x4000000
movl $0x3f, %edi
movl $0xfc000000, %esi       # imm = 0xFC000000
cmovbl %edi, %esi
andl %edx, %esi
cmpl $0x29, %esi
jg 0x417b
leal -0x8(%rsi), %edi
cmpl $0x1a, %edi
ja 0x419d
leaq 0x4f19(%rip), %rdx      # 0x9074
movslq (%rdx,%rdi,4), %rsi
addq %rdx, %rsi
jmpq *%rsi
movl 0x8c(%rbx), %ecx
movl %ecx, 0xac(%rbx)
movl %eax, 0x8c(%rbx)
jmp 0x42f8
cmpl $0xfffffff, %esi        # imm = 0xFFFFFFF
jg 0x41c7
cmpl $0x2a, %esi
je 0x42c9
cmpl $0x2b, %esi
jne 0x41ed
xorl %edx, %edx
cmpl %ecx, %eax
setb %dl
jmp 0x42d0
cmpl $0x8c000000, %esi       # imm = 0x8C000000
je 0x42ed
cmpl $0xac000000, %esi       # imm = 0xAC000000
jne 0x41ed
movswl %dx, %edx
addl %eax, %edx
movl %edx, 0xac(%rbx)
movl %ecx, 0xb0(%rbx)
jmp 0x42f8
cmpl $0x10000000, %esi       # imm = 0x10000000
je 0x42d8
cmpl $0x14000000, %esi       # imm = 0x14000000
jne 0x41ed
movswl %dx, %edx
shll $0x2, %edx
xorl %esi, %esi
cmpl %ecx, %eax
cmovnel %edx, %esi
jmp 0x42e5
leaq 0x10(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x4efe(%rip), %rsi      # 0x90fb
leaq 0x4f05(%rip), %rdx      # 0x9109
movq %rsp, %r14
movq %r14, %rdi
callq 0x3a82
movq %r14, %rdi
callq 0x7484
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x42f8
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3200
jmp 0x42f8
subl %ecx, %eax
movl %eax, 0xac(%rbx)
jmp 0x42f8
xorl %edx, %edx
divl %ecx
jmp 0x424c
cltd
idivl %ecx
movl %eax, 0x94(%rbx)
movl %edx, 0x90(%rbx)
jmp 0x42f8
addl %eax, %ecx
movl %ecx, 0xac(%rbx)
jmp 0x42f8
cltq
movslq %ecx, %rcx
imulq %rax, %rcx
rorq $0x20, %rcx
movq %rcx, 0x90(%rbx)
jmp 0x42f8
movl 0x8c(%rbx), %eax
movl %eax, 0xac(%rbx)
addl $0x4, %eax
movl %eax, 0x8c(%rbx)
jmp 0x42f8
movl 0x90(%rbx), %eax
jmp 0x42a5
movl 0x94(%rbx), %eax
movl %eax, 0xac(%rbx)
jmp 0x42f8
movq %rcx, %rdx
imulq %rax, %rdx
imull %eax, %ecx
movl %ecx, 0x94(%rbx)
shrq $0x20, %rdx
movl %edx, 0x90(%rbx)
jmp 0x42f8
xorl %edx, %edx
cmpl %ecx, %eax
setl %dl
movl %edx, 0xac(%rbx)
jmp 0x42f8
movswl %dx, %edx
shll $0x2, %edx
xorl %esi, %esi
cmpl %ecx, %eax
cmovel %edx, %esi
addl %esi, 0x8c(%rbx)
jmp 0x42f8
movswl %dx, %ecx
addl %eax, %ecx
movl %ecx, 0xac(%rbx)
movl $0x3, 0xa0(%rbx)
addq $0x20, %rsp
popq %rbx
popq %r14
popq %r15
retq
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %r15, %rdi
je 0x4325
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3200
movq %rbx, %rdi
callq 0x33a0
nop