M a65.c => a65.c +1 -1
@@ 274,7 274,7 @@ static void normal_op() {
case STXY:
if ((argattr & (opcode == 0x86 ? ~ARGY : ~ARGX)) != ARGNUM) {
- error ('A');
+ error('A');
return;
}
if (argattr & (ARGX + ARGY)) {
M a65.h => a65.h +10 -8
@@ 167,13 167,16 @@ typedef struct {
/* Lexical analyzer (A65EVAL.C) token attribute values: */
-#define EOL 0 /* end of line */
-#define SEP 1 /* field separator */
-#define OPR 2 /* operator */
-#define STR 3 /* character string */
-#define VAL 4 /* value */
-#define IMM 5 /* immediate designator */
-#define REG 6 /* register designator */
+typedef enum {
+ EOL = 0, /* end of line */
+ SEP, /* field separator */
+ OPR, /* operator */
+ STR, /* character string */
+ VAL, /* value */
+ IMM, /* immediate designator */
+ REG, /* register designator */
+ ABS, /* force absolute addressing */
+};
/* Lexical analyzer (A65EVAL.C) token attribute word flag masks: */
@@ 190,7 193,6 @@ typedef struct {
/* use ASCII characters): */
typedef enum {
- ABS = 0,
AND,
GE,
HIGH,
M a65eval.c => a65eval.c +10 -3
@@ 102,6 102,11 @@ unsigned do_args() {
argattr = ARGIMM + ARGNUM;
return expr();
+ case ABS:
+ argattr = ARGNUM;
+ forceabs = TRUE;
+ return expr();
+
case SEP:
u = 0; goto have_number;
@@ 172,6 177,7 @@ static unsigned eval(unsigned pre) {
for (;;) {
u = op = lex()->valu;
switch (token.attr & TYPE) {
+ case ABS:
case REG:
case IMM: exp_error('S'); break;
@@ 183,7 189,6 @@ static unsigned eval(unsigned pre) {
u = (op == '*' ? pc : eval((op == '+' || op == '-') ? (unsigned)UOP1 : token.attr & PREC));
switch (op) {
case '-': u = word(~u + 1); break;
- case ABS: forceabs = TRUE; break;
case NOT: u ^= 0xffff; break;
case HIGH: u = high(u); break;
case LOW: u = low(u); break;
@@ 320,6 325,9 @@ num: pops(token.sval);
case '#': token.attr = IMM;
break;
+ case '!': token.attr = ABS;
+ break;
+
case '(': token.attr = UNARY + LPREN + OPR;
goto opr1;
@@ 392,8 400,7 @@ static void make_number(unsigned base) {
}
int isalph(char c) {
- return (c >= 'A' && c <= '~') || c == '!' ||
- c == '&' || c == '.' || c == ':' || c == '?';
+ return (c >= 'A' && c <= '~') || c == '&' || c == '.' || c == ':' || c == '?';
}
static int isnum(char c) {
M a65util.c => a65util.c +12 -18
@@ 206,7 206,6 @@ OPCODE *find_code(char *nam) {
OPCODE *find_operator(char *nam) {
static OPCODE oprtbl[] = {
{ REG, 'A', "A" },
- { UNARY + UOP3 + OPR, ABS, "ABS" },
{ BINARY + LOG1 + OPR, AND, "AND" },
{ BINARY + RELAT + OPR, '=', "EQ" },
{ BINARY + RELAT + OPR, GE, "GE" },
@@ 336,21 335,20 @@ static void check_page() {
return;
}
-/* Buffer storage for hex output file. This allows the hex file */
+/* Buffer storage for binary output file. This allows the file */
/* output routines to do all of the required buffering and record */
/* forming without the main routine having to fool with it. */
-static FILE *hex = NULL;
static FILE *outfile = NULL;
static unsigned cnt = 0;
static unsigned addr = 0;
static unsigned sum = 0;
static uint8_t buf[HEXSIZE];
-/* Hex file open routine. If a hex file is already open, a warning */
-/* occurs. If the hex file doesn't open correctly, a fatal error */
-/* occurs. If no hex file is open, all calls to hputc(), hseek(), and */
-/* hclose() have no effect. */
+/* Binary file open routine. If the file is already open, a warning */
+/* occurs. If the file doesn't open correctly, a fatal error occurs. */
+/* If no binary file is open, all calls to bputc(), bseek(), and */
+/* bclose() have no effect. */
void bopen(char *filename) {
if (outfile) {
@@ 364,9 362,8 @@ void bopen(char *filename) {
}
}
-/* Hex file write routine. The data byte is appended to the current */
-/* record. If the record fills up, it gets written to disk. If the */
-/* disk fills up, a fatal error occurs. */
+/* Binary file write routine. The data byte is appended to the output */
+/* buffer. If the buffer fills up, it gets written to disk. */
void bputc(unsigned c) {
if (outfile) {
@@ 375,10 372,8 @@ void bputc(unsigned c) {
}
}
-/* Hex file address set routine. The specified address becomes the */
-/* load address of the next record. If a record is currently open, */
-/* it gets written to disk. If the disk fills up, a fatal error */
-/* occurs. */
+/* Binary file address set routine. Note that this can only be used to */
+/* seek forwards in the file. Seeking backwards will cause an error. */
void bseek(unsigned a) {
unsigned cursor = addr + cnt;
@@ 392,7 387,7 @@ void bseek(unsigned a) {
}
/* don't allow seeking backwards */
else if (cursor > a) {
- fatal_error("Invalid ORG statement");
+ error('S');
}
/* pad the file to make up the difference */
else {
@@ 404,9 399,8 @@ void bseek(unsigned a) {
}
}
-/* Hex file close routine. Any open record is written to disk, the */
-/* EOF record is added, and file is closed. If the disk fills up, a */
-/* fatal error occurs. */
+/* Binary file close routine. All buffered data is written to disk, */
+/* and the output file is closed. */
void bclose() {
if (outfile) {
M a65util.h => a65util.h +10 -14
@@ 109,32 109,28 @@ void lputs();
void lclose();
-/* Hex file open routine. If a hex file is already open, a warning */
-/* occurs. If the hex file doesn't open correctly, a fatal error */
-/* occurs. If no hex file is open, all calls to hputc(), hseek(), and */
-/* hclose() have no effect. */
+/* Binary file open routine. If the file is already open, a warning */
+/* occurs. If the file doesn't open correctly, a fatal error occurs. */
+/* If no binary file is open, all calls to bputc(), bseek(), and */
+/* bclose() have no effect. */
void bopen(char *nam);
-/* Hex file write routine. The data byte is appended to the current */
-/* record. If the record fills up, it gets written to disk. If the */
-/* disk fills up, a fatal error occurs. */
+/* Binary file write routine. The data byte is appended to the output */
+/* buffer. If the buffer fills up, it gets written to disk. */
void bputc(unsigned c);
-/* Hex file address set routine. The specified address becomes the */
-/* load address of the next record. If a record is currently open, */
-/* it gets written to disk. If the disk fills up, a fatal error */
-/* occurs. */
+/* Binary file address set routine. Note that this can only be used to */
+/* seek forwards in the file. Seeking backwards will cause an error. */
void bseek(unsigned a);
-/* Hex file close routine. Any open record is written to disk, the */
-/* EOF record is added, and file is closed. If the disk fills up, a */
-/* fatal error occurs. */
+/* Binary file close routine. All buffered data is written to disk, */
+/* and the output file is closed. */
void bclose();
M readme.txt => readme.txt +2 -2
@@ 30,8 30,8 @@ your workflow.
- Change the syntax so "DB" accepts string(s) as arguments - done
- Change the syntax so labels can have colons after them - done
- Give each .c file its own header file - done
-- Change the assembler to output binary files instead of Intel HEX
-- Allow for forcing loads/stores to not be optimized for zero page
+- Change the assembler to output binary files instead of Intel HEX - done
+- Allow for forcing loads/stores to not be optimized for zero page - done (! operator)
- Add a "MSG" statement that prints out arbitrary strings and symbols
- Print the error messages to stdout instead of the assembler listing
- Add a makefile for our GNU/Linux and Mac OS X using friends