void do_mem_stage() { bool_t read = gen_mem_read(); bool_t mem_ok = TRUE; word_t valm = 0; mem_addr = gen_mem_addr(); mem_data = ex_mem_curr->vala; mem_write = gen_mem_write(); if (read) { mem_ok = get_word_val(mem, mem_addr, &valm); sim_log("Memory: Read 0x%x from 0x%x, instruction = %s\n", valm, mem_addr, iname(HPACK(ex_mem_curr->icode, ex_mem_curr->ifun))); } if (mem_write) { word_t sink; /* Do a read of address just to check validity */ mem_ok = get_word_val(mem, mem_addr, &sink); } mem_wb_next->icode = ex_mem_curr->icode; mem_wb_next->ifun = ex_mem_curr->ifun; mem_wb_next->vale = ex_mem_curr->vale; mem_wb_next->valm = valm; mem_wb_next->deste = ex_mem_curr->deste; mem_wb_next->destm = ex_mem_curr->destm; mem_wb_next->exception = mem_ok ? ex_mem_curr->exception : EXC_ADDR; mem_wb_next->stage_pc = ex_mem_curr->stage_pc; }
/* 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; }
/* 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; }
/* Provide mechanism for simulator to generate memory display */ void create_memory_display() { int code; sprintf(tcl_msg, "createMem %d %d", minAddr, memCnt); code = Tcl_Eval(sim_interp, tcl_msg); if (code != TCL_OK) { fprintf(stderr, "Command '%s' failed\n", tcl_msg); fprintf(stderr, "Error Message was '%s'\n", sim_interp->result); } else { int i; for (i = 0; i < memCnt && code == TCL_OK; i+=4) { int addr = minAddr+i; int val; if (!get_word_val(mem, addr, &val)) { fprintf(stderr, "Out of bounds memory display\n"); return; } sprintf(tcl_msg, "setMem %d %d", addr, val); code = Tcl_Eval(sim_interp, tcl_msg); } if (code != TCL_OK) { fprintf(stderr, "Couldn't set memory value\n"); fprintf(stderr, "Error Message was '%s'\n", sim_interp->result); } } }
word_t get_reg_val(mem_t r, reg_id_t id) { word_t val; if (id >= REG_NONE) return 0; get_word_val(r,id*4, &val); return val; }
unsigned int read_multiple_register(unsigned char * buffer,unsigned int len) { typedef struct _modbus_head_t { unsigned char idhi; unsigned char idlo; unsigned char protocal_hi; unsigned char protocal_lo; unsigned char length_hi; unsigned char length_lo; unsigned char slave_addr; unsigned char function; unsigned char start_refnum_hi; unsigned char start_refnum_lo; unsigned char word_count_hi; unsigned char word_count_lo; } modbus_head_t; typedef struct _modbus_ack { unsigned char idhi; unsigned char idlo; unsigned char protocal_hi; unsigned char protocal_lo; unsigned char length_hi; unsigned char length_lo; unsigned char slave_addr; unsigned char function; unsigned char byte_count; unsigned char reg_base; } modbus_ack; modbus_head_t * pm = (modbus_head_t *)buffer; modbus_ack * pack = (modbus_ack *)buffer; unsigned int refnum,i; unsigned int word_count; WORD * pword = (WORD *)&(pack->reg_base); if(len < sizeof(modbus_head_t)) { return 0; } refnum = HSB_BYTES_TO_WORD(&pm->start_refnum_hi); word_count = HSB_BYTES_TO_WORD(&pm->word_count_hi); //直接调用PLC寄存器读写接口 //限制读的数量,以防内存溢出 word_count = ((word_count*2+sizeof(modbus_head_t)) > TCP_MODBUS_RX_MAX_LEN)? ((TCP_MODBUS_RX_MAX_LEN - sizeof(modbus_head_t))/2):(word_count); for(i=0;i<word_count;i++) { word_t * pw = pword; WORD w = get_word_val(refnum+i); pw->w_hi = w >> 8; pw->w_lo = w & 0xFF; pword++; } pack->length_hi = 0; pack->length_lo = word_count * 2 + 3; pack->byte_count = (unsigned char)(word_count * 2); return (sizeof(modbus_ack) - 1 + word_count * 2); }
bool_t diff_mem(mem_t oldm, mem_t newm, FILE *outfile) { word_t pos; int len = oldm->len; bool_t diff = FALSE; if (newm->len < len) len = newm->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { word_t ov, nv; get_word_val(oldm, pos, &ov); get_word_val(newm, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "0x%.4x:\t0x%.8x\t0x%.8x\n", pos, ov, nv); } } return diff; }
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; }
/* 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 */ } }
bool_t diff_reg(mem_t oldr, mem_t newr, FILE *outfile) { word_t pos; int len = oldr->len; bool_t diff = FALSE; if (newr->len < len) len = newr->len; for (pos = 0; (!diff || outfile) && pos < len; pos += 4) { word_t ov, nv; get_word_val(oldr, pos, &ov); get_word_val(newr, pos, &nv); if (nv != ov) { diff = TRUE; if (outfile) fprintf(outfile, "%s:\t0x%.8x\t0x%.8x\n", reg_table[pos/4].name, ov, nv); } } return diff; }
void do_mem_stage() { bool_t read = gen_mem_read(); word_t valm = 0; mem_addr = gen_mem_addr(); mem_data = ex_mem_curr->vala; mem_write = gen_mem_write(); mem_test = gen_mem_test(); dmem_error = FALSE; if (read && !mem_test) { dmem_error = dmem_error || !get_word_val(mem, mem_addr, &valm); if (!dmem_error) sim_log("\tMemory: Read 0x%x from 0x%x\n", valm, mem_addr); } if (mem_write && !mem_test) { word_t sink; /* Do a read of address just to check validity */ dmem_error = dmem_error || !get_word_val(mem, mem_addr, &sink); if (dmem_error) sim_log("\tMemory: Invalid address 0x%x\n", mem_addr); } if (mem_test && read){ mem_test_address = mem_addr; int ans = test_memory(mem, mem_test_address); valm = ans; } mem_wb_next->icode = ex_mem_curr->icode; mem_wb_next->ifun = ex_mem_curr->ifun; mem_wb_next->vale = ex_mem_curr->vale; mem_wb_next->valm = valm; mem_wb_next->deste = ex_mem_curr->deste; mem_wb_next->destm = ex_mem_curr->destm; mem_wb_next->status = gen_m_stat(); mem_wb_next->stage_pc = ex_mem_curr->stage_pc; }
void do_mem_stage() { bool_t read = gen_mem_read(); word_t valm = 0; mem_addr = gen_mem_addr(); if(ex_mem_curr->icode == I_MUTEXTEST || ex_mem_curr->icode == I_MUTEXCLEAR) mem_addr = MUTEX_BYTE; mem_data = ex_mem_curr->vala; if(ex_mem_curr->icode == I_MUTEXTEST) mem_data = 1; else if(ex_mem_curr->icode == I_MUTEXCLEAR) mem_data = 0; mem_write = gen_mem_write(); dmem_error = FALSE; if (read) { dmem_error = dmem_error || !get_word_val(mem, mem_addr, &valm); if (!dmem_error) sim_log("\tMemory: Read 0x%x from 0x%x\n", valm, mem_addr); } if (mem_write) { word_t sink; /* Do a read of address just to check validity */ dmem_error = dmem_error || !get_word_val(mem, mem_addr, &sink); if (dmem_error) sim_log("\tMemory: Invalid address 0x%x\n", mem_addr); } mem_wb_next->icode = ex_mem_curr->icode; mem_wb_next->ifun = ex_mem_curr->ifun; mem_wb_next->vale = ex_mem_curr->vale; mem_wb_next->valm = valm; mem_wb_next->deste = ex_mem_curr->deste; mem_wb_next->destm = ex_mem_curr->destm; mem_wb_next->status = gen_m_stat(); mem_wb_next->stage_pc = ex_mem_curr->stage_pc; }
void dump_reg(FILE *outfile, mem_t r) { reg_id_t id; for (id = 0; id < 8; id++) { fprintf(outfile, " %s ", reg_table[id].name); } fprintf(outfile, "\n"); for (id = 0; id < 8; id++) { word_t val; get_word_val(r, id*4, &val); fprintf(outfile, " %x", val); } fprintf(outfile, "\n"); }
static void add_word(ParseInfo pi, const char *str, int len) { ojcVal parent = stack_peek(&pi->stack); if (0 == parent) { // simple add *pi->stack.head = get_word_val(pi, str, len); } else { switch (parent->expect) { case NEXT_ARRAY_NEW: case NEXT_ARRAY_ELEMENT: ojc_array_append(&pi->err, parent, get_word_val(pi, str, len)); parent->expect = NEXT_ARRAY_COMMA; break; case NEXT_OBJECT_VALUE: pi_object_nappend(pi, parent, get_word_val(pi, str, len)); if (pi->kalloc) { free(pi->key); } pi->key = 0; pi->klen = 0; pi->kalloc = false; parent->expect = NEXT_OBJECT_COMMA; break; case NEXT_OBJECT_NEW: case NEXT_OBJECT_KEY: case NEXT_OBJECT_COMMA: case NEXT_NONE: case NEXT_ARRAY_COMMA: case NEXT_OBJECT_COLON: default: ojc_set_error_at(pi, OJC_PARSE_ERR, __FILE__, __LINE__, "expected %s, not a word", _ojc_stack_next_str((ValNext)parent->expect)); break; } } ojc_reader_release(&pi->rd); }
void dump_memory(FILE *outfile, mem_t m, word_t pos, int len) { int i, j; while (pos % BPL) { pos --; len ++; } len = ((len+BPL-1)/BPL)*BPL; if (pos+len > m->len) len = m->len-pos; for (i = 0; i < len; i+=BPL) { word_t val = 0; fprintf(outfile, "0x%.4x:", pos+i); for (j = 0; j < BPL; j+= 4) { get_word_val(m, pos+i+j, &val); fprintf(outfile, " %.8x", val); } } }
/* 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; }