2017-04-22 18:39:52 +00:00
|
|
|
/************************************
|
|
|
|
* C02 Conditional Parsing Routines *
|
|
|
|
************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#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
|
|
|
|
|
2018-02-13 22:25:57 +00:00
|
|
|
/* Encode Comparison Operator Character *
|
2017-04-22 18:39:52 +00:00
|
|
|
* Args: Comparison Operator Character *
|
|
|
|
* Returns: Comparison Operator Bit Mask */
|
2018-03-04 03:32:39 +00:00
|
|
|
int enccmp(char c) {
|
2017-04-22 18:39:52 +00:00
|
|
|
int e;
|
2018-03-04 19:04:04 +00:00
|
|
|
DEBUG("Encoding Comparison Character '%c'", c)
|
2018-03-04 03:32:39 +00:00
|
|
|
switch(c) {
|
2017-04-22 18:39:52 +00:00
|
|
|
case '=': e = 1; break;
|
|
|
|
case '<': e = 2; break;
|
|
|
|
case '>': e = 4; break;
|
|
|
|
default: e = 0;
|
|
|
|
}
|
2018-03-05 20:03:04 +00:00
|
|
|
if (e) { CCMNT(c); skpchr(); }
|
2018-03-04 03:32:39 +00:00
|
|
|
DETAIL(", encoded as %d\n", e);
|
2017-04-22 18:39:52 +00:00
|
|
|
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 */
|
2018-03-04 03:32:39 +00:00
|
|
|
void prccmp(void) {
|
2018-03-16 03:40:58 +00:00
|
|
|
DEBUG("Processing comparator %d\n", cmprtr)
|
2017-04-22 18:39:52 +00:00
|
|
|
switch(cmprtr) {
|
2017-05-01 01:17:50 +00:00
|
|
|
case 0: // Raw Expression (Skip)
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("BEQ", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 1: // = or ==
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CMP", term); asmlin("BNE", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 2: // <
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CMP", term); asmlin("BCS", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 3: // <= or =<
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCS", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 4: // >
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCC", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 5: // >= or =>
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CMP", term); asmlin("BCC", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 6: // <> or ><
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("CMP", term); asmlin("BEQ", cndlbl); break;
|
2017-05-01 01:17:50 +00:00
|
|
|
case 7: // Raw Expression (Normal)
|
2018-03-05 20:03:04 +00:00
|
|
|
asmlin("BNE", cndlbl); break;
|
2017-04-22 18:39:52 +00:00
|
|
|
default:
|
2018-03-04 18:38:40 +00:00
|
|
|
ERROR("Unsupported comparison operator index %d\n", cmprtr, EXIT_FAILURE)
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 00:25:11 +00:00
|
|
|
/* Parse Comparison */
|
2018-03-04 03:32:39 +00:00
|
|
|
void prscmp(int revrse) {
|
2017-05-16 00:25:11 +00:00
|
|
|
skpspc();
|
2017-04-22 18:39:52 +00:00
|
|
|
cmpenc = enccmp(nxtchr); //Encode Comparison Character
|
|
|
|
cmprtr = cmpenc; //Set Encoded Comparator
|
2017-05-05 03:15:53 +00:00
|
|
|
if (cmprtr) {
|
|
|
|
cmpenc = enccmp(nxtchr); //Encode Next Comparison Character
|
2018-03-05 20:03:04 +00:00
|
|
|
if (cmpenc != 0) cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
|
2017-05-05 03:15:53 +00:00
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
skpspc();
|
2018-03-05 20:03:04 +00:00
|
|
|
if (cmprtr) prstrm();
|
|
|
|
cmprtr = (cmprtr ^ revrse) & 7; //Apply reversal
|
2017-05-16 00:25:11 +00:00
|
|
|
prccmp();
|
2018-03-04 19:04:04 +00:00
|
|
|
DEBUG("Parsed comparator %d\n", cmprtr)
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
|
|
|
|
2017-05-16 00:25:11 +00:00
|
|
|
/* Parse Flag Operator */
|
2018-03-04 03:32:39 +00:00
|
|
|
void prsflg(int revrse) {
|
2018-03-04 19:04:04 +00:00
|
|
|
DEBUG("Parsing Flag Operator '%c'\n", nxtchr)
|
2018-03-05 20:03:04 +00:00
|
|
|
if (match('+')) cmprtr = 0;
|
|
|
|
else if (match('-')) cmprtr = 1;
|
|
|
|
else expctd("Flag operator");
|
2017-05-16 00:25:11 +00:00
|
|
|
skpchr();
|
2018-03-05 20:03:04 +00:00
|
|
|
cmprtr = (cmprtr ^ revrse) & 1; //Apply Reversal
|
|
|
|
if (cmprtr) asmlin("BPL", cndlbl);
|
|
|
|
else asmlin("BMI", cndlbl);
|
2017-05-16 00:25:11 +00:00
|
|
|
}
|
|
|
|
|
2017-04-22 18:39:52 +00:00
|
|
|
/* Parse and Compile Conditional Expression *
|
|
|
|
* Condition = <expression> <comparator> <term> */
|
2018-03-04 03:32:39 +00:00
|
|
|
void prscnd(char trmntr, int revrse) {
|
2018-03-16 03:40:58 +00:00
|
|
|
DEBUG("Parsing condition with REVRSE=%d\n", revrse)
|
2017-05-05 03:15:53 +00:00
|
|
|
if (look('!')) {
|
|
|
|
revrse = (revrse) ? FALSE: TRUE;
|
2018-03-16 03:40:58 +00:00
|
|
|
DEBUG("Set REVRSE to %d\n", revrse)
|
2017-05-05 03:15:53 +00:00
|
|
|
}
|
2018-03-05 20:03:04 +00:00
|
|
|
if (!look('*')) prsxpr(0);
|
|
|
|
if (look(':')) prsflg(revrse); //Parse Flag Operator
|
|
|
|
else prscmp(revrse); //Parse Comparison Operator
|
2017-04-22 18:39:52 +00:00
|
|
|
expect(trmntr);
|
|
|
|
}
|