// File: daniel5151[P]mips241/src/disasm.cc
// Function: MIPS::disasm[abi:cxx11](unsigned int)
std::string MIPS::disasm(uint32_t word) {
  std::stringstream instr_ss;

  uint8_t  $s, $t, $d;

  int32_t imm;
  uint16_t imm_u;

  $s = (word >> 21) & 0x1F;
  $t = (word >> 16) & 0x1F;
  $d = (word >> 11) & 0x1F;

  imm_u = (word & 0xFFFF);

  bool isNeg = imm_u & 0x8000;
  if (isNeg) {
    imm_u -= 1;
    imm_u = ~imm_u;
    imm = - ((int32_t)imm_u);
  } else {
    imm = imm_u;
  }

  bool hasImmediateValue = (word >> 26) != 0;
  uint32_t opcode = (hasImmediateValue)
    ? word & 0xFC000000   // Mask off all register identifiers + immediate bits
    : word & 0x0000003F;  // Mask off all register identifiers

  switch (opcode) {
      case OP_MULT:
      case OP_MULTU:
      case OP_DIV:
      case OP_DIVU:
        // 2 src
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$s
          << ", "
          << "$" << (int)$t;
        break;
      case OP_BEQ:
      case OP_BNE:
        // 2 src + immediate
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$s
          << ", "
          << "$" << (int)$t
          << ", "
          << imm;
        break;

      case OP_LW:
        // 1 source + immediate + 1 dst
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$t
          << ", "
          << imm
          << "("
          << "$" << (int)$s
          << ")";
        break;
      case OP_SW:
        // 2 source + immediate
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$t
          << ", "
          << imm
          << "("
          << "$" << (int)$s
          << ")";
        break;

      case OP_ADD:
      case OP_SUB:
      case OP_SLT:
      case OP_SLTU:
        // 2 sources, 1 dst
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$d
          << ", "
          << "$" << (int)$s
          << ", "
          << "$" << (int)$t;
        break;

      case OP_MFHI:
      case OP_MFLO:
      case OP_LIS:
        // 1 dst
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$d;
        break;
      case OP_JALR:
      case OP_JR:
        // 1 src
        instr_ss
          << opcode2str(opcode) << " "
          << "$" << (int)$s;
        break;
      default:
        instr_ss
          << ".word "
          << COUTHEX( word );
  }

  return instr_ss.str();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4b0, %rsp            # imm = 0x4B0
movq %rdi, -0x2b0(%rbp)
movq %rdi, %rax
movq %rax, -0x2a8(%rbp)
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x31b0
movl -0xc(%rbp), %eax
shrl $0x15, %eax
andl $0x1f, %eax
movb %al, -0x199(%rbp)
movl -0xc(%rbp), %eax
shrl $0x10, %eax
andl $0x1f, %eax
movb %al, -0x19a(%rbp)
movl -0xc(%rbp), %eax
shrl $0xb, %eax
andl $0x1f, %eax
movb %al, -0x19b(%rbp)
movl -0xc(%rbp), %eax
andl $0xffff, %eax           # imm = 0xFFFF
movw %ax, -0x1a2(%rbp)
movzwl -0x1a2(%rbp), %eax
andl $0x8000, %eax           # imm = 0x8000
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x1a3(%rbp)
testb $0x1, -0x1a3(%rbp)
je 0xbfc3
movzwl -0x1a2(%rbp), %eax
subl $0x1, %eax
movw %ax, -0x1a2(%rbp)
movzwl -0x1a2(%rbp), %eax
xorl $-0x1, %eax
movw %ax, -0x1a2(%rbp)
movzwl -0x1a2(%rbp), %ecx
xorl %eax, %eax
subl %ecx, %eax
movl %eax, -0x1a0(%rbp)
jmp 0xbfd0
movzwl -0x1a2(%rbp), %eax
movl %eax, -0x1a0(%rbp)
movl -0xc(%rbp), %eax
shrl $0x1a, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x1a4(%rbp)
testb $0x1, -0x1a4(%rbp)
je 0xbffd
movl -0xc(%rbp), %eax
andl $0xfc000000, %eax       # imm = 0xFC000000
movl %eax, -0x2b4(%rbp)
jmp 0xc009
movl -0xc(%rbp), %eax
andl $0x3f, %eax
movl %eax, -0x2b4(%rbp)
movl -0x2b4(%rbp), %eax
movl %eax, -0x1a8(%rbp)
movl -0x1a8(%rbp), %eax
movl %eax, -0x2b8(%rbp)
subl $0x8c000000, %eax       # imm = 0x8C000000
je 0xc36b
jmp 0xc02e
movl -0x2b8(%rbp), %eax
subl $0xac000000, %eax       # imm = 0xAC000000
je 0xc4d1
jmp 0xc041
movl -0x2b8(%rbp), %eax
addl $-0x8, %eax
subl $0x2, %eax
jb 0xc85d
jmp 0xc055
movl -0x2b8(%rbp), %eax
subl $0x10, %eax
je 0xc79e
jmp 0xc066
movl -0x2b8(%rbp), %eax
subl $0x12, %eax
je 0xc79e
jmp 0xc077
movl -0x2b8(%rbp), %eax
subl $0x14, %eax
je 0xc79e
jmp 0xc088
movl -0x2b8(%rbp), %eax
addl $-0x18, %eax
subl $0x4, %eax
jb 0xc0f7
jmp 0xc098
movl -0x2b8(%rbp), %eax
subl $0x20, %eax
je 0xc637
jmp 0xc0a9
movl -0x2b8(%rbp), %eax
subl $0x22, %eax
je 0xc637
jmp 0xc0ba
movl -0x2b8(%rbp), %eax
addl $-0x2a, %eax
subl $0x2, %eax
jb 0xc637
jmp 0xc0ce
movl -0x2b8(%rbp), %eax
subl $0x10000000, %eax       # imm = 0x10000000
je 0xc221
jmp 0xc0e1
movl -0x2b8(%rbp), %eax
subl $0x14000000, %eax       # imm = 0x14000000
je 0xc221
jmp 0xc91c
leaq -0x188(%rbp), %rax
movq %rax, -0x2c0(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x1c8(%rbp), %rdi
callq 0xb850
jmp 0xc119
movq -0x2c0(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x3220
movq %rax, -0x2c8(%rbp)
jmp 0xc135
movq -0x2c8(%rbp), %rdi
leaq 0x3f8b(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x2d0(%rbp)
jmp 0xc151
movq -0x2d0(%rbp), %rdi
leaq 0x3fa2(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x2d8(%rbp)
jmp 0xc16d
movq -0x2d8(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
movq %rax, -0x2e0(%rbp)
jmp 0xc189
movq -0x2e0(%rbp), %rdi
leaq 0x42ed(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x2e8(%rbp)
jmp 0xc1a5
movq -0x2e8(%rbp), %rdi
leaq 0x3f4e(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x2f0(%rbp)
jmp 0xc1c1
movq -0x2f0(%rbp), %rdi
movzbl -0x19a(%rbp), %esi
callq 0x34a0
jmp 0xc1d6
leaq -0x1c8(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
jmp 0xca5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x1c8(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x2f8(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x1f8(%rbp), %rdi
callq 0xb850
jmp 0xc243
movq -0x2f8(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x3220
movq %rax, -0x300(%rbp)
jmp 0xc25f
movq -0x300(%rbp), %rdi
leaq 0x3e61(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x308(%rbp)
jmp 0xc27b
movq -0x308(%rbp), %rdi
leaq 0x3e78(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x310(%rbp)
jmp 0xc297
movq -0x310(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
movq %rax, -0x318(%rbp)
jmp 0xc2b3
movq -0x318(%rbp), %rdi
leaq 0x41c3(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x320(%rbp)
jmp 0xc2cf
movq -0x320(%rbp), %rdi
leaq 0x3e24(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x328(%rbp)
jmp 0xc2eb
movq -0x328(%rbp), %rdi
movzbl -0x19a(%rbp), %esi
callq 0x34a0
movq %rax, -0x330(%rbp)
jmp 0xc307
movq -0x330(%rbp), %rdi
leaq 0x416f(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x338(%rbp)
jmp 0xc323
movq -0x338(%rbp), %rdi
movl -0x1a0(%rbp), %esi
callq 0x34a0
jmp 0xc337
leaq -0x1f8(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x1f8(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x340(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x218(%rbp), %rdi
callq 0xb850
jmp 0xc38d
movq -0x340(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x3220
movq %rax, -0x348(%rbp)
jmp 0xc3a9
movq -0x348(%rbp), %rdi
leaq 0x3d17(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x350(%rbp)
jmp 0xc3c5
movq -0x350(%rbp), %rdi
leaq 0x3d2e(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x358(%rbp)
jmp 0xc3e1
movq -0x358(%rbp), %rdi
movzbl -0x19a(%rbp), %esi
callq 0x34a0
movq %rax, -0x360(%rbp)
jmp 0xc3fd
movq -0x360(%rbp), %rdi
leaq 0x4079(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x368(%rbp)
jmp 0xc419
movq -0x368(%rbp), %rdi
movl -0x1a0(%rbp), %esi
callq 0x34a0
movq %rax, -0x370(%rbp)
jmp 0xc434
movq -0x370(%rbp), %rdi
leaq 0x4045(%rip), %rsi      # 0x10487
callq 0x3250
movq %rax, -0x378(%rbp)
jmp 0xc450
movq -0x378(%rbp), %rdi
leaq 0x3ca3(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x380(%rbp)
jmp 0xc46c
movq -0x380(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
movq %rax, -0x388(%rbp)
jmp 0xc488
movq -0x388(%rbp), %rdi
leaq 0x3bc8(%rip), %rsi      # 0x1005e
callq 0x3250
jmp 0xc49d
leaq -0x218(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x390(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x238(%rbp), %rdi
callq 0xb850
jmp 0xc4f3
movq -0x390(%rbp), %rdi
leaq -0x238(%rbp), %rsi
callq 0x3220
movq %rax, -0x398(%rbp)
jmp 0xc50f
movq -0x398(%rbp), %rdi
leaq 0x3bb1(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x3a0(%rbp)
jmp 0xc52b
movq -0x3a0(%rbp), %rdi
leaq 0x3bc8(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x3a8(%rbp)
jmp 0xc547
movq -0x3a8(%rbp), %rdi
movzbl -0x19a(%rbp), %esi
callq 0x34a0
movq %rax, -0x3b0(%rbp)
jmp 0xc563
movq -0x3b0(%rbp), %rdi
leaq 0x3f13(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x3b8(%rbp)
jmp 0xc57f
movq -0x3b8(%rbp), %rdi
movl -0x1a0(%rbp), %esi
callq 0x34a0
movq %rax, -0x3c0(%rbp)
jmp 0xc59a
movq -0x3c0(%rbp), %rdi
leaq 0x3edf(%rip), %rsi      # 0x10487
callq 0x3250
movq %rax, -0x3c8(%rbp)
jmp 0xc5b6
movq -0x3c8(%rbp), %rdi
leaq 0x3b3d(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x3d0(%rbp)
jmp 0xc5d2
movq -0x3d0(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
movq %rax, -0x3d8(%rbp)
jmp 0xc5ee
movq -0x3d8(%rbp), %rdi
leaq 0x3a62(%rip), %rsi      # 0x1005e
callq 0x3250
jmp 0xc603
leaq -0x238(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x238(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x3e0(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x258(%rbp), %rdi
callq 0xb850
jmp 0xc659
movq -0x3e0(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0x3220
movq %rax, -0x3e8(%rbp)
jmp 0xc675
movq -0x3e8(%rbp), %rdi
leaq 0x3a4b(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x3f0(%rbp)
jmp 0xc691
movq -0x3f0(%rbp), %rdi
leaq 0x3a62(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x3f8(%rbp)
jmp 0xc6ad
movq -0x3f8(%rbp), %rdi
movzbl -0x19b(%rbp), %esi
callq 0x34a0
movq %rax, -0x400(%rbp)
jmp 0xc6c9
movq -0x400(%rbp), %rdi
leaq 0x3dad(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x408(%rbp)
jmp 0xc6e5
movq -0x408(%rbp), %rdi
leaq 0x3a0e(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x410(%rbp)
jmp 0xc701
movq -0x410(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
movq %rax, -0x418(%rbp)
jmp 0xc71d
movq -0x418(%rbp), %rdi
leaq 0x3d59(%rip), %rsi      # 0x10484
callq 0x3250
movq %rax, -0x420(%rbp)
jmp 0xc739
movq -0x420(%rbp), %rdi
leaq 0x39ba(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x428(%rbp)
jmp 0xc755
movq -0x428(%rbp), %rdi
movzbl -0x19a(%rbp), %esi
callq 0x34a0
jmp 0xc76a
leaq -0x258(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x430(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x278(%rbp), %rdi
callq 0xb850
jmp 0xc7c0
movq -0x430(%rbp), %rdi
leaq -0x278(%rbp), %rsi
callq 0x3220
movq %rax, -0x438(%rbp)
jmp 0xc7dc
movq -0x438(%rbp), %rdi
leaq 0x38e4(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x440(%rbp)
jmp 0xc7f8
movq -0x440(%rbp), %rdi
leaq 0x38fb(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x448(%rbp)
jmp 0xc814
movq -0x448(%rbp), %rdi
movzbl -0x19b(%rbp), %esi
callq 0x34a0
jmp 0xc829
leaq -0x278(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x278(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rax
movq %rax, -0x450(%rbp)
movl -0x1a8(%rbp), %esi
leaq -0x298(%rbp), %rdi
callq 0xb850
jmp 0xc87f
movq -0x450(%rbp), %rdi
leaq -0x298(%rbp), %rsi
callq 0x3220
movq %rax, -0x458(%rbp)
jmp 0xc89b
movq -0x458(%rbp), %rdi
leaq 0x3825(%rip), %rsi      # 0x100ce
callq 0x3250
movq %rax, -0x460(%rbp)
jmp 0xc8b7
movq -0x460(%rbp), %rdi
leaq 0x383c(%rip), %rsi      # 0x10101
callq 0x3250
movq %rax, -0x468(%rbp)
jmp 0xc8d3
movq -0x468(%rbp), %rdi
movzbl -0x199(%rbp), %esi
callq 0x34a0
jmp 0xc8e8
leaq -0x298(%rbp), %rdi
callq 0x3528
jmp 0xca2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1d0(%rbp)
movl %eax, -0x1d4(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x3528
jmp 0xca5f
leaq -0x188(%rbp), %rdi
leaq 0x3b5f(%rip), %rsi      # 0x10489
callq 0x3250
movq %rax, -0x470(%rbp)
jmp 0xc938
movq -0x470(%rbp), %rdi
leaq 0x3e8e(%rip), %rsi      # 0x107d4
callq 0x3250
movq %rax, -0x478(%rbp)
jmp 0xc954
movl $0x30, %edi
callq 0x8410
movb %al, -0x479(%rbp)
jmp 0xc966
movq -0x478(%rbp), %rdi
movb -0x479(%rbp), %al
movb %al, -0x299(%rbp)
movzbl -0x299(%rbp), %esi
callq 0x3410
movq %rax, -0x488(%rbp)
jmp 0xc98e
movl $0x8, %edi
callq 0x8430
movl %eax, -0x48c(%rbp)
jmp 0xc9a0
movq -0x488(%rbp), %rdi
movl -0x48c(%rbp), %eax
movl %eax, -0x2a0(%rbp)
movl -0x2a0(%rbp), %esi
callq 0x3300
movq %rax, -0x498(%rbp)
jmp 0xc9c7
movq -0x498(%rbp), %rdi
leaq -0x20a5(%rip), %rsi     # 0xa930
callq 0x30e0
movq %rax, -0x4a0(%rbp)
jmp 0xc9e3
movq -0x4a0(%rbp), %rdi
leaq -0x4391(%rip), %rsi     # 0x8660
callq 0x30e0
movq %rax, -0x4a8(%rbp)
jmp 0xc9ff
movq -0x4a8(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0x33a0
movq %rax, -0x4b0(%rbp)
jmp 0xca17
movq -0x4b0(%rbp), %rdi
leaq -0x45a5(%rip), %rsi     # 0x8480
callq 0x30e0
jmp 0xca2c
jmp 0xca2e
movq -0x2b0(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x3240
jmp 0xca43
leaq -0x198(%rbp), %rdi
callq 0x31d0
movq -0x2a8(%rbp), %rax
addq $0x4b0, %rsp            # imm = 0x4B0
popq %rbp
retq
leaq -0x198(%rbp), %rdi
callq 0x31d0
movq -0x1d0(%rbp), %rdi
callq 0x34c0
nopw (%rax,%rax)