#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>

int getfield( unsigned int word, int start, int width ) { // MSB=0, LSB=31
  return (word>>(32-(start+width))) & ((1<<width)-1);
}

int fixsign( unsigned int imm ) { // sign extends a 16-bit value
  return imm | ((imm & 0x8000)?0xffff0000:0);
}

int main (int argc, char *argv[]) {
  char reg[32][5]={"zero","at","v0","v1","a0","a1","a2","a3",
		   "t0","t1","t2","t3","t4","t5","t6","t7",
		   "s0","s1","s2","s3","s4","s5","s6","s7",
		   "t8","t9","k0","k1","gp","sp","fp","ra"};
  unsigned int pc = 0x00400000;       /* spim puts text starting there */
  unsigned int instr,opcode,funct,rt,rs,rd,imm,shamt,target,pseudo;
  unsigned int unsigned_imm;

  printf("__start:\n");
  while (fread(&instr, 4, 1, stdin)) {
    instr=ntohl(instr);
    printf("L%08x: ", pc);
      
    opcode = getfield(instr,0,6);
    funct  = getfield(instr,26,6);
    rs     = getfield(instr,6,5);
    rt     = getfield(instr,11,5);
    rd     = getfield(instr,16,5); 
    shamt  = getfield(instr,21,5);
    unsigned_imm = getfield(instr,16,16);
    imm    = fixsign(unsigned_imm);
    target = getfield(instr,6,26);
    if( opcode==0x00 ) {
      pseudo = ((funct==37) && ((rd + rs + rt) == 0 )) || (funct==33 && rs==0);
           if( funct== 0 ) printf("sll $%s, $%s, %d",  reg[rd],reg[rt],shamt);
      else if( funct== 2 ) printf("srl $%s, $%s, %d",  reg[rd],reg[rt],shamt);
      else if( funct== 3 ) printf("sra $%s, $%s, %d",  reg[rd],reg[rt],shamt);
      else if( funct== 8 ) printf("jr $%s",            reg[rs]);
      else if( funct== 9 ) printf("jalr $%s, $%s",     reg[rd],reg[rs]);
      else if( funct==16 ) printf("mfhi $%s",          reg[rd]);
      else if( funct==18 ) printf("mflo $%s",          reg[rd]);
      else if( funct==24 ) printf("mult $%s, $%s",     reg[rs],reg[rt]);
      else if( funct==25 ) printf("multu $%s, $%s",    reg[rs],reg[rt]);
      else if( funct==26 ) printf("div $%s, $%s",      reg[rs],reg[rt]);
      else if( funct==27 ) printf("divu $%s, $%s",     reg[rs],reg[rt]);
      else if( funct==32 ) printf("add $%s, $%s, $%s", reg[rd],reg[rs],reg[rt]);
      else if( funct==33 && !pseudo ) printf("addu $%s, $%s, $%s",reg[rd],reg[rs],reg[rt]);
      else if( funct==33 && pseudo )  printf("move $%s, $%s",     reg[rd],reg[rt]);
      else if( funct==34 ) printf("sub $%s, $%s, $%s", reg[rd],reg[rs],reg[rt]);
      else if( funct==35 ) printf("subu $%s, $%s, $%s",reg[rd],reg[rs],reg[rt]);
      else if( funct==36 ) printf("and $%s, $%s, $%s", reg[rd],reg[rs],reg[rt]);
      else if( funct==37 && !pseudo ) printf("or $%s, $%s, $%s",  reg[rd],reg[rs],reg[rt]);
      else if( funct==37 && pseudo )  printf("nop");
      else if( funct==42 ) printf("slt $%s, $%s, $%s", reg[rd],reg[rs],reg[rt]);
      else if( funct==43 ) printf("sltu $%s, $%s, $%s",reg[rd],reg[rs],reg[rt]);
      else printf("nop #unknown: 0x%08x",instr);
    } else if( opcode==0x01 ) {
           if( rt==0 ) printf("bltz $%s, L%08x",reg[rs],pc+4+imm*4);
      else if( rt==1 ) printf("bgez $%s, L%08x",reg[rs],pc+4+imm*4);
      else printf("nop #unknown: 0x%08x",instr);
    } else
           if( opcode==0x02 ) printf("j L%08x",            (0xf0000000&(pc+4)) | (target<<2) ); 
      else if( opcode==0x03 ) printf("jal L%08x",          (0xf0000000&(pc+4)) | (target<<2));
      else if( opcode==0x04 ) printf("beq $%s, $%s, L%08x",reg[rs],reg[rt],pc+4+imm*4);
      else if( opcode==0x05 ) printf("bne $%s, $%s, L%08x",reg[rs],reg[rt],pc+4+imm*4);
      else if( opcode==0x06 ) printf("blez $%s, L%08x",    reg[rs],pc+4+imm*4);
      else if( opcode==0x07 ) printf("bgtz $%s, L%08x",    reg[rs],pc+4+imm*4);
      else if( opcode==0x08 ) printf("addi $%s, $%s, %d",  reg[rt],reg[rs],imm);
      else if( opcode==0x09 ) printf("addiu $%s, $%s, %d", reg[rt],reg[rs],imm);
      else if( opcode==0x0a ) printf("slti $%s, $%s, %d",  reg[rt],reg[rs],imm);
      else if( opcode==0x0b ) printf("sltiu $%s, $%s, %d", reg[rt],reg[rs],imm);
      else if( opcode==0x0c ) printf("andi $%s, $%s, 0x%04x",  reg[rt],reg[rs],unsigned_imm);
      else if( opcode==0x0d ) printf("ori $%s, $%s, 0x%04x",   reg[rt],reg[rs],unsigned_imm);
      else if( opcode==0x0f ) printf("lui $%s, 0x%04x",      reg[rt],unsigned_imm);
      else if( opcode==0x20 ) printf("lb $%s, %d($%s)",    reg[rt],imm,reg[rs]);
      else if( opcode==0x23 ) printf("lw $%s, %d($%s)",    reg[rt],imm,reg[rs]);
      else if( opcode==0x24 ) printf("lbu $%s, %d($%s)",   reg[rt],imm,reg[rs]);
      else if( opcode==0x28 ) printf("sb $%s, %d($%s)",    reg[rt],imm,reg[rs]);
      else if( opcode==0x2b ) printf("sw $%s, %d($%s)",    reg[rt],imm,reg[rs]);
      else printf("nop #unknown: 0x%08x",instr);

    printf("\n");
    pc += 4;
  }
  printf("done\n");
  return 0;
}


