Beispiel #1
0
void mop_take_branch(void)
{
  zbyte branch = HIBYTE(PC);
  PC++;

  if(branch & b10000000)  /* Bit 7 set means 'branch when true' */
    take_branch(branch);
  else
    skip_branch(branch);
}
Beispiel #2
0
void do_ex_stage()
{
    alu_t alufun = gen_alufun();
    bool_t setcc = gen_set_cc();
    word_t alua, alub;

    alua = gen_aluA();
    alub = gen_aluB();

    e_bcond = 	take_branch(cc, id_ex_curr->ifun);
    
    ex_mem_next->takebranch = id_ex_curr->icode == I_JMP &&
	e_bcond;

    if (id_ex_curr->icode == I_JMP)
	sim_log("Execute: %s instruction, cc = %s, branch %staken\n",
		iname(HPACK(id_ex_curr->icode, id_ex_curr->ifun)),
		cc_name(cc),
		ex_mem_next->takebranch ? "" : "not ");
    
    /* Perform the ALU operation */
    ex_mem_next->vale = compute_alu(alufun, alua, alub);

    {
	byte_t instr = HPACK(id_ex_curr->icode, id_ex_curr->ifun);
	sim_log("Execute: Instruction %s\n",
		iname(instr));
    }

    if (setcc) {
	cc_in = compute_cc(alufun, alua, alub);
	sim_log("Execute: CC cc = %s\n", cc_name(cc_in));
    }

    ex_mem_next->icode = id_ex_curr->icode;
    ex_mem_next->ifun = id_ex_curr->ifun;
    ex_mem_next->vala = gen_new_M_valA();
    ex_mem_next->deste = id_ex_curr->deste;
    ex_mem_next->destm = id_ex_curr->destm;
    ex_mem_next->srca = id_ex_curr->srca;
    ex_mem_next->exception = id_ex_curr->exception;
    ex_mem_next->stage_pc = id_ex_curr->stage_pc;
}
Beispiel #3
0
/* Execute single instruction.  Return exception condition. */
exc_t step_state(state_ptr s, FILE *error_file)
{
    word_t argA, argB;
    byte_t byte0 = 0;
    byte_t byte1 = 0;
    itype_t hi0;
    alu_t  lo0;
    reg_id_t hi1 = REG_NONE;
    reg_id_t lo1 = REG_NONE;
    bool_t ok1 = TRUE;
    word_t cval;
    word_t okc = TRUE;
    word_t val, dval;
    bool_t need_regids;
    bool_t need_imm;

    word_t ftpc = s->pc;

    if (!get_byte_val(s->m, ftpc, &byte0)) {
	if (error_file)
	    fprintf(error_file,
		    "PC = 0x%x, Invalid instruction address\n", s->pc);
	return EXC_ADDR;
    }
    ftpc++;

    hi0 = HI4(byte0);
    lo0 = LO4(byte0);

    need_regids =
	(hi0 == I_RRMOVL || hi0 == I_ALU || hi0 == I_PUSHL ||
	 hi0 == I_POPL || hi0 == I_IRMOVL || hi0 == I_RMMOVL ||
	 hi0 == I_MRMOVL || hi0 == I_ALUI);

    if (need_regids) {
	ok1 = get_byte_val(s->m, ftpc, &byte1);
	ftpc++;
	hi1 = HI4(byte1);
	lo1 = LO4(byte1);
    }

    need_imm =
	(hi0 == I_IRMOVL || hi0 == I_RMMOVL || hi0 == I_MRMOVL ||
	 hi0 == I_JXX || hi0 == I_CALL || hi0 == I_ALUI);

    if (need_imm) {
	okc = get_word_val(s->m, ftpc, &cval);
	ftpc += 4;
    }

    switch (hi0) {
    case I_NOP:
	s->pc = ftpc;
	break;
    case I_HALT:
	s->pc = ftpc;
	return EXC_HALT;
	break;
    case I_RRMOVL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (hi1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, hi1);
	    return EXC_INSTR;
	}
	if (lo1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, lo1);
	    return EXC_INSTR;
	}
	val = get_reg_val(s->r, hi1);
	set_reg_val(s->r, lo1, val);
	s->pc = ftpc;
	break;

	#if 0
    case I_IRMOVL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address",
			s->pc);
	    return EXC_INSTR;
	}
	if (lo1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, lo1);
	    return EXC_INSTR;
	}
	set_reg_val(s->r, lo1, cval);
	s->pc = ftpc;
	break;
	#endif
	
    case I_RMMOVL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_INSTR;
	}
	if (hi1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, hi1);
	    return EXC_INSTR;
	}
	if (lo1 < 8) 
	    cval += get_reg_val(s->r, lo1);
	val = get_reg_val(s->r, hi1);
	if (!set_word_val(s->m, cval, val)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid data address 0x%x\n",
			s->pc, cval);
	    return EXC_ADDR;
	}
	s->pc = ftpc;
	break;
    case I_MRMOVL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction addres\n", s->pc);
	    return EXC_INSTR;
	}
	if (hi1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, hi1);
	    return EXC_INSTR;
	}
	if (lo1 < 8) 
	    cval += get_reg_val(s->r, lo1);
	if (!get_word_val(s->m, cval, &val))
	    return EXC_ADDR;
	set_reg_val(s->r, hi1, val);
	s->pc = ftpc;
	break;
    case I_ALU:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	argA = get_reg_val(s->r, hi1);
	argB = get_reg_val(s->r, lo1);
	val = compute_alu(lo0, argA, argB);
	set_reg_val(s->r, lo1, val);
	s->cc = compute_cc(lo0, argA, argB);
	s->pc = ftpc;
	break;
    case I_JXX:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (take_branch(s->cc, lo0))
	    s->pc = cval;
	else
	    s->pc = ftpc;
	break;
    #if 0
    case I_CALL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	val = get_reg_val(s->r, REG_ESP) - 4;
	set_reg_val(s->r, REG_ESP, val);
	if (!set_word_val(s->m, val, ftpc)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid stack address 0x%x\n", s->pc, val);
	    return EXC_ADDR;
	}
	s->pc = cval;
	break;
    case I_RET:
	/* Return Instruction.  Pop address from stack */
	dval = get_reg_val(s->r, REG_ESP);
	if (!get_word_val(s->m, dval, &val)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid stack address 0x%x\n",
			s->pc, dval);
	    return EXC_ADDR;
	}
	set_reg_val(s->r, REG_ESP, dval + 4);
	s->pc = val;
	break;
    #endif
    case I_PUSHL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (hi1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1);
	    return EXC_INSTR;
	}
	val = get_reg_val(s->r, hi1);
	dval = get_reg_val(s->r, REG_ESP) - 4;
	set_reg_val(s->r, REG_ESP, dval);
	if  (!set_word_val(s->m, dval, val)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid stack address 0x%x\n", s->pc, dval);
	    return EXC_ADDR;
	}
	s->pc = ftpc;
	break;
    case I_POPL:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (hi1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1);
	    return EXC_INSTR;
	}
	dval = get_reg_val(s->r, REG_ESP);
	set_reg_val(s->r, REG_ESP, dval+4);
	if (!get_word_val(s->m, dval, &val)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid stack address 0x%x\n",
			s->pc, dval);
	    return EXC_ADDR;
	}
	set_reg_val(s->r, hi1, val);
	s->pc = ftpc;
	break;
    case I_LEAVE:
	dval = get_reg_val(s->r, REG_EBP);
	set_reg_val(s->r, REG_ESP, dval+4);
	if (!get_word_val(s->m, dval, &val)) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid stack address 0x%x\n",
			s->pc, dval);
	    return EXC_ADDR;
	}
	set_reg_val(s->r, REG_EBP, val);
	s->pc = ftpc;
	break;

	#if 0
    case I_ALUI:
	if (!ok1) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address\n", s->pc);
	    return EXC_ADDR;
	}
	if (!okc) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid instruction address",
			s->pc);
	    return EXC_INSTR;
	}
	if (lo1 >= 8) {
	    if (error_file)
		fprintf(error_file,
			"PC = 0x%x, Invalid register ID 0x%.1x\n",
			s->pc, lo1);
	    return EXC_INSTR;
	}
	argB = get_reg_val(s->r, lo1);
	val = argB + cval;
	set_reg_val(s->r, lo1, val);
	s->cc = compute_cc(A_ADD, cval, argB);
	s->pc = ftpc;
	break;
	#endif
	
    default:
	if (error_file)
	    fprintf(error_file,
		    "PC = 0x%x, Invalid instruction %.2x\n", s->pc, byte0);
	return EXC_INSTR;
    }
    return EXC_NONE;
}
Beispiel #4
0
/* Return resulting exception status */
static exc_t sim_step()
{
    word_t aluA;
    word_t aluB;
    word_t alufun;
    exc_t status = update_state(); /* Update state from last cycle */

    if (plusmode) {
	pc = gen_pc();
    }
    valp = pc;
    if (get_byte_val(mem, valp, &instr)) {
	icode = HI4(instr);
	ifun = LO4(instr);
    } else {
	instr = HPACK(I_NOP,0);
	icode = I_NOP;
	ifun = 0;
	status = EXC_ADDR;
	sim_log("Couldn't fetch at address 0x%x\n", valp);
    }
    valp++;
    if (gen_need_regids()) {
	byte_t regids;
	if (get_byte_val(mem, valp, &regids)) {
	    ra = GET_RA(regids);
	    rb = GET_RB(regids);
	} else {
	    ra = REG_NONE;
	    rb = REG_NONE;
	    status = EXC_ADDR;
	    sim_log("Couldn't fetch at address 0x%x\n", valp);
	}
	valp++;
    } else {
	ra = REG_NONE;
	rb = REG_NONE;
    }

    if (gen_need_valC()) {
	if (get_word_val(mem, valp, &valc)) {
	} else {
	    valc = 0;
	    status = EXC_ADDR;
	    sim_log("Couldn't fetch at address 0x%x\n", valp);
	}
	valp+=4;
    } else {
	valc = 0;
    }

    if (status == EXC_NONE && !gen_instr_valid()) {
	status = EXC_INSTR;
    }

    sim_log("IF: Fetched %s at 0x%x.  ra=%s, rb=%s, valC = 0x%x\n",
	    iname(HPACK(icode,ifun)), pc, reg_name(ra), reg_name(rb), valc);

    if (status == EXC_NONE && icode == I_HALT) {
	status = EXC_HALT;
    }
    
    srcA = gen_srcA();
    if (srcA != REG_NONE) {
	vala = get_reg_val(reg, srcA);
    } else {
	vala = 0;
    }
    
    srcB = gen_srcB();
    if (srcB != REG_NONE) {
	valb = get_reg_val(reg, srcB);
    } else {
	valb = 0;
    }

    destE = gen_dstE();
    destM = gen_dstM();

    aluA = gen_aluA();
    aluB = gen_aluB();
    alufun = gen_alufun();
    vale = compute_alu(alufun, aluA, aluB);
    cc_in = cc;
    if (gen_set_cc())
	cc_in = compute_cc(alufun, aluA, aluB);

    bcond = (icode == I_JMP) && take_branch(cc, ifun);

    mem_addr = gen_mem_addr();
    mem_data = gen_mem_data();

    if (status == EXC_NONE && gen_mem_read()) {
	if (!get_word_val(mem, mem_addr, &valm)) {
	    sim_log("Couldn't read at address 0x%x\n", mem_addr);
	    return EXC_ADDR;
	}
    } else
	valm = 0;

    mem_write = status == EXC_NONE && gen_mem_write();

    if (plusmode) {
	prev_icode_in = icode;
	prev_ifun_in = ifun;
	prev_valc_in = valc;
	prev_valm_in = valm;
	prev_valp_in = valp;
	prev_bcond_in = bcond;
    } else {
	/* Update PC */
	pc_in = gen_new_pc();
    } 
    sim_report();
    return status;
}