Example #1
0
void handle_syscall(processor_t* p)
{
  reg_t i;

  switch (p->R[2]) // syscall number is given by $v0 ($2)
  {
  case 1: // print an integer
    printf("%d", p->R[4]);
    break;

  case 4: // print a string
    for(i = p->R[4]; i < MEM_SIZE && load_mem(i, SIZE_BYTE); i++)
      printf("%c", load_mem(i, SIZE_BYTE));
    break;

  case 10: // exit
    printf("exiting the simulator\n");
    exit(0);
    break;

  case 11: // print a character
    printf("%c", p->R[4]);
    break;

  default: // undefined syscall
    fprintf(stderr, "%s: illegal syscall number %d\n", __FUNCTION__, p->R[2]);
    exit(-1);
    break;
  }
}
int main(int argc, char *argv[])
{
    FILE *code_file;
    int max_steps = 10000;

    // edit by leo
    init_sharemem();
    // edit end
	

    state_ptr s = new_state(MEM_SIZE);
    
    mem_t saver = copy_reg(s->r);
    mem_t savem;
    int step = 0;

    stat_t e = STAT_AOK;

    if (argc < 2 || argc > 3)
	usage(argv[0]);
    code_file = fopen(argv[1], "r");
    if (!code_file) {
	fprintf(stderr, "Can't open code file '%s'\n", argv[1]);
	exit(1);
    }
    
    if (!load_mem(s->m, code_file, 1)) {
	printf("Exiting\n");
	return 1;
    }    
    savem = copy_mem(s->m);
  
    // edit by leo
    // printf("error happen after here!\n");
    // edit end
    if (argc > 2)
	max_steps = atoi(argv[2]);

    for (step = 0; step < max_steps && e == STAT_AOK; step++)
	e = step_state(s, stdout);
    
    
    printf("Stopped in %d steps at PC = 0x%x.  Status '%s', CC %s\n",
	   step, s->pc, stat_name(e), cc_name(s->cc));

    printf("Changes to registers:\n");
    diff_reg(saver, s->r, stdout);

    printf("\nChanges to memory:\n");
    diff_mem(savem, s->m, stdout);

    free_state(s);
    free_reg(saver);
    free_mem(savem);

    return 0;
}
Example #3
0
bgfx::ShaderHandle shader_manager::load_shader(std::string name)
{
	std::string shader_path;
	switch (bgfx::getRendererType())
	{
		case bgfx::RendererType::Noop:
		case bgfx::RendererType::Direct3D9:
			shader_path = m_options.bgfx_path() + std::string("/shaders/dx9/");
			break;

		case bgfx::RendererType::Direct3D11:
		case bgfx::RendererType::Direct3D12:
			shader_path = m_options.bgfx_path() + std::string("/shaders/dx11/");
			break;

		case bgfx::RendererType::Gnm:
			shader_path = m_options.bgfx_path() + std::string("/shaders/pssl/");
			break;

		case bgfx::RendererType::Metal:
			shader_path = m_options.bgfx_path() + std::string("/shaders/metal/");
			break;

		case bgfx::RendererType::OpenGL:
			shader_path = m_options.bgfx_path() + std::string("/shaders/glsl/");
			break;

		case bgfx::RendererType::OpenGLES:
			shader_path = m_options.bgfx_path() + std::string("/shaders/essl/");
			break;

		case bgfx::RendererType::Vulkan:
			shader_path = m_options.bgfx_path() + std::string("/shaders/spirv/");
			break;

		default:
			fatalerror("Unknown BGFX renderer type %d", bgfx::getRendererType());
	}

	const bgfx::Memory* mem = load_mem(shader_path + name + ".bin");
	if (mem != nullptr)
	{
		bgfx::ShaderHandle handle = bgfx::createShader(mem);

		m_shaders[name] = handle;

		return handle;
	}

	return BGFX_INVALID_HANDLE;
}
int main(int argc, char *argv[])
{
    FILE *code_file;
    int max_steps = 10000;

    state_ptr s = new_state(MEM_SIZE);
    mem_t saver = copy_reg(s->r);
    mem_t savem;
    int step = 0;

    exc_t e = EXC_NONE;

    if (argc < 2 || argc > 3)
	usage(argv[0]);
    code_file = fopen(argv[1], "r");
    if (!code_file) {
	fprintf(stderr, "Can't open code file '%s'\n", argv[1]);
	exit(1);
    }

    if (!load_mem(s->m, code_file, 1)) {
	printf("Exiting\n");
	return 1;
    }

    savem = copy_mem(s->m);
  
    if (argc > 2)
	max_steps = atoi(argv[2]);

    for (step = 0; step < max_steps && e == EXC_NONE; step++)
	e = step_state(s, stdout);

    printf("Stopped in %d steps at PC = 0x%x.  Exception '%s', CC %s\n",
	   step, s->pc, exc_name(e), cc_name(s->cc));

    printf("Changes to registers:\n");
    diff_reg(saver, s->r, stdout);

    printf("\nChanges to memory:\n");
    diff_mem(savem, s->m, stdout);

    free_state(s);
    free_reg(saver);
    free_mem(savem);

    return 0;
}
Example #5
0
int simLoadCodeCmd(ClientData clientData, Tcl_Interp *interp,
		   int argc, char *argv[])
{
    FILE *object_file;
    int code_count;
    sim_interp = interp;
    if (argc != 2) {
	interp->result = "One argument required";
	return TCL_ERROR;
    }
    object_file = fopen(argv[1], "r");
    if (!object_file) {
	sprintf(tcl_msg, "Couldn't open code file '%s'", argv[1]);
	interp->result = tcl_msg;
	return TCL_ERROR;
    }
    sim_reset();
    code_count = load_mem(mem, object_file, 0);
    post_load_mem = copy_mem(mem);
    sprintf(tcl_msg, "%d", code_count);
    interp->result = tcl_msg;
    fclose(object_file);
    return TCL_OK;
}
Example #6
0
int execute(void)
{
    long long tmp;
    int cmp;
    switch(opcode)
    {
        //add
        case 0x18:
            ra += load_mem(&memory[path],3);
            break;
        //and
        case 0x40:
            ra &= load_mem(&memory[path],3);
            break;
        //comp
        // = -> 0b001
        // > -> 0b010
        // < -> 0b100
        // save status in register sw
        case 0x28:
            cmp = load_mem(&memory[path],3);
            if(ra==cmp)
                rsw = 0x1;
            else if (ra>cmp)
                rsw = 0x2;
            else if (ra<cmp)
                rsw = 0x4;
            else
                rsw = 0;
            break;
        //div
        case 0x24:
            ra /= load_mem(&memory[path],3);
            break;
        //j
        case 0x3C:
            rpc = path;
            break;
        //jeq
        case 0x30:
            if(rsw==0x1)
                rpc = path;
            break;
        //jgt
        case 0x34:
            if(rsw==0x2)
                rpc = path;
            break;
        //jlt
        case 0x38:
            if(rsw==0x4)
                rpc = path;
            break;
        //jsub
        case 0x48:
            rl = rpc;
            rpc = path;
            break;
        //lda
        case 0x00:
            ra = load_mem(&memory[path],3);
            break;
        //ldch
        case 0x50:
            ra = (ra&0xFFFF00) + load_mem(&memory[path], 1);
            break;
        //ldl
        case 0x08:
            rl = load_mem(&memory[path],3);
            break;
        //ldx
        case 0x04:
            rx = load_mem(&memory[path],3);
            break;
        //mul
        case 0x20:
            tmp = (long long) ra * load_mem(&memory[path],3);
            ra = (int) (0xFFFFFF & tmp);
            break;
        //or
        case 0x44:
            ra |= load_mem(&memory[path],3);
            break;
        //rsub
        case 0x4C:
            rpc = rl;
            break;
        //sta
        case 0x0C:
            //incomplete
            save_mem(ra, &memory[path], 3);
            break;
        //stch
        case 0x54:
            save_mem(ra, &memory[path], 1);
            break;
        //stl
        case 0x14:
            save_mem(rl, &memory[path], 3);
            break;
        //stsw
        case 0xE8:
            save_mem(rsw, &memory[path], 3);
            break;
        //stx
        case 0x10:
            save_mem(rx, &memory[path], 3);
            break;
        //sub
        case 0x1C:
            ra -= load_mem(&memory[path], 3);
            break;
        //tix
        case 0x2C:         
            cmp = load_mem(&memory[path],3);
            rx++;
            if(rx==cmp)
                rsw = 0x1;
            else if (rx>cmp)
                rsw = 0x2;
            else if (rx<cmp)
                rsw = 0x4;
            else
                rsw = 0;
            break;

        //td
        case 0xE0:
            rsw = test_device(memory[path]);
            break;
        //rd
        case 0xD8:
            ra = (ra&0xFFFF00) + read_device(memory[path]);
            break;
        //wd
        case 0xDC:
            write_device(memory[path], (ra&0x0000FF));
            break;
       //break
        case 0xFF:
            return 10;
            break;   
        default: 
            printf("CPU Error: Could not found opcode\n");
            printf("rpc= %06X\n", rpc);
            return 11;
            break;
    }
    return 0;
}
Example #7
0
/* 
 * run_tty_sim - Run the simulator in TTY mode
 */
