summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--asmmon.c554
-rw-r--r--asmmon.h79
-rw-r--r--assemble.c378
-rw-r--r--disasm.c53
-rw-r--r--lexer.c506
-rw-r--r--programs/subasm-2.s323
-rw-r--r--programs/subasm.s1019
-rw-r--r--programs/subeditor.s302
-rw-r--r--sux.c6
-rw-r--r--sux.h8
11 files changed, 1343 insertions, 1887 deletions
diff --git a/Makefile b/Makefile
index ae5be06..406a735 100644
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@ IO_CFLAGS=-DIO=0
endif
-OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o lexer.o
+OBJS = sux.o opcode.o io.o $(DBG_OBJ) asmmon.o assemble.o lexer.o
CFLAGS = $(PCC_CFLAGS) $(DBG_CFLAGS) $(IO_CFLAGS) $(BENCH_CFLAGS) $(CFLAGS_EXTRA)
OBJS2 = subasm.o subeditor.o
diff --git a/asmmon.c b/asmmon.c
index 81e4b28..840deae 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -13,7 +13,8 @@ char lexeme[MAX_TOK];
char *string[MAX_TOK];
char *comment[MAX_TOK];
uint16_t incl[MAX_TOK];
-struct line tokline[MAX_TOK];
+line *lines;
+line *last_line;
struct line tln[MAX_TOK];
struct symbol *symbols[MAX_TOK];
struct fixup *fixups[MAX_TOK];
@@ -109,8 +110,9 @@ char *showbits(uint64_t value, uint8_t bitnum, uint8_t dbg) {
}
-void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) {
- uint16_t i = start;
+void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) {
+ line *s = find_line(start, dbg);
+ line *e = find_line(end, dbg);
uint8_t j = 0;
uint8_t flags = 0;
uint8_t isstr;
@@ -125,31 +127,24 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,
char ch[6];
if (all) {
- end = lineidx;
+ s = lines;
+ e = last_line;
}
- for (; i < end; i++) {
- flags = 0;
- flags |= (l[i].dir != 0x00FF) << 0;
- flags |= (l[i].mne != 0x00FF) << 1;
- flags |= (l[i].rs != 0x00FF) << 2;
- flags |= (l[i].am != 0x00FF) << 3;
- flags |= (l[i].opbase != 0x00FF) << 4;
- flags |= (l[i].sym != 0xFFFF) << 5;
- flags |= (l[i].rs != 0x00FF) << 6;
- flags |= (l[i].am != 0x00FF) << 7;
- iscm = l[i].cm != 0xFF;
- isstr = l[i].str != 0xFFFF;
- iscom = l[i].com != 0xFFFF;
+
+ do {
+ token *t = s->tok;
+ uint8_t am = 0xFF;
+ uint8_t rs = 0xFF;
if (dbg) {
printf("list(): ");
}
if (ln) {
- printf("%u\t", l[i].linenum);
+ printf("%u\t", s->linenum);
} else if (addr) {
- printf("$%"PRIX64":\t", l[i].addr);
+ printf("$%"PRIX64":\t", s->addr);
}
- spaces = l[i].sspace;
- tabs = l[i].stab;
+ spaces = s->sspace;
+ tabs = s->stab;
while (spaces || tabs) {
if (spaces) {
putchar(' ');
@@ -160,136 +155,89 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,
tabs--;
}
}
- if (flags & 0x01) {
- printf(".%s ", dir_t[l[i].dir]);
- if (isstr) {
- printf("\"%s\"", string[l[i].str]);
- }
- }
- if (flags & 0x02) {
- for (; j < 3; j++) {
- mne_lower[j] = tolower(mne[l[i].mne][j]);
- }
- mne_lower[j] = '\0';
- j = 0;
- printf("%s", mne_lower);
- }
- if (flags & 0x04) {
- printf("%s ", rs_t[l[i].rs]);
- } else if (flags & 0x02) {
- printf(" ");
- }
- if (flags & 0x7F) {
- switch (l[i].am) {
- case IMM:
- putchar('#');
+ for (; t && t->id != TOK_COMMENT; t = t->next) {
+ switch (t->id) {
+ case TOK_DIR : printf(".%s ", dir_t[t->type]); break;
+ case TOK_STRING: printf("\"%s\"", t->str) ; break;
+ case TOK_OPCODE:
+ for (; j < 3; j++) {
+ mne_lower[j] = tolower(mne[t->byte][j]);
+ }
+ mne_lower[j] = '\0';
+ j = 0;
+ printf("%s", mne_lower);
+ am = t->type;
+ t = t->next;
+ if (t->id == TOK_RS) {
+ rs = t->type;
+ printf("%s", rs_t[t->type]);
+ }
+ switch (am) {
+ case IMM : putchar('#'); break;
+ case IND :
+ case INDX:
+ case INDY: putchar('('); break;
+ }
break;
- case INDX:
- case INDY:
- case IND:
- putchar('(');
+ case TOK_SYM:
+ case TOK_LABEL:
+ printf("%s", symbols[t->word]->name);
+ if (t->id == TOK_LABEL) {
+ putchar(':');
+ } else if (t == s->tok && t->id == TOK_SYM) {
+ printf(" = ");
+ }
break;
- }
- }
- if (flags & 0x20) {
- printf("%s", symbols[l[i].sym]->name);
- if (l[i].islabel) {
- printf(": ");
- } else if (l[i].issym) {
- printf(" = ");
- }
- }
- if (flags & 0x10) {
- if (flags & 0x04) {
- bitnum = (l[i].rs << 3);
- } else {
- opsize += (l[i].op <= 0x000000FF) + 0;
- opsize += (l[i].op > 0x000000FF) + 1;
- opsize += (l[i].op > 0x0000FFFF) + 2;
- opsize += (l[i].op > 0xFFFFFFFF) + 3;
- if (opsize) {
- bitnum = bitsize[opsize-1];
- }
- }
-
- j = 0;
-
- if (l[i].opbase == BASE_CHAR) {
- switch (l[i].op) {
- default : ch[j++] = l[i].op; break;
- case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break;
- case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break;
- case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break;
- case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break;
- case '\'': ch[j++] = '\\'; ch[j++] = '\''; break;
- case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break;
- }
- }
-
- ch[j] = '\0';
- j = 0;
-
- switch (l[i].opbase) {
- case BASE_HEX: printf("$%"PRIX64, l[i].op); break;
- case BASE_DEC: printf("%"PRIu64, l[i].op); break;
- case BASE_BIN: printf("%%%s", showbits(l[i].op, bitnum, dbg)); break;
- case BASE_CHAR: printf("\'%s\'", ch); break;
- }
- bitnum = 0;
- opsize = 0;
- }
- if (iscm) {
- switch (l[i].cm) {
- case 0:
- putchar('+');
+ case TOK_HEX: printf("$%"PRIX64, t->qword); break;
+ case TOK_DEC: printf( "%"PRIu64, t->qword); break;
+ case TOK_BIN:
+ if (rs != 0xFF) {
+ bitnum = (rs << 3);
+ } else {
+ opsize += (t->qword <= 0x000000FF) + 0;
+ opsize += (t->qword > 0x000000FF) + 1;
+ opsize += (t->qword > 0x0000FFFF) + 2;
+ opsize += (t->qword > 0xFFFFFFFF) + 3;
+ if (opsize) {
+ bitnum = bitsize[opsize-1];
+ }
+ }
+ printf("%%%s", showbits(t->qword, bitnum, dbg));
+ bitnum = 0;
+ opsize = 0;
break;
- case 1:
- putchar ('-');
+ case TOK_CHAR:
+ j = 0;
+ switch (t->byte) {
+ default : ch[j++] = t->byte; break;
+ case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break;
+ case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break;
+ case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break;
+ case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break;
+ case '\'': ch[j++] = '\\'; ch[j++] = '\''; break;
+ case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break;
+ }
+ ch[j] = '\0';
+ j = 0;
+ printf("\'%s\'", ch);
+ break;
+ case TOK_EXPR:
+ switch (t->type) {
+ case EXPR_PLUS : putchar('+'); break;
+ case EXPR_MINUS: putchar('-'); break;
+ }
break;
}
- opsize += (l[i].aop <= 0x000000FF) + 0;
- opsize += (l[i].aop > 0x000000FF) + 1;
- opsize += (l[i].aop > 0x0000FFFF) + 2;
- opsize += (l[i].aop > 0xFFFFFFFF) + 3;
- if (opsize) {
- bitnum = bitsize[opsize-1];
- }
-
- j = 0;
-
- if (l[i].aopbase == BASE_CHAR) {
- switch (l[i].aop) {
- default : ch[j++] = l[i].aop; break;
- case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break;
- case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break;
- case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break;
- case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break;
- case '\'': ch[j++] = '\\'; ch[j++] = '\''; break;
- case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break;
- }
- }
-
- ch[j] = '\0';
- j = 0;
-
- switch (l[i].aopbase) {
- case BASE_HEX : printf("$%"PRIX64, l[i].aop); break;
- case BASE_DEC : printf("%"PRIu64, l[i].aop); break;
- case BASE_BIN : printf("%%%s", showbits(l[i].aop, bitnum, dbg)); break;
- case BASE_CHAR: printf("\'%s\'", ch); break;
- }
- bitnum = 0;
- opsize = 0;
}
- if (flags & 0x7F) {
+ if (am != 0xFF) {
if (fall) {
fall = 0;
}
- switch (l[i].am) {
+ switch (am) {
case INDX:
case ZMX:
printf(", x");
- if (l[i].am == ZMX) {
+ if (am == ZMX) {
break;
}
fall = 1;
@@ -308,8 +256,8 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,
break;
}
}
- spaces = l[i].espace;
- tabs = l[i].etab;
+ spaces = s->espace;
+ tabs = s->etab;
while (spaces || tabs) {
if (spaces) {
putchar(' ');
@@ -320,302 +268,12 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln,
tabs--;
}
}
- if (iscom) {
- printf(";%s", comment[l[i].com]);
+ if (t->id == TOK_COMMENT) {
+ printf(";%s", t->str);
}
puts("");
- }
-}
-
-void assemble(struct line *line, bytecount *bc, uint8_t dbg) {
- bc->progsize = 0;
- bc->datasize = 0;
- uint64_t tmpaddr;
- uint64_t value;
- uint16_t flags = 0;
- uint16_t i = 0;
- uint16_t k = 0;
- uint16_t tmp;
- uint8_t c = 0;
- uint8_t prefix = 0;
- uint8_t opsize = 0;
- uint8_t skip = 0;
-
- uint64_t address;
- uint64_t op;
- uint64_t aop;
- uint16_t symid;
- uint16_t str;
- uint16_t com;
- uint8_t islabel;
- uint8_t opbase;
- uint8_t aopbase;
- uint8_t dir;
- uint8_t am;
- uint8_t cm;
- uint8_t rs;
- uint8_t ins;
-
- for (; i < lineidx; i++) {
- if (dbg) {
- printf("assemble(): i: $%X\n", i);
- }
- address = line[i].addr;
- tmpaddr = address;
- op = line[i].op;
- aop = line[i].aop;
- symid = line[i].sym;
- str = line[i].str;
- com = line[i].com;
- islabel = line[i].islabel;
- opbase = line[i].opbase;
- aopbase = line[i].aopbase;
- dir = line[i].dir;
- am = line[i].am;
- cm = line[i].cm;
- rs = line[i].rs;
- ins = line[i].mne;
- flags = 0;
- flags |= (dir != 0x00FF) << 0x00;
- flags |= (ins != 0x00FF) << 0x01;
- flags |= (rs != 0x00FF) << 0x02;
- flags |= (am != 0x00FF) << 0x03;
- flags |= (opbase != 0x00FF) << 0x04;
- flags |= (aopbase != 0x00FF) << 0x05;
- flags |= (symid != 0xFFFF) << 0x06;
- flags |= (islabel ) << 0x07;
- flags |= (am != 0x00FF) << 0x08;
- flags |= (cm != 0x00FF) << 0x09;
- flags |= (str != 0xFFFF) << 0x0A;
- if (dbg) {
- printf("assemble(): ");
- putchar('%');
- printf("%u", str != 0xFFFF);
- printf("%u", cm != 0x00FF);
- printf("%u", am != 0x00FF);
- printf("%u", islabel );
- printf("%u", symid != 0xFFFF);
- printf("%u", aopbase != 0x00FF);
- printf("%u", opbase != 0x00FF);
- printf("%u", am != 0x00FF);
- printf("%u", rs != 0x00FF);
- printf("%u", ins != 0x00FF);
- printf("%u", dir != 0x00FF);
- putchar('\n');
-
- printf("assemble(): ");
- printf("flags: $%04X\n", flags);
- }
- if (!flags) {
- if (dbg) {
- printf("assemble(): ");
- puts("This line only contains a comment, so skip it.");
- }
- continue;
- }
- opsize = 0;
- skip = 0;
- if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) {
- value = symbols[symid]->val;
- } else {
- value = op;
- }
- if (flags & 0x220) {
- switch (cm) {
- case 0: value += aop; break;
- case 1: value -= aop; break;
- }
- }
- if (dbg) {
- printf("assemble(): value: $%"PRIX64"\n", value);
- }
- switch (dir) {
- case DIR_ORG:
- tmpaddr = value;
- if (dbg) {
- printf("assemble(): ");
- printf("The Program Counter's origin is now at, $%"PRIX64".\n", value);
- }
- skip = 1;
- break;
- case DIR_BYTE:
- if (flags & 0x400) {
- for (k = 0; string[str][k] != '\0'; k++) {
- switch (string[str][k]) {
- case '\\':
- switch (string[str][k+1]) {
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case '0': c = '\0'; break;
- }
- k++;
- break;
- default:
- c = string[str][k];
- break;
- }
- bc->datasize++;
- addr[tmpaddr++] = c;
- }
- addr[tmpaddr] = '\0';
- if (dbg) {
- printf("assemble(): ");
- printf("Placed string \"%s\"", string[str]);
- printf(", at address(es) $%"PRIX64"-$%"PRIX64".\n", address, tmpaddr);
- }
- } else {
- bc->datasize++;
- addr[tmpaddr++] = value & 0xFF;
- }
- break;
- case DIR_QWORD:
- addr[tmpaddr+7] = value >> 0x38;
- addr[tmpaddr+6] = value >> 0x30;
- addr[tmpaddr+5] = value >> 0x28;
- addr[tmpaddr+4] = value >> 0x20;
- tmp+=4;
- bc->datasize+=4;
- case DIR_DWORD:
- addr[tmpaddr+3] = value >> 0x18;
- addr[tmpaddr+2] = value >> 0x10;
- tmp+=2;
- bc->datasize+=2;
- case DIR_WORD:
- addr[tmpaddr+1] = value >> 0x08;
- addr[tmpaddr ] = value & 0xFF;
- tmp+=2;
- bc->datasize+=2;
- break;
- }
- tmpaddr += tmp;
- tmp = 0;
- if (skip | (flags & 0x80) | (flags == 0x108)) {
- if (dbg) {
- printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address);
- printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr);
- }
- continue;
- }
- if (flags & 0x04) {
- prefix = (rs << 4) | 3;
- } else {
- rs = 0;
- }
- if (flags & 0x102) {
- if (ins == 80) {
- if (flags & 0x10) {
- am = IMM;
- prefix |= 0x13;
- } else {
- am = IMPL;
- addr[tmpaddr++] = opcodes[ins][IMM];
- bc->progsize++;
- if (dbg) {
- printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]);
- printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[IMM]);
- printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][IMM]);
- }
- }
- }
- opsize = 0;
- if (am != IMM && am != IMPL) {
- opsize = (value <= 0x00000000000000FF) ? 1 : opsize;
- opsize = (value > 0x00000000000000FF) ? 2 : opsize;
- opsize = (value > 0x000000000000FFFF) ? 3 : opsize;
- opsize = (value > 0x0000000000FFFFFF) ? 4 : opsize;
- opsize = (value > 0x00000000FFFFFFFF) ? 5 : opsize;
- opsize = (value > 0x000000FFFFFFFFFF) ? 6 : opsize;
- opsize = (value > 0x0000FFFFFFFFFFFF) ? 7 : opsize;
- opsize = (value > 0x00FFFFFFFFFFFFFF) ? 8 : opsize;
- if (opsize) {
- opsize--;
- prefix |= amp[opsize];
- }
- }
- if (prefix) {
- if (dbg) {
- printf("assemble(): ");
- puts("Prefix byte detected.");
- }
- addr[tmpaddr++] = prefix;
- bc->progsize++;
- if (dbg) {
- uint8_t addrsize = (prefix & 0x0C) >> 2;
- uint8_t regsize = (prefix & 0x30) >> 4;
-
- printf("assemble(): ");
- printf("The values of the prefix bits are");
- printf(", AM: %u, RS: %u\n", addrsize, regsize);
- }
- prefix = 0;
- }
- if (opcodes[ins][am] != 0xFF) {
- addr[tmpaddr++] = opcodes[ins][am];
- bc->progsize++;
- if (dbg) {
- printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]);
- printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[am]);
- printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][am]);
- }
- switch (am) {
- case IMM:
- switch (rs) {
- case 3:
- addr[tmpaddr+7] = value >> 0x38;
- addr[tmpaddr+6] = value >> 0x30;
- addr[tmpaddr+5] = value >> 0x28;
- addr[tmpaddr+4] = value >> 0x20;
- tmp+=4;
- case 2:
- addr[tmpaddr+3] = value >> 0x18;
- addr[tmpaddr+2] = value >> 0x10;
- tmp+=2;
- case 1:
- addr[tmpaddr+1] = value >> 0x08;
- tmp+=1;
- case 0:
- addr[tmpaddr ] = value & 0xFF;
- tmp+=1;
- }
- break;
- case ABS:
- case ZM:
- case ZMX:
- case ZMY:
- case IND:
- case INDX:
- case INDY:
- switch (opsize) {
- case 7: addr[tmpaddr+7] = value >> 0x38; tmp++;
- case 6: addr[tmpaddr+6] = value >> 0x30; tmp++;
- case 5: addr[tmpaddr+5] = value >> 0x28; tmp++;
- case 4: addr[tmpaddr+4] = value >> 0x20; tmp++;
- case 3: addr[tmpaddr+3] = value >> 0x18; tmp++;
- case 2: addr[tmpaddr+2] = value >> 0x10; tmp++;
- case 1: addr[tmpaddr+1] = value >> 0x08; tmp++;
- case 0: addr[tmpaddr ] = value & 0xFF; tmp++;
- }
- break;
- }
- tmpaddr += tmp;
- bc->progsize += tmp;
- tmp = 0;
- }
- }
- if (dbg) {
- printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address);
- printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr);
-
- printf("assemble(): The program size is now at");
- printf(", %"PRIu64" bytes in decimal", bc->progsize);
- printf(", and $%"PRIX64" bytes in hex.\n", bc->progsize);
-
- printf("assemble(): The data size is now at");
- printf(", %"PRIu64" bytes in decimal", bc->datasize);
- printf(", and $%"PRIX64" bytes in hex.\n", bc->datasize);
- }
- }
+ s = s->next;
+ } while (s != e && s);
}
int asmmon(const char *fn) {
@@ -700,6 +358,9 @@ int asmmon(const char *fn) {
if (fp2 != NULL) {
fclose(fp2);
}
+ if (lines) {
+ free_lines();
+ }
return 2;
case 0x02:
viewmem(address);
@@ -727,12 +388,12 @@ int asmmon(const char *fn) {
for (; isspace(tmp[i]); i++);
}
switch (tmp[i]) {
- case '$': base = BASE_HEX; i++; break;
- case '%': base = BASE_BIN; i++; break;
+ case '$': base = 16; i++; break;
+ case '%': base = 2; i++; break;
default:
j = i;
for (; isdigit(tmp[j]); j++, isflag++);
- base = (isflag) ? BASE_DEC : 0xFF;
+ base = (isflag) ? 10 : 0xFF;
isflag = 0;
j = 0;
break;
@@ -741,11 +402,7 @@ int asmmon(const char *fn) {
arg[j] = '\0';
j = 0;
if (base != 0xFF) {
- switch (base) {
- case BASE_HEX: value = strtol(arg, NULL, 16); break;
- case BASE_BIN: value = strtol(arg, NULL, 2); break;
- case BASE_DEC: value = strtol(arg, NULL, 10); break;
- }
+ value = strtol(arg, NULL, base);
base = 0xFF;
(isstart) ? (start = value) : (end = value);
if (isstart) {
@@ -765,15 +422,15 @@ int asmmon(const char *fn) {
}
i++;
}
- list(tokline, start, end, isstart, islinenum, isaddr, isdebug);
+ list(start, end, isstart, islinenum, isaddr, isdebug);
} else {
- list(tokline, 0, 0, 1, 0, 0, 0);
+ list(0, 0, 1, 0, 0, 0);
}
break;
case 0x08:
if (!inc_file) {
printf("Assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program.");
- assemble(tokline, &bc, dbg);
+ assemble(lines, &bc, dbg);
progsize = bc.progsize;
datasize = bc.datasize;
printf("Finished assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program.");
@@ -846,7 +503,7 @@ int asmmon(const char *fn) {
case 0xFF:
break;
default:
- address = lex(lex_line, tokline, address, dbg);
+ address = lex(lex_line, address, dbg);
break;
}
}
@@ -860,5 +517,8 @@ int asmmon(const char *fn) {
if (fp2 != NULL) {
fclose(fp2);
}
+ if (lines) {
+ free_lines();
+ }
return 0;
}
diff --git a/asmmon.h b/asmmon.h
index 019be00..52315a9 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -28,9 +28,40 @@ struct line {
uint64_t addr;
};
+struct tok {
+ struct tok *next; /* Pointer to the next token. */
+ uint8_t id; /* Token ID. */
+ uint8_t type; /* Token type ID. */
+
+ /* Token value(s). */
+ union {
+ char *str;
+ uint8_t byte ;
+ uint16_t word ;
+ uint32_t dword;
+ uint64_t qword;
+ };
+};
+
+struct ln {
+ struct ln *next; /* Pointer to the next line. */
+ struct tok *tok; /* The token(s) for this line. */
+ uint16_t count; /* Total tokens for this line. */
+ uint16_t linenum; /* Line number. */
+ uint64_t addr; /* The address of this line. */
+ uint8_t stab; /* Number of starting tabs. */
+ uint8_t sspace; /* Number of starting spaces. */
+ uint8_t etab; /* Number of ending tabs. */
+ uint8_t espace; /* Number of ending spaces. */
+};
+
+typedef struct tok token;
+typedef struct ln line;
+
+
struct fixup {
struct symbol *s;
- uint16_t ln;
+ token *t;
uint64_t adr;
};
@@ -45,6 +76,10 @@ extern char lexeme[];
extern char *string[];
extern char *comment[];
extern uint16_t incl[];
+extern line *lines;
+extern line *last_line;
+extern token *tokens;
+extern token *last_tok;
extern struct line tokline[];
extern struct line tln[];
extern struct symbol *symbols[];
@@ -52,7 +87,7 @@ extern struct fixup *fixups[];
extern uint8_t lex_type;
-enum {
+enum dir {
DIR_ORG,
DIR_BYTE,
DIR_WORD,
@@ -61,12 +96,12 @@ enum {
DIR_INCLUDE
};
-enum {
+enum token {
TOK_DIR,
TOK_LABEL,
TOK_SYM,
- TOK_PLUS,
- TOK_MINUS,
+ TOK_EXPR,
+ TOK_COMMA,
TOK_STRING,
TOK_CHAR,
TOK_IMM,
@@ -79,11 +114,12 @@ enum {
TOK_INCLUDE
};
-enum {
- BASE_HEX,
- BASE_DEC,
- BASE_BIN,
- BASE_CHAR
+enum expr {
+ EXPR_PLUS,
+ EXPR_MINUS,
+ EXPR_LOW,
+ EXPR_HIGH,
+ EXPR_NONE
};
static const uint8_t opcodes[OPNUM][9] = {
@@ -200,8 +236,8 @@ static const char *lex_tok[15] = {
[0x0] = "TOK_DIR",
[0x1] = "TOK_LABEL",
[0x2] = "TOK_SYM",
- [0x3] = "TOK_PLUS",
- [0x4] = "TOK_MINUS",
+ [0x3] = "TOK_EXPR",
+ [0x4] = "TOK_COMMA",
[0x5] = "TOK_STRING",
[0x6] = "TOK_CHAR",
[0x7] = "TOK_IMM",
@@ -437,10 +473,12 @@ extern uint16_t stridx;
extern uint16_t comidx;
extern uint16_t inc_file; /* Number of included files. */
-typedef struct {
+struct bc {
uint64_t progsize;
uint64_t datasize;
-} bytecount;
+};
+
+typedef struct bc bytecount;
extern uint8_t defined;
extern uint8_t isfixup;
@@ -450,7 +488,14 @@ extern uint16_t mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t us
extern uint64_t use_symbol(const char *name, uint16_t id, uint64_t val, uint8_t useid, uint8_t dbg);
extern uint8_t set_symval(const char *name, uint16_t id, uint64_t val, uint8_t useid, uint8_t dbg);
extern char *get_symname(uint16_t id, uint8_t dbg);
-extern uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg);
+extern uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg);
extern uint16_t get_comment(const char *cmnt, uint8_t dbg);
-extern uint16_t reslv_fixups(struct line *l, uint8_t dbg);
-extern uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg);
+extern uint16_t reslv_fixups(uint8_t dbg);
+extern line *find_line(uint16_t ln, uint8_t dbg);
+extern uint64_t lex(char *str, uint64_t address, uint8_t dbg);
+
+extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg);
+extern token *make_token(uint8_t id, uint8_t type, uint64_t value, char *str);
+extern void assemble(line *ln, bytecount *bc, uint8_t dbg);
+extern void free_tokens(token *t, uint16_t count);
+extern void free_lines();
diff --git a/assemble.c b/assemble.c
new file mode 100644
index 0000000..869e6b8
--- /dev/null
+++ b/assemble.c
@@ -0,0 +1,378 @@
+#include "asmmon.h"
+
+token *tok_global;
+
+uint8_t isexpr(uint8_t type, uint8_t dbg) {
+ switch (type) {
+ case EXPR_PLUS:
+ case EXPR_MINUS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+uint8_t get_rs(token *t, uint8_t inst, uint8_t dbg) {
+ if (t->id == TOK_RS) {
+ return t->type;
+ } else {
+ return 0xFF;
+ }
+}
+
+uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
+ uint64_t value = 0;
+ uint64_t tmp_val = 0;
+ uint16_t expr_count = 0;
+ uint8_t type = EXPR_NONE;
+ do {
+ if (expr_count) {
+ type = t->type;
+ t = t->next;
+ }
+ switch (t->id) {
+ case TOK_HEX:
+ case TOK_DEC:
+ case TOK_BIN:
+ case TOK_CHAR:
+ tmp_val = t->qword;
+ t = t->next;
+ break;
+ case TOK_SYM:
+ case TOK_LABEL:
+ tmp_val = use_symbol("", t->word, addr, 1, dbg);
+ t = t->next;
+ break;
+ }
+ switch (type) {
+ case EXPR_PLUS : value += tmp_val; break;
+ case EXPR_MINUS: value -= tmp_val; break;
+ case EXPR_LOW :
+ switch (size) {
+ default:
+ case 2 : value &= 0xFFFFFFFF; break;
+ case 1 : value &= 0x0000FFFF; break;
+ case 0 : value &= 0x000000FF; break;
+ }
+ break;
+ case EXPR_HIGH :
+ switch (size) {
+ default:
+ case 2 : value >>= 0x20; break;
+ case 1 : value >>= 0x10; break;
+ case 0 : value >>= 0x08; break;
+ }
+ break;
+ case EXPR_NONE : value = tmp_val; break;
+ }
+ expr_count++;
+ if (!t) {
+ break;
+ }
+ } while (t->id == TOK_EXPR && isexpr(t->type, dbg));
+ return value;
+}
+
+uint8_t get_dirsize(uint8_t type, uint8_t dbg) {
+ uint8_t size = 0;
+ switch (type) {
+ case DIR_QWORD: size = 3; break;
+ case DIR_DWORD: size = 2; break;
+ case DIR_WORD : size = 1; break;
+ case DIR_BYTE : size = 0; break;
+ }
+ return size;
+}
+
+uint64_t handle_dir(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+ union reg val;
+ uint8_t c = 0;
+ uint8_t tmp = 0;
+ uint8_t type = t->type;
+ uint64_t tmpaddr = address;
+ t = t->next;
+ for (; t; t = t->next) {
+ tmp = 0;
+ switch (t->id) {
+ case TOK_HEX:
+ case TOK_DEC:
+ case TOK_BIN:
+ case TOK_CHAR:
+ case TOK_SYM:
+ case TOK_LABEL:
+ val.u64 = get_val(t, tmpaddr, get_dirsize(type, dbg), dbg);
+ switch (type) {
+ case DIR_QWORD:
+ if (isasm) {
+ addr[tmpaddr+7] = val.u8[7];
+ addr[tmpaddr+6] = val.u8[6];
+ addr[tmpaddr+5] = val.u8[5];
+ addr[tmpaddr+4] = val.u8[4];
+ }
+ tmp += 4;
+ case DIR_DWORD:
+ if (isasm) {
+ addr[tmpaddr+3] = val.u8[3];
+ addr[tmpaddr+2] = val.u8[2];
+ }
+ tmp += 2;
+ case DIR_WORD:
+ if (isasm) {
+ addr[tmpaddr+1] = val.u8[1];
+ }
+ tmp++;
+ case DIR_BYTE:
+ if (isasm) {
+ addr[tmpaddr ] = val.u8[0];
+ }
+ tmp++;
+ tmpaddr += tmp;
+ bc->datasize += tmp;
+ break;
+ }
+ break;
+ case TOK_STRING:
+ if (type == DIR_BYTE) {
+ for (uint16_t k = 0; t->str[k] != '\0'; k++) {
+ switch (t->str[k]) {
+ case '\\':
+ switch (t->str[k+1]) {
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case '0': c = '\0'; break;
+ }
+ k++;
+ break;
+ default: c = t->str[k]; break;
+ }
+ if (isasm) {
+ addr[tmpaddr] = c;
+ }
+ tmpaddr++;
+ bc->datasize++;
+ }
+ if (isasm) {
+ addr[tmpaddr] = '\0';
+ }
+ tmpaddr++;
+ bc->datasize++;
+ }
+ break;
+ }
+ }
+ return tmpaddr;
+}
+
+uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+ union reg val;
+ uint8_t opsize;
+ uint8_t inst;
+ uint8_t opcode;
+ uint8_t type;
+ uint8_t tmp = 0;
+ uint8_t prefix = 0;
+ uint8_t rs = 0;
+
+ for (; t; t = t->next) {
+ if (t->id == TOK_OPCODE) {
+ inst = t->byte;
+ type = t->type;
+ } else {
+ break;
+ }
+ tmp = 0;
+ opsize = 0;
+ opcode = 0;
+ if (t->next) {
+ rs = get_rs(t->next, inst, dbg);
+ t = (rs != 0xFF) ? t->next : t;
+ }
+ prefix = (rs != 0xFF) ? ((rs << 4) | 3) : 0;
+ if (opcodes[inst][IMPL] != 0xFF && (!t->next || t->next->id == TOK_COMMENT)) {
+ type = IMPL;
+ } else {
+ if (t->next) {
+ t = t->next;
+ }
+ val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
+ }
+ opcode = opcodes[inst][type];
+ if (inst == 80) {
+ if (type == IMM) {
+ rs = 1;
+ } else {
+ type = IMPL;
+ opcode = opcodes[inst][IMM];
+ }
+ }
+ switch (type) {
+ case IMPL:
+ if (isasm) {
+ addr[address] = opcode;
+ }
+ address++;
+ bc->progsize++;
+ break;
+ case IMM:
+ if (prefix) {
+ if (isasm) {
+ addr[address] = prefix;
+ }
+ address++;
+ }
+ if (isasm) {
+ addr[address] = opcode;
+ }
+ address++;
+ bc->progsize++;
+ switch (rs) {
+ case 3:
+ if (isasm) {
+ addr[address+7] = val.u8[7];
+ addr[address+6] = val.u8[6];
+ addr[address+5] = val.u8[5];
+ addr[address+4] = val.u8[4];
+ }
+ tmp += 4;
+ case 2:
+ if (isasm) {
+ addr[address+3] = val.u8[3];
+ addr[address+2] = val.u8[2];
+ }
+ tmp += 2;
+ case 1 :
+ if (isasm) {
+ addr[address+1] = val.u8[1];
+ }
+ tmp++;
+ default:
+ if (isasm) {
+ addr[address ] = val.u8[0];
+ }
+ tmp++;
+ }
+ break;
+ default:
+ opsize = (val.u64 <= 0x00000000000000FF) ? 1 : opsize;
+ opsize = (val.u64 > 0x00000000000000FF) ? 2 : opsize;
+ opsize = (val.u64 > 0x000000000000FFFF) ? 3 : opsize;
+ opsize = (val.u64 > 0x0000000000FFFFFF) ? 4 : opsize;
+ opsize = (val.u64 > 0x00000000FFFFFFFF) ? 5 : opsize;
+ opsize = (val.u64 > 0x000000FFFFFFFFFF) ? 6 : opsize;
+ opsize = (val.u64 > 0x0000FFFFFFFFFFFF) ? 7 : opsize;
+ opsize = (val.u64 > 0x00FFFFFFFFFFFFFF) ? 8 : opsize;
+ if (type == 0xFF) {
+ switch (opsize-1) {
+ case 0: case 2: case 5: case 3: type = ZM ; break;
+ case 1: case 4: case 6: case 7: type = ABS; break;
+ }
+ }
+ if (opsize) {
+ if (type != ABS) {
+ switch (opsize) {
+ case 2: opsize = 3; break;
+ case 5: opsize = 6; break;
+ }
+ }
+ prefix |= amp[opsize-1];
+ }
+ if (prefix) {
+ if (isasm) {
+ addr[address] = prefix;
+ }
+ address++;
+ bc->progsize++;
+ }
+ opcode = opcodes[inst][type];
+ if (isasm) {
+ addr[address] = opcode;
+ }
+ address++;
+ bc->progsize++;
+ if (isasm) {
+ switch (opsize-1) {
+ case 7: addr[address+7] = val.u8[7];
+ case 6: addr[address+6] = val.u8[6];
+ case 5: addr[address+5] = val.u8[5];
+ case 4: addr[address+4] = val.u8[4];
+ case 3: addr[address+3] = val.u8[3];
+ case 2: addr[address+2] = val.u8[2];
+ case 1: addr[address+1] = val.u8[1];
+ case 0: addr[address ] = val.u8[0];
+ }
+ }
+ tmp = opsize;
+ break;
+ }
+ address += tmp;
+ bc->progsize += tmp;
+ }
+ return address;
+}
+
+uint64_t parse_tokens(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+ for (; t; t = t->next) {
+ 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_BYTE:
+ case DIR_WORD:
+ case DIR_DWORD:
+ case DIR_QWORD: address = handle_dir(t, bc, isasm, address, dbg); break;
+ }
+ break;
+ case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;
+ case TOK_COMMENT: break;
+ }
+ }
+ return address;
+}
+
+token *make_token(uint8_t id, uint8_t type, uint64_t value, char *str) {
+ token *new_tok = malloc(sizeof(token));
+ (last_tok) ? (last_tok->next = new_tok) : (tokens = new_tok);
+ new_tok->id = id;
+ new_tok->type = type;
+ if (!str[0]) {
+ new_tok->qword = value;
+ } else {
+ new_tok->str = str;
+ }
+ new_tok->next = NULL;
+ last_tok = new_tok;
+ return new_tok;
+}
+
+void assemble(line *ln, bytecount *bc, uint8_t dbg) {
+ uint64_t address = 0;
+ for (; ln; ln = ln->next) {
+ address = parse_tokens(ln->tok, bc, 1, address, dbg);
+ }
+}
+
+void free_tokens(token *t, uint16_t count) {
+ token *tok;
+ while (t != NULL) {
+ if (count--) {
+ break;
+ }
+ tok = t;
+ free(tok);
+ t = t->next;
+ }
+}
+
+void free_lines() {
+ line *l = lines;
+ line *ln;
+ for (; l != NULL; l = l->next) {
+ if (l < ln) {
+ break;
+ }
+ free_tokens(l->tok, l->count);
+ ln = l;
+ free(ln);
+ }
+}
diff --git a/disasm.c b/disasm.c
index c055d07..0a4b6ef 100644
--- a/disasm.c
+++ b/disasm.c
@@ -69,30 +69,45 @@ void disasm(struct sux *cpu, uint64_t *operands, uint8_t lines, uint8_t opcode,
if (subdbg) {
uint8_t ln = 33;
uint16_t line_idx = 0;
- uint16_t tmpad = 0x2000;
+ uint32_t tmpad = 0x31000;
int row, col;
uint8_t iscursor = 0;
- uint64_t ptr;
- uint8_t adr;
+ union reg ptr;
+ uint32_t adr;
wmove(scr, 30, 0);
- adr = 0x1F;
- ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 |
- (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38;
- wprintw(scr, "ptr1: $%04"PRIX64, ptr);
- adr = 0x27;
- ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 |
- (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38;
- wprintw(scr, ", ptr2: $%04"PRIX64, ptr);
- adr = 0x2F;
- ptr = (uint64_t)addr[adr+0] << 0x00 | (uint64_t)addr[adr+1] << 0x08 | (uint64_t)addr[adr+2] << 0x10 | (uint64_t)addr[adr+3] << 0x18 |
- (uint64_t)addr[adr+4] << 0x20 | (uint64_t)addr[adr+5] << 0x28 | (uint64_t)addr[adr+6] << 0x30 | (uint64_t)addr[adr+7] << 0x38;
- wprintw(scr, ", ptr3: $%04"PRIX64, ptr);
+ 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);
if (address == CTRL_ADDR || addr[STEP_ADDR]) {
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[0x1C], addr[0x1D]);
- mvwprintw(scr, 32, 0, "bitabl: %02X%02X%02X%02X%02X%02X%02X%02X"
- "%02X%02X%02X%02X%02X%02X%02X%02X"
- , addr[0x1000], addr[0x1001], addr[0x1002], addr[0x1003], addr[0x1004], addr[0x1005], addr[0x1006], addr[0x1007]
- , addr[0x1008], addr[0x1009], addr[0x100A], addr[0x100B], addr[0x100C], addr[0x100D], addr[0x100E], addr[0x100F]);
+ adr = 0x300000;
+ wmove(scr, 32, 0);
+ wprintw(scr, "bitabl: ");
+ for (uint8_t i = 0; i < 16; i++) {
+ wprintw(scr, "%02X", addr[adr+i]);
+ }
mvwprintw(scr, ln++, 0, "buffer:\r");
wmove(scr, ln++, 0);
for (uint8_t i = 0; i < 10; i++) {
diff --git a/lexer.c b/lexer.c
index 77dff16..ea83801 100644
--- a/lexer.c
+++ b/lexer.c
@@ -2,6 +2,8 @@
uint8_t lex_type;
uint16_t sym_count = 0;
+token *tokens = NULL;
+token *last_tok = NULL;
void init_symbol() {
uint16_t i = 0;
@@ -41,10 +43,8 @@ uint16_t mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t useid, ui
printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s\n", def, val, name);
printf("mksymbol(): i: $%X, id: $%04X\n", i, symbols[i]->id);
}
- return symbols[i]->id;
- } else {
- return symbols[i]->id;
}
+ return symbols[i]->id;
}
}
symbols[i] = malloc(sizeof(**symbols) + strlen(name));
@@ -123,8 +123,8 @@ char *get_symname(uint16_t id, uint8_t dbg) {
}
uint16_t fixup_cnt = 0;
-uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) {
- uint16_t i = mksymbol(name, 0, 0, 0, ln, dbg);
+uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg) {
+ uint16_t i = mksymbol(name, 0, 0, 0, 0, dbg);
if (dbg) {
printf("get_symid(): Symbol ID: $%X, i: $%X.\n", symbols[i]->id, i);
}
@@ -136,7 +136,7 @@ uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) {
}
fixups[fixup_cnt] = malloc(sizeof(**fixups));
fixups[fixup_cnt]->adr = val;
- fixups[fixup_cnt]->ln = ln;
+ fixups[fixup_cnt]->t = t;
fixups[fixup_cnt]->s = symbols[i];
fixup_cnt++;
return 0xFFFF;
@@ -196,14 +196,14 @@ uint16_t get_string(const char *str, uint8_t dbg) {
return i;
}
-uint16_t reslv_fixups(struct line *l, uint8_t dbg) {
+uint16_t reslv_fixups(uint8_t dbg) {
uint16_t i = 0, j = 0;
for (; fixups[j]; j++) {
if (fixups[j]->s->def) {
if (dbg) {
- printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%X.\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val);
+ printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%"PRIX64".\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val);
}
- l[fixups[j]->ln].sym = fixups[j]->s->id;
+ fixups[j]->t->word = fixups[j]->s->id;
} else {
if (dbg) {
printf("reslv_fixups(): oof, undefined reference to '%s', at $%016"PRIX64".\n", fixups[j]->s->name, fixups[j]->adr);
@@ -215,205 +215,40 @@ uint16_t reslv_fixups(struct line *l, uint8_t dbg) {
}
-uint64_t update_addr(struct line *ln, uint64_t address, uint8_t fixup, uint16_t l, uint8_t dbg) {
- uint64_t value = 0;
+line *find_line(uint16_t ln, uint8_t dbg) {
uint16_t i = 0;
- uint16_t j = 0;
- uint16_t flags = 0;
- uint8_t opsize = 0;
-
- uint16_t symid = ln[l].sym;
- uint16_t str = ln[l].str;
- uint16_t com = ln[l].com;
- uint8_t islabel = ln[l].islabel;
- uint8_t issym = ln[l].issym;
- uint8_t opbase = ln[l].opbase;
- uint8_t aopbase = ln[l].aopbase;
- uint8_t dir = ln[l].dir;
- uint8_t am = ln[l].am;
- uint8_t cm = ln[l].cm;
- uint8_t rs = ln[l].rs;
- uint8_t mne = ln[l].mne;
-
- flags |= (dir != 0x00FF) << 0x00;
- flags |= (mne != 0x00FF) << 0x01;
- flags |= (rs != 0x00FF) << 0x02;
- flags |= (am != 0x00FF) << 0x03;
- flags |= (opbase != 0x00FF) << 0x04;
- flags |= (aopbase != 0x00FF) << 0x05;
- flags |= (symid != 0xFFFF) << 0x06;
- flags |= (fixup > 0x0000) << 0x06;
- flags |= (islabel ) << 0x07;
- flags |= (issym ) << 0x07;
- flags |= (am != 0x00FF) << 0x08;
- flags |= (cm != 0x00FF) << 0x09;
- flags |= (str != 0xFFFF) << 0x0A;
-
- if (dbg) {
- printf("update_addr(): ");
- printf("flags: $%04X\n", flags);
- }
- if (!flags || flags == 0x40) {
- if (dbg) {
- printf("update_addr(): ");
- puts("This line only contains a comment, so don't update the address.");
- }
- return address;
- }
- if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) {
- if (fixup && symid == 0xFFFF && (opcodes[mne][IMPL] == 0xFF)) {
- value = address;
- } else if (opcodes[mne][IMPL] != 0xFF && symid == 0xFFFF) {
- value = 0;
- } else {
- value = use_symbol("", symid, address, 1, dbg);
- }
- } else {
- value = ln[l].op;
- }
- if (flags & 0x220) {
- switch (cm) {
- case 0: value += ln[l].aop; break;
- case 1: value -= ln[l].aop; break;
+ line *l = lines;
+ for (; l && l->linenum != ln; l = l->next);
+ /*if (dbg) {
+ if (l->linenum == ln) {
+ printf("find_line(): Found line number %u, at line index %X.\n", ln, i);
}
- }
- if (dbg) {
- printf("update_addr(): value: $%"PRIX64"\n", value);
- }
- switch (dir) {
- case DIR_ORG:
- address = value;
+ printf("find_line(): linenum: %u, i: %X\n", l->linenum, i);
+ }*/
+ if (l != NULL) {
+ if (l->linenum == ln) {
if (dbg) {
- printf("update_addr(): ");
- printf("Set the Program Counter's Origin to $%"PRIX64".\n", address);
- }
- break;
- case DIR_BYTE:
- if (flags & 0x400) {
- for (; string[str][i] != '\0'; i++, j++, address++) {
- i += string[str][i] == '\\';
- }
- j++;
- address++;
- if (dbg) {
- printf("update_addr(): ");
- printf("Increment Program Counter by $%04X", j);
- puts(", to make room for the string.");
- }
- } else {
- address += 1;
+ printf("find_line(): Found line number %u.\n", ln);
}
- break;
- case DIR_WORD: address += 2; break;
- case DIR_DWORD: address += 4; break;
- case DIR_QWORD: address += 8; break;
- }
- if (flags & 0x01) {
- if (dbg) {
- printf("update_addr(): ");
- puts("This line contains a directive, so skip everything else.");
- }
- return address;
- }
- if ((flags & 0x15B) == 0x02 || (opcodes[mne][IMPL] != 0xFF && am == 0xFF && opbase == 0xFF && symid == 0xFFFF)) {
- ln[l].am = IMPL;
- am = IMPL;
- if (dbg) {
- printf("update_addr(): ");
- puts("Addressing Mode has been set to Implied.");
- }
- }
- if (am == IMPL) {
- opsize = 0;
- } else if (am == IMM) {
- switch (rs) {
- case 3: address += 8; break;
- case 2: address += 4; break;
- case 1: address += 2; break;
- default: address += 1; break;
+ return l;
}
+ } else {
if (dbg) {
- if (!(flags & 0x04)) {
- rs = 0;
- }
- printf("update_addr(): ");
- printf("Increment Program Counter by $%02X", 1 << rs);
- puts(", to make room for the operand.");
- }
- } else if ((flags & 0x158) && (!(flags & 0x80))) {
- opsize = 0;
- opsize = (value <= 0x00000000000000FF) ? 1 : opsize;
- opsize = (value > 0x00000000000000FF) ? 2 : opsize;
- opsize = (value > 0x000000000000FFFF) ? 3 : opsize;
- opsize = (value > 0x0000000000FFFFFF) ? 4 : opsize;
- opsize = (value > 0x00000000FFFFFFFF) ? 5 : opsize;
- opsize = (value > 0x000000FFFFFFFFFF) ? 6 : opsize;
- opsize = (value > 0x0000FFFFFFFFFFFF) ? 7 : opsize;
- opsize = (value > 0x00FFFFFFFFFFFFFF) ? 8 : opsize;
- if (opsize) {
- switch (opsize-1) {
- case 0:
- case 2:
- case 5:
- case 3:
- if (!(flags & 0x100)) {
- am = ZM;
- ln[l].am = am;
- if (dbg) {
- printf("update_addr(): ");
- puts("Addressing Mode has been set to Zero Matrix.");
- }
- }
- break;
- case 1:
- case 4:
- case 6:
- case 7:
- if (!(flags & 0x100)) {
- am = ABS;
- ln[l].am = am;
- if (dbg) {
- printf("update_addr(): ");
- puts("Addressing Mode has been set to Absolute.");
- }
- }
- break;
- }
- address += opsize;
- if (dbg) {
- printf("update_addr(): ");
- printf("Increment Program Counter by $%02X", opsize);
- puts(", to make room for the address.");
- }
- }
- }
- if (dbg) {
- printf("update_addr(): ");
- printf("Address: $%"PRIX64"\n", address);
- }
- return address;
-}
-
-uint16_t find_line(struct line *l, uint16_t ln, uint8_t dbg) {
- uint16_t i = 0;
- for (; i < lineidx && l[i].linenum != ln; i++);
- if (dbg) {
- if (l[i].linenum == ln) {
- printf("find_line(): Found line number %u, at line index %X.\n", ln, i);
+ printf("find_line(): oof, could not find line number %u.\n", ln);
}
- printf("find_line(): linenum: %u, i: %X\n", l[i].linenum, i);
+ return NULL;
}
- return i;
+ return l;
}
-uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
+uint64_t lex(char *str, uint64_t address, uint8_t dbg) {
char sym[0x100];
uint16_t i = 0;
uint16_t j = 0;
uint16_t comid = 0;
uint16_t strid = 0;
uint16_t symid = 0;
- uint16_t line = 0;
+ uint64_t value = 0;
lex_type = 0xFF;
uint8_t k = 0;
@@ -436,6 +271,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
uint8_t isstart = 1;
uint8_t fall = 0;
uint8_t done = 0;
+ line *l = NULL;
+ token *st = NULL;
+ token *t = NULL;
+ token *lt = NULL;
while (isdigit(str[i]) && !isspace(str[i])) {
lnum[j++] = str[i++];
@@ -448,25 +287,18 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
} else {
ln = linenum;
}
- line = find_line(l, ln, dbg);
- if (line != lineidx) {
- address = l[line].addr;
+ l = find_line(ln, dbg);
+ if (l) {
+ address = l->addr;
+ } else {
+ l = malloc(sizeof(line));
+ (last_line) ? (last_line->next = l) : (lines = l);
+ l->tok = NULL;
+ l->next = NULL;
+ l->count = 0;
+ last_line = l;
+
}
- l[line].dir = 0xFF;
- l[line].mne = 0xFF;
- l[line].rs = 0xFF;
- l[line].am = 0xFF;
- l[line].cm = 0xFF;
- l[line].opbase = 0xFF;
- l[line].aopbase = 0xFF;
- l[line].islabel = 0;
- l[line].issym = 0;
- l[line].str = 0xFFFF;
- l[line].com = 0xFFFF;
- l[line].sym = 0xFFFF;
- l[line].op = 0;
- l[line].aop = 0;
- l[line].addr = address;
while (str[i] != '\0' && str[i] != '\n') {
base = 0;
space = 0;
@@ -481,10 +313,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
printf("lex(): tab: %u, space: %u\n", tab, space);
}
if (isstart) {
- l[line].stab = tab;
- l[line].sspace = space;
+ l->stab = tab;
+ l->sspace = space;
if (dbg) {
- printf("lex(): starting tabs: %u, starting spaces: %u\n", l[line].stab, l[line].sspace);
+ printf("lex(): starting tabs: %u, starting spaces: %u\n", l->stab, l->sspace);
}
}
if (isspace(str[i])) {
@@ -506,7 +338,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
break;
}
}
- l[line].dir = k;
+ l->count++;
+ t = make_token(lex_type, k, 0, "");
} else {
lex_type = TOK_RS;
switch (tolower(lexeme[j-1])) {
@@ -523,8 +356,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
rs = 3;
break;
}
- address++;
- l[line].rs = rs;
+ l->count++;
+ t = make_token(lex_type, rs, 0, "");
isop = 0;
}
break;
@@ -535,59 +368,45 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
}
strid = get_string(lexeme, dbg);
if (strid == 0xFFFF) {
- if (line != lineidx && l[line].str != 0xFFFF) {
- strid = l[line].str;
- } else {
- strid = stridx;
- }
+ strid = stridx;
string[strid] = malloc(j+1);
memcpy(string[strid], lexeme, j+1);
- l[line].str = strid;
- stridx += (line == lineidx);
+ stridx++;
} else {
- l[line].str = strid;
}
if (dbg) {
printf("lex(): str[0x%04X]: %s\n", strid, string[strid]);
}
- if (l[line].dir == DIR_INCLUDE) {
- l[line].incl = strid;
+ if (lt->id == TOK_DIR && lt->type == DIR_INCLUDE) {
incl[inc_file++] = strid;
}
lex_type = TOK_STRING;
+ l->count++;
+ t = make_token(lex_type, 0, 0, string[strid]);
break;
- if (str[i] == '$') {
- case '$': base = 16;
- } else if (str[i] == '%') {
- case '%': base = 2;
- }
+ case '$':
+ case '%':
+ value = 0;
+ base = (str[i] == '$') ? 16 : 2;
i++;
- while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n')) {
+ while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n' && str[i] != ',')) {
lexeme[j++] = str[i++];
}
lexeme[j] = '\0';
- switch (lex_type) {
- default:
- if (l[line].cm != 0xFF) {
- case TOK_PLUS :
- case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, base);
- l[line].aopbase = (base & 16) ? BASE_HEX : BASE_BIN;
- } else {
- case TOK_SYM: l[line].op = strtoull(lexeme, NULL, base);
- l[line].opbase = (base & 16) ? BASE_HEX : BASE_BIN;
- }
- if (lex_type == TOK_SYM) {
- mksymbol(sym, l[line].op, 1, 0, 0, dbg);
- l[line].sym = get_symid(sym, address, line, dbg);
- isfixup += (l[line].sym == 0xFFFF);
- if (dbg) {
- printf("lex(): isfixup: %u\n", isfixup);
- }
- }
- break;
+ lex_type = (base == 16) ? TOK_HEX : TOK_BIN;
+ value = strtoull(lexeme, NULL, base);
+ if (lt->id == TOK_SYM) {
+ mksymbol(sym, value, 1, 0, 0, dbg);
+ if (lt) {
+ lt->word = get_symid(sym, address, lt, dbg);
+ }
+ isfixup += (lt->word == 0xFFFF);
+ if (dbg) {
+ printf("lex(): isfixup: %u\n", isfixup);
+ }
}
-
- lex_type = (base & 16) ? TOK_HEX : TOK_BIN;
+ l->count++;
+ t = make_token(lex_type, 0, value, "");
break;
case '\'':
i++;
@@ -611,37 +430,35 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
break;
default: ch = lexeme[k];
}
- switch (lex_type) {
- case TOK_PLUS :
- case TOK_MINUS:
- l[line].aop = ch;
- l[line].aopbase = BASE_CHAR;
- break;
- default:
- l[line].op = ch;
- l[line].opbase = BASE_CHAR;
- break;
- }
lex_type = TOK_CHAR;
+ l->count++;
+ t = make_token(lex_type, 0, ch, "");
break;
- case '(':
- if (str[i] == '#' || str[i] == '(') {
- if (str[i] == '#') {
- case '#': lex_type = TOK_IMM;
- }
- l[line].am = (str[i] == '#') ? IMM : IND;
- } else {
+ case '(': l->tok->type = IND; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break;
+ case '#': l->tok->type = IMM; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break;
case '+':
- case '-': l[line].cm = (str[i] == '-');
- lex_type = (str[i] == '-') ? TOK_MINUS : TOK_PLUS;
+ case '-':
+ case '>':
+ case '<':
+ lex_type = TOK_EXPR;
+ switch (str[i]) {
+ case '+': value = EXPR_PLUS ; break;
+ case '-': value = EXPR_MINUS; break;
+ case '>': value = EXPR_LOW ; break;
+ case '<': value = EXPR_HIGH ; break;
}
+ l->count++;
+ t = make_token(lex_type, value, 0, "");
+ memset(lexeme, 0, strlen(lexeme)+1);
+ lexeme[j++] = str[i];
+ break;
+ case '=':
+ i++;
+ lex_type = TOK_SYM;
+ l->count++;
+ t = make_token(lex_type, 0, 0, "");
memset(lexeme, 0, strlen(lexeme)+1);
lexeme[j] = str[i];
- if (str[i] == '=') {
- case '=': i++;
- l[line].issym = 1;
- lex_type = TOK_SYM;
- }
break;
case ')':
i++;
@@ -650,9 +467,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
while (isspace(str[i])) {
lexeme[j++] = str[i++];
}
- if (l[line].am == IND && tolower(str[i]) == 'y') {
+ if (l->tok->type == IND && tolower(str[i]) == 'y') {
lexeme[j++] = 'y';
- l[line].am = INDY;
+ l->tok->type = INDY;
}
lexeme[j] = '\0';
} else {
@@ -666,20 +483,21 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
while (isspace(str[i])) {
lexeme[j++] = str[i++];
}
- if (l[line].am == IND && tolower(str[i]) == 'x') {
- l[line].am = INDX;
+ if (l->tok->type == IND && tolower(str[i]) == 'x') {
+ l->tok->type = INDX;
lexeme[j++] = 'x';
i++;
} else {
switch (tolower(str[i])) {
case 'x':
- l[line].am = ZMX;
+ l->tok->type = ZMX;
lexeme[j++] = 'x';
break;
case 'y':
- l[line].am = ZMY;
+ l->tok->type = ZMY;
lexeme[j++] = 'y';
break;
+ default: lex_type = TOK_COMMA; i--; break;
}
}
lexeme[j] = '\0';
@@ -689,13 +507,14 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
lexeme[j] = ':';
lexeme[j+1] = '\0';
lex_type = TOK_LABEL;
- l[line].islabel = 1;
+ l->count++;
+ t = make_token(lex_type, 0, 0, "");
mksymbol(sym, address, 1, 0, 0, dbg);
if (isfixup) {
- isfixup = reslv_fixups(l, dbg);
+ isfixup = reslv_fixups(dbg);
}
- l[line].sym = get_symid(sym, address, line, dbg);
- isfixup += (l[line].sym == 0xFFFF);
+ t->word = get_symid(sym, address, t, dbg);
+ isfixup += (t->word == 0xFFFF);
if (dbg) {
printf("lex(): isfixup: %u\n", isfixup);
}
@@ -708,22 +527,23 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
lexeme[j] = '\0';
comid = get_comment(lexeme, dbg);
if (comid == 0xFFFF) {
- if (line != lineidx && l[line].com != 0xFFFF) {
+ /*if (line != lineidx && l[line].com != 0xFFFF) {
comid = l[line].com;
} else {
comid = comidx;
- }
+ }*/
+ comid = comidx;
comment[comid] = malloc(j+1);
memcpy(comment[comid], lexeme, j+1);
- l[line].com = comid;
- comidx += (line == lineidx);
+ comidx++;
} else {
- l[line].com = comid;
}
if (dbg) {
printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]);
}
lex_type = TOK_COMMENT;
+ l->count++;
+ t = make_token(lex_type, 0, 0, comment[comid]);
break;
default:
if (isalnum(str[i]) || str[i] == '_') {
@@ -733,6 +553,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
case ',':
case '.':
case '+':
+ case '<':
+ case '>':
case '-':
case ':':
case '=':
@@ -759,8 +581,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
if (!strcasecmp(lexeme, mne[k])) {
lex_type = TOK_OPCODE;
isop = 1;
- l[line].mne = k;
- address++;
+ l->count++;
+ t = make_token(lex_type, 0xFF, k, "");
break;
}
}
@@ -774,6 +596,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
case '.':
case '+':
case '-':
+ case '<':
+ case '>':
case ':':
case ';':
case '=':
@@ -800,29 +624,25 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
}
if (lexeme[k] == '\0') {
if (num) {
- switch (lex_type) {
- default:
- if (l[line].cm != 0xFF) {
- case TOK_PLUS :
- case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, 10);
- l[line].aopbase = BASE_DEC;
- } else {
- case TOK_SYM: l[line].op = strtoull(lexeme, NULL, 10);
- l[line].opbase = BASE_DEC;
- }
- if (lex_type == TOK_SYM) {
- mksymbol(sym, l[line].op, 1, 0, 0, dbg);
- l[line].sym = get_symid(sym, address, line, dbg);
- isfixup += (l[line].sym == 0xFFFF);
- if (dbg) {
- printf("lex(): isfixup: %u\n", isfixup);
- }
- }
- break;
+ value = 0;
+ value = strtoull(lexeme, NULL, 10);
+ if (lt->id == TOK_SYM) {
+ mksymbol(sym, value, 1, 0, 0, dbg);
+ if (lt) {
+ lt->word = get_symid(sym, address, lt, dbg);
+ }
+ isfixup += (lt->word == 0xFFFF);
+ if (dbg) {
+ printf("lex(): isfixup: %u\n", isfixup);
+ }
}
lex_type = TOK_DEC;
+ l->count++;
+ t = make_token(lex_type, 0, value, "");
} else if (isch && lex_type != TOK_HEX && lex_type != TOK_BIN) {
lex_type = TOK_SYM;
+ l->count++;
+ t = make_token(lex_type, 0, 0, "");
memcpy(sym, lexeme, j+1);
uint8_t spaces = 0;
for (; isspace(str[i+spaces]); spaces++);
@@ -830,8 +650,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
printf("lex(): spaces: %u\n", spaces);
}
if (str[i+spaces] != ':' && str[i+spaces] != '=') {
- l[line].sym = get_symid(lexeme, address, line, dbg);
- isfixup += l[line].sym == 0xFFFF;
+ t->word = get_symid(lexeme, address, t, dbg);
+ isfixup += (t->word == 0xFFFF);
if (dbg) {
printf("lex(): isfixup: %u\n", isfixup);
}
@@ -842,6 +662,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
}
break;
}
+ if (!l->tok && t) {
+ l->tok = tokens;
+ }
if (dbg) {
printf("lex(): lexeme: %s, lex_type: %s\n", lexeme, (lex_type != 0xFF) ? lex_tok[lex_type] : "TOK_NONE");
}
@@ -850,7 +673,7 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
if (lex_type == TOK_OPCODE && !isop) {
j = 0;
} else {
- if (lex_type == TOK_PLUS || lex_type == TOK_MINUS) {
+ if (lex_type == TOK_EXPR) {
i++;
} else {
switch (str[i]) {
@@ -859,6 +682,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
case '.':
case '+':
case '-':
+ case '<':
+ case '>':
case ':':
case ';':
case '=':
@@ -875,10 +700,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
}
if (lex_type == TOK_COMMENT) {
if (!isstart) {
- l[line].etab = tab;
- l[line].espace = space;
+ l->etab = tab;
+ l->espace = space;
if (dbg) {
- printf("lex(): ending tabs: %u, ending spaces: %u\n", l[line].etab, l[line].espace);
+ printf("lex(): ending tabs: %u, ending spaces: %u\n", l->etab, l->espace);
}
}
}
@@ -886,48 +711,29 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) {
memset(lexeme, 0, strlen(lexeme)+1);
lex_type = 0xFF;
}
+ if (t) {
+ lt = t;
+ t = t->next;
+ }
}
if (i) {
- address = update_addr(l, address, isfixup, line, dbg);
+ l->tok = tokens;
+ tokens = NULL;
+ last_tok = NULL;
+ bytecount dummy;
+ address = parse_tokens(l->tok, &dummy, 0, address, dbg);
if (dbg) {
printf("lex(): Next address: $%"PRIX64"\n", address);
- printf(
- "lex(): "
- "address: $%"PRIX64
- ", dir: %u"
- ", mne: $%02X"
- ", rs: %u"
- ", am: %u"
- ", cm: %u"
- ", opbase: %u"
- ", com: $%04X"
- ", sym: $%04X"
- ", op: $%016"PRIX64
- ", aop: $%016"PRIX64
- ", ln: %u\n"
- , l[line].addr
- , l[line].dir
- , l[line].mne
- , l[line].rs
- , l[line].am
- , l[line].cm
- , l[line].opbase
- , l[line].com
- , l[line].sym
- , l[line].op
- , l[line].aop
- , line);
}
if (ln > linenum || islinenum) {
- l[line].linenum = ln;
+ l->linenum = ln;
if (ln > linenum) {
linenum+=(10+(ln & 10));
}
} else if (!islinenum) {
- l[line].linenum = linenum;
+ l->linenum = linenum;
linenum += 10;
}
- lineidx += (line == lineidx);
}
return address;
}
diff --git a/programs/subasm-2.s b/programs/subasm-2.s
deleted file mode 100644
index f10dac8..0000000
--- a/programs/subasm-2.s
+++ /dev/null
@@ -1,323 +0,0 @@
-; SuBAsm
-; The Sux Bootstrapped Assembler.
-;
-; by mr b0nk 500 <b0nk@b0nk.xyz>
-
-.org incl
-; String Constants.
-prg_name:
- .byte "SuBAsm"
-ver_txt:
- .byte ", version "
-ver_num:
- .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.
-mne:
- .byte "AAB"
- .byte "ABA"
- .byte "ADC"
- .byte "AND"
- .byte "ARB"
- .byte "ASR"
- .byte "BCC"
- .byte "BCS"
- .byte "BEQ"
- .byte "BNE"
- .byte "BNG"
- .byte "BPO"
- .byte "BRK"
- .byte "BVC"
- .byte "BVS"
- .byte "CAB"
- .byte "CLC"
- .byte "CLI"
- .byte "CLV"
- .byte "CMP"
- .byte "CPB"
- .byte "CPS"
- .byte "CPX"
- .byte "CPY"
- .byte "DAB"
- .byte "DEB"
- .byte "DEC"
- .byte "DEX"
- .byte "DEY"
- .byte "DIV"
- .byte "ENT"
- .byte "INB"
- .byte "INC"
- .byte "INX"
- .byte "INY"
- .byte "JMP"
- .byte "JSL"
- .byte "JSR"
- .byte "LDA"
- .byte "LDB"
- .byte "LDX"
- .byte "LDY"
- .byte "LLB"
- .byte "LRB"
- .byte "LSL"
- .byte "LSR"
- .byte "MAB"
- .byte "MUL"
- .byte "NOP"
- .byte "OAB"
- .byte "ORA"
- .byte "PHA"
- .byte "PHB"
- .byte "PHP"
- .byte "PHX"
- .byte "PHY"
- .byte "PLA"
- .byte "PLB"
- .byte "PLP"
- .byte "PLX"
- .byte "PLY"
- .byte "RLB"
- .byte "ROL"
- .byte "ROR"
- .byte "RRB"
- .byte "RTI"
- .byte "RTL"
- .byte "RTS"
- .byte "SAB"
- .byte "SBC"
- .byte "SEC"
- .byte "SEI"
- .byte "STA"
- .byte "STB"
- .byte "STT"
- .byte "STX"
- .byte "STY"
- .byte "TAB"
- .byte "TAX"
- .byte "TAY"
- .byte "TBA"
- .byte "TSX"
- .byte "TXA"
- .byte "TXS"
- .byte "TXY"
- .byte "TYA"
- .byte "TYX"
- .byte "WAI"
- .byte "XAB"
- .byte "XOR"
-
-; Command subroutine table.
-cmd_srt:
- .word viewmem
- .word list
- .word asm
- .word help
- .word inst
- .word run
- .word set
-
-; Hex character table.
-hex_char:
- .byte "0123456789ABCDEF"
-
-
-.org $4400
-; Subroutine pointer.
-sub_ptr:
- .word 0
-
-; Indecies.
-idx0:
- .word 0
-idx1:
- .word 0
-idx2:
- .word 0
-
-; Program Counter.
-prg_cnt:
- .qword 0
-
-; Start of program code.
-.org parser
-subasm:
- ldb #0 ; Set the first pointer
- lda.w #cmd_buf ; to the command buffer.
- jsl set_ptr ;
- tba ; Reset A.
- tax ; Reset X.
- jsl chk_shcmd ; Did we get a shortend command?
- bne parse_cmd ; Yes, so skip everything else.
- jsl chk_cmd ; No, but did we get a full command?
- bne parse_cmd ; Yes, so skip everything else.
- jsl lexer ; No, so start lexing this line.
-subasm_end:
- rtl ; End of subasm.
-
-parse_cmd:
- inb ; Set the second pointer
- lda.w #cmd_srt ; to the command subroutine table.
- jsl set_ptr ;
- deb ; Reset B.
- tba ; Reset A.
- lda f ; Get the command ID.
- cmp #8 ; Is the command ID greater than the command count?
- bcs subasm_end ; Yes, so we're done.
- lsl #1 ; No, so multiply the command ID by two.
- phy #2 ; 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 #2 ; Get back the screen buffer position.
- ldb #2 ; Save it in the third pointer.
- jsl set_ptr ;
- ldb #0 ; Reset B.
- jsr (ptr3) ; Run the command's subroutine.
- jmp subasm_end ; We are done.
-
-chk_shcmd:
- inb ; Set the second pointer
- lda.w #sh_cmds ; to the shortend command table.
- jsl set_ptr ;
- deb ; Reset B.
- tba ; Reset A.
- phy #2 ; Preserve the screen buffer position.
- txy ; Set our index to zero.
- lda (ptr), y ; Is there nothing in the command buffer?
- beq shcmd_fail ; Yes, so return that we failed.
- cmp #' ' ; No, but is this character, a space?
- beq shcmd_fail ; Yes, so return that we failed.
-shcmd_loop:
- ldb (ptr2), y ; Are we at the end of the table?
- beq shcmd_fail ; Yes, so return that we failed.
- cab ; No, so did the character match?
- beq shcmd_fnd ; Yes, so check if there are any arguments.
- iny ; No, so check the next command.
- jmp shcmd_loop ; Keep looping.
-shcmd_fnd:
- sty f ; Save the command ID.
- ldy #1 ; Check the next character in the command buffer.
- lda (ptr), y ; Is this the end of the buffer?
- beq shcmd_true ; Yes, so return that we succeded.
- cmp #' ' ; No, but is this a space?
- beq shcmd_true ; Yes, so return that we succeded.
- jmp shcmd_fail ; No, so return that we failed.
-shcmd_true:
- lda #1 ; Return true.
- jmp shcmd_end ; We are done.
-shcmd_fail:
- tba ; Return false.
- tax ; Reset X.
-shcmd_end:
- ldb #0 ; Reset B.
- ply #2 ; Get back the screen buffer position.
- rtl ; End of chk_shcmd.
-
-print_hex:
- pha #8 ; Preserve the hex value.
- ldb #1 ; Set the second pointer
- lda.w hex_char ; to the start of hex character table.
- jsl set_ptr ;
- ldb #0 ; Reset B.
- pla #8 ; Get the hex value back.
-pnthex_lp:
- pha #8 ; Preserve the hex value.
- and #$F ; Mask the lowest nibble.
- phx #2 ; Preserve the digit count.
- phy #2 ; Preserve the screen buffer position.
- tay ; Get the index for the hex digit.
- lda (ptr2), y ; Get the hex digit.
- ply #2 ; Get back the screen buffer position.
- jsl print_char ; Print the hex digit.
- plx #2 ; Get the digit count back.
- pla #8 ; Get the hex value back.
-pnthex_lp1:
- cpx #1 ; Is the digit count less than one?
- bcc pnthex_lp2 ; Yes, so don't decrement the digit count.
- dex ; No, but was the digit count zero, when decremented?
- beq pnthex_end ; Yes, so we're done.
- jmp pnthex_lp3 ; No, so get the next nibble.
-pnthex_lp2:
- ldb #1 ; Enable auto digit count.
-pnthex_lp3:
- lsr #4 ; No, but is the next nibble, a zero?
- beq pnthex_lp4 ; Yes, so check if auto digit count is enabled.
- jmp pnthex_lp ; No, so print the next digit.
-pnthex_lp4:
- cpb #1 ; Is auto digit count enabled?
- beq pnthex_end ; Yes, so we're done.
- jmp pnthex_lp ; No, so keep printing more digits.
-pnthex_end:
- ldb #0 ; Reset B.
- rtl ; End of print_hex.
-
-print_space:
- lda #' ' ; Set the character to a space.
- phb #1 ; Preserve the spacing count.
- ldb #1 ; Enable replace mode.
- stb b ;
- jsl print_char ; Print the space.
- plb #1 ; Get the spacing count back.
- deb ; Have we printed all of the spacing?
- beq pntsp_end ; Yes, so we're done.
- jmp print_space ; No, so keep printing spaces.
-pntsp_end:
- rtl ; End of print_space.
-
-viewmem:
- pha #8 ; Preserve the address.
- lda #'\n' ; Print a newline.
- jsl print_char ;
- ldb #19 ; Print 19 spaces.
- jsl print_space ;
-vmem_lp:
- pla #8 ; Get the address back.
- nop ;
-vmem_end:
- rts ; End of viewmem.
-
-list:
- nop ;
-list_end:
- rts ; End of list.
-asm:
- nop ;
-asm_end:
- rts ; End of asm.
-help:
- nop ;
-help_end:
- rts ; End of help.
-inst:
- nop ;
-inst_end:
- rts ; End of inst.
-run:
- nop ;
-run_end:
- rts ; End of run.
-set:
- nop ;
-set_end:
- rts ; End of set.
diff --git a/programs/subasm.s b/programs/subasm.s
index 50f2e8d..350e105 100644
--- a/programs/subasm.s
+++ b/programs/subasm.s
@@ -3,576 +3,471 @@
;
; by mr b0nk 500 <b0nk@b0nk.xyz>
-; Variables
-.org $1000
-prg_name:
+MAX_SYM = $800 ; Max symbol size.
+
+.org incl
+; String Constants.
+asm_name:
.byte "SuBAsm"
-ver_txt:
- .byte ", version "
-ver_num:
+asm_ver:
.byte "0.1"
; Directives.
dir:
- .byte "org"
+ .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.
-; Instruction mnemonics.
mne:
- .byte "CPS"
- .byte "ADC"
- .byte "AAB"
- .byte "PHB"
- .byte "PHP"
- .byte "PHA"
- .byte "PHY"
- .byte "TAY"
- .byte "PHX"
- .byte "TAX"
- .byte "TYX"
- .byte "JMP"
- .byte "SBC"
- .byte "SAB"
- .byte "PLB"
- .byte "PLP"
- .byte "PLA"
- .byte "PLY"
- .byte "TYA"
- .byte "PLX"
- .byte "TXA"
- .byte "TXY"
- .byte "JSR"
- .byte "AND"
- .byte "ABA"
- .byte "STT"
- .byte "TAB"
- .byte "TSX"
- .byte "BPO"
- .byte "ORA"
- .byte "OAB"
- .byte "TBA"
- .byte "SEI"
- .byte "TXS"
- .byte "BNG"
- .byte "XOR"
- .byte "XAB"
- .byte "CLI"
- .byte "BCS"
- .byte "LSL"
- .byte "LLB"
- .byte "STB"
- .byte "SEC"
- .byte "STA"
- .byte "STY"
- .byte "STX"
- .byte "BCC"
- .byte "LSR"
- .byte "LRB"
- .byte "LDB"
- .byte "CLC"
- .byte "LDA"
- .byte "LDY"
- .byte "LDX"
- .byte "BEQ"
- .byte "ROL"
- .byte "RLB"
- .byte "SSP"
- .byte "BNE"
- .byte "ROR"
- .byte "RRB"
- .byte "CSP"
- .byte "BVS"
- .byte "MUL"
- .byte "MAB"
- .byte "SEV"
- .byte "BVC"
- .byte "DIV"
- .byte "DAB"
- .byte "CLV"
- .byte "RTS"
- .byte "CMP"
- .byte "CAB"
- .byte "CPY"
- .byte "CPX"
- .byte "CPB"
- .byte "ENT"
- .byte "RTI"
- .byte "INC"
- .byte "IAB"
- .byte "INY"
- .byte "INX"
- .byte "DEC"
- .byte "DBA"
- .byte "DEY"
- .byte "DEX"
- .byte "WAI"
- .byte "JSL"
- .byte "ASR"
- .byte "ARB"
- .byte "NOP"
- .byte "RTL"
- .byte "BRK"
-
-
-scr_row:
- .byte $0
-scr_col:
- .byte $0
-a:
- .word $0
-b:
- .word $0
-c:
- .word $0
-d:
- .word $0
-
-str_buf:
-
-; Input buffer.
-.org $2000
-buf:
-
-.org $2400
-ptr1:
- .qword $2500
-
-ptr2:
- .qword $2900
-
-; Control Register.
-.org $C000
-ctrl_reg:
-
-; Screen.
-.org $C001
-scr:
-
-; Keyboard.
-.org $C002
-kbd:
-
-; Main program.
-.org $0
-reset:
- cps
- ldx.w #$FFFF
- txs
- ldy #0
- jsr clr_buf
- ldx.w #0 ; Reset x.
- ldy #0 ; Reset y.
- jmp print_title
-
-read:
- lda ctrl_reg ; Is the keyboard ready?
- beq read ; Loop until the keyboard is ready.
- lda #0 ; Start resetting the control register.
- sta ctrl_reg ; Reset the control register.
- jmp getchar ; We got a key.
-
-rset_x:
-
- ldx #0 ; Reset x.
- stx.w x
- rts
-
-print_title:
- lda prg_name, x
- beq print_ver ; Did we find a null terminator?
- sta ; Print character.
- inx ; Increment offset.
- inc x
- jmp print_title ; Keep printing more characters.
-
-print_ver
- jsr rset_x
- lda ver_txt, x
- beq print_num ; Did we find a null terminator?
- sta scr ; Print character.
- inx ; Increment offset.
- jmp print_ver ; Keep printing more characters.
-
-print_num:
- lda ver_num, x
- beq getline ; Did we find a null terminator?
- sta scr ; Print character.
- inx ; Increment offset.
- jmp print_num ; Keep printing more characters.
-getline:
- lda #$A
- sta scr ; Print newline
- inc scr_row
- lda #0
- sta scr_col
- inc y
- jsr rset_x
- jmp read
-
-getchar:
- lda kbd ; Get typed character.
- cmp #$1B ; Did the user type an escape?
- beq esc ; Yes, so start getting the escape code.
- cmp #$A ; Did the user type a newline?
- beq nl ; Yes, so start parsing the input.
- cmp #8 ; Did the user type a backspace?
- beq bs ; Yes, so start checking the buffer.
- jsr echo ; Print character to screen.
-
-store_char:
- sta buf, y ; Store typed character into the input buffer.
- iny ; Increment buffer offset.
- jmp read ; Get another character.
-
-esc:
- lda ctrl_reg ; Skip the '['.
- lda ctrl_reg ; Get the next character.
- beq read ; We have an error, so discard it, and go back to getting user input.
- lda kbd ; Get the escape code.
- sta c ; Store the escape code, until we need it.
- jsr isup ; Check if the user pressed up.
- lda d
- cmp #0
- bne esc_end
- jsr isdown ; Check if the user pressed down.
- lda d
- cmp #0
- bne esc_end
- lda #0
- jsr isleft ; Check if the user pressed left.
- lda d
- cmp #0
- bne esc_end
- jsr isright ; Check if the user pressed right.
-esc_end:
- lda #$0
- sta d
- jmp rset_a ; Go back to getting user input.
-
-isup:
- lda scr_row ; Is the cursor at the top of the screen?
- beq isup_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$41 ; Did the user press the up arrow key?
- beq up ; Yes, so move the cursor up.
-isup_done:
- rts ; End of isup.
-
-isdown:
- lda scr_row ; Start checking the y coordinate of the cursor.
- cmp #$17 ; Is the cursor at the bottom of the screen?
- beq isdown_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$42 ; Did the user press the down arrow key?
- beq down ; Yes, so move the cursor down.
-isdown_done:
- rts ; End of isdown.
-
-isright:
- lda scr_col ; Start checking the x coordinate of the cursor.
- cmp #$4F ; Is the cursor at the far right of the screen?
- beq isright_end ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$43 ; Did the user press the right arrow key?
- beq right ; Yes, so move the cursor right.
-isright_end:
- rts ; End of isright.
-
-isleft:
- lda scr_col ; Is the cursor at the far left of the screen?
- beq isleft_done ; Yes, so return.
- lda c ; No, so load the escape code back into the accumulator.
- cmp #$44 ; Did the user press the left arrow key?
- beq left ; Yes, so move the cursor left.
-isleft_done:
- rts ; End of isleft.
-
-up:
- dec scr_row
- jsr update_pos
- lda #1
- sta d
- jmp isup_done
-down:
- inc scr_row
- jsr update_pos
- lda #1
- sta d
- jmp isdown_done
-right:
- inc scr_col
- jsr update_pos
- jmp isright_end
-left:
- dec scr_col
- jsr update_pos
- lda #1
- sta d
- jmp isleft_done
-
-update_pos:
- lda #$1B ; Print an escape character
- sta scr ; to the screen.
- lda #$5B ; Print '['
- sta scr ; to the screen, and start the escape sequence.
- jsr getrow ; Start printing the row number to the screen.
- jsr getcol ; Start printing the column number to the screen.
- lda #$48 ; Print 'H'
- sta scr ; to the screen.
- rts ; End of update_pos.
-getrow:
- lda scr_row ; Get the cursor's y coordinate.
- div #$A ; Divide A by 10.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- tba ; Get the remainder.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- rts ; End of getrow.
-getcol:
- lda #$3B ; Print ';'
- sta scr ; to the screen.
- lda scr_col ; Get the cursor's x coordinate.
- div #$A ; Divide A by 10.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- tba ; Get the remainder.
- adc #$30 ; Convert it to ascii, and
- sta scr ; print to the screen.
- rts ; End of getrow.
-
-
-
-nl:
- sta scr ; Print newline.
- inc scr_row ; Move the cursor down one line.
- lda #0 ; Put a null terminator, in place of the newline.
- sta scr_col ; Move the cursor back to column 0.
- sta buf, y ; Place it into the input buffer.
- ldy.w #0 ; Reset y, to parse the input.
- jsr parse ; Start parsing input.
-
-back:
- sta scr ; Print backspace.
- lda #0 ; Put a null terminator, in place of the backspace.
- sta buf, y ; Place it into the input buffer.
- dey ; Decrement buffer offset.
- dec scr_col
- jmp read ; Get next character.
-
-bs:
- cpy #0 ; Are we at the start of the buffer?
- beq read ; We are, so do not store the backspace into the buffer.
- jmp back ; We are not, so add the backspace to the buffer.
-
-parse:
- jsr getdir
- jsr
- rts
-
-getdir:
- iny ; Increment offset.
- lda buf, y
- jsr iswhite
- bcs getdir ; Reset y, if we hit the null terminator.
- cmp #$2E ; Is this character a '.'?
- bne getdir_exit ; No, so return.
- jsr clr_ptr
-
-getdir_end:
- iny ; Increment offset.
- lda buf, y
- jsr iswhite
- bcs getdir_cmp
- ora #%00100000 ; Make character lower case.
- sta (ptr1), y
- jmp getdir_end
-gettok:
- ply #1
- iny
-gettok2:
- lda buf, y
- jsr istoken
- bcs gettok3
- jmp gettok2
-gettok3:
- cmp #$
- cmp #$24 ; Is this character, a '$'?
- beq getaddr ; Yes, so start getting the address.
-
-
-
-getdir_cmp:
- phy #1
- ldy.w #0
- tyx
-getdir_cpl:
- ldb dir, x ; Start checking if the directive we're using, is "org".
- stb (ptr2), y
- beq getdir_scmp
- inx
- iny
- jmp getdir_cpl
-getdir_scmp:
- ldy #0
- jsr strcmp
- cpx #0
- beq getdir_tok
-getdir_exit:
- rts ; End of getdir.
-
-
-istoken:
- cmp #$20 ; Is this character a space?
- beq istoken_f ; Yes, so return false.
- cmp #$09 ; Is this character a tab?
- beq istoken_f ; Yes, so return false.
- cmp #$A ; Is this character a newline?
- beq istoken_f ; Yes, so return false.
- cmp #$3B ; Is this character a ';'?
- beq istoken_f ; Yes, so return false.
- cmp #0 ; Is this character a null terminator?
- beq istoken_f ; Yes, so return false.
- sec ; Return true.
- rts ; End of istoken.
-istoken_f
- clc ; Return false.
- rts ; End of istoken_f.
-
-iswhite:
- cmp #$20 ; Is this character a space?
- beq iswhite_t ; Yes, so return true.
- cmp #9 ; Is this character a tab?
- beq iswhite_t ; Yes, so return true.
- clc ; No, so return false.
- rts ; End of iswhite.
-iswhite_t:
- sec ; Return true.
- rts ; End of iswhite_t.
-
-rset_y:
- ldy.w #0
- jmp print_buf ; Print the input buffer.
-
-print_buf:
- lda buf, y ; Get a character from the input buffer.
- beq fin ; Are we done with printing the buffer?
- sta scr ; Print said character.
- iny
- jmp print_buf ; Keep printing the buffer.
-
-spin:
- nop
- nop
- nop
- jmp spin
-
-clr_buf:
- lda #0
- cpy.w #$3FF
- beq clr_end
- sta buf, y
- iny
- jmp clr_buf
-clr_sbuf:
- lda #0
- cpy.w #$1FF
- beq clr_end
- sta str_buf, y
- iny
- jmp clr_sbuf
-
-clr_end:
- rts
-
-echo:
- tab
- ldx scr_col
- cpx #$4F
- bne echo_print
- cmp #$A
- beq linewrap
-linewrap:
- inc scr_row
- ldx #0
- stx scr_col
- jsr update_pos
-echo_print:
- tba
- sta scr ; Echo typed character.
- inc scr_col ; Increment the cursor's x coordinate.
- sta buf, y ; Store typed character into the input buffer.
- iny ; Increment the buffer offset.
- rts ; Return.
-
-clr_ptr:
- lda #0
- cpy.w #$3FF
- beq ptr_end
- sta (ptr1), y
- sta (ptr2), y
- iny
- jmp clr_ptr
-ptr_end:
- rts
-
-strcmp:
- lda (ptr1), y
- cmp (ptr2), y
- bne strcmp_l1
- tax
- beq strcmp_l3
- iny
- bne strcmp
- jmp strcmp
-
-
-strcmp_l1:
- bcs strcmp_l2
- ldx #0
- dex
- rts
-
-strcmp_l2:
- ldx #1
-strcmp_l3:
- rts
-
-
-.org $FFC0
-.qword reset
-
-.org $FF50
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-.qword spin
-
-.org $FFA0
-.qword irq_routine
-.org $0
-v
-.org $100
-v
-.org $200
-v
-.org $300
-v
-.org $1000
-v
-.org $1100
-v
-.org $1200
-v
-.org $1300
-v
-.org $1400
-v
-q
-
+; 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, $FF, $FF
+ .byte "JSL", $FF, $FF, $FF, $FF, $FF, $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 "RTL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B0
+ .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
+
+; Hex character table.
+hex_char:
+ .byte "0123456789ABCDEF"
+
+
+; 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
+
+; Lexeme string.
+lexeme:
+
+; Symbol tables.
+.org lexeme+$100
+sym_val:
+.org sym_val+$4000
+sym_id:
+.org sym_id+$1000
+sym_def:
+.org sym_def+$100
+sym_name:
+
+; Fixup table.
+; Fixups are unresolved symbols.
+.org sym_name+$1000
+fix_sym:
+.org fix_sym+$1000
+fix_ln:
+.org fix_ln+$1000
+fix_val:
+
+
+; Start of program code.
+.org parser
+subasm:
+ ldb #0 ; Set the first pointer
+ lda.d #cmd_buf ; to the command buffer.
+ jsl set_ptr ;
+ tba ; Reset A.
+ tax ; Reset X.
+ jsl chk_shcmd ; Did we get a shortend command?
+ bne parse_cmd ; Yes, so skip everything else.
+ jmp subasm_end ;
+ jsl chk_cmd ; No, but did we get a full command?
+ bne parse_cmd ; Yes, so skip everything else.
+ jsl lexer ; No, so start lexing this line.
+subasm_end:
+ rtl ; End of subasm.
+
+parse_cmd:
+ ldb #1 ; Set the second pointer
+ lda.d #cmd_srt ; to the command subroutine table.
+ jsl set_ptr ;
+ deb ; Reset B.
+ tba ; Reset A.
+ lda f ; Get the command ID.
+ cmp #8 ; Is the command ID greater than the command count?
+ bcs subasm_end ; Yes, so we're done.
+ lsl #1 ; No, so multiply the command ID by two.
+ phy #2 ; 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 #2 ; Get back the screen buffer position.
+ ldb #2 ; Save it in the third pointer.
+ jsl set_ptr ;
+ ldb #0 ; Reset B.
+ jsr (ptr3) ; Run the command's subroutine.
+ jmp subasm_end ; We are done.
+
+chk_shcmd:
+ tba ; Reset A.
+ inb ; Set the second pointer
+ lda.w #sh_cmds ; to the shortend command table.
+ jsl set_ptr ;
+ deb ; Reset B.
+ tba ; Reset A.
+ phy #2 ; Preserve the screen buffer position.
+ txy ; Set our index to zero.
+ lda (ptr), y ; Is there nothing in the command buffer?
+ beq shcmd_fail ; Yes, so return that we failed.
+ cmp #' ' ; No, but is this character, a space?
+ beq shcmd_fail ; Yes, so return that we failed.
+shcmd_loop:
+ ldb (ptr2), y ; Are we at the end of the table?
+ beq shcmd_fail ; Yes, so return that we failed.
+ cab ; No, so did the character match?
+ beq shcmd_fnd ; Yes, so check if there are any arguments.
+ iny ; No, so check the next command.
+ jmp shcmd_loop ; Keep looping.
+shcmd_fnd:
+ sty f ; Save the command ID.
+ ldy #1 ; Check the next character in the command buffer.
+ lda (ptr), y ; Is this the end of the buffer?
+ beq shcmd_true ; Yes, so return that we succeded.
+ cmp #' ' ; No, but is this a space?
+ beq shcmd_true ; Yes, so return that we succeded.
+ jmp shcmd_fail ; No, so return that we failed.
+shcmd_true:
+ lda #1 ; Return true.
+ jmp shcmd_end ; We are done.
+shcmd_fail:
+ ldb #0 ; Reset B.
+ tba ; Return false.
+ tax ; Reset X.
+shcmd_end:
+ ply #2 ; Get back the screen buffer position.
+ rtl ; End of chk_shcmd.
+
+print_hex:
+ pha #8 ; Preserve the hex value.
+ and #0 ; Reset A.
+ ldb #1 ; Set the second pointer
+ lda.w #hex_char ; to the start of hex character table.
+ jsl set_ptr ;
+ inb ; Set the third pointer
+ lda.d #hex_str ; to the end of hex string buffer.
+ clc ; Do a non carrying add.
+ adc #$10 ;
+ jsl set_ptr ;
+ ldb #0 ; Reset B.
+ pla #8 ; Get the hex value back.
+pnthex_lp:
+ pha #8 ; Preserve the hex value.
+ and #$F ; Mask the lowest nibble.
+ phy #2 ; Preserve the screen buffer position.
+ tay ; Get the index for the hex digit.
+ lda (ptr2), y ; Get the hex digit.
+ dec ptr3 ; Decrement the string pointer.
+ sta (ptr3) ; Save the hex digit character in the string.
+ ply #2 ; Get back the screen buffer position.
+ pla #8 ; Get the hex value back.
+pnthex_lp1:
+ cpx #1 ; Is the digit count less than one?
+ bcc pnthex_lp2 ; Yes, so don't decrement the digit count.
+ dex ; No, but was the digit count zero, when decremented?
+ beq pnthex_end ; Yes, so we're done.
+ jmp pnthex_lp3 ; No, so get the next nibble.
+pnthex_lp2:
+ ldb #1 ; Enable auto digit count.
+pnthex_lp3:
+ lsr #4 ; No, but is the next nibble, a zero?
+ beq pnthex_lp4 ; Yes, so check if auto digit count is enabled.
+ jmp pnthex_lp ; No, so print the next digit.
+pnthex_lp4:
+ cpb #1 ; Is auto digit count enabled?
+ beq pnthex_end ; Yes, so we're done.
+ jmp pnthex_lp ; No, so keep printing more digits.
+pnthex_end:
+ rtl ; End of print_hex.
+
+charcpy:
+ ldx idx3 ; Get the string index.
+ sta strbuf, x ; Save it in the string buffer.
+ inc idx3 ; Increment the string index.
+ rtl ; End of charcpy.
+
+print_hi:
+ and #0 ; Reset A.
+ sta idx3 ; Clear the string index.
+ lda #'$' ; Print the hex delimiter.
+ jsl charcpy ;
+ lda.q idx0 ; Get the masked address.
+ ldx #$10 ; Set digit count to 16.
+ jsl print_hex ; Print the address.
+ lda.q hex_str ; Get the lower half of the string.
+ sta.q strbuf+1 ; Save it in the string buffer.
+ lda.q hex_str+8 ; Get the upper half of the string.
+ sta.q strbuf+9 ; Save it in the string buffer.
+ ldx #$11 ; Add 16 to the index.
+ stx idx3 ;
+ lda #':' ; Print a colon.
+ jsl charcpy ;
+ lda # ' ' ; Print a space.
+ jsl charcpy ;
+ rtl ; End of print_hi.
+
+print_lo:
+ lda #0 ; Reset A.
+ sta idx3 ; Clear the string index.
+pntlo_lp:
+ ldx #2 ; Set digit count to 2.
+ pha #1 ; Preserve the nibble offset.
+ jsl print_hex ; Print the low nibble offset.
+ lda.w (ptr3) ; Get the two digits.
+ jsl charcpy ; Copy the first digit.
+ lsr #8 ; Copy the next digit.
+ jsl charcpy ;
+ pla #1 ; Get the nibble offset back.
+ inc ; Increment the offset.
+ cmp #$10 ; Are we at the last offset?
+ bcs pntlo_end ; Yes, so we're done.
+pntlo_lp1:
+ pha #1 ; No, so preserve the nibble offset.
+ lda #' ' ; Add a space to the string buffer.
+ jsl charcpy ;
+ pla #1 ; Get the nibble offset back.
+ jmp pntlo_lp ; Keep looping.
+pntlo_end:
+ inx ; Increment the index by one.
+ lda #0 ; Null terminate the string buffer.
+ sta strbuf, x ;
+ tax ; Reset X.
+ lda.d #strbuf ; Print the string buffer.
+ jsl print_str ;
+ rtl ; End of print_lo.
+
+print_chunk:
+ ldx #0 ; Reset X.
+ phy #2 ; Preserve the screen buffer index.
+ txy ; Copy the byte index to it.
+pntchnk_lp:
+ and #0 ; Reset A.
+ ldx #2 ; Set the digit count to 2.
+ lda (idx0), y ; Get the byte at that address.
+ jsl print_hex ; Print the byte.
+ lda.w (ptr3) ; Get the two digits.
+ jsl charcpy ; Copy the first digit.
+ lsr #8 ; Copy the next digit.
+ jsl charcpy ;
+ iny ; Increment the byte index.
+ cpy #$10 ; Have we read 16 bytes?
+ beq pntchnk_end ; Yes, so we're done.
+ lda #' ' ; No, so add a soace to the string buffer.
+ jsl charcpy ;
+ jmp pntchnk_lp ; Keep looping.
+pntchnk_end:
+ ply #2 ; Get the screen buffer index back.
+ inx ; Increment the index by one.
+ and #0 ; Null terminate the string.
+ sta strbuf, x ;
+ tax ; Reset X.
+ sta idx3 ; Clear the string index.
+ rtl ; End of print_chunk.
+
+viewmem:
+ lda.q prg_cnt ; Get the program counter.
+ sta.q idx0 ; Save the address in the first index.
+ and #$F0 ; Clear the first four bits of the address.
+ sta idx0 ; Overwrite the first byte, with the masked byte.
+ lda #19 ; Move the cursor to the right, by 19 columns.
+ sta scr_col ;
+ jsl update_pos ;
+ jsl print_lo ; Print the low nibble offsets.
+ ldx #0 ; Reset X.
+ ldb #0 ; Reset B.
+ stb idx1 ; Reset the byte count.
+vmem_lp0:
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ jsl print_hi ; Place the address in the string buffer.
+ jsl print_chunk ; Place the next 16 bytes in the string buffer.
+ lda.d #strbuf ; Print the string buffer.
+ jsl print_str ;
+ inc idx1 ; Increment the chunk count.
+ ldb idx1 ; Get the chunk count.
+ cpb #$10 ; Did we print 16 chunks?
+ beq vmem_end ; Yes, so we're done.
+ lda.q idx0 ; No, so get the address index.
+ clc ; Prepare for a non carrying add.
+ adc #$10 ; Add 16 to the address.
+ sta.q idx0 ; Put it back into the address.
+ and #0 ; Reset A.
+ jmp vmem_lp0 ; Keep looping.
+vmem_end:
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ and #0 ; Reset A.
+ rts ; End of viewmem.
+
+
+list:
+ nop ;
+list_end:
+ rts ; End of list.
+asm:
+ nop ;
+asm_end:
+ rts ; End of asm.
+help:
+ nop ;
+help_end:
+ rts ; End of help.
+inst:
+ nop ;
+inst_end:
+ rts ; End of inst.
+run:
+ nop ;
+run_end:
+ rts ; End of run.
+set:
+ nop ;
+set_end:
+ rts ; End of set.
diff --git a/programs/subeditor.s b/programs/subeditor.s
index bdd3a11..e344588 100644
--- a/programs/subeditor.s
+++ b/programs/subeditor.s
@@ -4,17 +4,17 @@
; mr b0nk 500 <b0nk@b0nk.xyz>
; I/O constants.
-status = $C000 ; Keyboard status.
-scr = $C001 ; Character that is to be printed.
-kbd = $C002 ; Character from the Keyboard.
-step = $C010 ; Enables clock stepping, when set.
+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-2.s"
+.include "subasm.s"
.org $A000
; String Literals/Constants.
@@ -22,36 +22,49 @@ tok:
.byte "dab"
msg:
.byte "oof, you divided a, and b on me.\n"
-string:
- .byte "Please, type something.\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"
+
+;sub_name:
+; .byte "SuB Suite"
+;sub_ver:
+; .byte "0.9"
+
string2:
.byte "You typed, "
; Linewrap bitmask table.
bits:
- .byte $80
- .byte $40
- .byte $20
- .byte $10
- .byte $08
- .byte $04
- .byte $02
- .byte $01
+ .byte $80, $40, $20, $10, $08, $04, $02, $01
; This label is for any included files.
incl:
; Linewrap table.
-.org $1000
+.org $30000
bitabl:
.qword 0
.qword 0
-; Input buffer.
-.org $2000
+; SCreen buffer.
+.org bitabl+$1000
buffer:
-.org $4000
+; Command buffer.
+.org buffer+$2000
cmd_buf:
@@ -93,7 +106,7 @@ zero:
; End of pseudo registers.
end:
- .word 0
+ .qword 0
bitmask:
.byte 0
scr_str:
@@ -129,8 +142,9 @@ reset:
inc end ;
lda.w #$1FFF ; Set the clear count to $1FFF.
sta.w scr_ptr ;
- lda.w #buffer ; Set the array to be cleared to the screen buffer.
+ lda.d #buffer ; Set the array to be cleared to the screen buffer.
jsl clr_arr ; Clear the screen buffer.
+ jsl pnt_strt ; Print the starting message.
jmp start ; Goto the start of the main program.
clr_arr:
@@ -163,6 +177,25 @@ clr_arr_end:
plb #1 ; Get whatever was in the B register, back.
rtl ; End of clr_arr.
+pnt_strt:
+ lda.w #ed_name ; Print the name of the editor.
+ jsl print_str ;
+ lda.w #ver_str ; Print the version text.
+ jsl print_str ;
+ lda.w #ed_ver ; Print the version number.
+ jsl print_str ;
+ lda.w #ed_sver ; Print the sub version number.
+ jsl print_str ;
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ lda.w #made ; Print the "Created by" text.
+ jsl print_str ;
+ lda.w #author ; Print the name of the author.
+ jsl print_str ;
+ lda #'\n' ; Print a newline.
+ jsl print_char ;
+ rtl ; 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.
@@ -171,12 +204,10 @@ start:
tay ; Reset the cursor index.
lda.w #$3FF ; Set the clear count to $3FF.
sta.w scr_ptr ;
- lda.w #cmd_buf ; Set the array to be cleared to the command buffer.
+ lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
jsl clr_arr ; Clear the command buffer.
ply #2 ; Get back the cursor index.
- lda.w #string ; Print the startup message.
- jsl print_str ;
- lsr #$10 ; Reset the Accumulator.
+ and #0 ; Reset the Accumulator.
sta end ;
jmp read ; Start reading the keyboard.
@@ -191,19 +222,20 @@ read:
jmp read ; No, so keep looping.
print_str:
- sta.w end ; Save the parameter.
+ ldx #0 ; Reset X.
+ sta.q end ; Save the parameter.
print_str2:
- lda.w end ; Get the parameter.
+ lda.q end ; Get the parameter.
ldb #0 ; Clear the B register.
jsl set_ptr ; Set the first pointer to the parameter.
tba ; Clear the Accumulator.
- inb ; Enable replace mode.
- stb b ;
pntstr_lp:
- lda.w ptr ; Get the first pointer.
- cmp.w end ; Did the pointer change?
+ ldb #1 ; Enable replace mode.
+ stb b ;
+ lda.q ptr ; Get the first pointer.
+ cmp.q end ; Did the pointer change?
bne print_str2 ; Yes, so set it back.
- lsr #$10 ; No, reset the accumulator.
+ and #0 ; No, reset the accumulator.
phy #2 ; Save the cursor index.
txy ; Copy the string index into Y.
lda (ptr), y ; Are we at the end of the string?
@@ -230,7 +262,7 @@ getbt0:
getbt1:
pha #1 ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.w #bitabl ; Set the second pointer to the linewrap table.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
jsl set_ptr ;
lsr #$10 ; Clear the Accumulator.
pla #1 ; Get the return byte back.
@@ -246,9 +278,9 @@ getbt1:
clrbit:
pha #1 ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.w #bitabl ; Set the second pointer to the linewrap table.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
jsl set_ptr ;
- lsr #$10 ; Clear the Accumulator.
+ and #0 ; Clear the Accumulator.
pla #1 ; Get the return byte back.
jsl bitpos ; Get the bit, and byte position.
xor #$FF ; Invert the bitmask.
@@ -266,9 +298,9 @@ bitout:
setbit:
pha #1 ; Save the parameter.
ldb #1 ; Make sure that set_ptr sets the second pointer.
- lda.w #bitabl ; Set the second pointer to the linewrap table.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
jsl set_ptr ;
- lsr #$10 ; Clear the Accumulator.
+ and #0 ; Clear the Accumulator.
pla #1 ; Get the return byte back.
jsl bitpos ; Get the bit, and byte position.
phy #2 ; Save the screen index.
@@ -282,7 +314,7 @@ bitpos:
ldb #0 ; Make sure that set_ptr sets the first pointer.
lda.w #bits ; Set the first pointer to the bitmask table.
jsl set_ptr ;
- lsr #$10 ; Clear the Accumulator.
+ and #0 ; Clear the Accumulator.
pla #1 ; Get the parameter back.
stx bitmask ; Make the line number the bitmask.
txa ; Copy it to the Accumulator.
@@ -361,10 +393,10 @@ cmd_cpy3:
tay ; Place it into the index.
ldx.w #0 ; Reset the X register.
ldb #0 ; Make sure that set_ptr sets the first pointer.
- lda.w #buffer ; Set the first pointer to the start of the screen buffer.
+ lda.d #buffer ; Set the first pointer to the start of the screen buffer.
jsl set_ptr ;
inb ; Make sure that set_ptr sets the second pointer.
- lda.w #cmd_buf ; Set the second pointer to the start of the command buffer.
+ lda.d #cmd_buf ; Set the second pointer to the start of the command buffer.
jsl set_ptr ;
deb ; Set B back to zero.
tba ; Set the accumulator to zero.
@@ -403,26 +435,26 @@ cmd_cpy_nd:
findst:
- lda #0 ;
+ lda #0 ; Reset A.
findst_lp:
- pha #1 ;
- jsl getbit ;
- pla #1 ;
- bcc findst_done ;
- inc ;
- dec scr_row ;
- bpo findst_lp ;
- dec ;
- inc scr_row ;
+ pha #1 ; Save the current line number.
+ jsl getbit ; Is this the start of the line?
+ pla #1 ; Get the current line number back.
+ bcc findst_done ; Yes, so we're done.
+ inc ; No, so check the next physical line.
+ dec scr_row ; Are we at the top of the screen?
+ bpo findst_lp ; No, so keep looping.
+ dec ; Yes, so move back one line.
+ inc scr_row ; Put the row postiion back to zero.
findst_done:
- cmp #0 ;
- rtl ;
+ cmp #0 ; Update all the flags.
+ rtl ; End of findst.
fndend:
phb #1 ; Save the contents of the B register.
ldb #0 ; Make sure that set_ptr sets the first pointer.
- lda.w #buffer ; Set the first pointer to the start of the screen buffer.
+ lda.d #buffer ; Set the first pointer to the start of the screen buffer.
jsl set_ptr ;
tba ; Set the Accumulator to zero.
plb #1 ; Restore the contents of the B register.
@@ -446,16 +478,13 @@ findend:
parse:
lda #0 ;
tax ;
- jsl dabbed ;
- beq start ;
- lda #0 ;
- tax ;
- jmp result ;
+ jsl subasm ;
+ jmp start ;
print_char:
sta a ; Save the typed character for now.
ldb #2 ; Make sure that set_ptr sets the third pointer.
- lda.w #buffer ; Set the third pointer to the start of the screen buffer.
+ lda.d #buffer ; Set the third pointer to the start of the screen buffer.
jsl set_ptr ;
ldb #0 ; Set B to zero.
tba ; Set the Accumulator to zero.
@@ -482,25 +511,25 @@ printc:
lda b ; No, but was the flag set?
bne printc_save ; Yes, so don't shift the line.
sty.w scr_ptr ; No, so save the cursor index for later.
- jsl fndend ;
- jmp prntc_movln ;
+ jsl fndend ; Find the end of the line.
+ jmp prntc_movln ; Start shifting the line right.
prntc_updt:
- lda scr_col ;
+ lda scr_col ; Save the current column position for later.
sta scr_tcol ;
prntc_updt2:
- jsl findend ;
- sta e ;
- sta scr_row ;
- jsl findst ;
- lda scr_row ;
+ jsl findend ; Find the end of the line.
+ sta e ; Use it for redrawing the line.
+ sta scr_row ; Set the row position to to the end of the line.
+ jsl findst ; Find the start of the line.
+ lda scr_row ; Get the start of the line.
prntc_updt3:
- sta f ;
- jsl rdrw_ln ;
- lda scr_trow ;
+ sta f ; Set the starting line, to the start of the line.
+ jsl rdrw_ln ; Redraw the line.
+ lda scr_trow ; Get the real row position back.
sta scr_row ;
- lda scr_tcol ;
+ lda scr_tcol ; Get the real column position back.
sta scr_col ;
- jsl update_pos ;
+ jsl update_pos ; Update the cursor's position.
dec d ;
jmp printc_sav1 ;
prntc_movln:
@@ -574,22 +603,22 @@ printc_end:
rtl ;
nl:
- lda #0 ;
- ldb (ptr3), y ;
- bne nl1 ;
- sta (ptr3), y ; Store said terminator into the input buffer.
+ lda #0 ; Reset A.
+ ldb (ptr3), y ; Is this character not a null terminator?
+ bne nl1 ; Yes, so don't overwrite it.
+ sta (ptr3), y ; No, so overwrite it.
nl1:
- sta scr_col ;
- lda scr_row ;
- cmp #maxrow ;
- bcc nl_inc ;
- jsl scrl_down ;
- jmp nl_end ;
+ sta scr_col ; Move the cursor to the start of the next line.
+ lda scr_row ; Get the row position.
+ cmp #maxrow ; Are we at the bottom of the screen?
+ bcc nl_inc ; No, so move down one line.
+ jsl scrl_down ; Yes, so scroll down one line.
+ jmp nl_end ; We are done.
nl_inc:
- inc scr_row ;
- jsl update_pos ;
+ inc scr_row ; Move the cursor down by one line.
+ jsl update_pos ; Update the cursor's position.
nl_end:
- lda #'\n' ;
+ lda #'\n' ; Print the newline.
sta a ;
jmp printc_end ;
@@ -603,12 +632,12 @@ clr_scr:
tay ;
lda.w #$1FFF ; Set the clear count to $1FFF.
sta.w scr_ptr ;
- lda.w #buffer ; Set the array to be cleared to the command buffer.
+ lda.d #buffer ; Set the array to be cleared to the screen buffer.
jsl clr_arr ; Clear the screen buffer.
tay ;
lda.w #$3FF ; Set the clear count to $3FF.
sta.w scr_ptr ;
- lda.w #buffer ; Set the array to be cleared to the command buffer.
+ lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
jsl clr_arr ; Clear the screen buffer.
sta scr_col ;
sta scr_row ;
@@ -636,18 +665,18 @@ step_dis:
jmp printc_end ;
back:
- ldb #0 ;
+ ldb #0 ; Reset B, and some flags.
stb e ;
stb f ;
- lda scr_row ;
+ lda scr_row ; Save the current row position for later.
sta scr_trow ;
- jsl findend ;
- sta scr_row ;
+ jsl findend ; Find the end of the line.
+ sta scr_row ; Set our row position to the end of the line.
back0:
- jsl findst ;
- beq back1 ;
- bcs back_updt ;
- lda scr_trow ;
+ jsl findst ; Does this line take up more than one real line?
+ beq back1 ; No, so skip updating any other lines.
+ bcs back_updt ; Yes, so update the other lines.
+ lda scr_trow ; Get the real row position back.
sta scr_row ;
back1:
dey ; Decrement the buffer's offset.
@@ -655,32 +684,32 @@ back1:
sta (ptr3), y ; into the buffer.
tyx ; Copy the current cursor index to X.
iny ; Increment cursor index.
- ldb #0 ;
+ ldb #0 ; Set shifting direction to left.
stb d ;
jsl shftln ; Shift line back by one character.
lda #$7F ; Print a backspace to the screen.
sta scr ;
- lda e ;
- beq back3 ;
+ lda e ; Are we updating more than one line?
+ beq back3 ; No, so skip to the next step.
back2:
- jsl findend ;
- sta e ;
- lda scr_col ;
+ jsl findend ; Yes, so find the end of the line.
+ sta e ; Set the end parameter to it.
+ lda scr_col ; Save the current column position for now.
sta scr_tcol ;
- jsl rdrw_ln ;
- lda scr_tcol ;
+ jsl rdrw_ln ; Start redrawing the line.
+ lda scr_tcol ; Get the real column position back.
sta scr_col ;
back3:
- lda scr_trow ;
+ lda scr_trow ; Get the real row position bac.
sta scr_row ;
dec scr_col ; Move the cursor back by one column,
jsl update_pos ; and update it's position.
jmp printc_end ; We are done.
back_updt:
- lda scr_row ;
+ lda scr_row ; Set the line to start redrawing, to the start of the line.
sta f ;
- inc e ;
- jmp back1 ;
+ inc e ; Set the redraw flag to true.
+ jmp back1 ; Start shifting the line back.
bs:
lda scr_col ; Are we at the far left of the screen?
@@ -1155,62 +1184,6 @@ rdrow_end:
rdrow_done:
rtl ;
-result:
- lda.w #string2 ;
- ldx.w zero ;
- jsl print_str ;
-rset_x:
- lda #0 ; Reset a.
- tax ; Reset x.
- jmp print_buf ; Print the input buffer.
-
-dabbed:
- ldb #0 ; Make sure that set_ptr is setting the first pointer.
- lda.w #cmd_buf ; Set the first pointer to the start of the command buffer.
- jsl set_ptr ;
- inb ; Make set_ptr set the second pointer.
- lda.w #tok ; Set the second pointer to the start of the token string.
- jsl set_ptr ;
- deb ; Set B back to zero.
- tba ; Also set the accumulator back to zero.
-dab_st:
- phy #2 ;
- txy ;
- lda (ptr), y ; Are we at the end of the string?
- beq dab_pend ; Yes, so return false.
- cmp (ptr2), y ; No, but is this character the same as the character in the token string?
- beq chk_str ; Yes, so increment the character count.
- jmp dab_pend ; No, so return false.
-chk_str:
- ply #2 ;
- inx ;
- cpx #3 ;
- bne dab_st ;
- ldx #0 ;
-pnt_msg:
- lda.w #msg ;
- ldx #0 ;
- jsl print_str ;
- jmp dab_peqnd ;
-dab_pend:
- ply #2 ;
- lda #1 ;
- jmp dab_end ;
-dab_peqnd:
- lda #0 ;
- jmp dab_end ;
-dab_end:
- rtl ;
-
-print_buf:
- lda.w #cmd_buf ;
- jsl print_str ;
- lsr #$10 ; Clear the Accumulator.
-cmd_clr:
- lda #'\n' ;
- jsl print_char ;
- jmp start ;
-
rdrw_ln:
lda scr_row ;
pha #1 ;
@@ -1246,12 +1219,15 @@ set_ptr:
cpb #2 ; No, but are we setting the third pointer?
beq set_ptr3 ; Yes, so start setting it.
set_ptr1:
+ stb.q ptr ; Reset the first pointer.
sta.q ptr ; No, so set the first pointer.
jmp setptr_end ; We are done.
set_ptr2:
+ stb.q ptr2 ; Reset the second pointer.
sta.q ptr2 ; Set the second pointer.
jmp setptr_end ; We are done.
set_ptr3:
+ stb.q ptr3 ; Reset the third pointer.
sta.q ptr3 ; Set the third pointer.
setptr_end:
rtl ; End of set_ptr.
diff --git a/sux.c b/sux.c
index b8c4ca7..75577d2 100644
--- a/sux.c
+++ b/sux.c
@@ -97,7 +97,11 @@ void *run(void *args) {
#if keypoll
pthread_mutex_lock(&mutex);
#endif
- wmove(scr, lines, 0);
+ for (uint8_t i = (24*thread)+2; i <= 24*(thread+1); i++) {
+ wmove(scr, i, 0);
+ waddch(scr, (i == lines) ? '>' : ' ');
+ }
+ wmove(scr, lines, 1);
wclrtoeol(scr);
wprintw(scr,
"pc: $%04"PRIX64
diff --git a/sux.h b/sux.h
index 3554011..241362b 100644
--- a/sux.h
+++ b/sux.h
@@ -8,10 +8,10 @@
#define THREADS 1
#define BENCH_INST 100000000 << (THREADS-1)
-#define CTRL_ADDR 0xC000
-#define TX_ADDR 0xC001
-#define RX_ADDR 0xC002
-#define STEP_ADDR 0xC010
+#define CTRL_ADDR 0x100
+#define TX_ADDR 0x101
+#define RX_ADDR 0x102
+#define STEP_ADDR 0x110
#define CURSES_BACKSPACE 0x7F
extern uint8_t kbd_rdy;