summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asmmon.c17
-rw-r--r--asmmon.h16
-rw-r--r--assemble.c13
-rw-r--r--disasm.c187
-rw-r--r--emumon.c47
-rw-r--r--enums.h4
-rw-r--r--lexer.c60
-rw-r--r--opcode-gen.c30
-rw-r--r--programs/sub-suite/declare.s430
-rw-r--r--programs/sub-suite/lexer.s152
-rw-r--r--programs/sub-suite/libc.s201
-rw-r--r--programs/sub-suite/subasm.s233
-rw-r--r--programs/sub-suite/subeditor.s232
-rw-r--r--programs/sub-suite/subsuite.s22
-rw-r--r--programs/sub-suite/utils.s257
-rw-r--r--sux.c73
-rw-r--r--sux.h2
-rw-r--r--test/popcnt.s44
-rw-r--r--test/popcnt2.s41
-rw-r--r--test/stack-frame.s14
20 files changed, 1204 insertions, 871 deletions
diff --git a/asmmon.c b/asmmon.c
index 5bc1993..1ad8d98 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -17,7 +17,9 @@ uint16_t incl[MAX_TOK];
line *lines;
line *last_line;
symbol *symbols = 0;
+symbol *last_sym = 0;
fixup *fixups = 0;
+fixup *last_fix = 0;
static char tstr[2048];
@@ -110,7 +112,7 @@ char *showbits(uint64_t value, uint8_t bitnum, uint8_t dbg) {
}
-void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) {
+void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint64_t address, uint8_t dbg) {
line *s = (!all) ? find_line(start, dbg) : lines ;
line *e = (!all) ? find_line( end, dbg) : last_line;
uint8_t j = 0;
@@ -125,8 +127,8 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
uint8_t tabs;
char mne_lower[4];
char ch[6];
-
do {
+ address = s->addr;
token *t = s->tok;
uint8_t am = 0xFF;
uint8_t rs = 0xFF;
@@ -174,6 +176,12 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
case INDY: putchar('('); break;
}
break;
+ case TOK_OF:
+ switch (t->type) {
+ case 1: printf("sp"); break;
+ case 2: printf("pc"); break;
+ }
+ break;
case TOK_SYM:
case TOK_LABEL:
if (t->type == 1) {
@@ -436,9 +444,9 @@ int asmmon(const char *fn) {
}
i++;
}
- list(start, end, isstart, islinenum, isaddr, isdebug);
+ list(start, end, isstart, islinenum, isaddr, 0, isdebug);
} else {
- list(0, 0, 1, 0, 0, 0);
+ list(0, 0, 1, 0, 0, 0, 0);
}
break;
case 0x08:
@@ -447,6 +455,7 @@ int asmmon(const char *fn) {
}
if (!inc_file) {
puts("Now assembling.");
+ address = 0;
bc.progsize = 0;
bc.datasize = 0;
assemble(lines, &bc, dbg);
diff --git a/asmmon.h b/asmmon.h
index eadbc83..29924e9 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -3,7 +3,6 @@
#include <string.h>
#define MAX_TOK 0x1000
-#define TXS_MNE_ID 78 /* Used for a special case in the assembler. */
typedef struct tok token ;
typedef struct ln line ;
@@ -66,8 +65,11 @@ extern line *last_line;
extern token *tokens;
extern token *last_tok;
extern symbol *symbols;
+extern symbol *last_sym;
extern symbol *locals;
+extern symbol *last_loc;
extern fixup *fixups;
+extern fixup *last_fix;
extern uint8_t lex_type;
@@ -77,7 +79,8 @@ enum dir {
DIR_WORD,
DIR_DWORD,
DIR_QWORD,
- DIR_INCLUDE
+ DIR_INCLUDE,
+ DIR_RES
};
enum token {
@@ -161,8 +164,8 @@ static const uint8_t opcodes[OPNUM][10] = {
[CMP] = {0xB1, 0xB6, 0xFF, 0xFF, 0x25, 0x7D, 0x7C, 0xB4, 0xFF, 0xFF}, /* CMP */
[CPB] = {0x2A, 0x2D, 0xFF, 0xFF, 0x55, 0xAD, 0xAC, 0x2C, 0xFF, 0xFF}, /* CPB */
[CPS] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, /* CPS */
- [CPX] = {0x3A, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF}, /* CPX */
- [CPY] = {0x4A, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0xFF, 0xFF}, /* CPY */
+ [CPX] = {0x3A, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF}, /* CPX */
+ [CPY] = {0x4A, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0xFF, 0xFF}, /* CPY */
[DAB] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA2}, /* DAB */
[DEB] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC2}, /* DEB */
[DEC] = {0xFF, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xFF, 0x0A}, /* DEC */
@@ -227,13 +230,14 @@ static const uint8_t opcodes[OPNUM][10] = {
[XOR] = {0x41, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0xFF, 0xFF} /* XOR */
};
-static const char *dir_t[6] = {
+static const char *dir_t[7] = {
[0] = "org",
[1] = "byte",
[2] = "word",
[3] = "dword",
[4] = "qword",
- [5] = "include"
+ [5] = "include",
+ [6] = "res"
};
static const char *rs_t[4] = {
diff --git a/assemble.c b/assemble.c
index 49137c3..8100485 100644
--- a/assemble.c
+++ b/assemble.c
@@ -364,7 +364,8 @@ uint64_t parse_tokens(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
switch (t->id) {
case TOK_DIR:
switch (t->type) {
- case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break;
+ case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break;
+ case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break;
case DIR_BYTE:
case DIR_WORD:
case DIR_DWORD:
@@ -422,7 +423,6 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
for (; l; l = l->next) {
address = parse_tokens(l->tok, bc, 1, address, dbg);
}
-
}
static inline void free_tokens(token *t) {
@@ -474,19 +474,24 @@ void cleanup() {
uint16_t i;
if (lines) {
free_lines();
+ lines = NULL;
}
if (symbols) {
free_symbols(symbols);
+ symbols = NULL;
}
if (fixups) {
free_fixups();
+ fixups = NULL;
}
while (i < stridx || i < comidx) {
- if (i < stridx) {
+ if (i < stridx && string[i]) {
free(string[i]);
+ string[i] = NULL;
}
- if (i < comidx) {
+ if (i < comidx && comment[i]) {
free(comment[i]);
+ comment[i] = NULL;
}
i++;
}
diff --git a/disasm.c b/disasm.c
index 67a8945..bbd8d2b 100644
--- a/disasm.c
+++ b/disasm.c
@@ -1,93 +1,138 @@
#include "sux.h"
#include "disasm.h"
+#include <string.h>
void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t thread) {
uint64_t value = operands[0];
uint64_t address = operands[1];
uint64_t tmpaddr = operands[2];
- char postfix[3];
+ char *postfix;
char *of;
char op[4];
- char sign;
+ char *sign = "";
uint8_t tmp = 0;
- op[0] = opname[opcode][0];
- op[1] = opname[opcode][1];
- op[2] = opname[opcode][2];
- op[3] = '\0';
+ union reg mask;
+ mask.u64 = 0;
+ memcpy(op, opname[opcode], 3);
+ op[3] = 0;
switch ((1 << ((prefix >> 4) & 3))) {
- case 1: postfix[0] = 0; postfix[1] = 0; postfix[2] = 0; break;
- case 2: postfix[0] = '.'; postfix[1] = 'W'; postfix[2] = 0; break;
- case 4: postfix[0] = '.'; postfix[1] = 'D'; postfix[2] = 0; break;
- case 8: postfix[0] = '.'; postfix[1] = 'Q'; postfix[2] = 0; break;
+ case 1: postfix = ""; break;
+ case 2: postfix = ".W"; break;
+ case 4: postfix = ".D"; break;
+ case 8: postfix = ".Q"; break;
}
if (prefix >> 6) {
tmp = 0;
}
switch (prefix >> 6) {
default: of = ""; break;
- case 1 : of = "SP, "; break;
- case 2 : of = "PC, "; break;
+ case 1 : of = "SP"; break;
+ case 2 : of = "PC"; break;
}
+ uint8_t addrsize = 0xFF;
+ char *idx;
+ switch (optype[opcode]) {
+ case IND : idx = ")"; break;
+ case INDX: idx = ", x)"; break;
+ case INDY: idx = "), y"; break;
+ case ZMX : idx = ", x"; break;
+ case ZMY : idx = ", y"; break;
+ default : idx = ""; break;
+ }
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
+ switch (optype[opcode]) {
+ case ZM :
+ case ZMX :
+ case ZMY :
+ case IND :
+ case INDX:
+ case INDY: addrsize = get_addrsize(prefix, ZM); break;
+ case ABS : addrsize = get_addrsize(prefix, ABS); break;
+ }
+ for (uint8_t i = 0; i < addrsize+1; i++) {
+ mask.u8[i] = (i == addrsize && addrsize != 0xFF) ? 0x7F : 0xFF;
+ }
+ switch (addrsize) {
+ case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break;
+ case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break;
+ case 2 :
+ case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break;
+ case 4 :
+ case 5 :
+ case 6 :
+ case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break;
+ }
+ }
+
switch (optype[opcode]) {
case IMPL: wprintw(scr, "%s%s" , opname[opcode], postfix); break;
case IMM:
switch ((1 << ((prefix >> 4) & 3))) {
- case 1: wprintw(scr, "%s #$%02X\r" , op, value); break;
- case 2: wprintw(scr, "%s%s #$%04X\r" , op, postfix, value); break;
- case 4: wprintw(scr, "%s%s #$%08X\r" , op, postfix, value); break;
- case 8: wprintw(scr, "%s%s #$%016"PRIX64"\r" , op, postfix, value); break;
+ case 1: wprintw(scr, "%s #$%02X" , op, value); break;
+ case 2: wprintw(scr, "%s%s #$%04X" , op, postfix, value); break;
+ case 4: wprintw(scr, "%s%s #$%08X" , op, postfix, value); break;
+ case 8: wprintw(scr, "%s%s #$%016"PRIX64 , op, postfix, value); break;
}
break;
case ZM:
case ZMX:
case ZMY:
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
+ tmpaddr &= mask.u64;
+ }
switch (optype[opcode]) {
case ZMX: tmpaddr = address - cpu->x; break;
case ZMY: tmpaddr = address - cpu->y; break;
}
switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s %s$%08X%s\r" , op, postfix, of, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break;
- case 2: wprintw(scr, "%s%s %s$%014"PRIX64"%s\r" , op, postfix, of, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break;
- case 1: wprintw(scr, "%s%s %s$%06X%s\r" , op, postfix, of, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break;
- case 0: wprintw(scr, "%s%s %s$%02X%s\r" , op, postfix, of, tmpaddr, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y")); break;
+ case 3: wprintw(scr, "%s%s %s%s$%08" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
+ case 2: wprintw(scr, "%s%s %s%s$%014"PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
+ case 1: wprintw(scr, "%s%s %s%s$%06" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
+ case 0: wprintw(scr, "%s%s %s%s$%02" PRIX64"%s" , op, postfix, of, sign, tmpaddr, idx); break;
}
break;
case IND:
case INDX:
case INDY:
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
+ tmpaddr &= mask.u64;
+ }
switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s (%s$%08X%s\r", op, postfix, of, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break;
- case 2: wprintw(scr, "%s%s (%s$%012"PRIX64"%s\r", op, postfix, of, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break;
- case 1: wprintw(scr, "%s%s (%s$%06X%s\r", op, postfix, of, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break;
- case 0: wprintw(scr, "%s%s (%s$%02X%s\r", op, postfix, of, tmpaddr, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y")); break;
+ case 3: wprintw(scr, "%s%s (%s%s$%08" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
+ case 2: wprintw(scr, "%s%s (%s%s$%014"PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
+ case 1: wprintw(scr, "%s%s (%s%s$%06" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
+ case 0: wprintw(scr, "%s%s (%s%s$%02" PRIX64"%s", op, postfix, of, sign, tmpaddr, idx); break;
}
break;
case ABS:
tmpaddr = address;
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2) {
+ tmpaddr &= mask.u64;
+ }
switch ((prefix & 0x0C) >> 2) {
- case 3: wprintw(scr, "%s%s %s$%016"PRIX64"\r" , op, postfix, of, tmpaddr); break;
- case 2: wprintw(scr, "%s%s %s$%014"PRIX64"\r" , op, postfix, of, tmpaddr); break;
- case 1: wprintw(scr, "%s%s %s$%010"PRIX64"\r" , op, postfix, of, tmpaddr); break;
- case 0: wprintw(scr, "%s%s %s$%04" PRIX64"\r" , op, postfix, of, tmpaddr); break;
+ case 3: wprintw(scr, "%s%s %s%s$%016"PRIX64 , op, postfix, of, sign, tmpaddr); break;
+ case 2: wprintw(scr, "%s%s %s%s$%014"PRIX64 , op, postfix, of, sign, tmpaddr); break;
+ case 1: wprintw(scr, "%s%s %s%s$%010"PRIX64 , op, postfix, of, sign, tmpaddr); break;
+ case 0: wprintw(scr, "%s%s %s%s$%04" PRIX64 , op, postfix, of, sign, tmpaddr); break;
}
break;
case REL:
switch((1 << ((prefix >> 4) & 3))) {
case 1:
- sign = ((int8_t)value < 0) ? '-' : '+';
- wprintw(scr, "%s %c$%02X" , op, sign, value & 0x7F);
+ sign = ((int8_t)value < 0) ? "-" : "+";
+ wprintw(scr, "%s %s$%02X" , op, sign, value & 0x7F);
break;
case 2:
- sign = ((int16_t)value < 0) ? '-' : '+';
- wprintw(scr, "%s%s %c$%04X" , op, postfix, sign, value & ~(1 << 15));
+ sign = ((int16_t)value < 0) ? "-" : "+";
+ wprintw(scr, "%s%s %s$%04X" , op, postfix, sign, value & ~(1 << 15));
break;
case 4:
- sign = ((int32_t)value < 0) ? '-' : '+';
- wprintw(scr, "%s%s %c$%08X" , op, postfix, sign, value & ~(1 << 31));
+ sign = ((int32_t)value < 0) ? "-" : "+";
+ wprintw(scr, "%s%s %s$%08X" , op, postfix, sign, value & ~(1 << 31));
break;
case 8:
- sign = ((int64_t)value < 0) ? '-' : '+';
- wprintw(scr, "%s%s %c$%016"PRIX64 , op, postfix, sign, value & ~((uint64_t)1 << 63));
+ sign = ((int64_t)value < 0) ? "-" : "+";
+ wprintw(scr, "%s%s %s$%016"PRIX64 , op, postfix, sign, value & ~((uint64_t)1 << 63));
break;
}
break;
@@ -97,6 +142,8 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
wmove(scr, 27, 0);
wprintw(scr, "TX_ADDR: $%02X, RX_ADDR: $%02X", addr[TX_ADDR], addr[RX_ADDR]);
}
+ wmove(scr, 29, 0);
+ wprintw(scr, "address: $%04"PRIX64, address);
if (subdbg) {
uint8_t ln = 33;
uint16_t line_idx = 0;
@@ -105,41 +152,9 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
uint8_t iscursor = 0;
union reg ptr;
uint32_t adr;
- wmove(scr, 30, 0);
- wclrtoeol(scr);
- adr = 0x25;
- ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
- ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
- ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
- ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
- wprintw(scr, "ptr1: $%04"PRIX64, ptr.u64);
- adr = 0x2D;
- ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
- ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
- ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
- ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
- wprintw(scr, ", ptr2: $%04"PRIX64, ptr.u64);
- adr = 0x35;
- ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
- ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
- ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
- ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
- wprintw(scr, ", ptr3: $%04"PRIX64, ptr.u64);
- adr = 0x3349A;
- ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
- ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
- ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
- ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
- wprintw(scr, ", idx0: $%04"PRIX64, ptr.u64);
- adr = 0x334BA;
- ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
- ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
- ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
- ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
- wprintw(scr, ", valbuf: $%016"PRIX64, ptr.u64);
if (address == CTRL_ADDR || addr[STEP_ADDR]) {
adr = 0x30000;
- mvwprintw(scr, 29, 0, "address: $%04"PRIX64", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u\r", address, addr[0], addr[1], addr[0x22], addr[0x23]);
+ wprintw(scr, ", scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u", addr[0], addr[1], addr[0x22], addr[0x23]);
wmove(scr, 32, 0);
wprintw(scr, "bitabl: ");
for (uint8_t i = 0; i < 16; i++) {
@@ -159,7 +174,7 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
wmove(scr, ln++, 0);
wclrtoeol(scr);
wmove(scr, row+1, col-2);
- wprintw(scr, "/\\\r");
+ wprintw(scr, "/\\");
wmove(scr, row, col);
}
}
@@ -172,6 +187,38 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
wmove(scr, ln++, 0);
}
}
+ wmove(scr, 30, 0);
+ wclrtoeol(scr);
+ adr = 0x25;
+ ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
+ ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
+ ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
+ ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
+ wprintw(scr, "ptr1: $%04"PRIX64, ptr.u64);
+ adr = 0x2D;
+ ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
+ ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
+ ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
+ ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
+ wprintw(scr, ", ptr2: $%04"PRIX64, ptr.u64);
+ adr = 0x35;
+ ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
+ ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
+ ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
+ ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
+ wprintw(scr, ", ptr3: $%04"PRIX64, ptr.u64);
+ adr = 0x3349A;
+ ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
+ ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
+ ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
+ ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
+ wprintw(scr, ", idx0: $%04"PRIX64, ptr.u64);
+ adr = 0x334BA;
+ ptr.u8[0] = addr[adr+0]; ptr.u8[1] = addr[adr+1];
+ ptr.u8[2] = addr[adr+2]; ptr.u8[3] = addr[adr+3];
+ ptr.u8[4] = addr[adr+4]; ptr.u8[5] = addr[adr+5];
+ ptr.u8[6] = addr[adr+6]; ptr.u8[7] = addr[adr+7];
+ wprintw(scr, ", valbuf: $%016"PRIX64, ptr.u64);
/*
wmove(scr, 47, 0);
wclrtoeol(scr);
diff --git a/emumon.c b/emumon.c
new file mode 100644
index 0000000..a24a5c5
--- /dev/null
+++ b/emumon.c
@@ -0,0 +1,47 @@
+#include "sux.h"
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+
+void init_win(WINDOW *w) {
+ init_screen();
+ box(w, 0, 0);
+ nodelay(w, 0);
+ crmode();
+ noecho();
+ nl();
+ keypad(w, 1);
+ curs_set(1);
+ werase(w);
+ scrollok(w, 1);
+ start_color();
+ use_default_colors();
+ init_pair(1, COLOR_WHITE, -1);
+ attron(COLOR_PAIR(1) | A_BOLD);
+ wmove(w, 0, 0);
+}
+
+int handle_char(int c) {
+
+}
+
+void emumon(WINDOW *w) {
+ init_win(w);
+ curs_set(0);
+ wprintw(w, "Welcome to the debug monitor for CISC 0.2.\n");
+ wprintw(w, "To get more info, type 'help'.\n");
+ int done = 0;
+ int row = 0;
+ int col = 0;
+ int insert = 1; /* Insert mode flag. */
+ while (!done) {
+ wmove(w, row, col);
+ wrefresh(w);
+ curs_set(1);
+ int c = wgetch(w);
+ curs_set(0);
+ handle_char(c);
+ }
+
+}
diff --git a/enums.h b/enums.h
index 955c27c..83cc7f0 100644
--- a/enums.h
+++ b/enums.h
@@ -156,7 +156,7 @@ enum base_isa {
INY_IMP = 0x39, /* INcrement Y register. */
CPX_IMM = 0x3A, /* ComPare X register. */
CPX_AB = 0x3C, /* CPX Absolute. */
- CPY_Z = 0x3D, /* CPY Zero Matrix. */
+ CPX_Z = 0x3D, /* CPX Zero Matrix. */
JSR_Z = 0x40, /* Jump to SubRoutine. */
XOR_IMM = 0x41, /* bitwise XOR with accumulator. */
XAB_IMP = 0x42, /* bitwise Xor with Accumulator, and B register. */
@@ -166,7 +166,7 @@ enum base_isa {
CLV_IMP = 0x48, /* CLear oVerflow flag. */
CPY_IMM = 0x4A, /* ComPare Y register. */
CPY_AB = 0x4C, /* CPY Absolute. */
- CPX_Z = 0x4D, /* CPX Zero Matrix. */
+ CPY_Z = 0x4D, /* CPY Zero Matrix. */
BPO_REL = 0x50, /* Branch if POsitive. */
LSL_IMM = 0x51, /* Logical Shift Left. */
LLB_IMP = 0x52, /* Logical shift Left accumulator by B. */
diff --git a/lexer.c b/lexer.c
index 14bf1c4..19a53ce 100644
--- a/lexer.c
+++ b/lexer.c
@@ -6,11 +6,12 @@ uint16_t sym_count = 0;
token *tokens = NULL;
token *last_tok = NULL;
symbol *locals = NULL;
+symbol *last_loc = NULL;
symbol *cur_sym = NULL;
symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, uint8_t useid, uint16_t id, uint8_t dbg) {
uint16_t i = 0;
- symbol *s = (!islocal || islocal == 2) ? symbols : locals;
+ symbol *s = (!islocal) ? symbols : locals;
uint8_t flag = 0;
for (; s; s = s->next, i++) {
if (!useid && name[0] != s->name[0]) {
@@ -39,20 +40,29 @@ symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, u
}
}
size_t str_size = strlen(name)+1;
- s = malloc(sizeof(*s));
+ s = malloc(sizeof(symbol));
+ s->local = NULL;
+ if (!islocal) {
+ (last_sym) ? (last_sym->next = s) : (symbols = s);
+ } else {
+ (last_loc) ? (last_loc->next = s) : (locals = s);
+ }
s->name = malloc(str_size);
s->def = def;
s->val = val;
s->count = 0;
memcpy(s->name, name, str_size);
- s->next = (!islocal) ? symbols : locals;
+ s->next = NULL;
s->id = sym_count++;
+ (!islocal) ? (last_sym = s) : (last_loc = s);
if (!islocal) {
s->local = NULL;
- symbols = s;
+ /*if (def) {
+ locals = NULL;
+ last_loc = NULL;
+ }*/
} else {
cur_sym->count++;
- locals = s;
}
defined = 0;
if (dbg) {
@@ -73,12 +83,13 @@ symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t islocal, uint8
if (dbg) {
printf("get_sym(): oof, symbol %s, does not exist, yet.\n", name);
}
- fixup *f = malloc(sizeof(*f));
- f->next = fixups;
+ fixup *f = malloc(sizeof(fixup));
+ (last_fix) ? (last_fix->next = f) : (fixups = f);
f->adr = val;
f->t = t;
f->s = s;
- fixups = f;
+ f->next = NULL;
+ last_fix = f;
fixup_cnt++;
return NULL;
}
@@ -263,8 +274,14 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
offset++;
if ((ptok == PTOK_S && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C')) {
offset++;
+ } else if (ptok == PTOK_S || ptok == PTOK_P) {
+
}
switch (get_ptok(str[i+offset], dbg)) {
+ case PTOK_X :
+ case PTOK_Y :
+ case PTOK_S :
+ case PTOK_P :
case PTOK_ALPHA :
case PTOK_NUMBER: ptok = PTOK_ALPHA; break;
}
@@ -277,7 +294,7 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
lexeme[j] = '\0';
i += j;
if (!isop) {
- for (k = 0; k < 6; k++) {
+ for (k = 0; k < 7; k++) {
if (tolower(lexeme[0]) == dir_t[k][0] && !strcasecmp(lexeme, dir_t[k])) {
lex_type = TOK_DIR;
break;
@@ -353,8 +370,8 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
lt->sym = get_sym(sym, address, lt, islocal, dbg);
}
if (!islocal) {
- cur_sym = symbols;
- locals = cur_sym->local;
+ cur_sym = last_sym;
+ /*last_loc = NULL;*/
}
islocal = 0;
isfixup += (lt->sym == NULL);
@@ -489,8 +506,12 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
isfixup += (lt->sym == NULL);
}
if (!islocal) {
- cur_sym = symbols;
- locals = cur_sym->local;
+ cur_sym = last_sym;
+ cur_sym->local = NULL;
+ locals = NULL;
+ last_loc = NULL;
+ } else if (cur_sym->local == NULL) {
+ cur_sym->local = locals;
}
islocal = 0;
if (dbg) {
@@ -535,10 +556,10 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
break;
case PTOK_ALPHA:
- while (!isdelm2(str[i], dbg)) {
- lexeme[j++] = str[i++];
- }
+ for (; !isdelm2(str[i+j], dbg); j++);
+ memcpy(lexeme, str+i, j);
lexeme[j] = '\0';
+ i += j;
isch = 0;
isop = 0;
if (j == 3 && str[i] != ':') {
@@ -555,12 +576,15 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
}
}
if (!isop) {
+ uint8_t spaces = 0;
+ for (; isdelm(str[i+spaces], dbg) == 16; spaces++);
+ if (get_ptok(str[i+spaces], dbg) == PTOK_COLON) {
+ islocal = (lex_type == TOK_LOCAL);
+ }
lex_type = TOK_SYM;
l->count++;
t = make_token(lex_type, islocal, 0, "", NULL);
memcpy(sym, lexeme, j+1);
- uint8_t spaces = 0;
- for (; isdelm(str[i+spaces], dbg) == 16; spaces++);
if (dbg) {
printf("lex(): spaces: %u\n", spaces);
}
diff --git a/opcode-gen.c b/opcode-gen.c
index 3091e05..be0028c 100644
--- a/opcode-gen.c
+++ b/opcode-gen.c
@@ -8,7 +8,7 @@ struct instruction {
char *mne; /* Mnemonic. */
char *desc; /* Description */
char *com; /* Comment. */
- uint8_t op[10]; /* Opcodes. */
+ uint8_t op[11]; /* Opcodes. */
};
struct opcode {
@@ -44,6 +44,7 @@ const char *ams[] = { /* Addressing modes. */
"IY ",
"AB ",
"REL ",
+ "B ",
"IMP "
};
@@ -58,6 +59,7 @@ enum am {
INDY, /* Indirect Indexed. */
ABS, /* Absolute. */
REL, /* Relative to Program Counter. */
+ BREG, /* B Register. */
IMPL, /* Implied. */
/* Part of Base Extension. */
ABSX, /* Absolute, Indexed with X. */
@@ -71,7 +73,7 @@ enum am {
EIND, /* Effective Address Register, Indirect. */
};
-static const char *addrmodes[10] = {
+static const char *addrmodes[11] = {
[IMM ] = "IMM",
[ZM ] = "ZM",
[ZMX ] = "ZMX",
@@ -81,10 +83,11 @@ static const char *addrmodes[10] = {
[INDY] = "INDY",
[ABS ] = "ABS",
[REL ] = "REL",
+ [BREG] = "BREG",
[IMPL] = "IMPL"
};
-static const char *amcom[10] = {
+static const char *amcom[11] = {
[IMM ] = "Immediate.",
[ZM ] = "Zero Matrix.",
[ZMX ] = "Zero Marrix, Indexed with X.",
@@ -94,10 +97,11 @@ static const char *amcom[10] = {
[INDY] = "Indirect Indexed.",
[ABS ] = "Absolute.",
[REL ] = "Relative.",
+ [BREG] = "B Register.",
[IMPL] = "Implied."
};
-static const char *am_tok[10] = {
+static const char *am_tok[11] = {
[IMM ] = "#",
[ZM ] = "zm",
[ZMX ] = "zmx",
@@ -107,6 +111,7 @@ static const char *am_tok[10] = {
[INDY] = "indy",
[ABS ] = "a",
[REL ] = "rel",
+ [BREG] = "B"
};
int get_instcount(list *l) {
@@ -121,7 +126,7 @@ inst *make_inst(opcode *opc, char *mne, char *desc, char *com) {
ins->desc = desc;
ins->com = com;
- for (int i = 0; i < 10; i++) {
+ for (int i = 0; i < 11; i++) {
ins->op[i] = 0xFF;
}
@@ -170,13 +175,13 @@ void free_opcodes() {
void print_optable(list *l, int maxop) {
int i = 0;
- puts("static const uint8_t opcodes[OPNUM][10] = {");
- puts("\t/*\t IMM\t ZM ZMX ZMY IND INDX INDY ABS REL IMPL*/");
+ puts("static const uint8_t opcodes[OPNUM][11] = {");
+ puts("\t/*\t IMM\t ZM ZMX ZMY IND INDX INDY ABS REL B IMPL*/");
while (l) {
inst *ins = l->inst;
printf("\t[%s] = {", ins->mne);
- for (int j = 0; j < 10; j++) {
- printf("0x%02X%s", ins->op[j], (j < 9) ? ", " : "}");
+ for (int j = 0; j < 11; j++) {
+ printf("0x%02X%s", ins->op[j], (j < 10) ? ", " : "}");
}
putchar((l->next) ? ',' : ' ');
printf(" /* %s */\n", ins->mne);
@@ -212,6 +217,7 @@ opcode *lex_value(char *str, int op) {
case 'A': opc->am = IMPL; break;
case '#': opc->am = IMM ; break;
case 'a': opc->am = ABS ; break;
+ case 'B': opc->am = BREG; break;
case 'r': opc->am = REL ; i += 2; break;
case 'z':
switch (str[i+2]) {
@@ -326,13 +332,13 @@ void print_mneenum(list *l, char *name) {
inst *ins = l->inst;
putchar('\t');
printf("%s = ", ins->mne);
- if (i < 100 && inst_count >= 100) {
+ /*if (i < 100 && inst_count >= 100) {
putchar(' ');
}
if (i < 10 && inst_count >= 10) {
putchar(' ');
- }
- printf("%i", i);
+ }*/
+ printf("%3i", i);
putchar((l->next) ? ',' : ' ');
putchar('\n');
i++;
diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s
new file mode 100644
index 0000000..745445b
--- /dev/null
+++ b/programs/sub-suite/declare.s
@@ -0,0 +1,430 @@
+
+; Enums.
+
+; I/O constants.
+status = $100 ; Keyboard status.
+scr = $101 ; Character that is to be printed.
+kbd = $102 ; Character from the Keyboard.
+step = $110 ; Enables clock stepping, when set.
+
+; Screen constants.
+maxrow = 23 ; Screen's row count.
+maxcol = 79 ; Screen's column count.
+
+MAX_SYM = $800 ; Max symbol size.
+OPNUM = 87 ; Instruction count.
+
+; Directives.
+DIR_ORG = 0 ; Origin.
+DIR_BYTE = 1 ; Byte = 8 bits.
+DIR_WORD = 2 ; Word = 16 bits.
+DIR_DWORD = 3 ; Dword = 32 bits.
+DIR_QWORD = 4 ; Qword = 64 bits.
+DIR_INCL = 5 ; Include.
+DIR_RES = 6 ; Reserved bytes.
+
+; Tokens.
+TOK_DIR = 0 ; Directive.
+TOK_LOCAL = 1 ; Local syobol.
+TOK_LABEL = 2 ; Label.
+TOK_SYM = 3 ; Symbol.
+TOK_EXPR = 4 ; Expression.
+TOK_CSV = 5 ; Comma separated value.
+TOK_STR = 6 ; String.
+TOK_CHAR = 7 ; Character.
+TOK_IND = 8 ; Indirect addressing.
+TOK_IMM = 9 ; Immediate data.
+TOK_MNE = 10 ; Opcode/Mnemonic.
+TOK_RS = 11 ; Register size prefix.
+TOK_COMM = 12 ; Comment.
+TOK_HEX = 13 ; Hex value.
+TOK_DEC = 14 ; Decimal value.
+TOK_BIN = 15 ; Binary value.
+TOK_INCL = 16 ; Include file.
+
+; Pre-Tokens.
+PTOK_DOT = 0 ; .
+PTOK_AT = 1 ; @
+PTOK_COLON = 2 ; :
+PTOK_EQU = 3 ; =
+PTOK_PLUS = 4 ; +
+PTOK_MINUS = 5 ; -
+PTOK_GT = 6 ; >
+PTOK_LT = 7 ; <
+PTOK_LBRAK = 8 ; (
+PTOK_RBRAK = 9 ; )
+PTOK_COMMA = 10 ; ,
+PTOK_X = 11 ; x
+PTOK_Y = 12 ; y
+PTOK_S = 13 ; s
+PTOK_P = 14 ; p
+PTOK_DQUOT = 15 ; "
+PTOK_SQUOT = 16 ; '
+PTOK_HASH = 17 ; #
+PTOK_SCOLN = 18 ; ;
+PTOK_DOLR = 19 ; $
+PTOK_PRCNT = 20 ; %
+PTOK_NUM = 21 ; 0-9
+PTOK_ALPH = 22 ; a-z A-Z
+PTOK_OTHR = 23 ; Everything else.
+
+; Expressions.
+EXPR_PLUS = 0 ; Plus.
+EXPR_MINUS = 1 ; Minus.
+EXPR_LOW = 2 ; Lower half of address.
+EXPR_HIGH = 3 ; Upper half of address.
+EXPR_NONE = 4 ; No expression.
+
+; RAM declarations.
+
+; Linewrap table.
+.org $30000
+bitabl:
+ .res $1000
+
+; Screen buffer.
+buffer:
+ .res $2000
+
+; Command buffer.
+cmd_buf:
+ .res $400
+
+; Screen variables.
+.org 0
+scr_row:
+ .res 1
+scr_col:
+ .res 1
+scr_trow:
+ .res 1
+scr_tcol:
+ .res 1
+scr_ptr:
+ .res 2
+scr_ptr2:
+ .res 2
+scr_ptr3:
+ .res 2
+
+; Pseudo registers.
+a:
+ .res 1
+b:
+ .res 1
+c:
+ .res 1
+d:
+ .res 1
+e:
+ .res 1
+f:
+ .res 1
+g:
+ .res 1
+; This pseudo register is always zero.
+zero:
+ .res 8
+; End of pseudo registers.
+
+end:
+ .res 8
+bitmask:
+ .res 1
+scr_str:
+ .res 1
+scr_end:
+ .res 1
+wrapped:
+ .res 1
+
+; Pointers
+ptr:
+ .res 8
+ptr2:
+ .res 8
+ptr3:
+ .res 8
+
+
+; Token table.
+.org $20000
+tokline:
+ .res $400
+
+; Program Counter.
+prg_cnt:
+ .res 8
+; Hex digit string buffer.
+hex_str:
+ .res 16
+; String buffer.
+strbuf:
+ .res $80
+
+; Subroutine pointer.
+sub_ptr:
+ .res 2
+
+; Indecies.
+idx0:
+ .res 8
+idx1:
+ .res 8
+idx2:
+ .res 8
+idx3:
+ .res 8
+
+; Value buffer used by strtoull.
+valbuf:
+ .res 8
+
+; Copy buffer used by delmcpy.
+cpybuf:
+ .res 8
+
+; Current token line.
+ctok:
+ .res 2
+
+; Last token line.
+ltok:
+ .res 2
+
+; Lexeme type.
+lex_type:
+ .res 1
+
+; Lexeme string.
+lexeme:
+ .res $100
+
+; Symbol table.
+sym:
+ .res $8000
+
+; Fixup table.
+; Fixups are unresolved symbols.
+fix:
+ .res $2000
+
+; ROM data declarations.
+
+.org $A000
+; String Literals/Constants.
+tok:
+ .byte "dab"
+msg:
+ .byte "oof, you divided a, and b on me.\n"
+
+ed_name:
+ .byte "SuBEditor"
+ed_ver:
+ .byte "1"
+ed_sver:
+ .byte ".0.0"
+
+ver_str:
+ .byte ", version "
+made:
+ .byte "Created by, "
+
+author:
+ .byte "mr b0nk 500"
+
+string2:
+ .byte "You typed, "
+
+asm_name:
+ .byte "SuBAsm"
+asm_ver:
+ .byte "0.1"
+
+; Directives.
+dir:
+ .byte "org"
+ .byte "byte"
+ .byte "word"
+ .byte "dword"
+ .byte "qword"
+ .byte "include"
+ .byte "res"
+
+; Short form Commands.
+sh_cmds:
+ .byte "vlahirs"
+
+; Commands.
+cmds:
+ .byte "viewmem"
+ .byte "list"
+ .byte "asm"
+ .byte "help"
+ .byte "inst"
+ .byte "run"
+ .byte "set"
+
+; Linewrap bitmask table.
+bits:
+ .byte $80, $40, $20, $10, $08, $04, $02, $01
+
+
+; Instruction mnemonics, and opcodes.
+
+; Legend.
+; mne = Mnemonic.
+; imm = Immediate data.
+; zm = Zero Matrix.
+; zmx = Zero Matrix, indexed with X.
+; zmy = Zero Matrix, indexed with Y.
+; ind = Indirect.
+; idx = Indexed Indirect.
+; idy = Indirect Indexed.
+; abs = Absolute.
+; rel = Relative.
+; imp = Implied.
+
+mne:
+; mne imm, zm, zmx, zmy, ind, idx, idy, abs, rel, imp
+ .byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF, $FF
+ .byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02
+ .byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22
+ .byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF, $FF
+ .byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF, $FF
+ .byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2
+ .byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF, $FF
+ .byte "BCC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $80, $FF
+ .byte "BCS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $70, $FF
+ .byte "BEQ", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $90, $FF
+ .byte "BNE", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A0, $FF
+ .byte "BNG", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $60, $FF
+ .byte "BPO", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $50, $FF
+ .byte "BRA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0, $FF
+ .byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $68
+ .byte "BVC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0, $FF
+ .byte "BVS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B0, $FF
+ .byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2
+ .byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $08
+ .byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $28
+ .byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $48
+ .byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF, $FF
+ .byte "CPB", $2A, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF, $FF
+ .byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00
+ .byte "CPX", $3A, $4D, $FF, $FF, $FF, $FF, $FF, $3C, $FF, $FF
+ .byte "CPY", $4A, $3D, $FF, $FF, $FF, $FF, $FF, $4C, $FF, $FF
+ .byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2
+ .byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C2
+ .byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $FF, $0A
+ .byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $09
+ .byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $29
+ .byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF, $FF
+ .byte "INB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D2
+ .byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $FF, $1A
+ .byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $19
+ .byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $39
+ .byte "JMP", $FF, $30, $FF, $FF, $B5, $FF, $FF, $10, $FF, $FF
+ .byte "JSR", $FF, $40, $FF, $FF, $A5, $FF, $FF, $20, $FF, $FF
+ .byte "LDA", $C1, $C6, $B8, $78, $05, $5D, $5C, $C4, $FF, $FF
+ .byte "LDB", $D1, $D6, $D8, $98, $35, $8D, $8C, $D4, $FF, $FF
+ .byte "LDX", $B9, $BD, $FF, $FF, $85, $FF, $FF, $BC, $FF, $FF
+ .byte "LDY", $E1, $E6, $FF, $FF, $65, $FF, $FF, $E4, $FF, $FF
+ .byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52
+ .byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62
+ .byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF, $FF
+ .byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF, $FF
+ .byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92
+ .byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF, $FF
+ .byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA
+ .byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32
+ .byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF, $FF
+ .byte "PHA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $79
+ .byte "PHB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $99
+ .byte "PHP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $59
+ .byte "PHX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E9
+ .byte "PHY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C9
+ .byte "PLA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $89
+ .byte "PLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A9
+ .byte "PLP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $69
+ .byte "PLX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F9
+ .byte "PLY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D9
+ .byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72
+ .byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF, $FF
+ .byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF, $FF
+ .byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82
+ .byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F0
+ .byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E0
+ .byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12
+ .byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF, $FF
+ .byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $18
+ .byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $38
+ .byte "STA", $FF, $CD, $C8, $88, $15, $6D, $6C, $CC, $FF, $FF
+ .byte "STB", $FF, $DD, $E8, $A8, $45, $9D, $9C, $DC, $FF, $FF
+ .byte "STX", $FF, $FD, $FF, $FF, $95, $FF, $FF, $FC, $FF, $FF
+ .byte "STY", $FF, $ED, $FF, $FF, $75, $FF, $FF, $EC, $FF, $FF
+ .byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $5A
+ .byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A
+ .byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A
+ .byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A
+ .byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA
+ .byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA
+ .byte "TXS", $FA, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
+ .byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA
+ .byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A
+ .byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA
+ .byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58
+ .byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42
+ .byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF, $FF
+
+; Command subroutine table.
+cmd_srt:
+ .word viewmem
+ .word list
+ .word asm
+ .word help
+ .word inst
+ .word run
+ .word set
+
+
+; Jump table for parsing pre-tokens.
+swtab:
+ .word ptok_dot ; PTOK_DOT
+ .word ptok_at ; PTOK_AT
+ .word ptok_col ; PTOK_COLON
+ .word ptok_equ ; PTOK_EQU
+ .word ptok_plus ; PTOK_PLUS
+ .word ptok_min ; PTOK_MINUS
+ .word ptok_gt ; PTOK_GT
+ .word ptok_lt ; PTOK_LT
+ .word ptok_lbrk ; PTOK_LBRAK
+ .word ptok_rbrk ; PTOK_RBRAK
+ .word ptok_com ; PTOK_COMMA
+ .word ptok_xr ; PTOK_X
+ .word ptok_yr ; PTOK_Y
+ .word ptok_sp ; PTOK_S
+ .word ptok_pc ; PTOK_P
+ .word ptok_dqu ; PTOK_DQUOT
+ .word ptok_squ ; PTOK_SQUOT
+ .word ptok_hash ; PTOK_HASH
+ .word ptok_scol ; PTOK_SCOLN
+ .word ptok_dolr ; PTOK_DOLR
+ .word ptok_prcn ; PTOK_PRCNT
+ .word ptok_num ; PTOK_NUM
+ .word ptok_alph ; PTOK_ALPH
+ .word ptok_othr ; PTOK_OTHR
+
+
+; Hex character table.
+hex_char:
+ .byte "0123456789ABCDEF"
+
+; Compare, and return table for pre-tokens.
+ptok_tab:
+ .byte ".@:=+-><(),xysp\"\'#;$%"
+; Compare, and return table for isdelm.
+dtab:
+ .byte "\n,\"\' \\"
+; Compare, and return table for isdelm2.
+dtab2:
+ .byte "),.+<>-=;\n"
diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s
index cd7a33a..c144f9a 100644
--- a/programs/sub-suite/lexer.s
+++ b/programs/sub-suite/lexer.s
@@ -1,103 +1,9 @@
; Lexer, and supporting routines for SuBAsm.
-; Enums.
-
-; Directives.
-DIR_ORG = 0 ; Origin.
-DIR_BYTE = 1 ; Byte = 8 bits.
-DIR_WORD = 2 ; Word = 16 bits.
-DIR_DWORD = 3 ; Dword = 32 bits.
-DIR_QWORD = 4 ; Qword = 64 bits.
-DIR_INCL = 5 ; Include.
-
-; Tokens.
-TOK_DIR = 0 ; Directive.
-TOK_LOCAL = 1 ; Local syobol.
-TOK_LABEL = 2 ; Label.
-TOK_SYM = 3 ; Symbol.
-TOK_EXPR = 4 ; Expression.
-TOK_CSV = 5 ; Comma separated value.
-TOK_STR = 6 ; String.
-TOK_CHAR = 7 ; Character.
-TOK_IND = 8 ; Indirect addressing.
-TOK_IMM = 9 ; Immediate data.
-TOK_MNE = 10 ; Opcode/Mnemonic.
-TOK_RS = 11 ; Register size prefix.
-TOK_COMM = 12 ; Comment.
-TOK_HEX = 13 ; Hex value.
-TOK_DEC = 14 ; Decimal value.
-TOK_BIN = 15 ; Binary value.
-TOK_INCL = 16 ; Include file.
-
-; Pre-Tokens.
-PTOK_DOT = 0 ; .
-PTOK_AT = 1 ; @
-PTOK_COLON = 2 ; :
-PTOK_EQU = 3 ; =
-PTOK_PLUS = 4 ; +
-PTOK_MINUS = 5 ; -
-PTOK_GT = 6 ; >
-PTOK_LT = 7 ; <
-PTOK_LBRAK = 8 ; (
-PTOK_RBRAK = 9 ; )
-PTOK_COMMA = 10 ; ,
-PTOK_X = 11 ; x
-PTOK_Y = 12 ; y
-PTOK_DQUOT = 13 ; "
-PTOK_SQUOT = 14 ; '
-PTOK_HASH = 15 ; #
-PTOK_SCOLN = 16 ; ;
-PTOK_DOLR = 17 ; $
-PTOK_PRCNT = 18 ; %
-PTOK_NUM = 19 ; 0-9
-PTOK_ALPH = 20 ; a-z A-Z
-PTOK_OTHR = 21 ; Everything else.
-
-; Expressions.
-EXPR_PLUS = 0 ; Plus.
-EXPR_MINUS = 1 ; Minus.
-EXPR_LOW = 2 ; Lower half of address.
-EXPR_HIGH = 3 ; Upper half of address.
-EXPR_NONE = 4 ; No expression.
-
-
-; Data.
-.org lexer_data
-; Jump table for parsing pre-tokens.
-swtab:
- .word ptok_dot ; PTOK_DOT
- .word ptok_at ; PTOK_AT
- .word ptok_col ; PTOK_COLON
- .word ptok_equ ; PTOK_EQU
- .word ptok_plus ; PTOK_PLUS
- .word ptok_min ; PTOK_MINUS
- .word ptok_gt ; PTOK_GT
- .word ptok_lt ; PTOK_LT
- .word ptok_lbrk ; PTOK_LBRAK
- .word ptok_rbrk ; PTOK_RBRAK
- .word ptok_com ; PTOK_COMMA
- .word ptok_xr ; PTOK_X
- .word ptok_yr ; PTOK_Y
- .word ptok_dqu ; PTOK_DQUOT
- .word ptok_squ ; PTOK_SQUOT
- .word ptok_hash ; PTOK_HASH
- .word ptok_scol ; PTOK_SCOLN
- .word ptok_dolr ; PTOK_DOLR
- .word ptok_prcn ; PTOK_PRCNT
- .word ptok_num ; PTOK_NUM
- .word ptok_alph ; PTOK_ALPH
- .word ptok_othr ; PTOK_OTHR
-
-; Data entry point for utility subroutines.
-util_data:
-
-
; Program code.
-.org lexer
lex:
ldx #0 ; Reset X.
txa ; Reset A.
- phy.w ; Preserve the screen buffer index.
txy ; Reset Y.
sty.q idx0 ; Clear the first index.
sty.q idx1 ; Clear the second index.
@@ -165,7 +71,9 @@ lex:
; beq @end ; We got to the end of the string.
bra @loop ; Keep looping.
@end:
- ply.w ; Get the screen buffer index back.
+ jsr update_ptr ; Get the screen buffer index.
+ tay ; Save it in Y.
+ and #0 ; Reset A.
rts ; End of lex.
@@ -208,21 +116,20 @@ ptok_dot:
stb.q idx1 ; Reset the first index.
jsr set_lexptr ; Set up the lexeme buffer.
@dir_loop:
+ ldb idx1 ; Get the directive ID.
+ cpb #7 ; Have we reached the end of the directive table?
+ beq @end ; Yes, so we're done.
lda.w #dir ; Get pointer to the start of the directive table.
clc ; Prepare for a non carrying add.
adc.w idx2 ; Offset the pointer, by the length of the previous string.
pha.q ; Preserve the directive string pointer.
- jsr strcasecmp ; Is the lexeme buffer, the same as the directive string?
+ jsr strcaseptr ; Is the lexeme buffer, the same as the directive string?
pla.q ; Get the directive string pointer back.
beq @found ; Yes, so create a new token.
- ldb idx1 ; No, so Get the directive ID.
- cpb #6 ; Have we reached the end of the directive table?
- beq @end ; Yes, so we're done.
inc idx1 ; No, so increment the directive ID.
@getlen:
jsr strlen ; Get the string's length.
- inx ; Add one to the length.
- txa ; Place it in the accumulator.
+ inc ; Add one to the length.
clc ; Prepare for a non carrying add.
adc.w idx2 ; Add the string offset to the current length
sta.w idx2 ; Save the offset in the third index.
@@ -243,16 +150,24 @@ ptok_equ:
inc.w idx0 ;
rts ; End of parse_ptok.
ptok_plus:
- inc.w idx0 ;
- rts ; End of parse_ptok.
+ lda #EXPR_PLUS ; Set the expresion type to EXPR_PLUS.
+ bra ptok_expr ; Set up the token.
ptok_min:
- inc.w idx0 ;
- rts ; End of parse_ptok.
+ lda #EXPR_MINUS ; Set the expresion type to EXPR_MINUS.
+ bra ptok_expr ; Set up the token.
ptok_gt:
- inc.w idx0 ;
- rts ; End of parse_ptok.
+ lda #EXPR_LOW ; Set the expresion type to EXPR_LOW.
+ bra ptok_expr ; Set up the token.
ptok_lt:
+ lda #EXPR_HIGH ; Set the expresion type to EXPR_HIGH.
+ptok_expr:
+ lda #TOK_EXPR ; Set the lexeme type to TOK_EXPR.
+ sta lex_type ;
inc.w idx0 ;
+; ldb #1 ; Make init_lex increment the string index.
+; jsr init_lex ; Initialize the lexeme buffer for copying.
+ jsr make_tok ; Create the token.
+ jsr set_cmdbuf ; Set the first pointer to the command buffer.
rts ; End of parse_ptok.
ptok_lbrk:
inc.w idx0 ;
@@ -269,6 +184,12 @@ ptok_xr:
ptok_yr:
inc.w idx0 ;
rts ; End of parse_ptok.
+ptok_sp:
+ inc.w idx0 ;
+ rts ; End of parse_ptok.
+ptok_pc:
+ inc.w idx0 ;
+ rts ; End of parse_ptok.
ptok_dqu:
ldb #1 ; Make init_lex increment the string index.
jsr init_lex ; Initialize the lexeme buffer for copying.
@@ -289,6 +210,7 @@ ptok_hash:
ptok_scol:
ldb #1 ; Make init_lex increment the string index.
jsr init_lex ; Initialize the lexeme buffer for copying.
+ ldb #1 ; Set the delimiter to EOL.
jsr delmcpy ; Copy the string, to the lexeme buffer, until EOL.
@end:
rts ; End of parse_ptok.
@@ -312,10 +234,10 @@ ptok_num:
ptok_num2:
pha ; Preserve the base.
jsr init_lex ; Initialize the lexeme buffer for copying.
- ldb #3 ; Set the delimiter to both the EOL, or a comma.
+ ldb #3 ; Set the delimiter to both the EOL, and a comma.
jsr delmcpy ; Copy the string, to the lexeme buffer, until delimiter.
pla ; Get the base back.
- jsr strtoull ; Convert the string into a numeric value.
+ jsr strtoullg ; Convert the string into a numeric value.
jsr make_tok ; Create the token.
jsr set_cmdbuf ; Set the first pointer to the command buffer.
rts ; End of parse_ptok.
@@ -335,14 +257,14 @@ ptok_alph:
lda.w #mne ; Get pointer to the start of the instruction table.
clc ; Prepare for a non carrying add.
adc.w idx2 ; Offset the pointer, by the length of the previous string.
- jsr strcasecmp ; Is the lexeme buffer, the same as the mnemonic string?
+ jsr strcaseg ; Is the lexeme buffer, the same as the mnemonic string?
beq @found ; Yes, so create a new token.
ldb idx1 ; No, so Get the instruction ID.
cpb #OPNUM-1 ; Have we reached the end of the instruction table?
beq @end ; Yes, so we're done.
inc idx1 ; No, so increment the instruction ID.
@offset:
- lda #13 ; Get the base size of the instruction table.
+ lda #14 ; Get the base size of the instruction table.
clc ; Prepare for a non carrying multiply.
mul idx1 ; Multiply the base offset, by the instruction ID.
sta.w idx2 ; Save the offset in the third index.
@@ -371,7 +293,8 @@ set_lexptr:
set_cmdbuf:
- ldb #0 ; Set the first pointer
+ and #0 ; Reset A.
+ tab ; Reset B.
lda.d #cmd_buf ; to the command buffer.
jsr set_ptr ;
and #0 ; Reset A.
@@ -414,7 +337,7 @@ delmcpy:
and #$FF ; Get the current byte.
pha ; Preserve the character.
lda a ; Are we calling isdelm2?
- pla ; Get the character back.
+ pla ; Get the character back.
bne @isdelm2 ; Yes, so use isdelm2.
jsr isdelm ; No, so get the delimiter value from isdelm.
@delmchk:
@@ -504,6 +427,3 @@ make_tok:
nop ;
@end:
rts ; End of make_tok.
-
-; Entry point for utility subroutines.
-utils:
diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s
new file mode 100644
index 0000000..bd55f9c
--- /dev/null
+++ b/programs/sub-suite/libc.s
@@ -0,0 +1,201 @@
+; Simple libc implementation for the SuB Suite
+
+strtoull:
+ phy.w ; Preserve Y.
+ and #0 ; Reset A.
+ tay ; Reset Y.
+ pha.q ; Reset the value buffer.
+@loop:
+ lda (sp+20), y ; Get a character from the string.
+ pha ; Preserve the character.
+ jsr isdigit ; Is this character, a digit?
+ pla ; Get the character back.
+ bne @digit ; Yes, so extract the value from it.
+ jsr tolower ; No, so convert the character to lowercase.
+ pha ; Preserve the character.
+ jsr islower ; Is this an alphabetical character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@alpha:
+ sec ; Yes, so prepare for a non borrowing subtract.
+ sbc #'a'-10 ; Get the numeric value from this digit.
+ bra @chkbase ; Check if the value matches the base.
+@digit:
+ sec ; Prepare for a non borrowing subtract.
+ sbc #'0' ; Get the numeric value from this digit.
+@chkbase:
+ cmp sp+19 ; Does the value match the base?
+ bcs @end ; No, so we're done.
+@addval:
+ tab ; Save the digit value.
+ lda.q sp+1 ; Get the value from the value buffer.
+ mul sp+19 ; Multiply the value by the base.
+ clc ; Prepare for a non carrying add.
+ aab ; Add the digit value to the total value.
+ sta.q sp+1 ; Place the value in the value buffer.
+ iny ; Increment the string index.
+ and #0 ; Reset A.
+ bra @loop ; Keep looping.
+@end:
+ pla.q ; Get the value buffer back.
+ ply.w ; Get Y back.
+ ldb #0 ; Reset B.
+ rts ; End of strtoull.
+
+
+strlen:
+ pha.q ; Set the temp variable to the argument.
+ ldb #0 ; Reset B.
+ tba ; Reset A.
+ tax ; Reset X.
+ phy.w ; Preserve Y.
+ txy ; Reset Y.
+@loop:
+ lda (sp+3), y ; Are we at the end of the string?
+ beq @end ; Yes, so we're done.
+ iny ; No, so increment the index.
+ bra @loop ; Keep looping.
+@end:
+ tyx ; Return the length in X.
+ ply.w ; Get the preserved value back.
+ pla.q ; Get the argument back.
+ txa ; Get the return value.
+ rts ; End of strlen.
+
+
+strcmp:
+ ldb #0 ; Reset B.
+ tba ; Reset A.
+ phy.w ; Preserve Y.
+ tay ; Reset Y.
+@loop:
+ ldb #0 ; Set the islong flag to false.
+ lda (sp+19), y ; Are we at the end of the first string?
+ beq cmpr ; Yes, so check if we're too short, or too long.
+ ldb #1 ; No, so set the islong flag to true.
+ cmp (sp+11), y ; Is the character of both strings, the same?
+ bne cmpr ; No, so check if we're too short, or too long.
+ iny ; Yes, so increment the index.
+ bra @loop ; Keep looping.
+
+strccmp:
+strcasecmp:
+ ldb #0 ; Reset B.
+ tba ; Reset A.
+ phy.w ; Preserve Y.
+ tay ; Reset Y.
+@loop:
+ ldb #0 ; Set the islong flag to false.
+ lda (sp+19), y ; Are we at the end of the first string?
+ beq cmpr ; Yes, so check if we're too short, or too long.
+ ldb #1 ; No, so set the islong flag to true.
+ jsr tolower ; Convert the character of string 1 to lowercase.
+ phb ; Preserve the islong flag.
+ pha ; Preserve the converted character.
+ lda (sp+13), y ; Get the character of the second string.
+ jsr tolower ; Convert the character of string 2 to lowercase.
+ tab ; Place it in B.
+ pla ; Get the character of string 1 back.
+ cab ; Is the character of both strings, the same?
+ plb ; Get the islong flag back.
+ bne cmpr ; No, so check if we're too short, or too long.
+ iny ; Yes, so increment the index.
+ bra @loop ; Keep looping.
+
+cmpr:
+ lda (sp+11), y ; Are we at the end of the second string?
+ beq @islong ; Yes, so check the islong flag.
+@isshort:
+ lda (sp+19), y ; No, but are we at the end of the first string?
+ beq @short ; Yes, so return -1.
+@islong:
+ cpb #1 ; Is the islong flag true?
+ bne @equ ; No, so return 0.
+@long:
+ lda #1 ; Yes, so return 1.
+ bra @end ; We are done.
+@equ:
+ lda #0 ; Return 0.
+ bra @end ; We are done.
+@short:
+ lda #$FF ; Return -1.
+@end:
+ ply.w ; Get the preserved value back.
+ rts ; End of cmpr.
+
+
+isdigit:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'0' ; Subtract $30 from the passed character.
+ and #$FF ; Make sure that we have only one byte.
+ cmp #10 ; Is the subtracted value, less than 10?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isdigit.
+
+isxdigit:
+ pha ; Preserve the character.
+ jsr isdigit ; Is this character, a decimal digit?
+ pla ; Get the character back.
+ bne @true ; Yes, so return true.
+@alpha:
+ sec ; No, so prepare for a non carrying subtract.
+ ora #$20 ; Convert it to lowercase.
+ sbc #'a' ; Subtract $61 from the character.
+ and #$FF ; Make sure that we have only one byte.
+ cmp #6 ; Is the subtracted value, less than 6?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isxdigit.
+
+
+isupper:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'A' ; Subtract $41 from the passed character.
+ bra isletter ; Check if it's less than 26.
+islower:
+ sec ; Prepare for a non carrying subtraction.
+ sbc #'a' ; Subtract $61 from the passed character.
+isletter:
+ and #$FF ; Make sure that we have only one byte.
+ cmp #26 ; Is the subtracted value, less than 26?
+ bcs @false ; No, so return false.
+@true:
+ lda #1 ; Yes, so return true.
+ bra @end ; We are done.
+@false:
+ lda #0 ; Return false.
+@end:
+ rts ; End of isletter.
+
+
+tolower:
+ pha ; Preserve the character.
+ jsr isupper ; Is this character, an uppercase character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@lower:
+ ora #$20 ; Yes, so convert it to lowercase.
+@end:
+ rts ; End of tolower.
+
+
+toupper:
+ pha ; Preserve the character.
+ jsr islower ; Is this character, a lowercase character?
+ pla ; Get the character back.
+ beq @end ; No, so we're done.
+@upper:
+ and #$5F ; Yes, so convert it to uppercase.
+@end:
+ rts ; End of toupper.
diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s
index d661695..0a7640d 100644
--- a/programs/sub-suite/subasm.s
+++ b/programs/sub-suite/subasm.s
@@ -3,225 +3,6 @@
;
; by mr b0nk 500 <b0nk@b0nk.xyz>
-MAX_SYM = $800 ; Max symbol size.
-OPNUM = 88 ; Instruction count.
-
-.include "lexer.s"
-.include "utils.s"
-
-.org incl
-; String Constants.
-asm_name:
- .byte "SuBAsm"
-asm_ver:
- .byte "0.1"
-
-; Directives.
-dir:
- .byte "org"
- .byte "byte"
- .byte "word"
- .byte "dword"
- .byte "qword"
- .byte "include"
-
-; Short form Commands.
-sh_cmds:
- .byte "vlahirs"
-
-; Commands.
-cmds:
- .byte "viewmem"
- .byte "list"
- .byte "asm"
- .byte "help"
- .byte "inst"
- .byte "run"
- .byte "set"
-
-; Instruction mnemonics, and opcodes.
-
-; Legend.
-; mne = Mnemonic.
-; imm = Immediate data.
-; zm = Zero Matrix.
-; zmx = Zero Matrix, indexed with X.
-; zmy = Zero Matrix, indexed with Y.
-; ind = Indirect.
-; idx = Indexed Indirect.
-; idy = Indirect Indexed.
-; abs = Absolute.
-; imp = Implied.
-
-mne:
-; mne imm, zm, zmx, zmy, ind, idx, idy, abs, imp
- .byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00
- .byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF
- .byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02
- .byte "PHP", $08, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "CPB", $09, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF
- .byte "PHB", $0A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $E5
- .byte "JMP", $FF, $0E, $FF, $FF, $CE, $FF, $FF, $10, $FF
- .byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF
- .byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12
- .byte "ENT", $18, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "CPY", $19, $3D, $FF, $FF, $85, $FF, $FF, $4C, $FF
- .byte "PLB", $1A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $F5
- .byte "JSR", $FF, $1E, $FF, $FF, $BE, $FF, $FF, $20, $FF
- .byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF
- .byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22
- .byte "PLP", $28, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "CPX", $29, $4D, $FF, $FF, $B5, $FF, $FF, $3C, $FF
- .byte "PHY", $2A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "BPO", $FF, $2E, $FF, $FF, $FF, $FF, $FF, $30, $FF
- .byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF
- .byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32
- .byte "STT", $38, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "PLY", $3A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "BNG", $FF, $3E, $FF, $FF, $FF, $FF, $FF, $40, $FF
- .byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF
- .byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42
- .byte "PHA", $48, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "PHX", $4A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "BCS", $FF, $4E, $FF, $FF, $FF, $FF, $FF, $50, $FF
- .byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF
- .byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52
- .byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58
- .byte "PLX", $5A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "BCC", $FF, $5E, $FF, $FF, $FF, $FF, $FF, $60, $FF
- .byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF
- .byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62
- .byte "PLA", $68, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A
- .byte "BEQ", $FF, $6E, $FF, $FF, $FF, $FF, $FF, $70, $FF
- .byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF
- .byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72
- .byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $78
- .byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A
- .byte "BNE", $FF, $7E, $FF, $FF, $FF, $FF, $FF, $80, $FF
- .byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF
- .byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82
- .byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $88
- .byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A
- .byte "BVS", $FF, $8E, $FF, $FF, $FF, $FF, $FF, $90, $FF
- .byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF
- .byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92
- .byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $98
- .byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A
- .byte "BVC", $FF, $9E, $FF, $FF, $FF, $FF, $FF, $A0, $FF
- .byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF
- .byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2
- .byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A8
- .byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA
- .byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AE
- .byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF
- .byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2
- .byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B8
- .byte "LDX", $B9, $BD, $FF, $C9, $95, $FF, $FF, $BC, $FF
- .byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA
- .byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0
- .byte "LDA", $C1, $C6, $79, $39, $05, $5D, $5C, $C4, $FF
- .byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C5
- .byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C8
- .byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA
- .byte "STA", $FF, $CD, $89, $49, $15, $6D, $6C, $CC, $FF
- .byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0
- .byte "LDB", $D1, $D6, $99, $59, $35, $8D, $8C, $D4, $FF
- .byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D5
- .byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D8
- .byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA
- .byte "STB", $FF, $DD, $A9, $69, $45, $9D, $9C, $DC, $FF
- .byte "TXS", $E0, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
- .byte "LDY", $E1, $E6, $E9, $FF, $65, $FF, $FF, $E4, $FF
- .byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E8
- .byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA
- .byte "STY", $FF, $ED, $F9, $FF, $75, $FF, $FF, $EC, $FF
- .byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EE
- .byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF
- .byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2
- .byte "STX", $FF, $FD, $FF, $D9, $A5, $FF, $FF, $FC, $FF
- .byte "INB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FE
-
-; Command subroutine table.
-cmd_srt:
- .word viewmem
- .word list
- .word asm
- .word help
- .word inst
- .word run
- .word set
-
-; Data entry point for the lexer.
-lexer_data:
-
-
-; Token table.
-.org $20000
-tokline:
-
-.org cmd_buf+$400
-; Program Counter.
-prg_cnt:
- .qword 0
-; Hex digit string buffer.
-hex_str:
- .qword 0, 0
-; String buffer.
-strbuf:
-
-.org strbuf+$80
-; Subroutine pointer.
-sub_ptr:
- .word 0
-
-; Indecies.
-idx0:
- .qword 0
-idx1:
- .qword 0
-idx2:
- .qword 0
-idx3:
- .qword 0
-
-; Value buffer used by strtoull.
-valbuf:
- .qword 0
-
-; Copy buffer used by delmcpy.
-cpybuf:
- .qword 0
-
-; Current token line.
-ctok:
- .word 0
-
-; Last token line.
-ltok:
- .word 0
-
-; Lexeme type.
-lex_type:
- .byte 0
-
-; Lexeme string.
-lexeme:
-
-; Symbol table.
-.org lexeme+$100
-sym:
-
-; Fixup table.
-; Fixups are unresolved symbols.
-.org sym+$8000
-fix:
-
-
-; Start of program code.
-.org parser
subasm:
ldb #0 ; Set the first pointer
lda.d #cmd_buf ; to the command buffer.
@@ -244,15 +25,17 @@ subasm:
cmp #8 ; Is the command ID greater than the command count?
bcs @end ; Yes, so we're done.
lsl #1 ; No, so multiply the command ID by two.
- phy.w ; Preserve the screen buffer position.
tay ; Set the index to the offset that we just calculated.
lda.w (ptr2), y ; Get the command subroutine, from the command subroutine table.
- ply.w ; Get back the screen buffer position.
ldb #2 ; Save it in the third pointer.
jsr set_ptr ;
ldb #0 ; Reset B.
jsr (ptr3) ; Run the command's subroutine.
@end:
+ and #0 ; Reset A.
+ jsr update_ptr ; Get the screen buffer index.
+ tay ; Save it in Y.
+ and #0 ; Reset A.
rts ; End of subasm.
chk_shcmd:
@@ -306,7 +89,7 @@ chk_cmd:
clc ; Prepare for a non carrying add.
adc.w idx0 ; Offset the pointer, by the length of the previous string.
pha.q ; Preserve the command string pointer.
- jsr strcasecmp ; Is the command buffer, the same as the command string?
+ jsr strcaseg ; Is the command buffer, the same as the command string?
pla.q ; Get the command string pointer back.
beq @true ; Yes, so return true.
ldb idx1 ; No, so Get the command ID.
@@ -315,8 +98,7 @@ chk_cmd:
inc idx1 ; No, so increment the command ID.
@getlen:
jsr strlen ; Get the string's length.
- inx ; Add one to the length.
- txa ; Place it in the accumulator.
+ inc ; Add one to the length.
clc ; Prepare for a non carrying add.
adc.w idx0 ; Add the string offset to the current length
sta.w idx0 ; Save the offset in the first index.
@@ -391,6 +173,3 @@ set:
nop ;
@end:
rts ; End of set.
-
-; Entry point for utility subroutines.
-lexer:
diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s
index cc18b4c..2282a72 100644
--- a/programs/sub-suite/subeditor.s
+++ b/programs/sub-suite/subeditor.s
@@ -3,145 +3,15 @@
; Writen in Sux assembly by
; mr b0nk 500 <b0nk@b0nk.xyz>
-; I/O constants.
-status = $100 ; Keyboard status.
-scr = $101 ; Character that is to be printed.
-kbd = $102 ; Character from the Keyboard.
-step = $110 ; Enables clock stepping, when set.
-
-; Screen constants.
-maxrow = 23 ; Screen's row count.
-maxcol = 79 ; Screen's column count.
-
-; Include SuBAsm.
-.include "subasm.s"
-
-.org $A000
-; String Literals/Constants.
-tok:
- .byte "dab"
-msg:
- .byte "oof, you divided a, and b on me.\n"
-
-ed_name:
- .byte "SuBEditor"
-ed_ver:
- .byte "1"
-ed_sver:
- .byte ".0.0"
-
-ver_str:
- .byte ", version "
-made:
- .byte "Created by, "
-
-author:
- .byte "mr b0nk 500"
-
-string2:
- .byte "You typed, "
-
-; Linewrap bitmask table.
-bits:
- .byte $80, $40, $20, $10, $08, $04, $02, $01
-
-; This label is for any included files.
-incl:
-
-; Linewrap table.
-.org $30000
-bitabl:
- .qword 0
- .qword 0
-
-; SCreen buffer.
-.org bitabl+$1000
-buffer:
-
-; Command buffer.
-.org buffer+$2000
-cmd_buf:
-
-
-; Screen variables.
-.org 0
-scr_row:
- .byte 0
-scr_col:
- .byte 0
-scr_trow:
- .byte 0
-scr_tcol:
- .byte 0
-scr_ptr:
- .word 0
-scr_ptr2:
- .word 0
-scr_ptr3:
- .word 0
-
-; Pseudo registers.
-a:
- .byte 0
-b:
- .byte 0
-c:
- .byte 0
-d:
- .byte 0
-e:
- .byte 0
-f:
- .byte 0
-g:
- .byte 0
-; This pseudo register is always zero.
-zero:
- .qword 0
-; End of pseudo registers.
-
-end:
- .qword 0
-bitmask:
- .byte 0
-scr_str:
- .byte 0
-scr_end:
- .byte 0
-wrapped:
- .byte 0
-
-; Pointers
-ptr:
- .qword 0
-ptr2:
- .qword 0
-ptr3:
- .qword 0
-
-; Main program
.org $8000
reset:
cps ; Reset the processor status register.
ldx.w #$FFFF ; Reset the stack pointer.
txs ;
- ldy #0 ; Reset the Y register.
- sty end ;
- tyx ; Reset the X register.
- lda #maxrow ; Set the end of the screen to the screen's max row count.
- sta scr_end ;
- tya ; Reset the Accumulator.
- sta scr_str ; Set the start of the screen back to zero.
- sta.q bitabl ; Reset the first half of the linewrap table.
- sta.q bitabl+8 ; Reset the second half of the linewrap table.
- inc end ;
- lda.w #$1FFF ; Set the clear count to $1FFF.
- sta.w scr_ptr ;
- lda.d #buffer ; Set the array to be cleared to the screen buffer.
- jsr clr_arr ; Clear the screen buffer.
+ ldy #0 ; Reset Y.
+ tyx ; Reset X.
+ jsr clr_scr ; Clear the screen.
jsr pnt_strt ; Print the starting message.
- lda #$C ; Clear the screen.
- sta scr ;
bra start ; Goto the start of the main program.
clr_arr:
@@ -193,30 +63,32 @@ pnt_strt:
jsr print_char ;
rts ; End of pnt_strt.
-start:
- lda #0 ; TODO: Update this for the Super VIA.
- sta status ; Clear the control register of the I/O adapter.
- tax ; Reset X.
- phy.w ; Save the cursor index for later.
- tay ; Reset the cursor index.
+
+clr_cmd:
+ and #0 ; Reset A.
+ tay ; Reset Y.
lda.w #$3FF ; Set the clear count to $3FF.
sta.w scr_ptr ;
lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
jsr clr_arr ; Clear the command buffer.
- ply.w ; Get back the cursor index.
+ rts ; End of clr_cmd.
+
+
+start:
+ lda #0 ; TODO: Update this for the Super VIA.
+ sta status ; Clear the control register of the I/O adapter.
+ tax ; Reset X.
+ jsr clr_cmd ; Clear the command buffer.
+ jsr update_ptr ; Get the screen buffer index.
+ tay ; Save it in Y.
and #0 ; Reset the Accumulator.
- sta end ;
bra read ; Start reading the keyboard.
read:
- lda #0 ; Reset the Accumulator.
- sta end ; Disable the dummy flag.
- inc end ; Enable the dummy flag.
- lda status ; Did we get a key?
- beq read ; No, so try again.
- jsr getchar ; Yes, and was it a newline?
- beq parse ; Yes, so start parsing the line.
- bra read ; No, so keep looping.
+ jsr getchar ; Get a character.
+ jsr handle_char ; Send the character to the handler routine.
+ beq parse ; The handled character was a newline, so start parsing.
+ bra read ; Keep looping.
parse:
lda #0 ;
@@ -225,6 +97,16 @@ parse:
bra start ;
+getchar:
+ and #0 ; Reset A.
+@loop:
+ lda status ; Did we get a key?
+ beq @loop ; No, so try again.
+ lda kbd ; Yes, so get the typed character.
+@end:
+ rts ; End of getchar.
+
+
print_str:
ldx #0 ; Reset X.
sta.q end ; Save the parameter.
@@ -240,17 +122,19 @@ print_str:
cmp.q end ; Did the pointer change?
bne @reset ; Yes, so set it back.
and #0 ; No, reset the accumulator.
- phy.w ; Save the cursor index.
txy ; Copy the string index into Y.
- lda (ptr), y ; Are we at the end of the string?
- ply.w ; Get the cursor index back.
- beq @end ; Yes, so we're done.
- inx ; No, so increment the string index.
+ ldb (ptr), y ; Are we at the end of the string?
+ beq @end ; Yes, so we're done.
+ jsr update_ptr ; No, so get the screen buffer index.
+ tay ; Save it in Y.
+ tba ; Get the character back.
+ inx ; Increment the string index.
jsr print_char ; Print the character.
bra @loop ; Keep looping.
@end:
ldb #0 ; Enable insert mode.
stb b ;
+ tba ; Reset A.
rts ; End of print_str.
getbit:
@@ -335,8 +219,8 @@ bitpos:
pla ; Get back the bitmask.
rts ; End of bitpos.
-getchar:
- lda kbd ; Get the character that was typed from the keyboard.
+
+handle_char:
ldb #0 ; Reset the B register.
stb e ; Set the temporary row position to zero, in case we get a newline.
stb b ; Enable insert mode.
@@ -354,7 +238,7 @@ getchar:
jsr print_char ; No, so print the character.
lda a ; Get the return value.
cmp #'\n' ; Is the return value, a newline?
- beq @true ; Yes, so return true.
+ beq @true ; Yes, so return true.
bra @false ; No, so return false.
@row:
ldb e ; Get the temporary row position.
@@ -373,7 +257,7 @@ getchar:
@false:
lda #1 ; Return false.
@end:
- rts ; End of getchar.
+ rts ; End of handle_char.
cmd_cpy:
@@ -633,11 +517,11 @@ clr_scr:
sta.w scr_ptr ;
lda.d #buffer ; Set the array to be cleared to the screen buffer.
jsr clr_arr ; Clear the screen buffer.
- tay ;
- lda.w #$3FF ; Set the clear count to $3FF.
- sta.w scr_ptr ;
- lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
- jsr clr_arr ; Clear the screen buffer.
+; tay ;
+; lda.w #$3FF ; Set the clear count to $3FF.
+; sta.w scr_ptr ;
+; lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
+; jsr clr_arr ; Clear the screen buffer.
sta scr_col ;
sta scr_row ;
jsr update_pos ;
@@ -1051,9 +935,7 @@ isshftdown:
rts ;
-update_pos:
- ldb #1 ; Set the F pseudo register to one, to fix some bugs.
- stb f ;
+update_ptr:
clc ; Clear the carry flag.
lda scr_row ; Add the cursor's line number,
adc scr_str ; with the starting line number to get the absolute line number.
@@ -1061,6 +943,13 @@ update_pos:
mul #maxcol+1 ; Multiply the line number by the screen's max column count, plus 1.
clc ; Clear the carry flag.
adc scr_col ; Add the cursor's column number to get the screen index.
+ rts ; End of update_ptr.
+
+
+update_pos:
+ ldb #1 ; Set the F pseudo register to one, to fix some bugs.
+ stb f ;
+ jsr update_ptr ; Update the screen buffer index.
tay ; Place the index into the Y register.
tba ; Reset A.
lda #$1B ; Print an escape character
@@ -1071,6 +960,7 @@ update_pos:
jsr getcol ; Start printing the column number to the screen.
lda #'H' ; Print 'H'
sta scr ; to the screen.
+ ;inc step ;
rts ; End of update_pos.
getrow:
@@ -1206,6 +1096,7 @@ rdrw_ln:
sta f ;
rts ;
+
set_ptr:
cpb #1 ; Are we setting the second pointer?
beq @ptr2 ; Yes, so start setting it.
@@ -1224,12 +1115,3 @@ set_ptr:
sta.q ptr3 ; Set the third pointer.
@end:
rts ; End of set_ptr.
-
-; Entry point for SuBAsm.
-parser:
-
-.org $FFC0
-.qword reset
-a
-d
-
diff --git a/programs/sub-suite/subsuite.s b/programs/sub-suite/subsuite.s
new file mode 100644
index 0000000..36ac541
--- /dev/null
+++ b/programs/sub-suite/subsuite.s
@@ -0,0 +1,22 @@
+.org 0
+
+; Include Declarations.
+.include "declare.s"
+
+; Include SuBEditor.
+.include "subeditor.s"
+; Include SuBAsm.
+.include "subasm.s"
+; Include Lexer.
+.include "lexer.s"
+; Include Utility subroutines.
+.include "utils.s"
+; Include libc routines.
+.include "libc.s"
+
+.org $FFC0
+.qword reset
+a
+;l a
+;q
+d
diff --git a/programs/sub-suite/utils.s b/programs/sub-suite/utils.s
index a66f036..046164a 100644
--- a/programs/sub-suite/utils.s
+++ b/programs/sub-suite/utils.s
@@ -1,22 +1,5 @@
; Utility subroutines for SuBAsm.
-.org util_data
-; Hex character table.
-hex_char:
- .byte "0123456789ABCDEF"
-
-; Compare, and return table for pre-tokens.
-ptok_tab:
- .byte ".@:=+-><(),xy\"\'#;$%"
-; Compare, and return table for isdelm.
-dtab:
- .byte "\n,\"\' "
-; Compare, and return table for isdelm2.
-dtab2:
- .byte "),.+<>-=;\n"
-
-.org utils
-
print_hi:
and #0 ; Reset A.
sta idx3 ; Clear the string index.
@@ -139,48 +122,6 @@ print_hex:
rts ; End of print_hex.
-strtoull:
- phy.w ; Preserve Y.
- sta f ; Save the base.
- and #0 ; Reset A.
- tay ; Reset Y.
- sta.q valbuf ; Reset the value buffer.
-@loop:
- lda (ptr3), y ; Get a character from the string.
- pha ; Preserve the character.
- jsr isdigit ; Is this character, a digit?
- pla ; Get the character back.
- bne @digit ; Yes, so extract the value from it.
- jsr tolower ; No, so convert the character to lowercase.
- pha ; Preserve the character.
- jsr islower ; Is this an alphabetical character?
- pla ; Get the character back.
- beq @end ; No, so we're done.
-@alpha:
- sec ; Yes, so prepare for a non borrowing subtract.
- sbc #'a'-10 ; Get the numeric value from this digit.
- bra @chkbase ; Check if the value matches the base.
-@digit:
- sec ; Prepare for a non borrowing subtract.
- sbc #'0' ; Get the numeric value from this digit.
-@chkbase:
- cmp f ; Does the value match the base?
- bcs @end ; No, so we're done.
-@addval:
- tab ; Save the digit value.
- lda.q valbuf ; Get the value from the value buffer.
- mul f ; Multiply the value by the base.
- clc ; Prepare for a non carrying add.
- aab ; Add the digit value to the total value.
- sta.q valbuf ; Place the value in the value buffer.
- iny ; Increment the string index.
- bra @loop ; Keep looping.
-@end:
- ply.w ; Get Y back.
- ldb #0 ; Reset B.
- rts ; End of strtoull.
-
-
charcpy:
ldx idx3 ; Get the string index.
sta strbuf, x ; Save it in the string buffer.
@@ -188,164 +129,46 @@ charcpy:
rts ; End of charcpy.
-strlen:
- ldb #1 ; Set the second pointer
- jsr set_ptr ; to the passed pointer.
- deb ; Reset B.
- tba ; Reset A.
- tax ; Reset X.
- phy.w ; Preserve Y.
- txy ; Reset Y.
-@loop:
- lda (ptr2), y ; Are we at the end of the string?
- beq @end ; Yes, so we're done.
- iny ; No, so increment the index.
- bra @loop ; Keep looping.
-@end:
- tyx ; Return the length in X.
- ply.w ; Get the preserved value back.
- rts ; End of strlen.
-
-
-strcmp:
- ldb #1 ; Set the second pointer
- jsr set_ptr ; to the passed pointer.
- deb ; Reset B.
- tba ; Reset A.
- phy.w ; Preserve Y.
- tay ; Reset Y.
-@loop:
- ldb #0 ; Set the islong flag to false.
- lda (ptr), y ; Are we at the end of the first string?
- beq cmpr ; Yes, so check if we're too short, or too long.
- ldb #1 ; No, so set the islong flag to true.
- cmp (ptr2), y ; Is the character of both strings, the same?
- bne cmpr ; No, so check if we're too short, or too long.
- iny ; Yes, so increment the index.
- bra @loop ; Keep looping.
-
-strcasecmp:
- ldb #1 ; Set the second pointer
- jsr set_ptr ; to the passed pointer.
- deb ; Reset B.
- tba ; Reset A.
- phy.w ; Preserve Y.
- tay ; Reset Y.
-@loop:
- ldb #0 ; Set the islong flag to false.
- lda (ptr), y ; Are we at the end of the first string?
- beq cmpr ; Yes, so check if we're too short, or too long.
- ldb #1 ; No, so set the islong flag to true.
- jsr tolower ; Convert the character of string 1 to lowercase.
- phb ; Preserve the islong flag.
- pha ; Preserve the converted character.
- lda (ptr2), y ; Get the character of the second string.
- jsr tolower ; Convert the character of string 2 to lowercase.
- tab ; Place it in B.
- pla ; Get the character of string 1 back.
- cab ; Is the character of both strings, the same?
- plb ; Get the islong flag back.
- bne cmpr ; No, so check if we're too short, or too long.
- iny ; Yes, so increment the index.
- bra @loop ; Keep looping.
-
-cmpr:
- lda (ptr2), y ; Are we at the end of the second string?
- beq @islong ; Yes, so check the islong flag.
-@isshort:
- lda (ptr), y ; No, but are we at the end of the first string?
- beq @short ; Yes, so return -1.
-@islong:
- cpb #1 ; Is the islong flag true?
- bne @equ ; No, so return 0.
-@long:
- lda #1 ; Yes, so return 1.
- bra @end ; We are done.
-@equ:
- lda #0 ; Return 0.
- bra @end ; We are done.
-@short:
- lda #$FF ; Return -1.
-@end:
- ply.w ; Get the preserved value back.
- rts ; End of strcmp.
-
-
-isdigit:
- sec ; Prepare for a non carrying subtraction.
- sbc #'0' ; Subtract $30 from the passed character.
- and #$FF ; Make sure that we have only one byte.
- cmp #10 ; Is the subtracted value, less than 10?
- bcs @false ; No, so return false.
-@true:
- lda #1 ; Yes, so return true.
- bra @end ; We are done.
-@false:
- lda #0 ; Return false.
-@end:
- rts ; End of isdigit.
-
-isxdigit:
- pha ; Preserve the character.
- jsr isdigit ; Is this character, a decimal digit?
- pla ; Get the character back.
- bne @true ; Yes, so return true.
-@alpha:
- sec ; No, so prepare for a non carrying subtract.
- ora #$20 ; Convert it to lowercase.
- sbc #'a' ; Subtract $61 from the character.
- and #$FF ; Make sure that we have only one byte.
- cmp #6 ; Is the subtracted value, less than 6?
- bcs @false ; No, so return false.
-@true:
- lda #1 ; Yes, so return true.
- bra @end ; We are done.
-@false:
- lda #0 ; Return false.
-@end:
- rts ; End of isxdigit.
-
-
-isupper:
- sec ; Prepare for a non carrying subtraction.
- sbc #'A' ; Subtract $41 from the passed character.
- bra isletter ; Check if it's less than 26.
-islower:
- sec ; Prepare for a non carrying subtraction.
- sbc #'a' ; Subtract $61 from the passed character.
-isletter:
- and #$FF ; Make sure that we have only one byte.
- cmp #26 ; Is the subtracted value, less than 26?
- bcs @false ; No, so return false.
-@true:
- lda #1 ; Yes, so return true.
- bra @end ; We are done.
-@false:
- lda #0 ; Return false.
-@end:
- rts ; End of isletter.
-
-
-tolower:
- pha ; Preserve the character.
- jsr isupper ; Is this character, an uppercase character?
- pla ; Get the character back.
- beq @end ; No, so we're done.
-@lower:
- ora #$20 ; Yes, so convert it to lowercase.
-@end:
- rts ; End of tolower.
-
-
-toupper:
- pha ; Preserve the character.
- jsr islower ; Is this character, a lowercase character?
- pla ; Get the character back.
- beq @end ; No, so we're done.
-@upper:
- and #$5F ; Yes, so convert it to uppercase.
-@end:
- rts ; End of toupper.
+strcmpg:
+ ldb.w #strcmp ; Get the address of strcmp.
+ phb.q ; Use it for an indirect call.
+ ldb.q ptr ; Get the first pointer.
+ bra gargs ; Jump to the argument handler.
+strcaseg:
+ ldb.w #strccmp ; Get the address of strcasecmp.
+ phb.q ; Use it for an indirect call.
+ ldb.q ptr ; Get the first pointer.
+ bra gargs ; Jump to the argument handler.
+gargs:
+ phb.q ; Use the pointer in B as the first arg.
+ pha.q ; Use the value in A as the second arg.
+ and #0 ; reset a.
+ tab ; reset b.
+ jsr (sp+17) ; call the pushed routine.
+ tab ; Preserve the return value.
+ pla.q ; Get the second arg back.
+ pla.q ; Get the first arg back.
+ pla.q ; Get the pushed routine back.
+ tba ; Get the return value back.
+ rts ; End of gargs.
+
+
+strtoullg:
+ ldb.q ptr3 ; Get the third pointer.
+ phb.q ; Push the first arg.
+ pha ; Push the second arg.
+ and #0 ; Reset A.
+ tab ; Reset B.
+ jsr strtoull ; Call strtoull.
+ tab ; Preserve the return value.
+ pla ; Get the second arg back.
+ pla.q ; Get the first arg back.
+ tba ; Get the return value back.
+ pha.q ; Preserve the return value.
+ and #0 ; Reset A.
+ tab ; Reset B.
+ pla.q ; Get the return value back.
+ rts ; End of strtoullg.
isdelm2:
diff --git a/sux.c b/sux.c
index ae99a8b..f6d01e7 100644
--- a/sux.c
+++ b/sux.c
@@ -145,6 +145,11 @@ void *run(void *args) {
#endif
if (optype[opcode] != IMPL) {
address.u64 = get_addr(cpu, &tmpaddr, opcode, prefix, thread);
+
+ if (address.u64 > mem_size-1) {
+ addr[STEP_ADDR] = 1;
+ step = 1;
+ }
setreg_sw(value.u8, 0, addr, address.u64, prefix, 0, RS);
if (optype[opcode] == REL) {
switch ((prefix >> 4) & 3) {
@@ -531,10 +536,26 @@ void *run(void *args) {
return NULL;
}
+void init_scr() {
+ if (!scr) {
+ scr = initscr();
+ }
+ nodelay(stdscr, 0);
+ crmode();
+ noecho();
+ nl();
+ curs_set(1);
+ scrollok(scr, 1);
+ start_color();
+ use_default_colors();
+ init_pair(1, COLOR_WHITE, -1);
+ attron(COLOR_PAIR(1) | A_BOLD);
+}
+
int main(int argc, char **argv) {
struct suxthr thr[THREADS];
char *tmp = malloc(2048);
- addr = malloc(0x04000000);
+ addr = malloc(mem_size);
#if bench
inss = 0;
#endif
@@ -546,7 +567,7 @@ int main(int argc, char **argv) {
}
} else {
#if debug
- subdbg = !strcmp(argv[1], "programs/sub-suite/subeditor.s");
+ subdbg = !strcmp(argv[1], "programs/sub-suite/subsuite.s");
#endif
if (asmmon(argv[1]) == 2) {
return 0;
@@ -555,20 +576,8 @@ int main(int argc, char **argv) {
sprintf(tmp, "\033[2J\033[H");
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
fflush(stdout);
- if(!scr) {
- scr = initscr();
- }
- nodelay(stdscr, 0);
- crmode();
- noecho();
- nl();
- curs_set(1);
+ init_scr();
werase(scr);
- scrollok(scr, 1);
- start_color();
- use_default_colors();
- init_pair(1, COLOR_WHITE, -1);
- attron(COLOR_PAIR(1) | A_BOLD);
wmove(scr, 0, 0);
wrefresh(scr);
pthread_t therads[THREADS];
@@ -628,7 +637,38 @@ int main(int argc, char **argv) {
#if keypoll
pthread_mutex_lock(&mutex);
#endif
- c = wgetch(scr);
+ if (step) {
+ keypad(scr, 1);
+ c = wgetch(scr);
+ if (c != 19 && c != 18 && c != 0x11 && !isalnum(c)) {
+ /*WINDOW *w;
+ int maxcol = getmaxx(scr)/2;
+ int maxrow = getmaxy(scr)/2;*/
+ switch (c) {
+ case KEY_F(1):
+ /*w = newwin(maxrow, maxcol, maxrow, maxcol);
+ emumon(w);
+ delwin(w);*/
+ endwin();
+ puts("Starting asmmon()");
+ asmmon("stdin");
+ puts("Reinitializing screen.");
+ init_scr();
+ wrefresh(scr);
+ break;
+ }
+ #if debug && !bench
+ wmove(scr, getmaxy(scr)-1, 0);
+ wclrtoeol(scr);
+ wprintw(scr, "c: %i", c);
+ wmove(scr, y, x);
+ #endif
+ c = 0;
+ }
+ keypad(scr, 0);
+ } else {
+ c = wgetch(scr);
+ }
if (c == 19) {
if (kbd_rdy) {
c = wgetch(scr);
@@ -643,6 +683,7 @@ int main(int argc, char **argv) {
case ERR:
addr[CTRL_ADDR] = 0;
break;
+ case '\0': break;
default:
if (kbd_rdy && c < 0x100) {
addr[RX_ADDR] = (uint8_t)c;
diff --git a/sux.h b/sux.h
index 9ac0ffc..4ff992e 100644
--- a/sux.h
+++ b/sux.h
@@ -22,6 +22,8 @@ extern WINDOW *scr;
extern uint8_t subdbg;
#endif
+static const uint64_t mem_size = 0x04000000; /* Size of address space. */
+
extern uint8_t step;
extern uint8_t esc;
diff --git a/test/popcnt.s b/test/popcnt.s
new file mode 100644
index 0000000..7682653
--- /dev/null
+++ b/test/popcnt.s
@@ -0,0 +1,44 @@
+; Calculate population count/hamming weight.
+
+.org $1000
+
+popcnt:
+ ldb #0 ; Reset bit count.
+ pha.q ; Create a temporary variable.
+ cmp #0 ; Set the status flags.
+@loop:
+ beq @end ; There are no more one bits left, so we're done.
+ dec.q sp+1 ; Decrement the temp variable.
+ dec.q sp+1 ; Decrement the temp variable.
+ inb ; Increment the bit count.
+ and.q sp+1 ; AND value with value-1.
+ sta.q sp+1 ; Place it back in the temp variable.
+ bra @loop ; Keep looping.
+@end:
+ pla.q ; Pull/Pop the temp variable off the stack.
+ tba ; Return the bit count.
+ rts ; End of popcnt.
+
+
+reset:
+ cps ; Boilerplate reset code.
+ ldx.w #$FFFF ;
+ txs ;
+ and #0 ; Reset A.
+ tab ; Reset B.
+ tax ; Reset X.
+ tay ; Reset Y.
+main:
+ pha.q ; Save A.
+ jsr popcnt ; Get population count.
+ tay ; Save it in Y.
+ pla.q ; Get A back.
+ inc ; Increment A by one.
+ bra main ; Keep looping.
+
+
+.org $FFC0
+.qword reset
+
+a
+d
diff --git a/test/popcnt2.s b/test/popcnt2.s
new file mode 100644
index 0000000..aaa4743
--- /dev/null
+++ b/test/popcnt2.s
@@ -0,0 +1,41 @@
+; Register only version of popcnt.
+
+.org $1000
+
+popcnt:
+ ldy #0 ; Reset bit count.
+ cmp #0 ; Set the status flags.
+@loop:
+ beq @end ; There are no more one bits left, so we're done.
+ tab ; Place the value in the B register.
+ deb ; Decrement the temp value by one.
+ iny ; Increment the bit count.
+ aba ; AND value with value-1.
+ bra @loop ; Keep looping.
+@end:
+ tya ; Return the bit count.
+ rts ; End of popcnt.
+
+
+reset:
+ cps ; Boilerplate reset code.
+ ldx.w #$FFFF ;
+ txs ;
+ and #0 ; Reset A.
+ tab ; Reset B.
+ tax ; Reset X.
+ tay ; Reset Y.
+main:
+ pha.q ; Save A.
+ jsr popcnt ; Get population count.
+ tay ; Save it in Y.
+ pla.q ; Get A back.
+ inc ; Increment A by one.
+ bra main ; Keep looping.
+
+
+.org $FFC0
+.qword reset
+
+a
+d
diff --git a/test/stack-frame.s b/test/stack-frame.s
index 6e64b86..0f631b9 100644
--- a/test/stack-frame.s
+++ b/test/stack-frame.s
@@ -1,6 +1,10 @@
; Testing stack frames.
; Written by mr b0nk 500 <b0nk@b0nk.xyz>
+.org $0
+var:
+ .byte 0
+
.org $8000
reset:
cps ;
@@ -10,16 +14,18 @@ reset:
tay ;
tax ;
tab ;
+ sta.q var ;
start:
inc ;
pha ;
- ldb sp, $1 ;
+ ldb sp+1 ;
pla ;
- sta $0 ;
+ sta var ;
+ ldy #var ;
phy.q ;
- ldb (sp, $8) ;
+ ldb (sp+1) ;
ply.q ;
- ldb (sp, -$8) ;
+ ldb (sp-7) ;
bra start ;
.org $FFC0