static void run_tty_sim() 
{
    int icount = 0;
    exc_t status = EXC_NONE;
    cc_t result_cc = 0;
    int byte_cnt = 0;
    mem_t mem0, reg0;
    state_ptr isa_state = NULL;


    /* In TTY mode, the default object file comes from stdin */
    if (!object_file) {
	object_file = stdin;
    }

    /* Initializations */
    if (verbosity >= 2)
	sim_set_dumpfile(stdout);
    sim_init();

    /* Emit simulator name */
    printf("%s\n", simname);

    byte_cnt = load_mem(mem, object_file, 1);
    if (byte_cnt == 0) {
	fprintf(stderr, "No lines of code found\n");
	exit(1);
    } else if (verbosity >= 2) {
	printf("%d bytes of code read\n", byte_cnt);
    }
    fclose(object_file);
    if (do_check) {
	isa_state = new_state(0);
	free_mem(isa_state->r);
	free_mem(isa_state->m);
	isa_state->m = copy_mem(mem);
	isa_state->r = copy_mem(reg);
	isa_state->cc = cc;
    }

    mem0 = copy_mem(mem);
    reg0 = copy_mem(reg);
    

    icount = sim_run(instr_limit, &status, &result_cc);
    if (verbosity > 0) {
	printf("%d instructions executed\n", icount);
	printf("Exception status = %s\n", exc_name(status));
	printf("Condition Codes: %s\n", cc_name(result_cc));
	printf("Changed Register State:\n");
	diff_reg(reg0, reg, stdout);
	printf("Changed Memory State:\n");
	diff_mem(mem0, mem, stdout);
    }
    if (do_check) {
	exc_t e = EXC_NONE;
	int step;
	bool_t match = TRUE;

	for (step = 0; step < instr_limit && e == EXC_NONE; step++) {
	    e = step_state(isa_state, stdout);
	}

	if (diff_reg(isa_state->r, reg, NULL)) {
	    match = FALSE;
	    if (verbosity > 0) {
		printf("ISA Register != Pipeline Register File\n");
		diff_reg(isa_state->r, reg, stdout);
	    }
	}
	if (diff_mem(isa_state->m, mem, NULL)) {
	    match = FALSE;
	    if (verbosity > 0) {
		printf("ISA Memory != Pipeline Memory\n");
		diff_mem(isa_state->m, mem, stdout);
	    }
	}
	if (isa_state->cc != result_cc) {
	    match = FALSE;
	    if (verbosity > 0) {
		printf("ISA Cond. Codes (%s) != Pipeline Cond. Codes (%s)\n",
		       cc_name(isa_state->cc), cc_name(result_cc));
	    }
	}
	if (match) {
	    printf("ISA Check Succeeds\n");
	} else {
	    printf("ISA Check Fails\n");
	}
    }
}
Example #8
0
/* 
 * run_tty_sim - Run the simulator in TTY mode
 */
