CPU: Added support for conditional branches, HLT and NOP
This commit is contained in:
parent
1dcc69ba50
commit
800e11be16
12
assembly.c
12
assembly.c
@ -73,6 +73,8 @@
|
||||
// | 13'd3 | SHIFT RIGHT | YES |
|
||||
// +-------+----------------------------------+--------------|
|
||||
// | 13'd4 | COMPARE (SUBTRACT WITHOUT SAVE) | YES |
|
||||
// +-------+----------------------------------+--------------+
|
||||
// | 13'd5 | HALT | NO |
|
||||
//
|
||||
//
|
||||
// INSTRUCTION FORMAT 2 OPCODE NUM:
|
||||
@ -146,6 +148,9 @@ char *disassemble(uint32_t opcode_be){
|
||||
case 0x04:
|
||||
snprintf(ret,MAX_INSTRUCTION_LENGTH,"CMP %%R%0d, %%R%0d",val1,val2);
|
||||
break;
|
||||
case 0x05:
|
||||
snprintf(ret,MAX_INSTRUCTION_LENGTH,"HALT");
|
||||
break;
|
||||
default:
|
||||
snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTRUCTION");
|
||||
break;
|
||||
@ -311,6 +316,13 @@ uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_cont
|
||||
return 0xFFFFFFFF;
|
||||
}else
|
||||
return 0xFFFFFFFF;
|
||||
}else if(strncmp(line,"HALT",4)==0){
|
||||
x=4;
|
||||
while(line[x]==' ')x++;
|
||||
if(line[x]==0)
|
||||
return 0x20050000;
|
||||
else
|
||||
return 0xFFFFFFFF;
|
||||
}else
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
36
cpu.c
36
cpu.c
@ -30,7 +30,21 @@ int decode(struct simdata_t *simdata){
|
||||
case 0:
|
||||
opcode=(simdata->decode_data->in_bytecode&0x1F000000)>>24;
|
||||
switch(opcode){
|
||||
case 0:
|
||||
simdata->exec_data->EXEC_ACTION=NOP;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
switch(opcode){
|
||||
case 1: simdata->exec_data->COND=NONE; break;
|
||||
case 2: simdata->exec_data->COND=ZERO; break;
|
||||
case 3: simdata->exec_data->COND=NZERO; break;
|
||||
case 4: simdata->exec_data->COND=CARRY; break;
|
||||
case 5: simdata->exec_data->COND=NCARRY; break;
|
||||
}
|
||||
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=JUMP;
|
||||
@ -51,7 +65,14 @@ int decode(struct simdata_t *simdata){
|
||||
simdata->exec_data->in_op2->OP_ADDR=REGISTER;
|
||||
simdata->exec_data->in_op2->data=op2;
|
||||
|
||||
switch(opcode){
|
||||
case 5:
|
||||
simdata->exec_data->EXEC_ACTION=HALT;
|
||||
break;
|
||||
default:
|
||||
simdata->exec_data->EXEC_ACTION=EXEC_ALU;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(opcode){
|
||||
case 0:
|
||||
@ -74,6 +95,7 @@ int decode(struct simdata_t *simdata){
|
||||
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;
|
||||
case 5: break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@ -144,10 +166,20 @@ void free_exec_data(struct exec_data_t *tofree){
|
||||
int exec(struct simdata_t *simdata){
|
||||
switch(simdata->exec_data->EXEC_ACTION){
|
||||
case JUMP:
|
||||
int condition=0;
|
||||
switch(simdata->exec_data->COND){
|
||||
case NONE: condition=1; break;
|
||||
case ZERO: condition=simdata->registers->FLAGS&1; break;
|
||||
case NZERO: condition=!(simdata->registers->FLAGS&1); break;
|
||||
case CARRY: condition=simdata->registers->FLAGS&2; break;
|
||||
case NCARRY: condition=!(simdata->registers->FLAGS&2); break;
|
||||
}
|
||||
if(condition){
|
||||
if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE)
|
||||
simdata->PC=simdata->exec_data->out_op->data;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case EXEC_ALU:
|
||||
if( simdata->exec_data->in_op1->OP_ADDR==REGISTER &&
|
||||
@ -209,6 +241,10 @@ int exec(struct simdata_t *simdata){
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
case NOP: break;
|
||||
case HALT:
|
||||
simdata->cpu_state=CPU_HALTED;
|
||||
break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
12
cpu.h
12
cpu.h
@ -15,7 +15,9 @@ struct decode_data_t{
|
||||
enum EXEC_ACTION_t {
|
||||
EXEC_ALU,
|
||||
MOVE,
|
||||
JUMP
|
||||
JUMP,
|
||||
NOP,
|
||||
HALT
|
||||
};
|
||||
|
||||
enum ALU_OP_t {
|
||||
@ -38,10 +40,18 @@ struct exec_op_t {
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
enum COND_t{
|
||||
NONE,
|
||||
ZERO,
|
||||
NZERO,
|
||||
CARRY,
|
||||
NCARRY
|
||||
};
|
||||
|
||||
struct exec_data_t {
|
||||
enum EXEC_ACTION_t EXEC_ACTION;
|
||||
enum ALU_OP_t ALU_OP;
|
||||
enum COND_t COND;
|
||||
struct exec_op_t *in_op1;
|
||||
struct exec_op_t *in_op2;
|
||||
struct exec_op_t *out_op;
|
||||
|
22
gui.c
22
gui.c
@ -67,7 +67,7 @@ char *tab_name[]={"Overview","Memory","Internal"};
|
||||
|
||||
unsigned int CURRENT_TAB=0;
|
||||
|
||||
enum CPU_STATE_t CPU_STATE=SINGLE_STEPPING;
|
||||
enum GUI_CPU_STATE_t CPU_STATE=GUI_CPU_SINGLE_STEPPING;
|
||||
|
||||
void update_tabs(){
|
||||
wattron(tabs,A_BOLD);
|
||||
@ -94,15 +94,15 @@ void update_tabs(){
|
||||
x+=strlen(tab_name[i])+2+3;
|
||||
}
|
||||
switch(CPU_STATE){
|
||||
case RUNNING:
|
||||
case GUI_CPU_RUNNING:
|
||||
wattron(tabs,COLOR_PAIR(6));
|
||||
mvwprintw(tabs,0,terminal_width-13,"[ RUNNING ");
|
||||
break;
|
||||
case SINGLE_STEPPING:
|
||||
case GUI_CPU_SINGLE_STEPPING:
|
||||
wattron(tabs,COLOR_PAIR(7));
|
||||
mvwprintw(tabs,0,terminal_width-21,"[ SINGLE-STEPPING ");
|
||||
break;
|
||||
case STOPPED:
|
||||
case GUI_CPU_STOPPED:
|
||||
wattron(tabs,COLOR_PAIR(8));
|
||||
mvwprintw(tabs,0,terminal_width-13,"[ STOPPED ");
|
||||
break;
|
||||
@ -398,6 +398,8 @@ int update_general_registers(struct simdata_t *simdata){
|
||||
int clear_back_window=1;
|
||||
|
||||
int update_gui(struct simdata_t *simdata){
|
||||
if(simdata->cpu_state==CPU_HALTED)
|
||||
CPU_STATE=GUI_CPU_STOPPED;
|
||||
if(clear_back_window){
|
||||
clear();
|
||||
clear_back_window=0;
|
||||
@ -416,25 +418,27 @@ int update_gui(struct simdata_t *simdata){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gui_continue_request(){
|
||||
int gui_continue_request(struct simdata_t *simdata){
|
||||
char inch;
|
||||
int release=0;
|
||||
while(release==0){
|
||||
if(((inch=getch())==ERR)){
|
||||
if(CPU_STATE==SINGLE_STEPPING)
|
||||
if(CPU_STATE==GUI_CPU_SINGLE_STEPPING)
|
||||
return 1;
|
||||
else
|
||||
release=1;
|
||||
}
|
||||
switch(inch){
|
||||
case 'r':
|
||||
if(CPU_STATE==RUNNING){
|
||||
CPU_STATE=SINGLE_STEPPING;
|
||||
if(simdata->cpu_state!=CPU_HALTED){
|
||||
if(CPU_STATE==GUI_CPU_RUNNING){
|
||||
CPU_STATE=GUI_CPU_SINGLE_STEPPING;
|
||||
nodelay(stdscr, FALSE);
|
||||
}else{
|
||||
CPU_STATE=RUNNING;
|
||||
CPU_STATE=GUI_CPU_RUNNING;
|
||||
nodelay(stdscr, TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
return 2;
|
||||
|
2
gui.h
2
gui.h
@ -1,7 +1,7 @@
|
||||
#include "simdata.h"
|
||||
|
||||
int start_gui();
|
||||
int gui_continue_request();
|
||||
int gui_continue_request(struct simdata_t*);
|
||||
int end_gui();
|
||||
int gui_error(char *);
|
||||
int update_gui(struct simdata_t *);
|
||||
|
12
main.c
12
main.c
@ -25,6 +25,7 @@
|
||||
#include <errno.h>
|
||||
#include "assembly.h"
|
||||
#include "cpu.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void help(char* progname){
|
||||
printf("Usage: %s -i <file> \n", progname);
|
||||
@ -89,7 +90,13 @@ int main(int argc, char* argd[] ){
|
||||
uint32_t opcode;
|
||||
uint32_t addr=0;
|
||||
while(fgets(line,sizeof(line),rom)!= NULL){
|
||||
|
||||
for(int i=0;line[i];i++)
|
||||
if(line[i]==0x0a)
|
||||
line[i]=0;
|
||||
|
||||
opcode=assemble_line(line,assembler_context);
|
||||
|
||||
if(opcode>0xFFFFFFF1){
|
||||
printf("Error assembling %s:%d\n", infile,linec+1);
|
||||
fclose(rom);
|
||||
@ -160,7 +167,7 @@ int main(int argc, char* argd[] ){
|
||||
update_gui(simdata);
|
||||
|
||||
int ret_code;
|
||||
if((ret_code=gui_continue_request())){
|
||||
if((ret_code=gui_continue_request(simdata))){
|
||||
if(ret_code==2)
|
||||
break;
|
||||
end_gui();
|
||||
@ -170,6 +177,7 @@ int main(int argc, char* argd[] ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(simdata->cpu_state==CPU_RUNNING){
|
||||
int ret;
|
||||
if((ret=cpu_cycle_clock(simdata))){
|
||||
cpu_simdata_free(simdata);
|
||||
@ -190,6 +198,8 @@ int main(int argc, char* argd[] ){
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}else
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if(end_gui()){
|
||||
|
@ -39,6 +39,7 @@ struct simdata_t *init_simdata(){
|
||||
ret->PC=0;
|
||||
ret->SP=0;
|
||||
ret->registers=NULL;
|
||||
ret->cpu_state=CPU_RUNNING;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
14
simdata.h
14
simdata.h
@ -1,6 +1,11 @@
|
||||
#ifndef SIMDATA_HEADER
|
||||
#include <stdint.h>
|
||||
|
||||
enum CPU_STATE_t{
|
||||
CPU_RUNNING,
|
||||
CPU_HALTED
|
||||
};
|
||||
|
||||
struct simdata_t{
|
||||
long unsigned int current_clock;
|
||||
uint8_t *RAM;
|
||||
@ -10,16 +15,17 @@ struct simdata_t{
|
||||
struct decode_data_t *decode_data;
|
||||
struct exec_data_t *exec_data;
|
||||
struct registers_t *registers;
|
||||
enum CPU_STATE_t cpu_state;
|
||||
};
|
||||
|
||||
struct simdata_t *init_simdata();
|
||||
|
||||
void free_simdata(struct simdata_t *);
|
||||
|
||||
enum CPU_STATE_t{
|
||||
RUNNING,
|
||||
SINGLE_STEPPING,
|
||||
STOPPED
|
||||
enum GUI_CPU_STATE_t{
|
||||
GUI_CPU_RUNNING,
|
||||
GUI_CPU_SINGLE_STEPPING,
|
||||
GUI_CPU_STOPPED
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user