예제 #1
0
파일: y86sim.c 프로젝트: Azard/icslabs
/* 
 * nexti: execute single instruction and return status.
 * args
 *     sim: the y86 image with PC, register and memory
 *
 * return
 *     STAT_AOK: continue
 *     STAT_HLT: halt
 *     STAT_ADR: invalid instruction address
 *     STAT_INS: invalid instruction, register id, data address, stack address, ...
 */
stat_t nexti(y86sim_t *sim)
{
    byte_t codefun = 0;
    itype_t icode;
    alu_t ifun;
    long_t next_pc = sim->pc;
	regid_t rA = REG_NONE;
	regid_t rB = REG_NONE;
	long_t im_value = 0;

    /* get code and function (1 byte) */
    if (!get_byte_val(sim->m, next_pc, &codefun)) {
        err_print("PC = 0x%x, Invalid instruction address", sim->pc);
        return STAT_ADR;
    }
    icode = GET_ICODE(codefun);
    ifun = GET_FUN(codefun);
    next_pc++;

    /* get registers if needed (1 byte) */
	byte_t reg = 0;
	switch (icode)
	{
		case I_RRMOVL:
		case I_IRMOVL:
		case I_RMMOVL:
		case I_MRMOVL:
		case I_ALU:
		case I_PUSHL:
		case I_POPL:
			if(!get_byte_val(sim->m, next_pc, &reg)) {
				err_print("PC = 0x%x, Invalid instruction address", sim->pc);
				return STAT_ADR;
			}
			rA = GET_REGA(reg);
			rB = GET_REGB(reg);
			next_pc++;

		case I_HALT:case I_NOP:case I_JMP:case I_CALL:case I_RET:default:
			break;
	}

    /* get immediate if needed (4 bytes) */
	switch(icode)
	{
		case I_IRMOVL:
		case I_RMMOVL:
		case I_MRMOVL:
		case I_JMP:
		case I_CALL:
			if(!get_long_val(sim->m, next_pc, &im_value)) {
				err_print("PC = 0x%x, Invalid instruction address", sim->pc);				return STAT_ADR;
			}
			next_pc += 4;

		case I_HALT:case I_NOP:case I_RRMOVL:case I_ALU:
		case I_RET:case I_PUSHL:case I_POPL:default:
			break;	
	}

    /* execute the instruction */
    switch (icode) {
      case I_HALT: /* 0:0 */
        return STAT_HLT;
        break;
      case I_NOP: /* 1:0 */
        sim->pc = next_pc;
        break;

      case I_RRMOVL:/* 2:x regA:regB */
		{
			long_t rr_temp = get_reg_val(sim->r, rA);
			if (cond_doit(sim->cc, ifun))	
				set_reg_val(sim->r, rB, rr_temp);
			sim->pc = next_pc;	
			break;
		}

      case I_IRMOVL: /* 3:0 F:regB imm */
		{
			set_reg_val(sim->r, rB, im_value);
			sim->pc = next_pc;
			break;
		}

      case I_RMMOVL: /* 4:0 regA:regB imm */
		{
			long_t rm_temp_rA = get_reg_val(sim->r, rA);
			long_t rm_temp_rB = get_reg_val(sim->r, rB);
			set_long_val(sim->m, im_value+rm_temp_rB, rm_temp_rA);
			sim->pc = next_pc;
			break;
		}

      case I_MRMOVL: /* 5:0 regB:regA imm */
		{ 
			long_t mr_temp_rB = get_reg_val(sim->r, rB);
			long_t temp_val = 0;
			if(!get_long_val(sim->m, im_value+mr_temp_rB, &temp_val))
			{
				err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, im_value+mr_temp_rB);
				return STAT_ADR;
			}
			set_reg_val(sim->r, rA, temp_val);
			sim->pc = next_pc;
			break;
		}

	  case I_ALU: /* 6:x regA:regB */
		{
			long_t rA_val = get_reg_val(sim->r, rA);
			long_t rB_val = get_reg_val(sim->r, rB);
			long_t alu_result = 0;
			switch (ifun)
			{
				case A_ADD:case A_SUB:case A_AND:case A_XOR:
					alu_result = compute_alu(ifun, rA_val, rB_val);
					set_reg_val(sim->r, rB, alu_result);
					break;
				case A_NONE:default:
					return STAT_INS;
			}
			sim->cc = compute_cc(ifun, rA_val, rB_val, alu_result);
			sim->pc = next_pc;
			break;
		}

      case I_JMP: /* 7:x imm */
		{
			if (cond_doit(sim->cc, ifun))
				sim->pc = im_value;
			else
				sim->pc=next_pc;
			break;

		}
      case I_CALL: /* 8:x imm */
		{
			long_t esp = get_reg_val(sim->r, REG_ESP);
			esp -= 4;
			set_reg_val(sim->r, REG_ESP, esp);
			if (esp < 0)
			{
				err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp);
				return STAT_ADR;
			}
			set_long_val(sim->m, esp, next_pc);
			sim->pc = im_value;
			break;
		}

      case I_RET: /* 9:0 */
		{
			long_t esp = get_reg_val(sim->r, REG_ESP);
			long_t return_value = 0;
			if(!get_long_val(sim->m, esp, &return_value))
			{
				err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, esp);
				return STAT_ADR;
			}
			esp += 4;
			set_reg_val(sim->r, REG_ESP, esp);
			if (esp < 0)
			{
				err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp);
				return STAT_ADR;
			}
			sim->pc = return_value;
			break;
		}

      case I_PUSHL: /* A:0 regA:F */
		{
			long_t esp = get_reg_val(sim->r, REG_ESP);
			long_t rA_value  = get_reg_val(sim->r, rA);
			esp -= 4;
			set_reg_val(sim->r, REG_ESP, esp);
			if (esp < 0)
			{
				err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp);
				return STAT_ADR;
			}
			set_long_val(sim->m, esp, rA_value);
			sim->pc = next_pc;
			break;
		}

      case I_POPL: /* B:0 regA:F */
		{
			long_t esp = get_reg_val(sim->r, REG_ESP);
			long_t temp_value = 0;
			if(!get_long_val(sim->m, esp, &temp_value))
			{
				err_print("PC = 0x%x, Invalid instruction address", esp);
				return STAT_ADR;
			}
			esp += 4;
			set_reg_val(sim->r, REG_ESP, esp);
			if (esp < 0)
			{
				err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, esp);
				return STAT_ADR;
			}
			set_reg_val(sim->r, rA, temp_value);
			sim->pc = next_pc;
			break;
		}
		
		return STAT_INS; /* unsupported now, replace it with your implementation */
		break;
	  default:
        err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun);
        return STAT_INS;
    }
    
    return STAT_AOK;
}
예제 #2
0
/* 
 * nexti: execute single instruction and return status.
 * args
 *     sim: the y64 image with PC, register and memory
 *
 * return
 *     STAT_AOK: continue
 *     STAT_HLT: halt
 *     STAT_ADR: invalid instruction address
 *     STAT_INS: invalid instruction, register id, data address, stack address, ...
 */
