mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-21 10:32:08 +00:00
Added pointer dereferencing to C02 compiler
This commit is contained in:
parent
9478d41299
commit
f94ddd63fc
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
43
src/expr.c
43
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
18
src/parse.c
18
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)
|
||||
|
@ -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
|
||||
|
112
src/stmnt.c
112
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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user