mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-22 01:31:33 +00:00
Added ENDSUBROUTINE mnemonic to c02 compiler and a02 assembler
This commit is contained in:
parent
67514ba522
commit
3077a43859
126
a02.c
126
a02.c
@ -12,6 +12,9 @@
|
||||
#define DEBUG FALSE
|
||||
int debug; //Ouput Debug Info
|
||||
|
||||
#define INCLEN 255
|
||||
char incpath[INCLEN];
|
||||
|
||||
enum otypes {BINFIL, PRGFIL}; //Object File Types
|
||||
|
||||
char objtyp; //Object File Type
|
||||
@ -23,16 +26,18 @@ struct sym {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
|
||||
struct sym symbol; //Current Symbol
|
||||
struct sym symtbl[MAXSYM]; //Global Symbol Table
|
||||
int symcnt; //Number of Global Labels
|
||||
int blkcnt; //Number of Block Labels Generated
|
||||
int blknum; //Local Label Block Number (0 = Global)
|
||||
|
||||
char label[MAXSTR]; //Assembly Line Label
|
||||
char mnmnc[MAXSTR]; //Opcode Mnemonic
|
||||
char oprnd[MAXSTR]; //Opcode Mnemonic
|
||||
char oprnd[MAXSTR]; //Operand Text
|
||||
char cmmnt[MAXSTR]; //Assembly Line Comment
|
||||
char mcode[MAXSTR]; //Generated Bytes
|
||||
char strng[MAXSTR]; //Parsed String
|
||||
|
||||
int opridx; //Index into Operand
|
||||
char cpdchr; //Last Character Copied into oprnd
|
||||
|
||||
unsigned char token, opmod; //OpCode Token, Modifier
|
||||
unsigned int amode; //Addressing Modes
|
||||
@ -67,25 +72,52 @@ void usage(char* appnam) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Print Symbol Table */
|
||||
void prtsym(void) {
|
||||
fprintf(lstfil, "\n%s Symbol Table\nBlock Name Size Value Rfd\n", "Global");
|
||||
for (int i=0; i<symcnt; i++) {
|
||||
int refrd = (symtbl[i].refrd) ? '*' : ' ';
|
||||
fprintf(lstfil, "%5d %-8s %4d %5d %c \n", symtbl[i].block, symtbl[i].name, symtbl[i].bytes, symtbl[i].value, refrd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Error Dump Info */
|
||||
void xdump(void) {
|
||||
puts("Error Dump");
|
||||
oprnd[opridx]=0; printf("Operand: %s\n", oprnd);
|
||||
}
|
||||
|
||||
/* Print Error Message to Stream */
|
||||
void xprint(FILE *fp, char* format, char *s) {
|
||||
if (lineno) fprintf(fp, "%04d: ", lineno);
|
||||
fprintf(fp, format, s);
|
||||
}
|
||||
|
||||
/* Print Error Message and Exit */
|
||||
void xerror(char* format, char *s) {
|
||||
if (debug) xdump();
|
||||
if (lineno) fprintf(stderr, "%04d: ", lineno);
|
||||
fprintf(stderr, format, s);
|
||||
xprint(stderr, format, s);
|
||||
if (lstfil) xprint(stderr, format, s);
|
||||
if (lstfil && symcnt) prtsym();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Open File with Error Checking */
|
||||
FILE * opnfil(char* name, char* mode) {
|
||||
FILE * opnfil(char* name, char* mode, char* path) {
|
||||
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
|
||||
FILE *fp = fopen(name, mode);
|
||||
if (!fp) {
|
||||
char spec[256];
|
||||
char *token = strtok(path, " ");
|
||||
while (token) {
|
||||
strcpy(spec, path); strcat(spec, "\\"); strcat(spec, name);
|
||||
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
|
||||
fp = fopen(spec, mode); if (fp) break;
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
if (!fp) xerror("Error Opening File '%s'\n", name);
|
||||
if (debug) printf("File Opened\n");
|
||||
return fp;
|
||||
}
|
||||
|
||||
@ -120,8 +152,11 @@ int pword(int skip, char* word) {
|
||||
}
|
||||
|
||||
struct sym *fndsym(int block, char* name) {
|
||||
if (debug) printf("Searching for Symbol %s in block %d\n", name, block);
|
||||
for (int i=0; i < symcnt; i++) {
|
||||
if (symtbl[i].block != block || strcmp(symtbl[i].name,name)) continue;
|
||||
if (debug) printf("Found Symbol %s, block %d, size %d, value %04x\n",
|
||||
symtbl[i].name, symtbl[i].block, symtbl[i].bytes, symtbl[i].value);
|
||||
return &symtbl[i];
|
||||
}
|
||||
return NULL;
|
||||
@ -129,13 +164,14 @@ struct sym *fndsym(int block, char* name) {
|
||||
|
||||
/* Set Symbol Value and Size */
|
||||
void setsym(int value, int bytes) {
|
||||
if (debug) printf("Setting Symbol %s to %d\n", symbol.name, value);
|
||||
symbol.value = value;
|
||||
if (bytes) symbol.bytes = bytes;
|
||||
else symbol.bytes = (value > 0xFF) ? 2 : 1;
|
||||
symbol.refrd = FALSE;
|
||||
if (debug) printf("Set Symbol %s in block %d to value %d, size %d, referred=False\n",
|
||||
symbol.name, symbol.block, symbol.bytes, symbol.value);
|
||||
}
|
||||
|
||||
|
||||
/* Add Character to Beginning of String */
|
||||
void pfxstr(char c, char* s) {
|
||||
for (int i=strlen(s)+1; i; i--)
|
||||
@ -172,7 +208,8 @@ int plabel(void) {
|
||||
/* Copy Character to Operand and Increment */
|
||||
int cpychr(int c) {
|
||||
if (c && toupper(*linptr) != c) return FALSE;
|
||||
if (opridx < MAXSTR) oprnd[opridx++] = toupper(*linptr);
|
||||
cpdchr = *linptr;
|
||||
if (opridx < MAXSTR) oprnd[opridx++] = toupper(cpdchr);
|
||||
linptr++;
|
||||
return TRUE;
|
||||
}
|
||||
@ -267,10 +304,12 @@ int evlopd(int maxsiz) {
|
||||
if (hilo) prns = cpychr('(');
|
||||
result = evltrm();
|
||||
if (result >= 0)
|
||||
while (cpychr('+')) {
|
||||
while (cpychr('+') || cpychr('-')) {
|
||||
int opertr = cpdchr;
|
||||
int opdval = evltrm();
|
||||
if (opdval < 0) break;
|
||||
result += opdval;
|
||||
if (opertr == '+') result += opdval;
|
||||
else result -= opdval;
|
||||
}
|
||||
if (hilo) {
|
||||
if (result < 0) xerror("Hi/Low Operator Requires Operand", "");
|
||||
@ -386,11 +425,18 @@ void asmprc(void) {
|
||||
|
||||
/* Assemble SUBROUTINE Pseudo-Op */
|
||||
void asmsub(void) {
|
||||
blknum++;
|
||||
blknum = ++blkcnt;
|
||||
sprintf(oprnd, "%d", blknum); opridx = strlen(oprnd);
|
||||
if (debug) printf("Block Number set to %s\n", oprnd);
|
||||
}
|
||||
|
||||
/* Assemble ENDSUBROUTINE Pseudo-Op */
|
||||
void asmens(void) {
|
||||
blknum = 0;
|
||||
sprintf(oprnd, "%d", blknum); opridx = strlen(oprnd);
|
||||
if (debug) printf("Block Number reset to %s\n", oprnd);
|
||||
}
|
||||
|
||||
/* Assemble INCLUDE Pseudo-Op */
|
||||
void asminf(void) {
|
||||
int incidx = 0;
|
||||
@ -419,11 +465,12 @@ int asmpso(int dot) {
|
||||
if (debug) printf("Assembling Pseudo-Op %s, Token '%c'\n", mnmnc, token);
|
||||
switch (token) {
|
||||
case '=': asmequ(); break; //EQU
|
||||
case 'B': asmbyt(); break; //BYTE
|
||||
case 'H': asmhex(); break; //BYTE
|
||||
case 'B': asmbyt(); break; //BYTE or DC
|
||||
case 'H': asmhex(); break; //HEX
|
||||
case 'W': asmwrd(); break; //WORD
|
||||
case 'F': asmfll(); break; //FILL
|
||||
case 'F': asmfll(); break; //FILL or DS
|
||||
case 'S': asmsub(); break; //SUBRoutine
|
||||
case 'M': asmens(); break; //ENDSubroutine
|
||||
case 'I': asminf(); break; //INCLude
|
||||
case '*': asmorg(); break; //ORG
|
||||
case 'P': asmprc(); break; //PROCessor
|
||||
@ -614,6 +661,7 @@ void pcmmnt(void) {
|
||||
void addsym() {
|
||||
if (symbol.value<0) xerror("Origin Not Set", "");
|
||||
memcpy(&symtbl[symcnt++], &symbol, sizeof(symbol));
|
||||
if (debug) printf("Added symbol %s in block %d to Symbol Table\n", symbol.name, symbol.block);
|
||||
}
|
||||
|
||||
|
||||
@ -621,7 +669,7 @@ void addsym() {
|
||||
void opninc(void) {
|
||||
if (debug) printf("Opening Include File %s\n", incnam);
|
||||
if (lstfil) fputs("\n", lstfil);
|
||||
incfil = opnfil(incnam, "r");
|
||||
incfil = opnfil(incnam, "r", incpath);
|
||||
savlno = lineno;
|
||||
lineno = 1;
|
||||
}
|
||||
@ -634,7 +682,7 @@ void clsinc(void) {
|
||||
incfil = NULL;
|
||||
incnam[0] = 0;
|
||||
lineno = savlno;
|
||||
endasm = FALSE; //Clear End Flag for Return to Maun File
|
||||
endasm = FALSE; //Clear End Flag for Return to Main File
|
||||
}
|
||||
|
||||
/* Assemble Input File (Two Pass) *
|
||||
@ -647,7 +695,8 @@ void asmfil(int pass) {
|
||||
passno = pass; //Assembly Pass Number
|
||||
if (debug) printf("Assembling Pass %d\n", pass);
|
||||
lineno = 1; //Initialize Input File Line Number
|
||||
blknum = 1; //Initialize Local Block Number
|
||||
blkcnt = 0; //Initialize Local Block Count
|
||||
blknum = 0; // and Local Block Number
|
||||
orgadr = -1; //Origin Address Not Set
|
||||
curadr = orgadr; //Set Current Address to Origin
|
||||
if (debug) printf("Rewinding Input File\n");
|
||||
@ -656,7 +705,7 @@ void asmfil(int pass) {
|
||||
if (incfil) linptr = fgets(inplin, MAXSTR, incfil);
|
||||
else linptr = fgets(inplin, MAXSTR, inpfil);
|
||||
if (endasm || linptr == NULL) {if (incfil) {clsinc(); continue;} else break;}
|
||||
if (debug) printf("%05d %04X: %s", lineno, curadr, inplin);
|
||||
if (debug) printf("%1d %05d %04X: %s", passno, lineno, curadr, inplin);
|
||||
lstadr = curadr; //Set List Address
|
||||
mcode[0] = 0; //Clear Generated Macbine Code
|
||||
plabel(); //Parse Label
|
||||
@ -673,15 +722,6 @@ void asmfil(int pass) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Symbol Table */
|
||||
void prtsym(void) {
|
||||
fprintf(lstfil, "\n%s Symbol Table\nBlock Name Size Value Rfd\n", "Global");
|
||||
for (int i=0; i<symcnt; i++) {
|
||||
int refrd = (symtbl[i].refrd) ? '*' : ' ';
|
||||
fprintf(lstfil, "%5d %-8s %4d %5d %c \n", symtbl[i].block, symtbl[i].name, symtbl[i].bytes, symtbl[i].value, refrd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Command Line Option */
|
||||
int pcoptn(char *argval) {
|
||||
if (argval[0] != '-') return FALSE;
|
||||
@ -701,6 +741,11 @@ void pcargs(int argc, char *argv[]) {
|
||||
for (int arg = 0; arg<argc; arg++) {
|
||||
if (debug) printf("Arg %d='%s'\n", arg, argv[arg]);
|
||||
if (arg == 0) {strcpy(prgnam, argv[arg]); continue;}
|
||||
if (strcmp(argv[arg], "-i") ==0) {
|
||||
strcpy(incpath, argv[++arg]);
|
||||
if (debug) printf("Include Path set to \"%s\"\n", incpath);
|
||||
continue;
|
||||
}
|
||||
if (pcoptn(argv[arg])) continue;
|
||||
switch (argnum++) {
|
||||
case 0: strcpy(inpnam, argv[arg]); break;
|
||||
@ -713,19 +758,20 @@ void pcargs(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
debug = DEBUG; //Initialize Debug Flag
|
||||
lstnam[0] = 0; lstfil = NULL; //Default to No List File
|
||||
incnam[0] = 0; incfil = NULL; //Include File Not Opened
|
||||
lineno = 0; //No Line Number (yet)
|
||||
objtyp = BINFIL; //Default Object File Type to Binary
|
||||
pcargs(argc, argv); //Parse Command Line Arguments
|
||||
inpfil = opnfil(inpnam, "r"); //Open Input File
|
||||
outfil = opnfil(outnam, "wb"); //Open Output File
|
||||
if (lstnam[0]) //If List File Name Specified
|
||||
lstfil = opnfil(lstnam, "w"); // Open List File
|
||||
asmfil(1); //Assemble Input File (First Pass)
|
||||
asmfil(2); //Assemble Input File (First Pass)
|
||||
if (lstfil && symcnt) prtsym(); //Print Symbol Table
|
||||
exit(0); //Exit with No Errors
|
||||
debug = DEBUG; //Initialize Debug Flag
|
||||
incpath[0] = 0; //Initialize Include File Path
|
||||
lstnam[0] = 0; lstfil = NULL; //Default to No List File
|
||||
incnam[0] = 0; incfil = NULL; //Include File Not Opened
|
||||
lineno = 0; //No Line Number (yet)
|
||||
objtyp = BINFIL; //Default Object File Type to Binary
|
||||
pcargs(argc, argv); //Parse Command Line Arguments
|
||||
inpfil = opnfil(inpnam, "r", ""); //Open Input File
|
||||
outfil = opnfil(outnam, "wb", ""); //Open Output File
|
||||
if (lstnam[0]) //If List File Name Specified
|
||||
lstfil = opnfil(lstnam, "w", ""); // Open List File
|
||||
asmfil(1); //Assemble Input File (First Pass)
|
||||
asmfil(2); //Assemble Input File (First Pass)
|
||||
if (lstfil && symcnt) prtsym(); //Print Symbol Table
|
||||
exit(0); //Exit with No Errors
|
||||
}
|
||||
|
||||
|
4
a02.h
4
a02.h
@ -2,7 +2,7 @@
|
||||
|
||||
#define MAXSTR 128 //Maximum String Length
|
||||
#define MAXLBL 8 //Maximum Symbol Length
|
||||
#define MAXSYM 1024 //Maximum Number of Global Labels
|
||||
#define MAXSYM 1024 //Maximum Number of Labels
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE -1
|
||||
@ -45,7 +45,7 @@ struct opc {char name[5], token; int amode;};
|
||||
struct opc psolst[] = {
|
||||
{"BYTE", 'B', 0}, {"HEX", 'H'}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0},
|
||||
{"INCL", 'I', 0}, {"SUBR", 'S', 0}, {"DC", 'B', 0}, {"DS", 'F', 0}, {"ALIG", 'A', 0},
|
||||
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"", 0, 0}
|
||||
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"ENDS", 'M', 0}, {"", 0, 0}
|
||||
};
|
||||
|
||||
struct opc opclst[] = {
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define ALNOP "ALIGN" //Align Pseudo-Op
|
||||
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
|
||||
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
|
||||
#define LOCEND "ENDSUB" //End Local Variables Pseudo-Op
|
||||
|
||||
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
|
||||
|
||||
|
@ -110,6 +110,7 @@ void reqlbl(char* lbname) {
|
||||
void endfnc(void) {
|
||||
DEBUG("label.endfnc: Ending function definition with lsrtrn set to %d\n", lsrtrn)
|
||||
if (!lsrtrn) asmlin("RTS", "");
|
||||
asmlin(LOCEND, "");
|
||||
infunc = FALSE;
|
||||
DEBUG("label.endfnc: Set infunc to %d\n", infunc)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user