// File: /workspace/github_cpp_makefile_star2_O2/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 %r14
pushq %rbx
subq $0x28, %rsp
movq %rdi, %rbx
movl 0x88(%rdi), %edx
movl 0xa4(%rdi), %eax
cmpl $0x4000000, %edx        # imm = 0x4000000
pushq $0x3f
popq %rcx
movl $0xfc000000, %esi       # imm = 0xFC000000
cmovbl %ecx, %esi
movl 0xa8(%rdi), %ecx
andl %edx, %esi
leal -0x8(%rsi), %edi
cmpl $0x1a, %edi
ja 0x3086
leaq 0x400e(%rip), %rdx      # 0x7074
movslq (%rdx,%rdi,4), %rsi
addq %rdx, %rsi
jmpq *%rsi
movl 0x8c(%rbx), %ecx
movl %ecx, 0xac(%rbx)
movl %eax, 0x8c(%rbx)
jmp 0x31e4
cmpl $0x8c000000, %esi       # imm = 0x8C000000
je 0x31d9
cmpl $0xac000000, %esi       # imm = 0xAC000000
je 0x31c6
cmpl $0x2a, %esi
je 0x3199
cmpl $0x2b, %esi
je 0x31b7
cmpl $0x10000000, %esi       # imm = 0x10000000
je 0x31a2
cmpl $0x14000000, %esi       # imm = 0x14000000
jne 0x30d6
movswl %dx, %edx
shll $0x2, %edx
xorl %esi, %esi
cmpl %ecx, %eax
cmovnel %edx, %esi
jmp 0x31af
leaq 0x401e(%rip), %rsi      # 0x70fb
leaq 0x8(%rsp), %r14
leaq 0x7(%rsp), %rdx
movq %r14, %rdi
callq 0x2740
movq %r14, %rdi
callq 0x575c
leaq 0x8(%rsp), %rdi
callq 0x23e8
jmp 0x31e4
cltq
movslq %ecx, %rcx
imulq %rax, %rcx
rorq $0x20, %rcx
movq %rcx, 0x90(%rbx)
jmp 0x31e4
xorl %edx, %edx
divl %ecx
jmp 0x3128
cltd
idivl %ecx
movl %eax, 0x94(%rbx)
movl %edx, 0x90(%rbx)
jmp 0x31e4
movl 0x94(%rbx), %eax
jmp 0x3147
movl 0x90(%rbx), %eax
movl %eax, 0xac(%rbx)
jmp 0x31e4
movl 0x8c(%rbx), %eax
movl %eax, 0xac(%rbx)
addl $0x4, %eax
movl %eax, 0x8c(%rbx)
jmp 0x31e4
addl %eax, %ecx
movl %ecx, 0xac(%rbx)
jmp 0x31e4
movq %rcx, %rdx
imulq %rax, %rdx
imull %eax, %ecx
movl %ecx, 0x94(%rbx)
shrq $0x20, %rdx
movl %edx, 0x90(%rbx)
jmp 0x31e4
subl %ecx, %eax
movl %eax, 0xac(%rbx)
jmp 0x31e4
xorl %edx, %edx
cmpl %ecx, %eax
setl %dl
jmp 0x31be
movswl %dx, %edx
shll $0x2, %edx
xorl %esi, %esi
cmpl %ecx, %eax
cmovel %edx, %esi
addl %esi, 0x8c(%rbx)
jmp 0x31e4
xorl %edx, %edx
cmpl %ecx, %eax
setb %dl
movl %edx, 0xac(%rbx)
jmp 0x31e4
movswl %dx, %edx
addl %eax, %edx
movl %edx, 0xac(%rbx)
movl %ecx, 0xb0(%rbx)
jmp 0x31e4
movswl %dx, %ecx
addl %eax, %ecx
movl %ecx, 0xac(%rbx)
movl $0x3, 0xa0(%rbx)
addq $0x28, %rsp
popq %rbx
popq %r14
retq
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x23e8
movq %rbx, %rdi
callq 0x23a0
nop