static void run_tty_sim() 
{
    int icount = 0;
    byte_t run_status = STAT_AOK;
    cc_t result_cc = 0;
    int byte_cnt = 0;
    mem_t mem0, reg0;
    state_ptr isa_state = NULL;


    /* In TTY mode, the default object file comes from stdin */
    if (!object_file) {
        object_file = stdin;
    }

    if (verbosity >= 2)
        sim_set_dumpfile(stdout);
    sim_init();

    /* Emit simulator name */
    if (verbosity >= 2)
        printf("%s\n", simname);

    byte_cnt = load_mem(mem, object_file, 1, START_PLACE);
    if (byte_cnt == 0) {
        fprintf(stderr, "No lines of code found\n");
        exit(1);
    } else if (verbosity >= 2) {
        printf("%d bytes of code read\n", byte_cnt);
    }
    fclose(object_file);
    if (do_check) {
        isa_state = new_state(0);
        free_reg(isa_state->r);
        free_mem(isa_state->m);
        isa_state->m = copy_mem(mem);
        isa_state->r = copy_reg(reg);
        isa_state->cc = cc;
    }

    if(verbosity > 0){
        mem0 = copy_mem(mem);
        reg0 = copy_reg(reg);
    }

    icount = sim_run_pipe(instr_limit, 5*instr_limit, &run_status, &result_cc);
    if (verbosity > 0) {
        printf("%d instructions executed\n", icount);
        printf("Status = %s\n", stat_name(run_status));
        printf("Condition Codes: %s\n", cc_name(result_cc));
        printf("Changed Register State:\n");
        diff_reg(reg0, reg, stdout);
        printf("Changed Memory State:\n");
        diff_mem(mem0, mem, stdout);
    }
    if (do_check) {
        exit(0);
        byte_t e = STAT_AOK;
        int step;
        bool_t match = TRUE;

        for (step = 0; step < instr_limit && e == STAT_AOK; step++) {
            e = step_state(isa_state, stdout);
        }

        if (diff_reg(isa_state->r, reg, NULL)) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Register != Pipeline Register File\n");
                diff_reg(isa_state->r, reg, stdout);
            }
        }
        if (diff_mem(isa_state->m, mem, NULL)) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Memory != Pipeline Memory\n");
                diff_mem(isa_state->m, mem, stdout);
            }
        }
        if (isa_state->cc != result_cc) {
            match = FALSE;
            if (verbosity > 0) {
                printf("ISA Cond. Codes (%s) != Pipeline Cond. Codes (%s)\n",
                        cc_name(isa_state->cc), cc_name(result_cc));
            }
        }
        if (match) {
            printf("ISA Check Succeeds\n");
        } else {
            printf("ISA Check Fails\n");
        }
    }

    /* Emit CPI statistics */
    {
        double cpi = instructions > 0 ? (double) cycles/instructions : 1.0;
        printf("%d CPI: %d cycles/%d instructions = %.2f\n", PSIM_ID,
                cycles, instructions, cpi);
    }
}
Example #9
0
void execute_one_inst(processor_t* p, int prompt, int print_regs)
{
  inst_t inst;

  /* fetch an instruction */
  inst.bits = load_mem(p->pc, SIZE_WORD);

  /* interactive-mode prompt */
  if(prompt)
  {
    if (prompt == 1) {
      printf("simulator paused, enter to continue...");
      while(getchar() != '\n')
        ;
    }
    printf("%08x: ",p->pc);
    disassemble(inst);
  }
	uint32_t temp;
  switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */
  {
  case 0x0: // opcode == 0x0 (SPECIAL)
  
    switch (inst.rtype.funct) {
    	case 0x0: // funct == 0x0 (sll)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt;
     	 	p->pc += 4;
      	break;    		
    
    	case 0x2: // funct == 0x0 (srl)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt;
     	 	p->pc += 4;
      	break;   
      
      case 0x3: // funct == 0x0 (sra)
      	p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rt] >> inst.rtype.shamt;
    		p->pc += 4;
      	break;
      
      case 0x8: // funct == 0x8 (jr)
      	p->pc = p->R[inst.rtype.rs];
    		break;
    	
    	case 0x9: // funct == 0x9 (jalr)
    		temp = p->pc + 4;
    		p->pc = p->R[inst.rtype.rs];
    		p->R[inst.rtype.rd] = temp;
    		break;
				
    	case 0x10: // funct == 0x10 (mfhi)
    		p->R[inst.rtype.rd] = p->RHI;
    		p->pc += 4;
    		break;
    
    	case 0x12: // funct == 0x12 (mflo)
    		p->R[inst.rtype.rd] = p->RLO;
    		p->pc += 4;
    		break;
    	
    	case 0x18: // funct == 0x18 (mult)
    		perform_mult(p->R[inst.rtype.rs], p->R[inst.rtype.rt], &(p->RHI), &(p->RLO));
    		p->pc += 4;
    		break;
    	
    	case 0x21: // funct == 0x21 (addu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x23: // funct == 0x23 (subu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rd];
    		p->pc += 4;
    		break;
    	
    	case 0x24: // funct == 0x24 (and)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x26: // funct == 0x26 (xor)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x27: // funct == 0x27 (nor)
    		p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] | p->R[inst.rtype.rt]);
    		p->pc += 4;
    		break;
    	
    	case 0x2a: // funct == 0x2a (slt)
    		p->R[inst.rtype.rd] = (signed)p->R[inst.rtype.rs] < (signed)p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    	
    	case 0x2b: // funct == 0x2a (sltu)
    		p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt];
    		p->pc += 4;
    		break;
    		
    	case 0xc: // funct == 0xc (SYSCALL)
      	handle_syscall(p);
     	 	p->pc += 4;
      	break;

    	case 0x25: // funct == 0x25 (OR)
      	p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt];
      	p->pc += 4;
      	break;

    	default: // undefined funct
      	fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits);
      	exit(-1);
      	break;
    	}
    break;
	
	case 0x3: // opcode == 0x3 (jal)
		p->R[31] = p->pc += 4;
		p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
		break;
	
	case 0x4: // opcode == 0x4 (beq)
		if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) {
			p->pc += 4 + signext(inst.itype.imm)*4;
		}
		else {
			p->pc += 4;
		}
		break;
	
	case 0x5: // opcode == 0x4 (bne)
		if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) {
			p->pc += 4 + signext(inst.itype.imm)*4;
		}
		else {
			p->pc += 4;
		}
		break;
	
	case 0x9: // opcode == 0x9 (addiu)
		p->R[inst.rtype.rt] = p->R[inst.itype.rs] + signext(inst.itype.imm);
    p->pc += 4;
    break;
  
  case 0xa: // opcode == 0xa (slti)
  	p->R[inst.itype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm);
    p->pc += 4;
    break;
		
	case 0xb: // opcode == 0xb (sltiu)
		p->R[inst.rtype.rt] = (signed)p->R[inst.itype.rs] < signext(inst.itype.imm);
    p->pc += 4;
    break;
  
  case 0xc: // opcode == 0xc (andi)
  	p->R[inst.rtype.rt] = p->R[inst.itype.rs] & zeroext(inst.itype.imm);
  	p->pc += 4;
  	break;
  
  case 0xe: // opcode == 0xe (xori)
  	p->R[inst.rtype.rt] = p->R[inst.itype.rs] ^ zeroext(inst.itype.imm);
  	p->pc += 4;
  	break;
  
  case 0xf: // opcode == 0xf (lui)
  	p->R[inst.rtype.rt] = inst.itype.imm << 16;
  	p->pc += 4;
  	break;
  
  case 0x20: // opcode == 0x20 (lb)
  	p->R[inst.rtype.rt] = signext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE));
  	p->pc += 4;
  	break;
  
  case 0x23: // opcode == 0x23 (lw)
  	p->R[inst.rtype.rt] = load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD);
  	p->pc += 4;
  	break;
  
  case 0x24: // opcode == 0x24 (lbu)
  	p->R[inst.itype.rt] = zeroext(load_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD));
  	p->pc += 4;
  	break;
  
  case 0x28: // opcode == 0x28 (sb)
  	store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]);
  	p->pc += 4;
  	break;
  
  case 0x2b: // opcode == 0x20 (sw)
  	store_mem(p->R[inst.itype.rs] + signext(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]);
  	p->pc += 4;
  	break;
	
  case 0xd: // opcode == 0xd (ORI)
    p->R[inst.itype.rt] = (p->R[inst.itype.rs] | inst.itype.imm);
    p->pc += 4;
    break;

  case 0x2: // opcode == 0x2 (J)
    p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
    break;

  default: // undefined opcode
    fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits);
    exit(-1);
    break;
  }

  // enforce $0 being hard-wired to 0
  p->R[0] = 0;

  if(print_regs) {
    print_registers(p);
	}
}
Example #10
0
void execute_one_inst(processor_t* p, int prompt, int print_regs)
{
	inst_t inst;
	
	/* fetch an instruction */
	inst.bits = load_mem(p->pc, SIZE_WORD);
	
	/* interactive-mode prompt */
	if(prompt)
	{
		if (prompt == 1) {
			printf("simulator paused, enter to continue...");
			while(getchar() != '\n')
				;
		}
		printf("%08x: ",p->pc);
		disassemble(inst);
	}
	
	switch (inst.rtype.opcode) /* could also use e.g. inst.itype.opcode */
	{
		case 0x0: // opcode == 0x0 (SPECIAL)
			
			switch (inst.rtype.funct)
		{
			case 0x0: //opcode = 0x0 (SLL)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rt] << inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x2: //opcode = 0x2 (SRL)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rt] >> inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x3: //opcode = 0x3 (SRA)
				p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rt]) >> inst.rtype.shamt;
				p->pc += 4;
				break;
				
			case 0x8: //opcode = 0x8 (JR)
				p->pc = p->R[inst.rtype.rs];
				break;
				
			case 0x9: //opcode = 0x9 (JALR)
			{
				int tmp = p->pc + 4;
				p->pc = p->R[inst.rtype.rs];
				p->R[inst.rtype.rd] = tmp;
			}
				break;
				
			case 0xc: // funct == 0xc (SYSCALL)
				handle_syscall(p);
				p->pc += 4;
				break;
				
			case 0x21: //opcode = 0x21 (ADDU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] + p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x23: //opcode = 0x23 (SUBU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] - p->R[inst.rtype.rt]; 
				p->pc += 4;
				break;
				
			case 0x24: //opcode = 0x24 (AND)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] & p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x25: // funct == 0x25 (OR)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] | p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x26: // funct == 0x26 (XOR)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			case 0x27: // funct == 0x27 (NOR)
				p->R[inst.rtype.rd] = ~(p->R[inst.rtype.rs] ^ p->R[inst.rtype.rt]);
				p->pc += 4;
				break;
				
			case 0x2a: // funct == 0x2a (SLT)
				p->R[inst.rtype.rd] = (signed int)(p->R[inst.rtype.rs]) < (signed int)(p->R[inst.rtype.rt]);
				p->pc += 4;
				break;
				
			case 0x2b: // funct == 0x2b (SLTU)
				p->R[inst.rtype.rd] = p->R[inst.rtype.rs] < p->R[inst.rtype.rt];
				p->pc += 4;
				break;
				
			default: // undefined funct
				fprintf(stderr, "%s: pc=%08x, illegal instruction=%08x\n", __FUNCTION__, p->pc, inst.bits);
				exit(-1);
				break;
		}
			break;
			
		case 0x2: // opcode == 0x2 (J)
			p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
			break;
			
		case 0x3: // opcode == 0x3 (JAL)
			p->R[31] = p->pc + 4;
			p->pc = ((p->pc+4) & 0xf0000000) | (inst.jtype.addr << 2);
			break;
			
		case 0x4: // opcode == 0x4 (BEQ)
			if (p->R[inst.itype.rs] == p->R[inst.itype.rt]) {
				p->pc += (4 + (((int16_t)inst.itype.imm) << 2));
			}
			else {
				p->pc += 4;
			}
			break;
			
		case 0x5: // opcode == 0x5 (BNE)
			if (p->R[inst.itype.rs] != p->R[inst.itype.rt]) {
				p->pc += (4 + (((int16_t)inst.itype.imm) << 2));
			}
			else {
				p->pc += 4;
			}
			break;
			
		case 0x9: // opcode == 0x9 (ADDIU)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] + (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xa: // opcode == 0xa (SLTI)
			p->R[inst.itype.rt] = (signed int)p->R[inst.itype.rs] < (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xb: // opcode == 0xb (SLTIU)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] < (int16_t)(inst.itype.imm);
			p->pc += 4;
			break;
			
		case 0xc: // opcode == 0xc (ANDI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] & inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xd: // opcode == 0xd (ORI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] | inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xe: // opcode == 0xe (XORI)
			p->R[inst.itype.rt] = p->R[inst.itype.rs] ^ inst.itype.imm;
			p->pc += 4;
			break;
			
		case 0xf: // opcode == 0xf (LUI)
			p->R[inst.itype.rt] = inst.itype.imm << 16;
			p->pc += 4;
			break;
			
		case 0x20: // opcode == 0x20 (LB)
			p->R[inst.itype.rt] = (int8_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE));  
			p->pc += 4;
			break;
			
		case 0x21: // opcode == 0x21 (LH)
			p->R[inst.itype.rt] = (int16_t)(load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD));  
			p->pc += 4;
			break;
			
		case 0x23: // opcode == 0x23 (LW)
			p->R[inst.itype.rt] = (int32_t)load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD);  
			p->pc += 4;
			break;
			
		case 0x24: // opcode == 0x24 (LBU)
			p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE);  
			p->pc += 4;
			break;
			
		case 0x25: // opcode == 0x25 (LHU)
			p->R[inst.itype.rt] = load_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD);  
			p->pc += 4;
			break;
			
		case 0x28: // opcode == 0x28 (SB)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_BYTE, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		case 0x29: // opcode == 0x29 (SH)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_HALF_WORD, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		case 0x2b: // opcode == 0x2b (SW)
			store_mem(p->R[inst.itype.rs] + (int16_t)(inst.itype.imm), SIZE_WORD, p->R[inst.itype.rt]);
			p->pc += 4;
			break;
			
		default: // undefined opcode
			fprintf(stderr, "%s: pc=%08x, illegal instruction: %08x\n", __FUNCTION__, p->pc, inst.bits);
			exit(-1);
			break;
	}
	
	// enforce $0 being hard-wired to 0
	p->R[0] = 0;
	
	if(print_regs)
		print_registers(p);
}