void set_reg_val(mem_t r, reg_id_t id, word_t val) { if (id < REG_NONE) { set_word_val(r,id*4,val); #ifdef HAS_GUI signal_register_update(id, val); #endif } }
void set_reg_val(mem_t r, reg_id_t id, word_t val) { if (id < REG_NONE) { set_word_val(r,id*4,val); #ifdef HAS_GUI if (gui_mode) { signal_register_update(id, val); } #endif /* HAS_GUI */ } }
/* May need to disable updating of memory & condition codes */ static void update_state(bool_t update_mem, bool_t update_cc) { /* Writeback(s): If either register is REG_NONE, write will have no effect . Order of two writes determines semantics of popl %esp. According to ISA, %esp will get popped value */ if (wb_destE != REG_NONE) { sim_log("Writeback: Wrote 0x%x to register %s\n", wb_valE, reg_name(wb_destE)); set_reg_val(reg, wb_destE, wb_valE); } if (wb_destM != REG_NONE) { sim_log("Writeback: Wrote 0x%x to register %s\n", wb_valM, reg_name(wb_destM)); set_reg_val(reg, wb_destM, wb_valM); } /* Memory write */ if (mem_write && !update_mem) { sim_log("Disabled write of 0x%x to address 0x%x\n", mem_data, mem_addr); } if (update_mem && mem_write) { if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("Couldn't write to address 0x%x\n", mem_addr); } else { sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif } } if (update_cc) cc = cc_in; }
/* May need to disable updating of memory & condition codes */ static void update_state(bool_t update_mem, bool_t update_cc) { /* Writeback(s): If either register is REG_NONE, write will have no effect . Order of two writes determines semantics of popl %esp. According to ISA, %esp will get popped value */ if (wb_destE != REG_NONE) { sim_log("\tWriteback: Wrote 0x%x to register %s\n", wb_valE, reg_name(wb_destE)); set_reg_val(reg, wb_destE, wb_valE); //printf("set_reg_valE %d %d %d\n", PSIM_ID, wb_destE, wb_valE); //fflush(stdout); } if (wb_destM != REG_NONE && wb_testM == REG_NONE) { sim_log("\tWriteback: Wrote 0x%x to register %s\n", wb_valM, reg_name(wb_destM)); set_reg_val(reg, wb_destM, wb_valM); //printf("set_reg_valM %d %d %d\n", PSIM_ID, wb_destM, wb_valM); //fflush(stdout); } /* Memory write */ if(wb_testM != REG_NONE){ set_reg_val(reg, wb_testM, wb_valM); printf("PSIM_ID %d test_result: %d on %d\n", PSIM_ID, wb_valM, mem_test_address); //fflush(stdout); } if (mem_write && !update_mem) { sim_log("\tDisabled write of 0x%x to address 0x%x\n", mem_data, mem_addr); } if (update_mem && mem_write) { // printf("WRITE: %d %d\n", mem_addr, mem_data); if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("\tCouldn't write to address 0x%x\n", mem_addr); } else { sim_log("\tWrote 0x%x to address 0x%x\n", mem_data, mem_addr); } /* int ans; printf("%d %d\n",mem_addr, mem_data); int b = get_word_val(mem, mem_addr, &ans); printf("%d\n", ans); */ } if (update_cc) cc = cc_in; }
/* Update the processor state */ static exc_t update_state() { exc_t status = EXC_NONE; if (plusmode) { prev_icode = prev_icode_in; prev_ifun = prev_ifun_in; prev_valc = prev_valc_in; prev_valm = prev_valm_in; prev_valp = prev_valp_in; prev_bcond = prev_bcond_in; } else { pc = pc_in; } cc = cc_in; /* Writeback */ if (destE != REG_NONE) set_reg_val(reg, destE, vale); if (destM != REG_NONE) set_reg_val(reg, destM, valm); if (mem_write) { if (!set_word_val(mem, mem_addr, mem_data)) { sim_log("Couldn't write to address 0x%x\n", mem_addr); status = EXC_ADDR; } else { sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif// HAS_GUI } } return status; }
/* Update the processor state */ static void update_state() { if (plusmode) { prev_icode = prev_icode_in; prev_ifun = prev_ifun_in; prev_valc = prev_valc_in; prev_valm = prev_valm_in; prev_valp = prev_valp_in; prev_bcond = prev_bcond_in; } else { pc = pc_in; } cc = cc_in; /* Writeback */ if (destE != REG_NONE) set_reg_val(reg, destE, vale); if (destM != REG_NONE) set_reg_val(reg, destM, valm); if (mem_write) { /* Should have already tested this address */ set_word_val(mem, mem_addr, mem_data); sim_log("Wrote 0x%x to address 0x%x\n", mem_data, mem_addr); #ifdef HAS_GUI if (gui_mode) { if (mem_addr % 4 != 0) { /* Just did a misaligned write. Need to display both words */ word_t align_addr = mem_addr & ~0x3; word_t val; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); align_addr+=4; get_word_val(mem, align_addr, &val); set_memory(align_addr, val); } else { set_memory(mem_addr, mem_data); } } #endif /* HAS_GUI */ } }
/* 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; }
/* 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; }