From 7ba25336342282bfe57dbb6ddf8f3e2ae3e1b719 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Thu, 28 May 2020 20:03:09 -0400 Subject: Refactored the assembler, yet again, and implemented support for comma separated values. The assembler now uses a linked list of tokenized lines, each containing a linked list of tokens for that line. I also moved all of the large tables into the higher parts of memory, in order to free up the lower part of memory for the user. Comma sepparated values only work with directives, and only with the byte", word, dword, and qword directives. I also added support for getting the upper, and lower halves of an address. The tokens for both of those are '<', and '>' respectively. --- Makefile | 2 +- asmmon.c | 554 ++++++--------------------- asmmon.h | 79 +++- assemble.c | 378 +++++++++++++++++++ disasm.c | 53 ++- lexer.c | 506 ++++++++----------------- programs/subasm-2.s | 323 ---------------- programs/subasm.s | 1019 ++++++++++++++++++++++---------------------------- programs/subeditor.s | 302 +++++++-------- sux.c | 6 +- sux.h | 8 +- 11 files changed, 1343 insertions(+), 1887 deletions(-) create mode 100644 assemble.c delete mode 100644 programs/subasm-2.s 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 - -.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 -; 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 ; 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; -- cgit v1.2.3-13-gbd6f