From f94ddd63fc16825e022e5961fa8e5bd6db0b6474 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Thu, 14 Nov 2019 11:13:45 -0500 Subject: [PATCH] Added pointer dereferencing to C02 compiler --- src/c02.c | 8 ++++ src/common.h | 2 +- src/dclrtn.c | 1 + src/expr.c | 43 ++++++++++++++++++- src/expr.h | 2 + src/include.c | 4 +- src/parse.c | 18 ++++---- src/parse.h | 2 +- src/stmnt.c | 112 ++++++++++++++++++++++++++++++++------------------ src/stmnt.h | 2 + 10 files changed, 141 insertions(+), 53 deletions(-) diff --git a/src/c02.c b/src/c02.c index be0a59e..fd633d6 100644 --- a/src/c02.c +++ b/src/c02.c @@ -56,6 +56,13 @@ void init(void) { strcpy(incdir, "../include/"); } +/* Parse Pointer Dereference Assignment */ +void ppntr(void) { + lsrtrn = FALSE; //Clear RETURN flag + if (xstmnt[0]) ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE) + prcasp(';'); +} + /* Reads and parses the next Word in Source File */ void pword(void) { lsrtrn = FALSE; //Clear RETURN flag @@ -111,6 +118,7 @@ void compile(void) { else if (match('}')) endblk(TRUE); //End Multi-Line Program Block else if (match('#')) pdrctv(); //Parse Directive else if (match('/')) skpcmt(TRUE); //Skip Comment + else if (match('*')) ppntr(); //Parse Pointer else if (isalph()) pword(); //Parse Word else ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE) } diff --git a/src/common.h b/src/common.h index 7c054ee..1ac2d8b 100644 --- a/src/common.h +++ b/src/common.h @@ -29,7 +29,7 @@ #define CPUARG "6502" //Target CPU Operand #define ORGOP "ORG" //Origin Pseudo-Op #define EQUOP "EQU" //Equate Pseudo-Op -#define BYTEOP "DC" //Define Byte Pseudo-Op +#define BYTEOP "BYTE" //Define Byte Pseudo-Op #define STROP "DS" //Define String Pseudo-Op #define ALNOP "ALIGN" //Align Pseudo-Op #define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op diff --git a/src/dclrtn.c b/src/dclrtn.c index 445257e..5b54d83 100644 --- a/src/dclrtn.c +++ b/src/dclrtn.c @@ -53,6 +53,7 @@ void addfnc(void) { infunc = TRUE; //Set Inside Function Definition Flag DEBUG("Set infunc to %d\n", infunc) setlbl(fncnam); //Set Function Entry Point + asmlin(LOCOP, ""); //Set Local Variables Boundary if (prmtra[0]) asmlin("STA", prmtra); //Store First Parameter if (prmtry[0]) asmlin("STY", prmtry); //Store Second Parameter if (prmtrx[0]) asmlin("STX", prmtrx); //Store Third Parameter diff --git a/src/expr.c b/src/expr.c index 1de9040..5cfc17c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -111,10 +111,43 @@ void chkidx(void) { } } -/* Parse Term in Expression * - * Sets: term - the term (as a string) */ +/* Parse Pointer * + * Sets: term - Compiled Pointer */ +void prsptr(void) { + DEBUG("Parsing pointer\n", 0) + expect('*'); //Pointer Dereference Operator + prsvar(FALSE,FALSE); //Parse Variable to Dereference + if (varble.modifr != MTZP) ERROR("Illegal dereference of non-pointer variable %s.\n", value, EXIT_FAILURE) +} + +/* Process Pointer Index * + * Sets: term - Compiled Pointer */ +void prcptx(char *index) { + if (strcmp(index,"X")==0) ERROR("Illegal use of register X\n", 0, EXIT_FAILURE); + if (strcmp(index,"A")==0) asmlin("TAY", ""); + else if (strcmp(index,"Y") != 0) asmlin("LDY", index); +} + +/* Process Pointer * + * Sets: term - Compiled Pointer */ +int prcptr(void) { + prsptr(); + DEBUG("Dereferencing pointer %s\n", value); + sprintf(term, "(%s),Y", value); + if (valtyp == ARRAY) { + prsidx(TRUE); + prcptx(value); + } + else asmlin("LDY","0"); + return FALSE; //Return Value Not an Integer +} + +/* Parse Term in Expression * + * Sets: term - the term (as a string) * + * Returns: TRUE if term is an integer */ int prstrm(int alwint) { DEBUG("Parsing term\n", 0) + if (match('*')) return prcptr(); //Parse and Deference Pointer prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE) strcpy(term, value); @@ -303,6 +336,12 @@ int prcftm(int alwint) { /* Parse first term of expession * * First term can include function calls */ int prsftm(int alwint) { + DEBUG("Parsing first term\n", 0) + if (match('*')) { + prcptr(); //Parse and Deference Pointer + asmlin("LDA", term); + return FALSE; + } prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants return prcftm(alwint); } diff --git a/src/expr.h b/src/expr.h index 2e50211..0844a97 100644 --- a/src/expr.h +++ b/src/expr.h @@ -15,6 +15,7 @@ int trmcnt; //Number of total terms in current expression int chkadr(int adract, int alwstr); //Check for and Process Address or String void chkidx(); //Check for, Parse, and Process Index int prcftm(int alwint); //Process First Term +void prcptx(char *index); //Process Pointer Index void prcvri(void); //Process Integer Variable int prcivr(int alwint); //Process Integer Variable in Term void prsadr(int adract); //Parse and Compile Address of Operator @@ -23,6 +24,7 @@ void prsval(int alwreg, int alwcon); //Parse Value void prsfnc(char trmntr); //Parse function call void prsfpr(char trmntr); //Parse Function Paraeters or Return void prsidx(); //Parse Array Index +void prsptr(void); //Parse Pointer int prstrm(int alwint); //Parse Term in Expression void prsrxp(char trmntr); //Parse Rest of Expression int prsxpf(char trmntr); //Parse Expression in Function Call diff --git a/src/include.c b/src/include.c index 62b1ddc..9e300db 100644 --- a/src/include.c +++ b/src/include.c @@ -37,8 +37,8 @@ void pincnm(void) { sublen[subidx] = strlen(subnam[subidx]); subnam[subidx][sublen[subidx]++] = '/'; } - dlmtr = '>'; } + dlmtr = '>'; } else if (dlmtr != '"') ERROR("Unexpected character '%c' after include\n", dlmtr, EXIT_FAILURE) @@ -146,7 +146,7 @@ void pprgma(void) { else if (wordis("ORIGIN")) porign(); //Parse Origin else if (wordis("PADDING")) - ppddng(); //Parse Origin + ppddng(); //Parse Padding else if (wordis("RAMBASE")) prambs(); //Parse RamBase else if (wordis("VARTABLE")) diff --git a/src/parse.c b/src/parse.c index d85095d..9dce446 100644 --- a/src/parse.c +++ b/src/parse.c @@ -13,6 +13,8 @@ #include "asm.h" #include "parse.h" #include "label.h" +#include "expr.h" +#include "stmnt.h" /* Various tests against nxtchr */ int match(char c) {return TF(nxtchr == c);} @@ -372,21 +374,23 @@ void poperr(char* name) { } /* Process Post Operator */ -void prcpst(int isint, char* name, char *index) { +void prcpst(int isint, char* name, char *index, char indtyp, char ispntr) { DEBUG("Processing post operation '%c'\n", oper) + if (ispntr) {sprintf(word,"(%s),Y", name); strcpy(name, word); } char name1[VARLEN+3]; strcpy(name1, name); strcat(name1, "+1"); if (strlen(index)) { - asmlin("LDX", index); - strcat(name,",X"); + if (ispntr) prcptx(index); //Process Pointer Index + else prcidx(indtyp, name, index); //Process Index } + else if (ispntr) asmlin("LDY","0"); switch(oper) { case '+': if (strcmp(name, "X")==0) asmlin("INX", ""); else if (strcmp(name, "Y")==0) asmlin("INY", ""); else if (strcmp(name, "A")==0) poperr(name); //65C02 supports implicit INC, 6502 does not else { - asmlin("INC", name); + asmlin("INC", word); if (isint) { newlbl(skplbl); asmlin("BNE", skplbl); @@ -407,7 +411,7 @@ void prcpst(int isint, char* name, char *index) { asmlin("DEC", name1); setlbl(skplbl); } - asmlin("DEC", name); + asmlin("DEC", name); } break; case '<': @@ -434,7 +438,7 @@ void prcpst(int isint, char* name, char *index) { } /* Parse Post Operator */ -int prspst(char trmntr, int isint, char* name, char* index) { +int prspst(char trmntr, int isint, char* name, char* index, char indtyp, char ispntr) { oper = getnxt(); CCMNT(oper); DEBUG("Checking for post operation '%c'\n", oper) @@ -442,7 +446,7 @@ int prspst(char trmntr, int isint, char* name, char* index) { skpchr(); CCMNT(oper); expect(trmntr); - prcpst(isint, name, index); //Process Post-Op + prcpst(isint, name, index, indtyp, ispntr); //Process Post-Op return 0; } DEBUG("Not a post operation\n", 0) diff --git a/src/parse.h b/src/parse.h index 6e8c5b2..8c3b36e 100644 --- a/src/parse.h +++ b/src/parse.h @@ -55,7 +55,7 @@ int prsbyt(); //Parse Numeric Byte void prslit(); //Parse Literal int prsnum(int maxval); //Parse Numeric void prsopr(); //Parse Arithmetic Operator -int prspst(char trmntr, int isint, char* name, char* index); //Parse Post Operator +int prspst(char trmntr, int isint, char* name, char* index, char indtyp, char ispntr); //Parse Post Operator int psizof(void); //Parse SizeOf Operator int pidxof(void); //Parse SizeOf Operator void skpchr(); //Skip Next Character diff --git a/src/stmnt.c b/src/stmnt.c index b3884e2..cf28365 100644 --- a/src/stmnt.c +++ b/src/stmnt.c @@ -73,42 +73,52 @@ void prcidx(int idxtyp, char *name, char *index) /* Set word to assignment variable * * adding write offset (if set) */ -void setasn(char *name) { - strcpy(word, name); +void setasn(char *name, char ispntr) { + if (ispntr) strcpy(word,"("); + else word[0] = 0; + strcat(word, name); if (wrtofs[0]) strcat(word, wrtofs); + if (ispntr) strcat(word,"),Y"); +} + +void prcixy(char rgstr, char* idx, int ivt) { + DEBUG("Processing %c register indexed assignment\n", rgstr) + if (strlen(idx)) { //Process X variable Index + if (ivt != LITERAL) { + asmlin("PHA", ""); //Save Accumulator + if (rgstr == 'X') asmlin("TXA", ""); //Transfer Return Value to Accumulator + else asmlin("TYA", ""); + prcidx(ivt, word, idx); //Process Index + asmlin("STA", word); //Store Return Value + asmlin("PLA", ""); //Restore Accumulator + } else { + prcidx(ivt, word, idx); //Process Index + if (rgstr == 'X') asmlin("STX", word); //Store Return Value + else asmlin("STY", word); + } + } } /* Process Assignment of X and Y variables */ void prcaxy(void) { DEBUG("Processing X assignment variable '%s'\n", xsnvar) if (xsnvar[0]) { - setasn(xsnvar); - if (strlen(xsnidx)) { //Process X variable Index - if (xsnivt != LITERAL) { - asmlin("PHA", ""); //Save Accumulator - asmlin("TXA", ""); //Transfer Return Value to Accumulator - prcidx(xsnivt, word, xsnidx); //Process Index - asmlin("STA", word); //Store Return Value - asmlin("PLA", ""); //Restore Accumulator - } else { - prcidx(xsnivt, word, xsnidx); //Process Index - asmlin("STX", word); //Store Return Value - } - } + setasn(xsnvar, FALSE); + if (strlen(xsnidx)) prcixy('X', xsnidx, xsnivt); //Process Index else asmlin("STX", word); //Store Return Value xsnvar[0] = 0; } DEBUG("Processing Y assignment variable '%s'\n", ysnvar) if (ysnvar[0]) { - setasn(ysnvar); - if (strlen(ysnidx)) prcidx(ysnivt, word, ysnidx); //Process Index - asmlin("STY", word); //Store Return Value + setasn(ysnvar, FALSE); + if (strlen(ysnidx)) prcixy('Y', ysnidx, ysnivt); //Process Index + else asmlin("STY", word); //Store Return Value ysnvar[0] = 0; } } /* Process Assignment */ -void prcasn(char trmntr) { +void prcasn(char trmntr, char ispntr) { expect('='); if (look('(')) prssif(trmntr); //Parse Shortcut If else prsxpr(trmntr); //Parse Expression @@ -118,8 +128,12 @@ void prcasn(char trmntr) { else if (strcmp(asnvar, "Y")==0) asmlin("TAY", ""); else if (strcmp(asnvar, "A")==0) return; DEBUG("Processing assignment variable '%s'\n", asnvar) - setasn(asnvar); - if (asnidx[0]) prcidx(asnivt, word, asnidx); //Process Index + setasn(asnvar, ispntr); + if (asnidx[0]) { + if (ispntr) prcptx(asnidx); //Process Pointer Index + else prcidx(asnivt, word, asnidx); //Process Index + } + else if (ispntr) asmlin("LDY","0"); asmlin("STA", word); //Store Return Value } @@ -143,6 +157,26 @@ int getidx(char* idx) { return valtyp; } +/* Process Accumulator Assignment Variable */ +int prcava(char *name, char trmntr, char ispntr) { + strcpy(asnvar, name); + asntyp = valtyp; //Set Assigned Variable Type + DEBUG("Set STA variable to %s\n", asnvar) + if (asntyp == VARIABLE && look(';')) { + asmlin("STA", asnvar); + return TRUE; + } + if (asntyp == ARRAY) asnivt = getidx(asnidx); //Get Array Index and Type + else asnidx[0] = 0; + if (ispntr && strcmp(asnidx, "X") == 0) ERROR("Illegal use of register X\n", 0, EXIT_FAILURE) + DEBUG("Set STA index to '%s'", asnidx) DETAIL(" and type to %d\n", asnivt) + if (ispopr()) { + if (prspst(trmntr, FALSE, asnvar, asnidx, asnivt, ispntr)) expctd("post operator"); + return TRUE; + } + return FALSE; +} + /* Process Assignment Variable(s) */ void prcavr(char trmntr) { chksym(TRUE, FALSE, word); @@ -150,24 +184,11 @@ void prcavr(char trmntr) { strcpy(vrname, word); //save variable to assign to if (valtyp == STRUCTURE) prsmbr(vrname); //Updates word and vartyp if (vartyp == VTINT) { - if (ispopr()) {if (prspst(trmntr, TRUE, vrname, "")) expctd("post operator");} + if (ispopr()) {if (prspst(trmntr, TRUE, vrname, "", 0, FALSE)) expctd("post operator");} else prcasi(trmntr); //Process Integer Assignment return; } - strcpy(asnvar, vrname); - asntyp = valtyp; //Set Assigned Variable Type - DEBUG("Set STA variable to %s\n", asnvar) - if (asntyp == VARIABLE && look(';')) { - asmlin("STA", asnvar); - return; - } - if (asntyp == ARRAY) asnivt = getidx(asnidx); //Get Array Index and Type - else asnidx[0] = 0; - DEBUG("Set STA index to '%s'", asnidx) DETAIL(" and type to %d\n", asnivt) - if (ispopr()) { - if (prspst(trmntr, FALSE, asnvar, asnidx)) expctd("post operator"); - return; - } + if (prcava(vrname, trmntr, FALSE)) return; if (look(',')) { if (asntyp == REGISTER) ERROR("Register %s not allowed in plural assignment\n", asnvar, EXIT_FAILURE) prsvar(FALSE, FALSE); //get variable name @@ -185,7 +206,7 @@ void prcavr(char trmntr) { else xsnidx[0] = 0; } } - prcasn(trmntr); + prcasn(trmntr, FALSE); } /* Parse 'asm' String Parameter */ @@ -210,11 +231,22 @@ void pasm(void) { asmlin(opcode, word); } +/* Parse and Compile Assignment of Pointer */ +void prcasp(char trmntr) { + prsptr(); //Parse Pointer Dereference + DEBUG("Processing assignment to dereferenced pointer %s\n", value) + if (prcava(value, trmntr, TRUE)) return; //Process Accumulator Assignment Variable + prcasn(trmntr, TRUE); +} + /* Parse and Compile an Assignment */ void prsasn(char trmntr) { - getwrd(); //Get Variable to be Assigned - DEBUG("Parsing assignment of word %s\n", word) - prcavr(trmntr); + if (match('*')) prcasp(trmntr); + else { + getwrd(); //Get Variable to be Assigned + DEBUG("Parsing assignment of word %s\n", word) + prcavr(trmntr); + } } /* parse and compile 'break'/'continue' statement */ diff --git a/src/stmnt.h b/src/stmnt.h index 4a95bc2..7809a6d 100644 --- a/src/stmnt.h +++ b/src/stmnt.h @@ -17,5 +17,7 @@ char xstmnt[LINELEN]; //Expected Statement void bgnblk(char blkchr); //End Program Block void endblk(int blkflg); //End Program Block +void prcasp(char trmntr); //Process Pointer Assignment +void prcidx(int idxtyp, char *name, char *index); void pdowhl(); //Parse and Compile WHILE after DO void pstmnt(); //Parse and Compile Program Statement