diff --git a/.gitignore b/.gitignore index fb596ee..37d3d43 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o first +test.rom diff --git a/Makefile b/Makefile index 2a6a072..6ee73f9 100644 --- a/Makefile +++ b/Makefile @@ -7,16 +7,23 @@ OBJECT_FILES=gui.o main.o simdata.o assembly.o ifeq "${QUIET}" "1" QUIET_CC = @echo ' CC '$@; QUIET_LINK = @echo ' LINK '$@; + QUIET_FAS = @echo ' FAS '$@; QUIET_CLEAN = @echo ' CLEAN .'; Q = @ else Q = endif +all:test.rom + first: ${OBJECT_FILES} ${QUIET_LINK} ${Q}gcc -ggdb $^ -fsanitize=address -lncurses -ltinfo -o $@ +%.rom:%.asm first + $(QUIET_FAS) + ${Q}./first -i test.asm -a test.rom + %.o:%.c ${QUIET_CC} ${Q} gcc -ggdb -c $< -Wall -Wextra -Werror -fsanitize=address diff --git a/assembly.c b/assembly.c index 982f39f..bcdf244 100644 --- a/assembly.c +++ b/assembly.c @@ -13,6 +13,10 @@ // +===================================================+ // // +// Exception: +// The bytecode 0xFFFFFFFx is an invalid command +// where x is any nibble +// // // INSTRUCTION FORMAT 0: // +===================================================+ @@ -110,11 +114,11 @@ char *disassemble(uint32_t opcode_be){ break; case 0x02: case 0x03: - snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP %s,$%06X",opcode_num&1?"Z":"NZ",val); + snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP,%s $%06X",opcode_num&1?"NZ":"Z",val); break; case 0x04: case 0x05: - snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP %s,$%06X",opcode_num&1?"C":"NC",val); + snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP,%s $%06X",opcode_num&1?"NC":"C",val); break; default: snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTR"); @@ -148,7 +152,7 @@ char *disassemble(uint32_t opcode_be){ } }else if(instruction_format==2){ // 16bit opcode - opcode_num=(opcode&0x1FFF0000)>>16; + opcode_num=(opcode&0x1F000000)>>24; val1=(opcode&0x00FF0000)>>16; val=opcode&0x0000FFFF; @@ -168,3 +172,150 @@ char *disassemble(uint32_t opcode_be){ return ret; } + + +uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context){ + uint16_t opcode; + int x; + if(strncmp(line,"JMP",3)==0){ + x=3; + if(line[x]==' '){ + opcode=0x01; + }else if(line[x]==','){ + x++; + if(line[x]=='Z'){ + opcode=0x02; + x++; + }else if(line[x]=='C'){ + opcode=0x04; + x++; + }else if(line[x]=='N'){ + x++; + if(line[x]=='Z'){ + opcode=0x03; + x++; + }else if(line[x]=='C'){ + opcode=0x05; + x++; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + while(line[x]==' ')x++; + uint32_t addr; + if(line[x]=='$'){ + x++; + if(sscanf(line+x,"%06X",&addr)!=1) + return 0xFFFFFFFF; + else + return opcode<<24|(addr&0x00FFFFFF); + }else + return 0xFFFFFFFF; + }else{ + uint8_t r1,r0,params; + if(strncmp(line,"ADD",3)==0){ + x=3; + opcode=0x2000; + params=2; + }else if(strncmp(line,"SUB",3)==0){ + x=3; + opcode=0x2001; + params=2; + }else if(strncmp(line,"SL",2)==0){ + x=2; + opcode=0x2002; + params=1; + }else if(strncmp(line,"SR",2)==0){ + x=2; + opcode=0x2003; + params=1; + }else if(strncmp(line,"CMP",3)==0){ + x=3; + opcode=0x2004; + params=2; + }else + params=0; + if(params!=0){ + while(line[x]==' ')x++; + if(line[x]=='%'){ + x++; + if(line[x]=='R'){ + x++; + if(line[x]>='0'&&line[x]<='7'){ + r0=line[x]-'0'; + if(params==2){ + x++; + while(line[x]==' ')x++; + if(line[x]==','){ + x++; + while(line[x]==' ')x++; + if(line[x]=='%'){ + x++; + if(line[x]=='R'){ + x++; + if(line[x]>='0'&&line[x]<='7'){ + r1=line[x]-'0'; + return (opcode<<16)|r0<<8|r1; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return (opcode<<16)|r0<<8; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else if(strncmp(line,"MOV",3)==0){ + uint32_t data; + x=3; + while(line[x]==' ')x++; + if(line[x]=='$'){ + x++; + if(sscanf(line+x,"%04X",&data)==1){ + x+=4; + while(line[x]==' ')x++; + if(line[x]==','){ + x++; + while(line[x]==' ')x++; + if(line[x]=='%'){ + x++; + if(line[x]=='R'){ + x++; + if(line[x]>='0'&&line[x]<='7'){ + r1=line[x]-'0'; + x++; + if(line[x]=='l') + return 0x40000000|r1<<16|data; + else if(line[x]=='h') + return 0x41000000|r1<<16|data; + else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + }else + return 0xFFFFFFFF; + } +} + +void free_assembler_context(struct assembler_context_t *tofree){ + free(tofree); +} diff --git a/assembly.h b/assembly.h index 373cff4..ff02910 100644 --- a/assembly.h +++ b/assembly.h @@ -1,3 +1,16 @@ -#include "stdint.h" +#include char* disassemble(uint32_t opcode); + +struct label_ll_t{ + char* name; + uint32_t address; + struct label_ll_t *next; +}; + +struct assembler_context_t{ + struct label_ll_t label_ll; +}; + +uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context); +void free_assembler_context(struct assembler_context_t *tofree); diff --git a/main.c b/main.c index c182ec0..a912457 100644 --- a/main.c +++ b/main.c @@ -23,16 +23,28 @@ #include "simdata.h" #include #include +#include "assembly.h" void help(char* progname){ printf("Usage: %s -i \n", progname); } +#define ADDR_SIZE 16777216 + +int dump_rom(char* filename, struct simdata_t *simdata){ + FILE* outfile=fopen(filename,"w"); + for(int i=0;iRAM+i),outfile); + fclose(outfile); + return 0; +} + int main(int argc, char* argd[] ){ /// PARSE COMMAND LINE /// char *infile = NULL; + char *assemble = NULL; int opt; - while ((opt = getopt(argc, argd, "hi:")) != -1) { + while ((opt = getopt(argc, argd, "hi:a:")) != -1) { switch (opt) { case 'h': help(argd[0]); @@ -41,6 +53,9 @@ int main(int argc, char* argd[] ){ case 'i': infile=optarg; break; + case 'a': + assemble=optarg; + break; default: help(argd[0]); return 1; @@ -52,57 +67,103 @@ int main(int argc, char* argd[] ){ return 1; } - /// READ ROM FILE /// + /// READ INPUT FILE /// FILE* rom=fopen(infile,"r"); - if (rom == NULL) { - printf("ERROR: Couldn't open rom file\n"); - perror(infile); - return 1; - } - - fseek(rom, 0, SEEK_END); - if(ftell(rom)!=16777216){ - printf("ERROR: ROM file isn't 16MiB\n"); - return 1; - } - fseek(rom, 0, SEEK_SET); - struct simdata_t *simdata = init_simdata(); - if(!simdata){ - gui_error("failed to initialise simdata"); - return 1; - } - if(fread(simdata->RAM, 16777216, 1, rom)==0){ - printf("ERROR: failed to read input file\n"); + + if ( assemble != NULL ){ + /* RUN ASSEMBLER */ + struct assembler_context_t *assembler_context=malloc(sizeof(struct assembler_context_t)); + + for (int i=0;iRAM[i]=0; + int linec=0; + if (rom != NULL) { + char line [1000]; + uint32_t opcode; + uint32_t addr=0; + while(fgets(line,sizeof(line),rom)!= NULL){ + opcode=assemble_line(line,assembler_context); + if(opcode>0xFFFFFFF1){ + printf("Error assembling %s:%d\n", infile,linec+1); + fclose(rom); + free_assembler_context(assembler_context); + free_simdata(simdata); + return 1; + }else{ + simdata->RAM[addr]=(0xFF000000&opcode)>>24; + addr++; + simdata->RAM[addr]=(0xFF0000&opcode)>>16; + addr++; + simdata->RAM[addr]=(0xFF00&opcode)>>8; + addr++; + simdata->RAM[addr]=(0xFF&opcode); + addr++; + } + linec++; + } + } + free_assembler_context(assembler_context); + dump_rom(assemble,simdata); free_simdata(simdata); - return 1; - } - fclose(rom); + }else{ + /* RUN SIMULATOR */ + if (rom == NULL) { + printf("ERROR: Couldn't open rom file\n"); + perror(infile); + fclose(rom); + free_simdata(simdata); + return 1; + } + + fseek(rom, 0, SEEK_END); + if(ftell(rom)!=ADDR_SIZE){ + printf("ERROR: ROM file isn't 16MiB\n"); + fclose(rom); + free_simdata(simdata); + return 1; + } + fseek(rom, 0, SEEK_SET); + + if(!simdata){ + gui_error("failed to initialise simdata"); + fclose(rom); + free_simdata(simdata); + return 1; + } + if(fread(simdata->RAM, ADDR_SIZE, 1, rom)==0){ + printf("ERROR: failed to read input file\n"); + free_simdata(simdata); + fclose(rom); + return 1; + } + fclose(rom); - /// INITIALISE GUI /// - if(start_gui()){ - printf("Failed on start_gui()\n"); + /// INITIALISE GUI /// + if(start_gui()){ + printf("Failed on start_gui()\n"); + free_simdata(simdata); + return 1; + } + + update_gui(simdata); + + if(gui_continue_request()){ + end_gui(); + printf("Failed on gui_continue_request()\n"); + free_simdata(simdata); + return 1; + } + + if(end_gui()){ + printf("Failed on end_gui()\n"); + free_simdata(simdata); + return 1; + } + free_simdata(simdata); - return 1; } - - update_gui(simdata); - - if(gui_continue_request()){ - end_gui(); - printf("Failed on gui_continue_request()\n"); - free_simdata(simdata); - return 1; - } - - if(end_gui()){ - printf("Failed on end_gui()\n"); - free_simdata(simdata); - return 1; - } - - free_simdata(simdata); return 0; } diff --git a/test.asm b/test.asm new file mode 100644 index 0000000..b7a8abd --- /dev/null +++ b/test.asm @@ -0,0 +1,7 @@ +JMP $ABCDEF +JMP,NZ $DEADBA +JMP,C $EEEEEF +SL %R7 +CMP %R2,%R0 +MOV $1238,%R5h +MOV $8321,%R2l