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 = cond_holds(cc, id_ex_curr->ifun); ex_mem_next->takebranch = e_bcond; if (id_ex_curr->icode == I_JMP) sim_log("\tExecute: instr = %s, 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 */ word_t aluout = compute_alu(alufun, alua, alub); ex_mem_next->vale = aluout; sim_log("\tExecute: ALU: %c 0x%x 0x%x --> 0x%x\n", op_name(alufun), alua, alub, aluout); if (setcc) { cc_in = compute_cc(alufun, alua, alub); sim_log("\tExecute: New 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_e_valA(); ex_mem_next->deste = gen_e_dstE(); ex_mem_next->destm = id_ex_curr->destm; ex_mem_next->srca = id_ex_curr->srca; ex_mem_next->status = id_ex_curr->status; ex_mem_next->stage_pc = id_ex_curr->stage_pc; }
/* Execute single instruction. Return status. */ stat_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 = 0; word_t okc = TRUE; word_t val, dval; bool_t need_regids; bool_t need_imm; word_t ftpc = s->pc; /* Fall-through 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 STAT_ADR; } 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_IADDL || hi0 == I_ISUBL); 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_JMP || hi0 == I_CALL || hi0 == I_IADDL || hi0 == I_ISUBL); 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: return STAT_HLT; break; case I_RRMOVL: /* Both unconditional and conditional moves */ if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } val = get_reg_val(s->r, hi1); if (cond_holds(s->cc, lo0)) set_reg_val(s->r, lo1, val); s->pc = ftpc; break; case I_IRMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } set_reg_val(s->r, lo1, cval); s->pc = ftpc; break; case I_RMMOVL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_INS; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (reg_valid(lo1)) 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 STAT_ADR; } 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 STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction addres\n", s->pc); return STAT_INS; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } if (reg_valid(lo1)) cval += get_reg_val(s->r, lo1); if (!get_word_val(s->m, cval, &val)) return STAT_ADR; 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 STAT_ADR; } 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_JMP: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (cond_holds(s->cc, lo0)) s->pc = cval; else s->pc = ftpc; break; case I_CALL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } 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 STAT_ADR; } 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 STAT_ADR; } set_reg_val(s->r, REG_ESP, dval + 4); s->pc = val; break; case I_PUSHL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } 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 STAT_ADR; } 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 STAT_ADR; } if (!reg_valid(hi1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, hi1); return STAT_INS; } 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 STAT_ADR; } 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 STAT_ADR; } set_reg_val(s->r, REG_EBP, val); s->pc = ftpc; break; case I_IADDL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } 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; case I_ISUBL: if (!ok1) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address\n", s->pc); return STAT_ADR; } if (!okc) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction address", s->pc); return STAT_INS; } if (!reg_valid(lo1)) { if (error_file) fprintf(error_file, "PC = 0x%x, Invalid register ID 0x%.1x\n", s->pc, lo1); return STAT_INS; } argB = get_reg_val(s->r, lo1); val = argB - cval; set_reg_val(s->r, lo1, val); s->cc = compute_cc(A_SUB, cval, argB); s->pc = ftpc; break; default: if (error_file) fprintf(error_file, "PC = 0x%x, Invalid instruction %.2x\n", s->pc, byte0); return STAT_INS; } return STAT_AOK; }
/* Return resulting status */ static byte_t sim_step() { word_t aluA; word_t aluB; word_t alufun; status = STAT_AOK; imem_error = dmem_error = FALSE; update_state(); /* Update state from last cycle */ if (plusmode) { pc = gen_pc(); } valp = pc; instr = HPACK(I_NOP, F_NONE); imem_error = !get_byte_val(mem, valp, &instr); if (imem_error) { sim_log("Couldn't fetch at address 0x%x\n", valp); } imem_icode = HI4(instr); imem_ifun = LO4(instr); icode = gen_icode(); ifun = gen_ifun(); instr_valid = gen_instr_valid(); valp++; if (gen_need_regids()) { byte_t regids; if (get_byte_val(mem, valp, ®ids)) { ra = GET_RA(regids); rb = GET_RB(regids); } else { ra = REG_NONE; rb = REG_NONE; status = STAT_ADR; 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 = STAT_ADR; sim_log("Couldn't fetch at address 0x%x\n", valp); } valp+=4; } else { valc = 0; } 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 == STAT_AOK && icode == I_HALT) { status = STAT_HLT; } 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; } cond = cond_holds(cc, ifun); 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 = cond && (icode == I_JMP); mem_addr = gen_mem_addr(); mem_data = gen_mem_data(); if (gen_mem_read()) { dmem_error = dmem_error || !get_word_val(mem, mem_addr, &valm); if (dmem_error) { sim_log("Couldn't read at address 0x%x\n", mem_addr); } } else valm = 0; mem_write = gen_mem_write(); if (mem_write) { /* Do a test read of the data memory to make sure address is OK */ word_t junk; dmem_error = dmem_error || !get_word_val(mem, mem_addr, &junk); } status = gen_Stat(); 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; }