diff --git a/cpu.c b/cpu.c index 27fdb43..1e88d3b 100644 --- a/cpu.c +++ b/cpu.c @@ -25,7 +25,7 @@ void free_decode_data(struct decode_data_t *tofree){ free(tofree); } int decode(struct simdata_t *simdata){ - uint16_t opcode; + uint16_t opcode,op1,op2,imm; switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){ case 0: opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24; @@ -40,10 +40,66 @@ int decode(struct simdata_t *simdata){ } break; case 1: - return 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->OP_ADDR=REGISTER; + simdata->exec_data->in_op1->data=op1; + + simdata->exec_data->in_op2->OP_ADDR=REGISTER; + simdata->exec_data->in_op2->data=op2; + + simdata->exec_data->EXEC_ACTION=EXEC_ALU; + + switch(opcode){ + case 0: + case 1: + case 4: + simdata->exec_data->out_op->OP_ADDR=REGISTER; + simdata->exec_data->out_op->data=op2; + break; + case 2: + case 3: + simdata->exec_data->out_op->OP_ADDR=REGISTER; + simdata->exec_data->out_op->data=op1; + break; + } + + + switch(opcode){ + case 0: simdata->exec_data->ALU_OP=ALU_ADD; break; + case 1: simdata->exec_data->ALU_OP=ALU_SUB; break; + case 2: simdata->exec_data->ALU_OP=ALU_SL; break; + case 3: simdata->exec_data->ALU_OP=ALU_SR; break; + case 4: simdata->exec_data->ALU_OP=ALU_CMP; break; + default: + return 1; + } break; case 2: - return 1; + 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; @@ -94,7 +150,66 @@ int exec(struct simdata_t *simdata){ return 1; break; case EXEC_ALU: - return 1; + 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: + 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; + break; + case ALU_SUB: + case ALU_CMP: + 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; + break; + case ALU_SL: + 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; + break; + case ALU_SR: + 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; + 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) + 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); + 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]); + break; + case REGISTERH: + if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE) + 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); + 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); + break; + default: + return 1; + } + } return 0; } @@ -107,8 +222,8 @@ int state=0; int cpu_cycle_clock(struct simdata_t *simdata){ switch(state){ - case 0: if( fetch(simdata) ) return 1; break; - case 1: if( decode(simdata) ) return 1; break; + case 0: if( fetch(simdata) ) return 3; break; + case 1: if( decode(simdata) ) return 2; break; case 2: if( exec(simdata) ) return 1; break; } if(state==2) diff --git a/cpu.h b/cpu.h index 05f7795..7ae544a 100644 --- a/cpu.h +++ b/cpu.h @@ -14,6 +14,7 @@ struct decode_data_t{ ///// EXEC DATA STRUCTURES /////// enum EXEC_ACTION_t { EXEC_ALU, + MOVE, JUMP }; @@ -28,6 +29,8 @@ enum ALU_OP_t { enum OP_ADDR_t { IMMEDIATE, REGISTER, + REGISTERL, //low word + REGISTERH, //high word }; struct exec_op_t { diff --git a/main.c b/main.c index 70bb1eb..d70e3dc 100644 --- a/main.c +++ b/main.c @@ -170,11 +170,24 @@ int main(int argc, char* argd[] ){ return 1; } - if(cpu_cycle_clock(simdata)){ + int ret; + if((ret=cpu_cycle_clock(simdata))){ cpu_simdata_free(simdata); free_simdata(simdata); end_gui(); - printf("Failed to execute instruction\n"); + switch(ret){ + case 1: + printf("Failed to execute instruction\n"); + break; + case 2: + printf("Failed to decode instruction\n"); + break; + case 3: + printf("Failed to fetch instruction\n"); + break; + default: + printf("Unkown CPU failure\n"); + } return 1; } } diff --git a/test.asm b/test.asm index d21cc29..4f42000 100644 --- a/test.asm +++ b/test.asm @@ -1,9 +1,7 @@ -JMP $000008 -SL %R7 -JMP $000000 -JMP,NZ $DEADBA -JMP,C $EEEEEF -SL %R7 -CMP %R2,%R0 -MOV $1238,%R5h -MOV $8321,%R2l +MOV $0000,%R0l +MOV $8000,%R0h +MOV $0001,%R1l +MOV $0000,%R1h +CMP %R1,%R0 +SR %R0,%R1 +JMP $000014