2024-02-03 22:54:20 +00:00
|
|
|
#include "simdata.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include <stdlib.h>
|
2024-02-16 19:46:25 +00:00
|
|
|
#include <math.h>
|
2024-02-20 21:56:48 +00:00
|
|
|
#include <string.h>
|
2024-02-03 22:54:20 +00:00
|
|
|
|
2024-05-02 11:55:29 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2024-02-03 22:54:20 +00:00
|
|
|
|
|
|
|
struct fetch_data_t *malloc_fetch_data(){
|
2024-02-20 21:56:48 +00:00
|
|
|
struct fetch_data_t *ret=malloc(sizeof(struct fetch_data_t));
|
|
|
|
ret->wait_for_exec=0;
|
2024-03-06 02:37:55 +00:00
|
|
|
ret->exec_done=1;
|
|
|
|
ret->decode_done=1;
|
|
|
|
ret->fetch_wait=0;
|
2024-02-20 21:56:48 +00:00
|
|
|
return ret;
|
2024-02-03 22:54:20 +00:00
|
|
|
}
|
2024-02-20 21:56:48 +00:00
|
|
|
void free_fetch_data(struct fetch_data_t *tofree){
|
|
|
|
free(tofree);
|
2024-02-03 22:54:20 +00:00
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
|
2024-02-03 22:54:20 +00:00
|
|
|
int fetch(struct simdata_t *simdata){
|
2024-02-07 00:31:23 +00:00
|
|
|
free_instr_list(&simdata->cpu_gui_hints->fetching_list);
|
2024-03-06 02:37:55 +00:00
|
|
|
|
2024-02-20 21:56:48 +00:00
|
|
|
if(simdata->fetch_data->wait_for_exec!=0){
|
2024-03-06 02:37:55 +00:00
|
|
|
simdata->fetch_data->fetch_wait=1;
|
2024-02-20 21:56:48 +00:00
|
|
|
simdata->decode_data->valid=0;
|
2024-03-06 02:37:55 +00:00
|
|
|
simdata->fetch_data->wait_for_exec=0;
|
2024-02-20 21:56:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
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;
|
|
|
|
|
2024-02-12 14:16:41 +00:00
|
|
|
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]);
|
2024-02-20 21:56:48 +00:00
|
|
|
simdata->decode_data->valid=1;
|
2024-02-12 14:16:41 +00:00
|
|
|
simdata->decode_data->address=simdata->registers->PC;
|
|
|
|
add_to_instr_list(&simdata->cpu_gui_hints->fetching_list,simdata->registers->PC);
|
|
|
|
simdata->registers->PC+=4;
|
2024-02-03 22:54:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct decode_data_t *malloc_decode_data(){
|
2024-02-20 21:56:48 +00:00
|
|
|
struct decode_data_t *ret=malloc(sizeof(struct decode_data_t));
|
|
|
|
if(ret)
|
|
|
|
ret->valid=0;
|
2024-03-06 02:37:55 +00:00
|
|
|
ret->exec_done=1;
|
2024-02-20 21:56:48 +00:00
|
|
|
return ret;
|
2024-02-03 22:54:20 +00:00
|
|
|
}
|
|
|
|
void free_decode_data(struct decode_data_t *tofree){
|
|
|
|
free(tofree);
|
|
|
|
}
|
|
|
|
int decode(struct simdata_t *simdata){
|
2024-02-06 21:53:42 +00:00
|
|
|
uint16_t opcode,op1,op2,imm;
|
2024-02-07 00:31:23 +00:00
|
|
|
free_instr_list(&simdata->cpu_gui_hints->decoding_list);
|
2024-03-06 02:37:55 +00:00
|
|
|
if(simdata->decode_data->exec_done==0){
|
|
|
|
simdata->fetch_data->decode_done=0;
|
|
|
|
return 0;
|
|
|
|
}
|
2024-02-20 21:56:48 +00:00
|
|
|
if(simdata->decode_data->valid==0){
|
|
|
|
simdata->exec_data->valid=0;
|
2024-03-06 02:37:55 +00:00
|
|
|
simdata->fetch_data->decode_done=1;
|
2024-02-20 21:56:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2024-02-03 22:54:20 +00:00
|
|
|
switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){
|
|
|
|
case 0:
|
|
|
|
opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24;
|
|
|
|
switch(opcode){
|
2024-02-12 13:43:13 +00:00
|
|
|
case 0x00:
|
2024-02-06 23:14:33 +00:00
|
|
|
simdata->exec_data->EXEC_ACTION=NOP;
|
|
|
|
break;
|
2024-02-12 13:43:13 +00:00
|
|
|
case 0x01:
|
|
|
|
case 0x02:
|
|
|
|
case 0x03:
|
|
|
|
case 0x04:
|
|
|
|
case 0x05:
|
|
|
|
case 0x11:
|
|
|
|
case 0x12:
|
|
|
|
case 0x13:
|
|
|
|
case 0x14:
|
|
|
|
case 0x15:
|
2024-02-06 23:14:33 +00:00
|
|
|
switch(opcode){
|
2024-02-20 15:27:24 +00:00
|
|
|
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;
|
2024-02-12 13:43:13 +00:00
|
|
|
default: return 1;
|
2024-02-06 23:14:33 +00:00
|
|
|
}
|
2024-02-03 22:54:20 +00:00
|
|
|
simdata->exec_data->out_op->OP_ADDR=IMMEDIATE;
|
|
|
|
simdata->exec_data->out_op->data=simdata->decode_data->in_bytecode&0x00FFFFFF;
|
2024-02-12 13:43:13 +00:00
|
|
|
simdata->exec_data->EXEC_ACTION=(opcode&0x10)?CALL:JUMP;
|
2024-02-20 21:56:48 +00:00
|
|
|
simdata->fetch_data->wait_for_exec=1;
|
2024-02-12 13:43:13 +00:00
|
|
|
break;
|
2024-02-14 14:03:03 +00:00
|
|
|
case 0x0F:/* load SP */
|
2024-02-12 13:43:13 +00:00
|
|
|
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;
|
2024-02-14 14:03:03 +00:00
|
|
|
simdata->exec_data->out_op->data=0xFF;
|
2024-02-12 13:43:13 +00:00
|
|
|
break;
|
|
|
|
case 0x10:
|
|
|
|
simdata->exec_data->EXEC_ACTION=RET;
|
2024-02-20 21:56:48 +00:00
|
|
|
simdata->fetch_data->wait_for_exec=1;
|
2024-02-03 22:54:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
2024-02-06 21:53:42 +00:00
|
|
|
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;
|
2024-02-13 22:37:36 +00:00
|
|
|
switch(opcode){
|
2024-02-16 17:06:27 +00:00
|
|
|
case 0x00:
|
2024-02-13 22:37:36 +00:00
|
|
|
case 0x01:
|
|
|
|
case 0x02:
|
|
|
|
case 0x03:
|
|
|
|
case 0x04:
|
|
|
|
case 0x05:
|
|
|
|
case 0x06:
|
|
|
|
case 0x07:
|
2024-02-14 17:15:04 +00:00
|
|
|
case 0x0A:
|
|
|
|
case 0x0B:
|
2024-02-16 17:48:04 +00:00
|
|
|
case 0x0C:
|
|
|
|
case 0x0D:
|
2024-02-16 19:46:25 +00:00
|
|
|
case 0x0E:
|
|
|
|
case 0x0F:
|
2024-02-17 19:30:39 +00:00
|
|
|
case 0x10:
|
|
|
|
case 0x11:
|
2024-02-17 19:52:27 +00:00
|
|
|
case 0x12:
|
2024-02-13 22:37:36 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-06 21:53:42 +00:00
|
|
|
|
2024-02-06 23:14:33 +00:00
|
|
|
switch(opcode){
|
2024-02-12 19:42:27 +00:00
|
|
|
case 0x05:
|
2024-02-06 23:14:33 +00:00
|
|
|
simdata->exec_data->EXEC_ACTION=HALT;
|
|
|
|
break;
|
2024-02-12 19:42:27 +00:00
|
|
|
case 0x06:
|
|
|
|
simdata->exec_data->EXEC_ACTION=PUSH;
|
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
simdata->exec_data->EXEC_ACTION=POP;
|
|
|
|
break;
|
2024-02-13 22:37:36 +00:00
|
|
|
case 0x08:
|
|
|
|
case 0x09:
|
2024-02-17 19:52:27 +00:00
|
|
|
case 0x12:
|
2024-02-13 22:37:36 +00:00
|
|
|
simdata->exec_data->EXEC_ACTION=MOVE;
|
|
|
|
break;
|
2024-02-06 23:14:33 +00:00
|
|
|
default:
|
|
|
|
simdata->exec_data->EXEC_ACTION=EXEC_ALU;
|
|
|
|
break;
|
|
|
|
}
|
2024-02-06 21:53:42 +00:00
|
|
|
|
|
|
|
switch(opcode){
|
2024-02-14 17:15:04 +00:00
|
|
|
case 0x00:
|
|
|
|
case 0x01:
|
|
|
|
case 0x04:
|
|
|
|
case 0x0A:
|
|
|
|
case 0x0B:
|
2024-02-16 17:48:04 +00:00
|
|
|
case 0x0C:
|
|
|
|
case 0x0D:
|
2024-02-17 19:52:27 +00:00
|
|
|
case 0x12:
|
2024-02-06 21:53:42 +00:00
|
|
|
simdata->exec_data->out_op->OP_ADDR=REGISTER;
|
|
|
|
simdata->exec_data->out_op->data=op2;
|
|
|
|
break;
|
2024-02-16 19:46:25 +00:00
|
|
|
case 0x02:
|
|
|
|
case 0x03:
|
|
|
|
case 0x0E:
|
|
|
|
case 0x0F:
|
2024-02-17 19:30:39 +00:00
|
|
|
case 0x10:
|
|
|
|
case 0x11:
|
2024-02-06 21:53:42 +00:00
|
|
|
simdata->exec_data->out_op->OP_ADDR=REGISTER;
|
|
|
|
simdata->exec_data->out_op->data=op1;
|
|
|
|
break;
|
2024-02-13 22:37:36 +00:00
|
|
|
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;
|
2024-02-06 21:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(opcode){
|
2024-02-14 17:15:04 +00:00
|
|
|
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:
|
2024-02-17 19:52:27 +00:00
|
|
|
case 0x12:
|
2024-02-13 22:37:36 +00:00
|
|
|
break;
|
2024-02-14 17:15:04 +00:00
|
|
|
case 0x0A: simdata->exec_data->ALU_OP=ALU_FDIV; break;
|
|
|
|
case 0x0B: simdata->exec_data->ALU_OP=ALU_FMUL; break;
|
2024-02-16 17:48:04 +00:00
|
|
|
case 0x0C: simdata->exec_data->ALU_OP=ALU_FADD; break;
|
|
|
|
case 0x0D: simdata->exec_data->ALU_OP=ALU_FSUB; break;
|
2024-02-16 19:46:25 +00:00
|
|
|
case 0x0E: simdata->exec_data->ALU_OP=ALU_FSIN; break;
|
|
|
|
case 0x0F: simdata->exec_data->ALU_OP=ALU_FCOS; break;
|
2024-02-17 19:30:39 +00:00
|
|
|
case 0x10: simdata->exec_data->ALU_OP=ALU_DEC; break;
|
|
|
|
case 0x11: simdata->exec_data->ALU_OP=ALU_INC; break;
|
2024-02-06 21:53:42 +00:00
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
2024-02-03 22:54:20 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2024-02-06 21:53:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-03 22:54:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
simdata->fetch_data->decode_done=1;
|
2024-02-20 21:56:48 +00:00
|
|
|
simdata->exec_data->valid=1;
|
2024-02-07 00:31:23 +00:00
|
|
|
simdata->exec_data->address=simdata->decode_data->address;
|
|
|
|
add_to_instr_list(&simdata->cpu_gui_hints->decoding_list,simdata->decode_data->address);
|
2024-02-03 22:54:20 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-20 21:56:48 +00:00
|
|
|
ret->valid=0;
|
2024-03-06 02:37:55 +00:00
|
|
|
ret->cycles_left=0;
|
2024-02-03 22:54:20 +00:00
|
|
|
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);
|
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
|
|
|
|
#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
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2024-02-03 22:54:20 +00:00
|
|
|
int exec(struct simdata_t *simdata){
|
2024-02-07 00:31:23 +00:00
|
|
|
free_instr_list(&simdata->cpu_gui_hints->executing_list);
|
2024-03-06 02:37:55 +00:00
|
|
|
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;
|
|
|
|
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;
|
2024-02-12 13:43:13 +00:00
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
switch(simdata->exec_data->COND){
|
|
|
|
case COND_NONE:
|
|
|
|
simdata->exec_data->cycles_left=delay_values[BRNCH_UNCO_INDX];
|
2024-02-14 17:15:04 +00:00
|
|
|
break;
|
2024-03-06 02:37:55 +00:00
|
|
|
default:
|
|
|
|
if(condition)
|
|
|
|
simdata->exec_data->cycles_left=delay_values[BRNCH_TAKN_INDX];
|
|
|
|
else
|
|
|
|
simdata->exec_data->cycles_left=delay_values[BRNCH_MISS_INDX];
|
2024-02-16 17:48:04 +00:00
|
|
|
break;
|
2024-03-06 02:37:55 +00:00
|
|
|
}
|
|
|
|
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=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:
|
|
|
|
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:
|
|
|
|
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->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ALU_FDIV:
|
|
|
|
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:
|
|
|
|
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:
|
|
|
|
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:
|
|
|
|
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:
|
|
|
|
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:
|
|
|
|
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:
|
|
|
|
*(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:
|
|
|
|
*(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){
|
|
|
|
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;
|
|
|
|
}
|
2024-02-16 19:46:25 +00:00
|
|
|
break;
|
2024-03-06 02:37:55 +00:00
|
|
|
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);
|
|
|
|
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;
|
|
|
|
}
|
2024-02-16 19:46:25 +00:00
|
|
|
break;
|
2024-03-06 02:37:55 +00:00
|
|
|
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){
|
|
|
|
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){
|
|
|
|
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;
|
2024-02-17 19:30:39 +00:00
|
|
|
break;
|
2024-03-06 02:37:55 +00:00
|
|
|
case REGISTER_IND:
|
|
|
|
if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){
|
|
|
|
*(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;
|
2024-02-17 19:30:39 +00:00
|
|
|
break;
|
2024-02-06 21:53:42 +00:00
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
}
|
2024-03-06 02:37:55 +00:00
|
|
|
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:
|
|
|
|
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:
|
|
|
|
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;
|
2024-05-02 07:28:15 +00:00
|
|
|
simdata->finished_instructions++;
|
2024-02-03 22:54:20 +00:00
|
|
|
}
|
2024-02-07 00:31:23 +00:00
|
|
|
add_to_instr_list(&simdata->cpu_gui_hints->executing_list,simdata->exec_data->address);
|
2024-02-03 22:54:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int state=0;
|
|
|
|
|
2024-02-12 13:43:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* RETURN CODES:
|
|
|
|
* 0 : success
|
|
|
|
* 1 : error in execution stage
|
|
|
|
* 2 : error in decode stage
|
|
|
|
* 3 : error in fetch stage
|
|
|
|
* 4 : internal error
|
|
|
|
*/
|
2024-02-03 22:54:20 +00:00
|
|
|
int cpu_cycle_clock(struct simdata_t *simdata){
|
2024-02-07 00:31:23 +00:00
|
|
|
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);
|
2024-05-02 11:55:29 +00:00
|
|
|
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;
|
|
|
|
|
2024-02-20 21:56:48 +00:00
|
|
|
}
|
2024-02-17 00:07:29 +00:00
|
|
|
simdata->current_clock++;
|
2024-02-03 22:54:20 +00:00
|
|
|
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();
|
2024-02-05 21:25:00 +00:00
|
|
|
simdata->registers=malloc(sizeof(struct registers_t));
|
2024-02-12 14:16:41 +00:00
|
|
|
simdata->registers->PC=0x00000000;
|
2024-02-20 15:27:24 +00:00
|
|
|
simdata->registers->SP=0;
|
2024-02-03 22:54:20 +00:00
|
|
|
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);
|
2024-02-05 21:25:00 +00:00
|
|
|
free(simdata->registers);
|
2024-02-03 22:54:20 +00:00
|
|
|
}
|
2024-02-20 21:56:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|