CPU: Added support for the add,sub,sl,sr and cmp instructions

This commit is contained in:
(Tim) Efthimis Kritikos 2024-02-06 21:53:42 +00:00
parent e86bf547cb
commit 1dcc69ba50
4 changed files with 146 additions and 17 deletions

123
cpu.c
View File

@ -25,7 +25,7 @@ void free_decode_data(struct decode_data_t *tofree){
free(tofree); free(tofree);
} }
int decode(struct simdata_t *simdata){ int decode(struct simdata_t *simdata){
uint16_t opcode; uint16_t opcode,op1,op2,imm;
switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){ switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){
case 0: case 0:
opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24; opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24;
@ -40,10 +40,66 @@ int decode(struct simdata_t *simdata){
} }
break; break;
case 1: 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; break;
case 2: 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; 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; break;
default: default:
return 1; return 1;
@ -94,8 +150,67 @@ int exec(struct simdata_t *simdata){
return 1; return 1;
break; break;
case EXEC_ALU: 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:
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; 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; return 0;
} }
@ -107,8 +222,8 @@ int state=0;
int cpu_cycle_clock(struct simdata_t *simdata){ int cpu_cycle_clock(struct simdata_t *simdata){
switch(state){ switch(state){
case 0: if( fetch(simdata) ) return 1; break; case 0: if( fetch(simdata) ) return 3; break;
case 1: if( decode(simdata) ) return 1; break; case 1: if( decode(simdata) ) return 2; break;
case 2: if( exec(simdata) ) return 1; break; case 2: if( exec(simdata) ) return 1; break;
} }
if(state==2) if(state==2)

3
cpu.h
View File

@ -14,6 +14,7 @@ struct decode_data_t{
///// EXEC DATA STRUCTURES /////// ///// EXEC DATA STRUCTURES ///////
enum EXEC_ACTION_t { enum EXEC_ACTION_t {
EXEC_ALU, EXEC_ALU,
MOVE,
JUMP JUMP
}; };
@ -28,6 +29,8 @@ enum ALU_OP_t {
enum OP_ADDR_t { enum OP_ADDR_t {
IMMEDIATE, IMMEDIATE,
REGISTER, REGISTER,
REGISTERL, //low word
REGISTERH, //high word
}; };
struct exec_op_t { struct exec_op_t {

15
main.c
View File

@ -170,11 +170,24 @@ int main(int argc, char* argd[] ){
return 1; return 1;
} }
if(cpu_cycle_clock(simdata)){ int ret;
if((ret=cpu_cycle_clock(simdata))){
cpu_simdata_free(simdata); cpu_simdata_free(simdata);
free_simdata(simdata); free_simdata(simdata);
end_gui(); end_gui();
switch(ret){
case 1:
printf("Failed to execute instruction\n"); 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; return 1;
} }
} }

View File

@ -1,9 +1,7 @@
JMP $000008 MOV $0000,%R0l
SL %R7 MOV $8000,%R0h
JMP $000000 MOV $0001,%R1l
JMP,NZ $DEADBA MOV $0000,%R1h
JMP,C $EEEEEF CMP %R1,%R0
SL %R7 SR %R0,%R1
CMP %R2,%R0 JMP $000014
MOV $1238,%R5h
MOV $8321,%R2l