#include "simdata.h" #include "cpu.h" #include #include #include /* Known errors: * 1) Exec does the calculations on the first clock cycle, there is a bug where in some cases exec isn't run on the last cycle and because of this the CPU still works. */ struct fetch_data_t *malloc_fetch_data(){ struct fetch_data_t *ret=malloc(sizeof(struct fetch_data_t)); ret->wait_for_exec=0; ret->exec_done=1; ret->decode_done=1; ret->fetch_wait=0; return ret; } void free_fetch_data(struct fetch_data_t *tofree){ free(tofree); } int fetch(struct simdata_t *simdata){ free_instr_list(&simdata->cpu_gui_hints->fetching_list); if(simdata->fetch_data->wait_for_exec!=0){ simdata->fetch_data->fetch_wait=1; simdata->decode_data->valid=0; simdata->fetch_data->wait_for_exec=0; return 0; } if(simdata->fetch_data->fetch_wait){ if(simdata->fetch_data->exec_done){ simdata->fetch_data->fetch_wait=0; }else return 0; } if(!simdata->fetch_data->decode_done) return 0; simdata->decode_data->in_bytecode=(uint32_t)(simdata->RAM[simdata->registers->PC])<<24|(uint32_t)(simdata->RAM[simdata->registers->PC+1])<<16|(uint32_t)(simdata->RAM[simdata->registers->PC+2])<<8|(uint32_t)(simdata->RAM[simdata->registers->PC+3]); simdata->decode_data->valid=1; simdata->decode_data->address=simdata->registers->PC; add_to_instr_list(&simdata->cpu_gui_hints->fetching_list,simdata->registers->PC); simdata->registers->PC+=4; return 0; } struct decode_data_t *malloc_decode_data(){ struct decode_data_t *ret=malloc(sizeof(struct decode_data_t)); if(ret) ret->valid=0; ret->exec_done=1; return ret; } void free_decode_data(struct decode_data_t *tofree){ free(tofree); } int decode(struct simdata_t *simdata){ uint16_t opcode,op1,op2,imm; free_instr_list(&simdata->cpu_gui_hints->decoding_list); if(simdata->decode_data->exec_done==0){ simdata->fetch_data->decode_done=0; return 0; } if(simdata->decode_data->valid==0){ simdata->exec_data->valid=0; simdata->fetch_data->decode_done=1; return 0; } switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){ case 0: opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24; switch(opcode){ case 0x00: simdata->exec_data->EXEC_ACTION=NOP; break; case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: switch(opcode){ case 0x01: case 0x11: simdata->exec_data->COND=COND_NONE; break; case 0x02: case 0x12: simdata->exec_data->COND=COND_ZERO; break; case 0x03: case 0x13: simdata->exec_data->COND=COND_NZERO; break; case 0x04: case 0x14: simdata->exec_data->COND=COND_CARRY; break; case 0x05: case 0x15: simdata->exec_data->COND=COND_NCARRY; break; case 0x06: case 0x16: simdata->exec_data->COND=COND_SIGN; break; case 0x07: case 0x17: simdata->exec_data->COND=COND_NSIGN; break; default: return 1; } simdata->exec_data->out_op->OP_ADDR=IMMEDIATE; simdata->exec_data->out_op->data=simdata->decode_data->in_bytecode&0x00FFFFFF; simdata->exec_data->EXEC_ACTION=(opcode&0x10)?CALL:JUMP; simdata->fetch_data->wait_for_exec=1; break; case 0x0F:/* load SP */ simdata->exec_data->EXEC_ACTION=MOVE; simdata->exec_data->in_op1->OP_ADDR=IMMEDIATE; simdata->exec_data->in_op1->data=simdata->decode_data->in_bytecode&0x00FFFFFF; simdata->exec_data->out_op->OP_ADDR=REGISTER; simdata->exec_data->out_op->data=0xFF; break; case 0x10: simdata->exec_data->EXEC_ACTION=RET; simdata->fetch_data->wait_for_exec=1; break; default: return 1; } break; case 1: opcode=(simdata->decode_data->in_bytecode&0x1FFF0000)>>16; op1=(simdata->decode_data->in_bytecode&0x0000FF00)>>8; op2=(simdata->decode_data->in_bytecode&0x000000FF); simdata->exec_data->in_op1->data=op1; simdata->exec_data->in_op2->data=op2; switch(opcode){ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: case 0x10: case 0x11: case 0x12: simdata->exec_data->in_op1->OP_ADDR=REGISTER; simdata->exec_data->in_op2->OP_ADDR=REGISTER; break; case 0x08: simdata->exec_data->in_op1->OP_ADDR=REGISTER; simdata->exec_data->in_op2->OP_ADDR=REGISTER_IND; break; case 0x09: simdata->exec_data->in_op1->OP_ADDR=REGISTER_IND; simdata->exec_data->in_op2->OP_ADDR=REGISTER; break; } switch(opcode){ case 0x05: simdata->exec_data->EXEC_ACTION=HALT; break; case 0x06: simdata->exec_data->EXEC_ACTION=PUSH; break; case 0x07: simdata->exec_data->EXEC_ACTION=POP; break; case 0x08: case 0x09: case 0x12: simdata->exec_data->EXEC_ACTION=MOVE; break; default: simdata->exec_data->EXEC_ACTION=EXEC_ALU; break; } switch(opcode){ case 0x00: case 0x01: case 0x04: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x12: simdata->exec_data->out_op->OP_ADDR=REGISTER; simdata->exec_data->out_op->data=op2; break; case 0x02: case 0x03: case 0x0E: case 0x0F: case 0x10: case 0x11: simdata->exec_data->out_op->OP_ADDR=REGISTER; simdata->exec_data->out_op->data=op1; break; case 0x08: simdata->exec_data->out_op->data=op2; simdata->exec_data->out_op->OP_ADDR=REGISTER_IND; break; case 0x09: simdata->exec_data->out_op->data=op2; simdata->exec_data->out_op->OP_ADDR=REGISTER; break; } switch(opcode){ case 0x00: simdata->exec_data->ALU_OP=ALU_ADD; break; case 0x01: simdata->exec_data->ALU_OP=ALU_SUB; break; case 0x02: simdata->exec_data->ALU_OP=ALU_SL; break; case 0x03: simdata->exec_data->ALU_OP=ALU_SR; break; case 0x04: simdata->exec_data->ALU_OP=ALU_CMP; break; case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x12: break; case 0x0A: simdata->exec_data->ALU_OP=ALU_FDIV; break; case 0x0B: simdata->exec_data->ALU_OP=ALU_FMUL; break; case 0x0C: simdata->exec_data->ALU_OP=ALU_FADD; break; case 0x0D: simdata->exec_data->ALU_OP=ALU_FSUB; break; case 0x0E: simdata->exec_data->ALU_OP=ALU_FSIN; break; case 0x0F: simdata->exec_data->ALU_OP=ALU_FCOS; break; case 0x10: simdata->exec_data->ALU_OP=ALU_DEC; break; case 0x11: simdata->exec_data->ALU_OP=ALU_INC; break; default: return 1; } break; case 2: opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24; op1=(simdata->decode_data->in_bytecode&0x00FF0000)>>16; imm=(simdata->decode_data->in_bytecode&0x0000FFFF); switch(opcode){ case 0: simdata->exec_data->EXEC_ACTION=MOVE; simdata->exec_data->in_op1->OP_ADDR=IMMEDIATE; simdata->exec_data->in_op1->data=imm; simdata->exec_data->out_op->OP_ADDR=REGISTERL; simdata->exec_data->out_op->data=op1; break; case 1: simdata->exec_data->EXEC_ACTION=MOVE; simdata->exec_data->in_op1->OP_ADDR=IMMEDIATE; simdata->exec_data->in_op1->data=imm; simdata->exec_data->out_op->OP_ADDR=REGISTERH; simdata->exec_data->out_op->data=op1; break; } break; default: return 1; } simdata->fetch_data->decode_done=1; simdata->exec_data->valid=1; simdata->exec_data->address=simdata->decode_data->address; add_to_instr_list(&simdata->cpu_gui_hints->decoding_list,simdata->decode_data->address); return 0; } struct exec_data_t *malloc_exec_data(){ struct exec_data_t *ret; ret=malloc(sizeof(struct exec_data_t)); if(!ret) return 0; ret->in_op1=malloc(sizeof(struct exec_op_t)); if(!ret->in_op1){ free(ret); return 0; } ret->in_op2=malloc(sizeof(struct exec_op_t)); if(!ret->in_op2){ free(ret->in_op1); free(ret); return 0; } ret->out_op=malloc(sizeof(struct exec_op_t)); if(!ret->out_op){ free(ret->in_op1); free(ret->in_op2); free(ret); return 0; } ret->valid=0; ret->cycles_left=0; return ret; } void free_exec_data(struct exec_data_t *tofree){ free(tofree->in_op1); free(tofree->in_op2); free(tofree->out_op); free(tofree); } #define RR_SIMPL_INDX 0 #define RR_COMPLX_INDX 1 #define RR_FCOMPLX_INDX 2 #define MEM_ACCS_INDX 3 #define IMM_LOAD_INDX 4 #define BRNCH_MISS_INDX 5 #define BRNCH_TAKN_INDX 6 #define BRNCH_UNCO_INDX 7 #define CALL_RET_INDX 8 #define RR_FTRI_INDX 9 #define RR_MOVE_INDX 10 int delay_values[]={ 1, // register-register (integer) add,sub,inc,dec,shift left/right float add,sub 4, // register-register integer multiply, divide 4, // register-register float multiply, divide 2, // push / pop / read mem / write mem 1, // immediate to register 1, // branch not taken 3, // branch taken 3, // branch unconditional 4, // call/ret 4, // float sin/cos 1 // register-register move }; int exec(struct simdata_t *simdata){ free_instr_list(&simdata->cpu_gui_hints->executing_list); if(simdata->exec_data->valid==1){ simdata->fetch_data->exec_done=0; simdata->decode_data->exec_done=0; } if(simdata->exec_data->cycles_left==0){ if(simdata->exec_data->valid==0) return 0; int condition=0; #define SANITY_CHECK(x) { if(x>0x0F){return 1;} } switch(simdata->exec_data->EXEC_ACTION){ case CALL: case JUMP: switch(simdata->exec_data->COND){ case COND_NONE: condition=1; break; case COND_ZERO: condition=simdata->registers->FLAGS&1; break; case COND_NZERO: condition=!(simdata->registers->FLAGS&1); break; case COND_CARRY: condition=simdata->registers->FLAGS&2; break; case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break; case COND_SIGN: condition=simdata->registers->FLAGS&4; break; case COND_NSIGN: condition=!(simdata->registers->FLAGS&4); break; } switch(simdata->exec_data->COND){ case COND_NONE: simdata->exec_data->cycles_left=delay_values[BRNCH_UNCO_INDX]; break; default: if(condition) simdata->exec_data->cycles_left=delay_values[BRNCH_TAKN_INDX]; else simdata->exec_data->cycles_left=delay_values[BRNCH_MISS_INDX]; break; } if(condition){ if(simdata->exec_data->EXEC_ACTION==CALL){ *(uint32_t*)(simdata->RAM+simdata->registers->SP)=simdata->registers->PC; simdata->registers->SP+=4; } if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE) simdata->registers->PC=(uint32_t)(simdata->exec_data->out_op->data); else return 1; } break; case RET: simdata->exec_data->cycles_left=delay_values[CALL_RET_INDX]; simdata->registers->SP-=4; simdata->registers->PC=*(uint32_t*)(simdata->RAM+simdata->registers->SP); break; case EXEC_ALU: if( simdata->exec_data->in_op1->OP_ADDR==REGISTER && simdata->exec_data->in_op2->OP_ADDR==REGISTER && simdata->exec_data->out_op->OP_ADDR==REGISTER ){ uint32_t result; switch(simdata->exec_data->ALU_OP){ case ALU_ADD: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = simdata->registers->GPR[simdata->exec_data->in_op1->data] + simdata->registers->GPR[simdata->exec_data->in_op2->data]; simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| (simdata->registers->GPR[simdata->exec_data->out_op->data] < simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1; simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_SUB: case ALU_CMP: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = simdata->registers->GPR[simdata->exec_data->in_op2->data] - simdata->registers->GPR[simdata->exec_data->in_op1->data]; simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| (simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1; simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFB)| (simdata->registers->GPR[simdata->exec_data->in_op2->data]registers->GPR[simdata->exec_data->in_op1->data])<<2; simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_SL: SANITY_CHECK(simdata->exec_data->in_op1->data); simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| ((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x80000000)?2:0); result = simdata->registers->GPR[simdata->exec_data->in_op1->data]<<1; simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_SR: SANITY_CHECK(simdata->exec_data->in_op1->data); simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| ((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00000001)?2:0); result = simdata->registers->GPR[simdata->exec_data->in_op1->data]>>1; simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_FDIV: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])/ uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])); simdata->exec_data->cycles_left=delay_values[RR_COMPLX_INDX]; break; case ALU_FMUL: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])* uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])); simdata->exec_data->cycles_left=delay_values[RR_COMPLX_INDX]; break; case ALU_FADD: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])+ uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])); simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_FSUB: SANITY_CHECK(simdata->exec_data->in_op1->data); SANITY_CHECK(simdata->exec_data->in_op2->data); result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])- uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])); simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; case ALU_FSIN: SANITY_CHECK(simdata->exec_data->in_op1->data); result = ieee754_float_to_uint32(sinf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]))); simdata->exec_data->cycles_left=delay_values[RR_FTRI_INDX]; break; case ALU_FCOS: SANITY_CHECK(simdata->exec_data->in_op1->data); result = ieee754_float_to_uint32(cosf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]))); simdata->exec_data->cycles_left=delay_values[RR_FTRI_INDX]; break; case ALU_DEC: SANITY_CHECK(simdata->exec_data->in_op1->data); *(uint32_t*)&result = *(uint32_t*)(&simdata->registers->GPR[simdata->exec_data->in_op1->data])-1; simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| (simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1; simdata->exec_data->cycles_left=delay_values[RR_FCOMPLX_INDX]; break; case ALU_INC: SANITY_CHECK(simdata->exec_data->in_op1->data); *(uint32_t*)&result = *(uint32_t*)(&simdata->registers->GPR[simdata->exec_data->in_op1->data])+1; simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| (simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1; simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX]; break; default: return 1; } simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFE)|(result==0); if(simdata->exec_data->ALU_OP!=ALU_CMP) simdata->registers->GPR[simdata->exec_data->out_op->data]=result; }else return 1; break; case MOVE: switch(simdata->exec_data->out_op->OP_ADDR){ case REGISTERL: if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){ SANITY_CHECK(simdata->exec_data->out_op->data); simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF& simdata->exec_data->in_op1->data); simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX]; }else{ //simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF& // simdata->registers->GPR[simdata->exec_data->in_op1->data]); //simdata->exec_data->cycles_left= return 1; } break; case REGISTERH: if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){ SANITY_CHECK(simdata->exec_data->out_op->data); simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x0000FFFF)|((0x0000FFFF& simdata->exec_data->in_op1->data)<<16); simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX]; }else{ //simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x0000FFFF)|((0x0000FFFF& // simdata->registers->GPR[simdata->exec_data->in_op1->data])<<16); //simdata->exec_data->cycles_left= return 1; } break; case REGISTER: /* This is for special registers like the SP which is 24bits long */ if(simdata->exec_data->out_op->data==0xFF){ if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){ if( (simdata->exec_data->in_op1->data&0xFF000000) == 0 ) simdata->registers->SP=simdata->exec_data->in_op1->data; else return 2; simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX]; }else if( simdata->exec_data->in_op1->OP_ADDR==REGISTER ){ /*for completeion, not valid ( yet )*/ //if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 ) // simdata->registers->SP=simdata->registers->GPR[simdata->exec_data->in_op1->data]; //else // return 2; return 1; } }else if(simdata->exec_data->in_op1->OP_ADDR==REGISTER_IND){ SANITY_CHECK(simdata->exec_data->out_op->data); SANITY_CHECK(simdata->exec_data->in_op1->data); if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 ){ simdata->registers->GPR[simdata->exec_data->out_op->data]=*(uint32_t*)(simdata->RAM+simdata->registers->GPR[simdata->exec_data->in_op1->data]); simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX]; }else return 2; }else if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){ if(simdata->exec_data->in_op1->data==0xFF){ /*Reading from SP*/ SANITY_CHECK(simdata->exec_data->out_op->data); simdata->registers->GPR[simdata->exec_data->out_op->data]=simdata->registers->SP; }else{ SANITY_CHECK(simdata->exec_data->out_op->data); SANITY_CHECK(simdata->exec_data->in_op1->data); simdata->registers->GPR[simdata->exec_data->out_op->data]=simdata->registers->GPR[simdata->exec_data->in_op1->data]; } simdata->exec_data->cycles_left=delay_values[RR_MOVE_INDX]; }else return 1; break; case REGISTER_IND: if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){ SANITY_CHECK(simdata->exec_data->out_op->data); SANITY_CHECK(simdata->exec_data->in_op1->data); *(uint32_t*)(simdata->RAM+(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x00FFFFFF))=simdata->registers->GPR[simdata->exec_data->in_op1->data]; if(simdata->registers->GPR[simdata->exec_data->out_op->data]==0x00FFFFFC) if(terminal_output(simdata->registers->GPR[simdata->exec_data->in_op1->data],simdata)) return 1; simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX]; }else return 1; break; default: return 1; } break; case NOP: simdata->exec_data->cycles_left=1; break; case HALT: simdata->exec_data->cycles_left=1; simdata->cpu_state=CPU_HALTED; break; case PUSH: SANITY_CHECK(simdata->exec_data->in_op1->data); simdata->RAM[simdata->registers->SP ]=simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x000000FF; simdata->RAM[simdata->registers->SP+1]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x0000FF00)>>8; simdata->RAM[simdata->registers->SP+2]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00FF0000)>>16; simdata->RAM[simdata->registers->SP+3]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000)>>24; simdata->registers->SP+=4; simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX]; break; case POP: SANITY_CHECK(simdata->exec_data->in_op1->data); simdata->registers->SP-=4; simdata->registers->GPR[simdata->exec_data->in_op1->data]=simdata->RAM[simdata->registers->SP]; simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+1]<<8; simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+2]<<16; simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+3]<<24; simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX]; break; } } if(simdata->exec_data->cycles_left!=0) simdata->exec_data->cycles_left--; else return 1;//internal error if(simdata->exec_data->cycles_left==0){ simdata->fetch_data->exec_done=1; simdata->decode_data->exec_done=1; simdata->finished_instructions++; } add_to_instr_list(&simdata->cpu_gui_hints->executing_list,simdata->exec_data->address); return 0; } int state=0; /* * RETURN CODES: * 0 : success * 1 : error in execution stage * 2 : error in decode stage * 3 : error in fetch stage * 4 : internal error */ int cpu_cycle_clock(struct simdata_t *simdata){ free_instr_list(&simdata->cpu_gui_hints->fetching_list); free_instr_list(&simdata->cpu_gui_hints->decoding_list); free_instr_list(&simdata->cpu_gui_hints->executing_list); switch(simdata->cpu_structure){ case CPU_STRUCTURE_SIMPLE_PIPELINED: switch(exec(simdata)){ case 0: break; case 2: return 4; default: return 1; } switch(decode(simdata)){ case 0: break; default: return 2; } switch(fetch(simdata)){ case 0: break; default: return 3; } break; case CPU_STRUCTURE_SIMPLE_NON_PIPELINED: switch(state){ case 0: switch(fetch(simdata)){ case 0: break; default: return 3; } break; case 1: switch(decode(simdata)){ case 0: break; default: return 2; } break; case 2: switch(exec(simdata)){ case 0: break; case 2: return 4; default: return 1; } break; } if(state==2){ if(simdata->decode_data->exec_done) state=0; }else state++; break; default: return 4; } simdata->current_clock++; return 0; } int cpu_simdata_malloc(struct simdata_t *simdata){ simdata->fetch_data=malloc_fetch_data(); simdata->decode_data=malloc_decode_data(); simdata->exec_data=malloc_exec_data(); simdata->registers=malloc(sizeof(struct registers_t)); simdata->registers->PC=0x00000000; simdata->registers->SP=0; if((simdata->fetch_data!=NULL)&&(simdata->decode_data!=NULL)&&(simdata->exec_data!=NULL)) return 1; else return 0; } void cpu_simdata_free(struct simdata_t *simdata){ free_fetch_data(simdata->fetch_data); free_decode_data(simdata->decode_data); free_exec_data(simdata->exec_data); free(simdata->registers); } char* EXEC_ACTION_t_to_string(enum EXEC_ACTION_t in){ char* ret; switch(in){ case EXEC_ALU: ret="EXEC_ALU"; break; case MOVE: ret="MOVE"; break; case JUMP: ret="JUMP"; break; case CALL: ret="CALL"; break; case NOP: ret="NOP"; break; case HALT: ret="HALT"; break; case RET: ret="RET"; break; case PUSH: ret="PUSH"; break; case POP: ret="POP"; break; default: ret=""; } char *real_ret=malloc(9); *real_ret=0; strncpy(real_ret,ret,9); return real_ret; } char* ALU_OP_t_to_string(enum ALU_OP_t in){ char* ret; switch(in){ case ALU_ADD: ret="LU_ADD"; break; case ALU_SUB: ret="LU_SUB"; break; case ALU_SL: ret="LU_SL"; break; case ALU_SR: ret="LU_SR"; break; case ALU_CMP: ret="LU_CMP"; break; case ALU_FDIV: ret="LU_FDIV"; break; case ALU_FMUL: ret="LU_FMUL"; break; case ALU_FADD: ret="LU_FADD"; break; case ALU_FSUB: ret="LU_FSUB"; break; case ALU_FSIN: ret="LU_FSIN"; break; case ALU_FCOS: ret="LU_FCOS"; break; case ALU_DEC: ret="LU_DEC"; break; case ALU_INC: ret="LU_INC"; break; default: ret=""; } char *real_ret=malloc(8); *real_ret=0; strncpy(real_ret,ret,8); return real_ret; } char* COND_t_to_string(enum COND_t in){ char* ret; switch(in){ case COND_NONE: ret="COND_NONE"; break; case COND_ZERO: ret="COND_ZERO"; break; case COND_NZERO: ret="COND_NZERO"; break; case COND_CARRY: ret="COND_CARRY"; break; case COND_NCARRY: ret="COND_NCARRY"; break; default: ret=""; } char *real_ret=malloc(12); *real_ret=0; strncpy(real_ret,ret,12); return real_ret; } char* OP_ADDR_t_to_string(enum OP_ADDR_t in){ char* ret; switch(in){ case IMMEDIATE: ret="IMMEDIATE"; break; case REGISTER: ret="REGISTER"; break; case REGISTERL: ret="REGISTERL"; break; case REGISTERH: ret="REGISTERH"; break; case REGISTER_IND: ret="REGISTER_IND"; break; default: ret=""; } char *real_ret=malloc(13); *real_ret=0; strncpy(real_ret,ret,13); return real_ret; }