/************************************ * C02 Conditional Parsing Routines * ************************************/ #include #include #include #include #include #include "common.h" #include "asm.h" #include "parse.h" #include "vars.h" #include "expr.h" #include "label.h" #include "cond.h" int cmprtr; //Encoded Comparison Operator int cmpenc; //Encoded Comparator Character /* Encode Comparison Operator Character * * Args: Comparison Operator Character * * Returns: Comparison Operator Bit Mask */ int enccmp(char c) { int e; DEBUG("cond.enccm: Encoding Comparison Character '%c'", c) switch(c) { case '=': e = 1; break; case '<': e = 2; break; case '>': e = 4; break; default: e = 0; } if (e) { CCMNT(c); skpchr(); } DETAIL(", encoded as %d\n", e); return e; } /* Process and Compile Comparison Operator and * * Args: comparator - Encoded Comparison Operator * * Uses: term - Term Being Compared Against * * label - Branch Target if Comparison is FALSE */ void prccmp(void) { DEBUG("cond.prccmp: Processing comparator %d", cmprtr) DETAIL(" with REVCMP=%d\n", revcmp) if (cmprtr > 7) { //Process Flag cmprtr = (cmprtr ^ revcmp) & 1; //Apply Reversal if (cmprtr) asmlin("BPL", cmplbl); else asmlin("BMI", cmplbl); return; } cmprtr = (cmprtr ^ revcmp) & 7; //Apply reversal switch(cmprtr) { case 0: // Raw Expression (Skip) asmlin("BEQ", cmplbl); break; case 1: // = or == asmlin("CMP", term); asmlin("BNE", cmplbl); break; case 2: // < asmlin("CMP", term); asmlin("BCS", cmplbl); break; case 3: // <= or =< asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCS", cmplbl); break; case 4: // > asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCC", cmplbl); break; case 5: // >= or => asmlin("CMP", term); asmlin("BCC", cmplbl); break; case 6: // <> or >< asmlin("CMP", term); asmlin("BEQ", cmplbl); break; case 7: // Raw Expression (Normal) asmlin("BNE", cmplbl); break; default: ERROR("Unsupported comparison operator index %d\n", cmprtr, EXIT_FAILURE) } } /* Parse Comparison */ void prscmp(int revrse) { skpspc(); cmpenc = enccmp(nxtchr); //Encode Comparison Character cmprtr = cmpenc; //Set Encoded Comparator if (cmprtr) { cmpenc = enccmp(nxtchr); //Encode Next Comparison Character if (cmpenc != 0) cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator } skpspc(); if (cmprtr) prstrm(FALSE, TRUE); //prccmp(); - Do after check for logical operator DEBUG("cond.prscmp: Parsed comparator %d\n", cmprtr) } /* Parse Flag Operator */ void prsflg(int revrse) { DEBUG("cond.prsflg: Parsing Flag Operator '%c'\n", nxtchr) if (match('+')) cmprtr = 8; //Bit 0 = 0 else if (match('-')) cmprtr = 9; //Bit 1 = 1 else expctd("Flag operator"); skpchr(); } /* Parse Logical Operator * * Sets: logops */ void prslop(void) { DEBUG("cond.prslop: Checking for Logical Operator\n", 0) logopr = LOPNONE; skpspc(); if (isalph()) { getwrd(); //Get Logical Operator DEBUG("cond.prslop: Parsing Logical Operator %s\n", word) if (wordis("AND")) logopr = LOPAND; else if (wordis("OR")) logopr = LOPOR; else ERROR("Encountered invalid token \"%s\"\n", word, EXIT_FAILURE) } DEBUG("cond.prslop: Set LOGOPR to %d\n", logopr) } /* Parse and Compile Conditional Expression * * Condition = */ void prscnd(char trmntr, int revrse) { DEBUG("cond.prscnd: Parsing condition with REVRSE=%d\n", revrse) tmplbl[0] = 0; do { strcpy(cmplbl, cndlbl); DEBUG("cond.prscnd: Set CMPLBL to \"%s\"\n", cmplbl); revcmp = revrse; if (look('!')) revcmp = (revcmp) ? FALSE: TRUE; DEBUG("cond.prscnd: Set REVCMP to %d\n", revcmp) if (!look('.')) prsxpr(0); if (look(':')) prsflg(revcmp); //Parse Flag Operator else prscmp(revcmp); //Parse Comparison Operator prslop(); //Parse Logical Operator if (logopr == LOPOR) { revcmp = (revcmp) ? FALSE: TRUE; DEBUG("cond.prscnd: Set REVCMP to %d\n", revcmp) } if (logopr && revcmp) { if (!tmplbl[0]) newlbl(tmplbl); strcpy(cmplbl, tmplbl); DEBUG("cond.prscnd: Set CMPLBL to \"%s\"\n", cmplbl); } prccmp(); //Process Comparison/Flag Operator } while (logopr); if (tmplbl[0]) setlbl(tmplbl); expect(trmntr); }