// File: 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 %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x58(%rbp)
movl 0xa4(%rdi), %eax
movl %eax, -0xc(%rbp)
movl 0xa8(%rdi), %eax
movl %eax, -0x10(%rbp)
movw 0x88(%rdi), %ax
movw %ax, -0x12(%rbp)
movl 0x88(%rdi), %esi
callq 0x5740
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x50(%rbp)
subl $0x8c000000, %eax       # imm = 0x8C000000
je 0x5c30
jmp 0x5922
movl -0x50(%rbp), %eax
subl $0xac000000, %eax       # imm = 0xAC000000
je 0x5c09
jmp 0x5932
movl -0x50(%rbp), %eax
subl $0x8, %eax
je 0x5b59
jmp 0x5940
movl -0x50(%rbp), %eax
subl $0x9, %eax
je 0x5b6e
jmp 0x594e
movl -0x50(%rbp), %eax
subl $0x10, %eax
je 0x5a67
jmp 0x595c
movl -0x50(%rbp), %eax
subl $0x12, %eax
je 0x5a7c
jmp 0x596a
movl -0x50(%rbp), %eax
subl $0x14, %eax
je 0x5c4b
jmp 0x5978
movl -0x50(%rbp), %eax
subl $0x18, %eax
je 0x5a91
jmp 0x5986
movl -0x50(%rbp), %eax
subl $0x19, %eax
je 0x5ac2
jmp 0x5994
movl -0x50(%rbp), %eax
subl $0x1a, %eax
je 0x5afb
jmp 0x59a2
movl -0x50(%rbp), %eax
subl $0x1b, %eax
je 0x5b24
jmp 0x59b0
movl -0x50(%rbp), %eax
subl $0x20, %eax
je 0x59fb
jmp 0x59ba
movl -0x50(%rbp), %eax
subl $0x22, %eax
je 0x5a10
jmp 0x59c4
movl -0x50(%rbp), %eax
subl $0x2a, %eax
je 0x5a25
jmp 0x59ce
movl -0x50(%rbp), %eax
subl $0x2b, %eax
je 0x5a43
jmp 0x59d8
movl -0x50(%rbp), %eax
subl $0x10000000, %eax       # imm = 0x10000000
je 0x5b8f
jmp 0x59e8
movl -0x50(%rbp), %eax
subl $0x14000000, %eax       # imm = 0x14000000
je 0x5bcc
jmp 0x5c6c
movq -0x58(%rbp), %rax
movl -0xc(%rbp), %ecx
addl -0x10(%rbp), %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl -0xc(%rbp), %ecx
subl -0x10(%rbp), %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl -0xc(%rbp), %ecx
cmpl -0x10(%rbp), %ecx
setl %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0xa4(%rax), %ecx
cmpl 0xa8(%rax), %ecx
setb %cl
andb $0x1, %cl
movzbl %cl, %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0x90(%rax), %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0x94(%rax), %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movslq -0xc(%rbp), %rcx
movslq -0x10(%rbp), %rdx
imulq %rdx, %rcx
movl %ecx, 0x94(%rax)
movslq -0xc(%rbp), %rcx
movslq -0x10(%rbp), %rdx
imulq %rdx, %rcx
sarq $0x20, %rcx
movl %ecx, 0x90(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0xa4(%rax), %ecx
movl 0xa8(%rax), %edx
imulq %rdx, %rcx
movl %ecx, 0x94(%rax)
movl 0xa4(%rax), %ecx
movl 0xa8(%rax), %edx
imulq %rdx, %rcx
shrq $0x20, %rcx
movl %ecx, 0x90(%rax)
jmp 0x5cdc
movl -0xc(%rbp), %eax
cltd
idivl -0x10(%rbp)
movl %eax, %ecx
movq -0x58(%rbp), %rax
movl %ecx, 0x94(%rax)
movl -0xc(%rbp), %eax
cltd
idivl -0x10(%rbp)
movq -0x58(%rbp), %rax
movl %edx, 0x90(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rcx
movl 0xa4(%rcx), %eax
xorl %edx, %edx
divl 0xa8(%rcx)
movl %eax, 0x94(%rcx)
movl 0xa4(%rcx), %eax
xorl %edx, %edx
divl 0xa8(%rcx)
movq -0x58(%rbp), %rax
movl %edx, 0x90(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0xa4(%rax), %ecx
movl %ecx, 0x8c(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0x8c(%rax), %ecx
movl %ecx, 0xac(%rax)
movl 0xa4(%rax), %ecx
movl %ecx, 0x8c(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rcx
movl 0xa4(%rcx), %eax
cmpl 0xa8(%rcx), %eax
jne 0x5bad
movswl -0x12(%rbp), %eax
shll $0x2, %eax
movl %eax, -0x5c(%rbp)
jmp 0x5bb4
xorl %eax, %eax
movl %eax, -0x5c(%rbp)
jmp 0x5bb4
movq -0x58(%rbp), %rax
movl -0x5c(%rbp), %ecx
addl 0x8c(%rax), %ecx
movl %ecx, 0x8c(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rcx
movl 0xa4(%rcx), %eax
cmpl 0xa8(%rcx), %eax
je 0x5bea
movswl -0x12(%rbp), %eax
shll $0x2, %eax
movl %eax, -0x60(%rbp)
jmp 0x5bf1
xorl %eax, %eax
movl %eax, -0x60(%rbp)
jmp 0x5bf1
movq -0x58(%rbp), %rax
movl -0x60(%rbp), %ecx
addl 0x8c(%rax), %ecx
movl %ecx, 0x8c(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0xa4(%rax), %ecx
movswl -0x12(%rbp), %edx
addl %edx, %ecx
movl %ecx, 0xac(%rax)
movl 0xa8(%rax), %ecx
movl %ecx, 0xb0(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0xa4(%rax), %ecx
movswl -0x12(%rbp), %edx
addl %edx, %ecx
movl %ecx, 0xac(%rax)
jmp 0x5cdc
movq -0x58(%rbp), %rax
movl 0x8c(%rax), %ecx
movl %ecx, 0xac(%rax)
movl 0x8c(%rax), %ecx
addl $0x4, %ecx
movl %ecx, 0x8c(%rax)
jmp 0x5cdc
leaq -0x39(%rbp), %rdi
movq %rdi, -0x68(%rbp)
callq 0x34d0
movq -0x68(%rbp), %rdx
leaq 0xa40b(%rip), %rsi      # 0x1008f
leaq -0x38(%rbp), %rdi
callq 0x3a90
jmp 0x5c8f
leaq -0x38(%rbp), %rdi
callq 0xca80
jmp 0x5c9a
leaq -0x38(%rbp), %rdi
callq 0x3528
leaq -0x39(%rbp), %rdi
callq 0x32d0
jmp 0x5cdc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x5cd1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x3528
leaq -0x39(%rbp), %rdi
callq 0x32d0
jmp 0x5cf0
movq -0x58(%rbp), %rax
movl $0x3, 0xa0(%rax)
addq $0x70, %rsp
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x34c0
nopl (%rax)