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 */
|
|
|
|
int enccmp(char c)
|
|
|
|
{
|
|
|
|
int e;
|
2017-05-05 03:15:53 +00:00
|
|
|
DEBUG("Encoding Comparison Character '%c'\n", c);
|
2017-04-22 18:39:52 +00:00
|
|
|
switch(c)
|
|
|
|
{
|
|
|
|
case '=': e = 1; break;
|
|
|
|
case '<': e = 2; break;
|
|
|
|
case '>': e = 4; break;
|
|
|
|
default: e = 0;
|
|
|
|
}
|
|
|
|
if (e) {
|
|
|
|
CCMNT(c);
|
2017-05-05 03:15:53 +00:00
|
|
|
skpchr();
|
2017-04-22 18:39:52 +00:00
|
|
|
}
|
2017-05-05 03:15:53 +00:00
|
|
|
DEBUG("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 */
|
2017-05-01 01:17:50 +00:00
|
|
|
void prccmp()
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
|
|
|
DEBUG("Processing comparison operator %d\n", cmprtr);
|
|
|
|
switch(cmprtr) {
|
2017-05-01 01:17:50 +00:00
|
|
|
case 0: // Raw Expression (Skip)
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("BEQ", cndlbl);
|
2017-05-01 01:17:50 +00:00
|
|
|
break;
|
2017-04-22 18:39:52 +00:00
|
|
|
case 1: // = or ==
|
|
|
|
asmlin("CMP", term);
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("BNE", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
|
|
|
case 2: // <
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("CMP", term);
|
|
|
|
asmlin("BCS", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
|
|
|
case 3: // <= or =<
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("CLC", "");
|
|
|
|
asmlin("SBC", term);
|
|
|
|
asmlin("BCS", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
|
|
|
case 4: // >
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("CLC", "");
|
|
|
|
asmlin("SBC", term);
|
|
|
|
asmlin("BCC", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
|
|
|
case 5: // >= or =>
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("CMP", term);
|
|
|
|
asmlin("BCC", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
|
|
|
case 6: // <> or ><
|
|
|
|
asmlin("CMP", term);
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("BEQ", cndlbl);
|
2017-04-22 18:39:52 +00:00
|
|
|
break;
|
2017-05-01 01:17:50 +00:00
|
|
|
case 7: // Raw Expression (Normal)
|
2017-05-16 00:25:11 +00:00
|
|
|
asmlin("BNE", cndlbl);
|
2017-05-01 01:17:50 +00:00
|
|
|
break;
|
2017-04-22 18:39:52 +00:00
|
|
|
default:
|
2018-02-09 04:21:46 +00:00
|
|
|
fprintf(stderr, "Unsupported comparison operator index %d\n", cmprtr);
|
2017-04-22 18:39:52 +00:00
|
|
|
exterr(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 00:25:11 +00:00
|
|
|
/* Parse Comparison */
|
2017-06-27 00:16:23 +00:00
|
|
|
int prscmp(int revrse)
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
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
|
|
|
|
if (cmpenc != 0)
|
|
|
|
cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
|
|
|
|
}
|
2017-04-22 18:39:52 +00:00
|
|
|
skpspc();
|
2017-05-16 00:25:11 +00:00
|
|
|
if (cmprtr)
|
|
|
|
prstrm();
|
|
|
|
cmprtr = cmprtr ^ revrse & 7;
|
|
|
|
prccmp();
|
2017-04-22 18:39:52 +00:00
|
|
|
DEBUG("Parsed comparator %d\n", cmprtr);
|
|
|
|
}
|
|
|
|
|
2017-05-16 00:25:11 +00:00
|
|
|
/* Parse Flag Operator */
|
|
|
|
void prsflg(int revrse)
|
|
|
|
{
|
|
|
|
DEBUG("Parsing Flag Operator '%c'\n", nxtchr);
|
|
|
|
if (match('+'))
|
|
|
|
cmprtr = 0;
|
|
|
|
else if (match('-'))
|
|
|
|
cmprtr = 1;
|
|
|
|
else
|
|
|
|
expctd("Flag operator");
|
|
|
|
skpchr();
|
|
|
|
cmprtr = cmprtr ^ revrse & 1;
|
|
|
|
if (cmprtr)
|
|
|
|
asmlin("BPL", cndlbl);
|
|
|
|
else
|
|
|
|
asmlin("BMI", cndlbl);
|
|
|
|
}
|
|
|
|
|
2017-04-22 18:39:52 +00:00
|
|
|
/* Parse and Compile Conditional Expression *
|
|
|
|
* Condition = <expression> <comparator> <term> */
|
2017-05-01 01:17:50 +00:00
|
|
|
void prscnd(char trmntr, int revrse)
|
2017-04-22 18:39:52 +00:00
|
|
|
{
|
2017-05-05 03:15:53 +00:00
|
|
|
DEBUG("Parsing condition with revrse=%d\n", revrse);
|
|
|
|
if (look('!')) {
|
|
|
|
revrse = (revrse) ? FALSE: TRUE;
|
|
|
|
DEBUG("Set revrse to %d\n", revrse);
|
|
|
|
}
|
2017-06-27 00:16:23 +00:00
|
|
|
if (!look('*'))
|
|
|
|
prsxpr(0);
|
2017-05-16 00:25:11 +00:00
|
|
|
if (look(':'))
|
|
|
|
prsflg(revrse); //Parse Flag Operator
|
|
|
|
else
|
|
|
|
prscmp(revrse); //Parse Comparison Operator
|
2017-04-22 18:39:52 +00:00
|
|
|
expect(trmntr);
|
|
|
|
}
|