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