void cpu_state_print() {//print the state of cpu and contents in memory printf("Registers:\n"); for(int i=0;i<NUM_OF_REGS-1;++i) { printf("R%d=%d(%d) ",i,regs[i],reg_valid_bits[i]); } printf("X=0x%08x(%d) PC=0x%08x\n",regs[NUM_OF_REGS-1],reg_valid_bits[8],PC); static const char * name[] ={"Fetch","D/RF","EXE","MEM","WB"}; printf("content of each stage:\n"); for(int i=0;i<NUM_OF_STAGES;++i) { printf("%s:\t",name[i]); if(stage_context[i].ins==-1) { printf("NOP\n"); } else { printf("%s",ins_buffer[stage_context[i].ins]); printf("PC=0x%x\n",stage_context[i].pc); } } printf("Memory contexts from 0-99:"); for(int i=0;i<100;) { if(i%16==0) { printf("\n0x%-5x:",i); } int j=0; while(i+j<100 && j<16) { u32_t con; mem_fetch(i+j,&con); printf("%08x ",con); ++j; } i+=j; } puts(""); }
static int exec_4() {//Mem stage if(stage_context[3].ins<0) goto end;//nop assert(stage_context[3].decoded != NULL); if(stage_context[3].decoded->type == 6) {//Load. //Note:there is no forwarding.Thus the result should be written back in WB //decoded->result should contain the address. if(mem_fetch(stage_context[3].decoded->result,&stage_context[3].decoded->result)<0) { fprintf(stderr,"invalid access to memory address %u",stage_context[3].decoded->result); exit(1); } } else if(stage_context[3].decoded->type==10 ) {//Store mem_write(stage_context[3].decoded->result,stage_context[3].decoded->src1); } end: stage_context[4] = stage_context[3]; return 0; }
word_t mem_sval_fetch(struct vm *vm, sval_t sval, unsigned int offset) { return mem_fetch(vm, mem_sval_to_vaddr(vm, sval, offset)); }
int lsa_sim ( void ) { unsigned int ra; unsigned int rb; unsigned int rc; unsigned int rega; unsigned int regb; unsigned int simcount; reset_lsa(); simcount=0; while(1) { //if(simcount++>30) break; if(state==STATE_HALTED) break; //printf("[0x%04X] 0x%04X\n",read_register(0),read_register(3]); switch(state) { case STATE_HALTED: break; case STATE_FETCH: rega=read_register(0); inst=mem_fetch(rega); rega++; write_register(0,rega); rd=0; wr=0; switch(inst&0xF000) { case 0x0000: // lpc load pc relative rd=1; add=read_register(0)+(inst&0xFF); break; case 0x1000: // lsp load sp relative rd=1; add=read_register(2)+(inst&0xFF); break; case 0x2000: // spc store pc relative wr=1; add=read_register(0)+(inst&0xFF); data=read_register((inst>>8)&0xF); break; case 0x3000: // ssp store sp relative wr=1; add=read_register(2)+(inst&0xFF); data=read_register((inst>>8)&0xF); break; case 0x4000: // ldw/stw load/store switch(inst&0xF) { case 0x0: // ldw rd,[rs] rd=1; add=read_register((inst>>4)&0xF); break; case 0x1: // ldw rd,[rs++] rd=1; rega=read_register((inst>>4)&0xF); add=rega; rega++; write_register((inst>>4)&0xF,rega); break; case 0x2: // ldw rd,[++rs] rd=1; rega=read_register((inst>>4)&0xF); rega++; add=rega; write_register((inst>>4)&0xF,rega); break; case 0x3: // ldw rd,[rs--] rd=1; rega=read_register((inst>>4)&0xF); add=rega; rega--; write_register((inst>>4)&0xF,rega); break; case 0x4: // ldw rd,[--rs] rd=1; rega=read_register((inst>>4)&0xF); rega--; add=rega; write_register((inst>>4)&0xF,rega); break; case 0x6: // mov rd,rs rega=read_register((inst>>4)&0xF); write_register((inst>>8)&0xF,rega); break; case 0x8: // stw [rd],rs wr=1; add=read_register((inst>>8)&0xF); data=read_register((inst>>4)&0xF); break; case 0x9: // stw [rd++],rs wr=1; rega=read_register((inst>>8)&0xF); add=rega; rega++; write_register((inst>>8)&0xF,rega); data=read_register((inst>>4)&0xF); break; case 0xA: // stw [++rd],rs wr=1; rega=read_register((inst>>8)&0xF); rega++; add=rega; write_register((inst>>8)&0xF,rega); data=read_register((inst>>4)&0xF); break; case 0xB: // stw [rd--],rs wr=1; rega=read_register((inst>>8)&0xF); add=rega; rega--; write_register((inst>>8)&0xF,rega); data=read_register((inst>>4)&0xF); break; case 0xC: // stw [--rd],rs wr=1; rega=read_register((inst>>8)&0xF); rega--; add=rega; write_register((inst>>8)&0xF,rega); data=read_register((inst>>4)&0xF); break; case 0xE: // swap rd,rs rega=read_register((inst>>4)&0xF); regb=read_register((inst>>8)&0xF); write_register((inst>>4)&0xF,regb); write_register((inst>>8)&0xF,rega); break; } break; case 0x5000: // move to/from high register if(inst&0x80) { rega=read_register((inst>>8)&0xF); write_register((inst>>0)&0x7F,rega); } else { rega=read_register((inst>>0)&0x7F); write_register((inst>>8)&0xF,rega); } break; case 0x6000: // alu operation switch(inst&0xF) { case 0x6: opa=0; opb=read_register((inst>>4)&0xF); break; case 0x8: case 0x9: opa=read_register((inst>>4)&0xF); opb=1; break; default: opa=read_register((inst>>8)&0xF); opb=read_register((inst>>4)&0xF); break; } switch(inst&0xF) { case 0x0: res = opa + opb; break; //add case 0x1: res = opa - opb; break; //sub case 0x2: res = opa & opb; break; //and case 0x3: res = opa & (~opb); break; //dna case 0x4: res = opa | opb; break; //or case 0x5: res = opa ^ opb; break; //xor case 0x6: res = opa - opb; break; //neg case 0x7: res = ~ opb; break; //not case 0x8: res = opa + opb; break; //inc case 0x9: res = opa - opb; break; //dec case 0xA: res = opa - opb; break; //cmp case 0xB: res = opa & opb; break; //tst } rega=read_register(1); //dont use rega until after the switch if((res&0xFFFF)==0) rega|=ZBIT; else rega&=(~ZBIT); if(res&0x8000) rega|=NBIT; else rega&=(~NBIT); switch(inst&0xF) { case 0x0: case 0x8: //add if(res&0x10000) rega|=CBIT; else rega&=(~CBIT); if ( ((opa&0x8000) == (opb&0x8000)) && ((res&0x8000) != (opb&0x8000)) ) rega|=VBIT; else rega&=(~VBIT); break; case 0x1: case 0x6: case 0x9: case 0xA: //sub if(res&0x10000) rega&=(~CBIT); else rega|=CBIT; if ( ((opa&0x8000) != (opb&0x8000)) && ((res&0x8000) == (opb&0x8000)) ) rega|=VBIT; else rega&=(~VBIT); break; default: rega&=(~CBIT); rega&=(~VBIT); break; } write_register(1,rega); //can use rega now switch(inst&0xF) { case 0x0: //add case 0x1: //sub case 0x2: //and case 0x3: //dna case 0x4: //or case 0x5: //xor case 0x6: //neg case 0x7: //not case 0x8: //inc case 0x9: //dec write_register((inst>>8)&0xF,res); break; case 0xA: //cmp case 0xB: //tst //these set flags but do not store break; } break; case 0x7000: // shift opa=read_register((inst>>8)&0xF); switch(inst&0xF) { case 0x0: // register based case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: opb=read_register((inst>>4)&0xF)&0xF; break; case 0x8: // immediate case 0x9: case 0xA: case 0xB: case 0xC: case 0xD: case 0xE: opb=(inst>>4)&0xF; break; } res=opa; if(opb) { switch(inst&0x7) { case 0x0: // lsr res=opa>>opb; break; case 0x1: // asr res=opa>>opb; if(opa&0x8000) res|=(~0)<<(15-opb); break; case 0x2: // lsl res=opa<<opb; break; case 0x3: // ror res=opa>>opb; res|=opa<<(16-opb); break; case 0x4: // rol res=opa<<opb; res|=opa>>(16-opb); break; case 0x5: // rrc rega=read_register(1); res=opa>>opb; res|=opa<<(17-opb); if(rega&CBIT) { res|=0x8000>>(opb-1); } else { res&=~(0x8000>>(opb-1)); } if(opa&(0x0001<<(opb-1))) rega|=CBIT; else rega&=~(CBIT); write_register(1,rega); break; case 0x6: // rlc rega=read_register(1); res=opa<<opb; res|=opa>>(17-opb); if(rega&CBIT) { res|=1<<(opb-1); } else { res&=~(1<<(opb-1)); } if(opa&(0x8000>>(opb-1))) rega|=CBIT; else rega&=~(CBIT); write_register(1,rega); break; }