1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-11-19 12:32:08 +00:00
C02/src/cond.c

135 lines
3.2 KiB
C
Raw Normal View History

/************************************
* 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 *
* Args: Comparison Operator Character *
* Returns: Comparison Operator Bit Mask */
2018-03-04 03:32:39 +00:00
int enccmp(char c) {
int e;
DEBUG("Encoding Comparison Character '%c'", c)
2018-03-04 03:32:39 +00:00
switch(c) {
case '=': e = 1; break;
case '<': e = 2; break;
case '>': e = 4; break;
default: e = 0;
}
if (e) {
CCMNT(c);
skpchr();
}
2018-03-04 03:32:39 +00:00
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 */
2018-03-04 03:32:39 +00:00
void prccmp(void) {
DEBUG("Processing comparitor %d\n", cmprtr)
switch(cmprtr) {
2017-05-01 01:17:50 +00:00
case 0: // Raw Expression (Skip)
asmlin("BEQ", cndlbl);
2017-05-01 01:17:50 +00:00
break;
case 1: // = or ==
asmlin("CMP", term);
asmlin("BNE", cndlbl);
break;
case 2: // <
asmlin("CMP", term);
asmlin("BCS", cndlbl);
break;
case 3: // <= or =<
asmlin("CLC", "");
asmlin("SBC", term);
asmlin("BCS", cndlbl);
break;
case 4: // >
asmlin("CLC", "");
asmlin("SBC", term);
asmlin("BCC", cndlbl);
break;
case 5: // >= or =>
asmlin("CMP", term);
asmlin("BCC", cndlbl);
break;
case 6: // <> or ><
asmlin("CMP", term);
asmlin("BEQ", cndlbl);
break;
2017-05-01 01:17:50 +00:00
case 7: // Raw Expression (Normal)
asmlin("BNE", cndlbl);
2017-05-01 01:17:50 +00:00
break;
default:
ERROR("Unsupported comparison operator index %d\n", cmprtr, EXIT_FAILURE)
}
}
/* Parse Comparison */
2018-03-04 03:32:39 +00:00
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();
2018-03-04 03:32:39 +00:00
cmprtr = (cmprtr ^ revrse) & 7;
prccmp();
DEBUG("Parsed comparator %d\n", cmprtr)
}
/* Parse Flag Operator */
2018-03-04 03:32:39 +00:00
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();
2018-03-04 03:32:39 +00:00
cmprtr = (cmprtr ^ revrse) & 1;
if (cmprtr)
asmlin("BPL", cndlbl);
else
asmlin("BMI", cndlbl);
}
/* Parse and Compile Conditional Expression *
* Condition = <expression> <comparator> <term> */
2018-03-04 03:32:39 +00:00
void prscnd(char trmntr, int revrse) {
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);
if (look(':'))
prsflg(revrse); //Parse Flag Operator
else
prscmp(revrse); //Parse Comparison Operator
expect(trmntr);
}