stat_t nexti(y64sim_t *sim)
{
    byte_t codefun = 0; /* 1 byte */
    itype_t icode;
    alu_t ifun;
    long_t next_pc = sim->pc;
    
    /* get code and function (1 byte) */
    if (!get_byte_val(sim->m, next_pc, &codefun)) {
        err_print("PC = 0x%lx, Invalid instruction address", sim->pc);
        return STAT_ADR;
    }
    icode = GET_ICODE(codefun);
    ifun = GET_FUN(codefun);
    next_pc++;
	
    /* get registers if needed (1 byte) */
  	byte_t rArB = 0; 
	regid_t rA = REG_ERR, rB = REG_ERR;
	if((icode == I_RRMOVQ) || (icode == I_ALU) || (icode == I_RMMOVQ) || 
					(icode == I_PUSHQ) || (icode == I_POPQ) ||
					(icode == I_IRMOVQ) || (icode == I_MRMOVQ) ){
   		get_byte_val(sim->m, next_pc, &rArB);
		rA = GET_REGA(rArB);
		rB = GET_REGB(rArB);
		next_pc++;
	}

    /* get immediate if needed (8 bytes) */
    long_t valC;
	if(icode == I_IRMOVQ || icode == I_RMMOVQ ||icode == I_MRMOVQ ||
				   	icode == I_JMP || icode == I_CALL){
		get_long_val(sim->m,next_pc,&valC);
		next_pc += 8;
	}

    /* execute the instruction*/
    long_t valA,valB,valE,valM;
   	switch (icode) {
      case I_HALT: /* 0:0 */
	    return STAT_HLT;
	    break;
      case I_NOP: /* 1:0 */
    	sim->pc = next_pc;
    	break;
      case I_RRMOVQ:  /* 2:x regA:regB */
	  	if(!NORM_REG(rA) || !NORM_REG(rB)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
        	return STAT_INS;
		}
			
	  	valA = get_reg_val(sim->r,rA);
		
		valE = valA + 0;
		if(cond_doit(sim->cc, ifun))
			set_reg_val(sim->r, rB, valE);
		sim->pc = next_pc;
		break;
      case I_IRMOVQ: /* 3:0 F:regB imm */
		
		if(!NORM_REG(rB) || !NONE_REG(rA)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
        	return STAT_INS;
		}
		valA = get_reg_val(sim->r, rA);
		valB = get_reg_val(sim->r, rB);
		valE = 0 + valC;
		set_reg_val(sim->r, rB, valE);
		sim->pc = next_pc;
		break;
      case I_RMMOVQ: /* 4:0 regA:regB imm */
		
		if(!NORM_REG(rA) || !NORM_REG(rB)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
        	return STAT_INS;
		}
		valA = get_reg_val(sim->r, rA);
		valB = get_reg_val(sim->r, rB);
		valE = valB + valC;
		if(!set_long_val(sim->m, valE, valA)){
			err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE);
			return STAT_ADR;
		}
		sim->pc = next_pc;
		break;
      case I_MRMOVQ: /* 5:0 regB:regA imm */
		
		if(!NORM_REG(rA) || !NORM_REG(rB)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
        	return STAT_INS;
		}
		
		valA = get_reg_val(sim->r, rA);
		valB = get_reg_val(sim->r, rB);
		valE = valB + valC;
		if(!get_long_val(sim->m, valE, &valM)){
			err_print("PC = 0x%lx, Invalid data address 0x%.8lx", sim->pc, valE);
			return STAT_ADR;
		}
		set_reg_val(sim->r, rA, valM);
		sim->pc = next_pc;
		break;
      case I_ALU: /* 6:x regA:regB */
		if(!NORM_REG(rA) || !NORM_REG(rB)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
        	return STAT_INS;
		}
		valA = get_reg_val(sim->r, rA);
		valB = get_reg_val(sim->r, rB);	
		valE = compute_alu(ifun, valA, valB);
		sim->cc = compute_cc(ifun, valA, valB, valE);
		set_reg_val(sim->r, rB, valE);
		sim->pc = next_pc;
		break;
      case I_JMP: /* 7:x imm */
		if(ifun > 6){
			err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun);
    		return STAT_INS;
		}
		sim->pc = cond_doit(sim->cc,ifun)? valC : next_pc;
		break;
      case I_CALL: /* 8:x imm */
		valB = get_reg_val(sim->r, REG_RSP); 
		valE = valB + (-8);
		
		set_reg_val(sim->r, REG_RSP, valE);
		if(!set_long_val(sim->m, valE, next_pc)){
			err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE);
    		return STAT_ADR;	
		}
		sim->pc = valC;
		break;
      case I_RET: /* 9:0 */
		valA = get_reg_val(sim->r, REG_RSP);
		valB = valA;
		
		valE = valB + 8;

		get_long_val(sim->m, valA, &valM);
		set_reg_val(sim->r, REG_RSP, valE);
		sim->pc = valM;
		break;
      case I_PUSHQ: /* A:0 regA:F */
		if(!NORM_REG(rA)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
    		return STAT_INS;
		}
		valA = get_reg_val(sim->r, rA);
		valB = get_reg_val(sim->r, REG_RSP);
		
		valE = valB + (-8);
		
		set_reg_val(sim->r, REG_RSP, valE);
		if(!set_long_val(sim->m, valE, valA)){
			err_print("PC = 0x%lx, Invalid stack address 0x%.8lx", sim->pc, valE);
    		return STAT_ADR;
		}
		sim->pc = next_pc;
		break;
      case I_POPQ: /* B:0 regA:F */
		if(!NORM_REG(rA)){
			err_print("PC = 0x%lx, Invalid register id %.2x", sim->pc, rArB);
    		return STAT_INS;
		}
		valA = get_reg_val(sim->r, REG_RSP);
		valB = valA;

		valE = valB + 8;
		
		get_long_val(sim->m, valA, &valM);
		set_reg_val(sim->r, REG_RSP, valE);
		set_reg_val(sim->r, rA, valM);
		sim->pc = next_pc;
		break;

    //	return STAT_INS; /* unsupported now, replace it with your implementation */
      default:
    	err_print("PC = 0x%lx, Invalid instruction %.2x", sim->pc, codefun);
    	return STAT_INS;
    }
    
    return STAT_AOK;
}