void do_if_stage() { byte_t instr = HPACK(I_NOP, F_NONE); byte_t regids = HPACK(REG_NONE, REG_NONE); word_t valc = 0; word_t valp = f_pc = gen_f_pc(); /* Ready to fetch instruction. Speculatively fetch register byte and immediate word */ imem_error = !get_byte_val(mem, valp+START_PLACE, &instr); imem_icode = HI4(instr); imem_ifun = LO4(instr); if (!imem_error) { byte_t junk; /* Make sure can read maximum length instruction */ imem_error = !get_byte_val(mem, valp+5 + START_PLACE, &junk); } if_id_next->icode = gen_f_icode(); if_id_next->ifun = gen_f_ifun(); if (!imem_error) { sim_log("\tFetch: f_pc = 0x%x, imem_instr = %s, f_instr = %s\n", f_pc, iname(instr), iname(HPACK(if_id_next->icode, if_id_next->ifun))); } instr_valid = gen_instr_valid(); if (!instr_valid) sim_log("\tFetch: Instruction code 0x%x invalid\n", instr); if_id_next->status = gen_f_stat(); valp++; if (gen_need_regids()) { get_byte_val(mem, valp + START_PLACE, ®ids); valp ++; } if_id_next->ra = HI4(regids); if_id_next->rb = LO4(regids); if (gen_need_valC()) { get_word_val(mem, valp + START_PLACE, &valc); valp+= 4; } if_id_next->valp = valp; if_id_next->valc = valc; /* if(gen_need_regids() && if_id_next->valc) printf("##### vap: %d %d %d\n", if_id_next->ra, if_id_next->rb, if_id_next->valc); */ pc_next->pc = gen_f_predPC(); pc_next->status = (if_id_next->status == STAT_AOK) ? STAT_AOK : STAT_BUB; if_id_next->stage_pc = f_pc; }
/* * 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, data address, stack address, ... * STAT_INS: invalid instruction, register id, ... */ stat_t nexti(y86sim_t *sim) { byte_t codefun = 0; itype_t icode; alu_t ifun; long_t valP = sim->pc; /* get code and function (1 byte) */ if (!get_byte_val(sim->m, valP, &codefun)) { err_print("PC = 0x%x, Invalid instruction address", sim->pc); return STAT_ADR; } icode = GET_ICODE(codefun); ifun = GET_FUN(codefun); valP++; /* get registers if needed (1 byte) */ byte_t byte; long_t valA, valB, valC, val; regid_t regA, regB; if ((icode>1 && icode<7) || icode==I_PUSHL || icode==I_POPL) { if (!get_byte_val(sim->m, valP, &byte)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP++; regA = HIGH(byte); regB = LOW(byte); } /* get immediate if needed (4 bytes) */ if (icode>=3 && icode<=8 && icode!=I_ALU) { if (!get_long_val(sim->m, valP, &valC)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } valP+=4; } /* execute the instruction */ switch (icode) { case I_HALT: /* 0:0 */ return STAT_HLT; break; case I_NOP: /* 1:0 */ sim->pc = valP; break; case I_RRMOVL: sim->pc = valP; if (!cond_doit(sim->cc,ifun)) break; val = get_reg_val(sim->r, regA); set_reg_val(sim->r, regB, val); break; /* 2:x regA:regB */ case I_IRMOVL: set_reg_val(sim->r, regB, valC); sim->pc = valP; break; /* 3:0 F:regB imm */ case I_RMMOVL: valC += get_reg_val(sim->r, regB); val = get_reg_val(sim->r, regA); set_long_val(sim->m, valC, val); sim->pc = valP; break; /* 4:0 regA:regB imm */ case I_MRMOVL: valC += get_reg_val(sim->r, regB); if (!get_long_val(sim->m, valC, &val)) { err_print("PC = 0x%x, Invalid data address 0x%x", sim->pc, valC); return STAT_ADR; } set_reg_val(sim->r, regA, val); sim->pc = valP; break; /* 5:0 regB:regA imm */ case I_ALU: valA = get_reg_val(sim->r,regA); valB = get_reg_val(sim->r,regB); val = compute_alu(ifun, valA, valB); set_reg_val(sim->r, regB, val); sim->cc = compute_cc(ifun, valA, valB, val); sim->pc = valP; break; /* 6:x regA:regB */ case I_JMP: sim->pc = (cond_doit(sim->cc,ifun))?valC:valP; break; /* 7:x imm */ case I_CALL: val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valP)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valC; break; /* 8:x imm */ case I_RET: valA = get_reg_val(sim->r, REG_ESP); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, REG_ESP, valA+4); sim->pc = valB; break; /* 9:0 */ case I_PUSHL: valA = get_reg_val(sim->r, regA); val = get_reg_val(sim->r, REG_ESP) - 4; set_reg_val(sim->r, REG_ESP, val); if (!set_long_val(sim->m, val, valA)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, val); return STAT_ADR; } sim->pc = valP; break; /* A:0 regA:F */ case I_POPL: valA = get_reg_val(sim->r, REG_ESP); set_reg_val(sim->r, REG_ESP, valA+4); if (!get_long_val(sim->m, valA, &valB)) { err_print("PC = 0x%x, Invalid stack address 0x%x", sim->pc, valA); return STAT_ADR; } set_reg_val(sim->r, regA, valB); sim->pc = valP; break; /* B:0 regA:F */ default: err_print("PC = 0x%x, Invalid instruction %.2x", sim->pc, codefun); return STAT_INS; } return STAT_AOK; }
/* 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; }
/* 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, ®ids)) { 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; }
void do_if_stage() { exc_t nstatus = EXC_NONE; word_t fetchpc = gen_f_pc(); word_t valp = fetchpc; bool_t fetch_ok; byte_t instr; byte_t regids = HPACK(REG_NONE, REG_NONE); word_t valc = 0; f_pc = fetchpc; if (fetchpc == 0) { sim_log("Fetch: Fetch pc = 0, nominal pc = 0x%x\n", pc_curr->pc); } /* Ready to fetch instruction. Speculatively fetch register byte and immediate word */ fetch_ok = get_byte_val(mem, valp, &instr); if (fetch_ok) { if_id_next->icode = GET_ICODE(instr); if_id_next->ifun = GET_FUN(instr); } else { if_id_next->icode = I_NOP; if_id_next->ifun = 0; nstatus = EXC_ADDR; } valp++; if (fetch_ok && gen_need_regids()) { fetch_ok = get_byte_val(mem, valp, ®ids); valp ++; } if_id_next->ra = HI4(regids); if_id_next->rb = LO4(regids); if (fetch_ok && gen_need_valC()) { fetch_ok = get_word_val(mem, valp, &valc); valp+= 4; } if_id_next->valp = valp; if_id_next->valc = valc; pc_next->pc = gen_new_F_predPC(); if (!gen_instr_valid()) { byte_t instr = HPACK(if_id_next->icode, if_id_next->ifun); sim_log("Fetch: Instruction code %s (0x%x) invalid\n", iname(instr), instr); nstatus = EXC_INSTR; } pc_next->exception = (nstatus == EXC_NONE) ? EXC_NONE : EXC_BUBBLE; if_id_next->stage_pc = fetchpc; if_id_next->exception = nstatus; /* Recompute icode for one-write implementation of popl */ if_id_next->icode = gen_new_D_icode(); sim_log("Fetch: Fetched %s at 0x%x, ra = %s, rb = %s, valp = 0x%x, status = %s\n", iname(HPACK(if_id_next->icode, if_id_next->ifun)), if_id_next->stage_pc, reg_name(if_id_next->ra), reg_name(if_id_next->rb), if_id_next->valp, exc_name(nstatus)); }
/* 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; }
/* * 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, ®)) { 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; }
/* * 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; }