diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | asmmon.c | 554 | ||||
-rw-r--r-- | asmmon.h | 79 | ||||
-rw-r--r-- | assemble.c | 378 | ||||
-rw-r--r-- | disasm.c | 53 | ||||
-rw-r--r-- | lexer.c | 506 | ||||
-rw-r--r-- | programs/subasm-2.s | 323 | ||||
-rw-r--r-- | programs/subasm.s | 1019 | ||||
-rw-r--r-- | programs/subeditor.s | 302 | ||||
-rw-r--r-- | sux.c | 6 | ||||
-rw-r--r-- | sux.h | 8 |
11 files changed, 1343 insertions, 1887 deletions
@@ -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 @@ -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; } @@ -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); + } +} @@ -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++) { @@ -2,6 +2,8 @@ uint8_t lex_type; uint16_t sym_count = 0; +token *tokens = NULL; +token *last_tok = NULL; void init_symbol() { uint16_t i = 0; @@ -41,10 +43,8 @@ uint16_t mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t useid, ui printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s\n", def, val, name); printf("mksymbol(): i: $%X, id: $%04X\n", i, symbols[i]->id); } - return symbols[i]->id; - } else { - return symbols[i]->id; } + return symbols[i]->id; } } symbols[i] = malloc(sizeof(**symbols) + strlen(name)); @@ -123,8 +123,8 @@ char *get_symname(uint16_t id, uint8_t dbg) { } uint16_t fixup_cnt = 0; -uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) { - uint16_t i = mksymbol(name, 0, 0, 0, ln, dbg); +uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg) { + uint16_t i = mksymbol(name, 0, 0, 0, 0, dbg); if (dbg) { printf("get_symid(): Symbol ID: $%X, i: $%X.\n", symbols[i]->id, i); } @@ -136,7 +136,7 @@ uint16_t get_symid(const char *name, uint64_t val, uint16_t ln, uint8_t dbg) { } fixups[fixup_cnt] = malloc(sizeof(**fixups)); fixups[fixup_cnt]->adr = val; - fixups[fixup_cnt]->ln = ln; + fixups[fixup_cnt]->t = t; fixups[fixup_cnt]->s = symbols[i]; fixup_cnt++; return 0xFFFF; @@ -196,14 +196,14 @@ uint16_t get_string(const char *str, uint8_t dbg) { return i; } -uint16_t reslv_fixups(struct line *l, uint8_t dbg) { +uint16_t reslv_fixups(uint8_t dbg) { uint16_t i = 0, j = 0; for (; fixups[j]; j++) { if (fixups[j]->s->def) { if (dbg) { - printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%X.\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val); + printf("reslv_fixups(): Symbol ID: $%X, Symbol Name: %s, Symbol Value: $%"PRIX64".\n", fixups[j]->s->id, fixups[j]->s->name, fixups[j]->s->val); } - l[fixups[j]->ln].sym = fixups[j]->s->id; + fixups[j]->t->word = fixups[j]->s->id; } else { if (dbg) { printf("reslv_fixups(): oof, undefined reference to '%s', at $%016"PRIX64".\n", fixups[j]->s->name, fixups[j]->adr); @@ -215,205 +215,40 @@ uint16_t reslv_fixups(struct line *l, uint8_t dbg) { } -uint64_t update_addr(struct line *ln, uint64_t address, uint8_t fixup, uint16_t l, uint8_t dbg) { - uint64_t value = 0; +line *find_line(uint16_t ln, uint8_t dbg) { uint16_t i = 0; - uint16_t j = 0; - uint16_t flags = 0; - uint8_t opsize = 0; - - uint16_t symid = ln[l].sym; - uint16_t str = ln[l].str; - uint16_t com = ln[l].com; - uint8_t islabel = ln[l].islabel; - uint8_t issym = ln[l].issym; - uint8_t opbase = ln[l].opbase; - uint8_t aopbase = ln[l].aopbase; - uint8_t dir = ln[l].dir; - uint8_t am = ln[l].am; - uint8_t cm = ln[l].cm; - uint8_t rs = ln[l].rs; - uint8_t mne = ln[l].mne; - - flags |= (dir != 0x00FF) << 0x00; - flags |= (mne != 0x00FF) << 0x01; - flags |= (rs != 0x00FF) << 0x02; - flags |= (am != 0x00FF) << 0x03; - flags |= (opbase != 0x00FF) << 0x04; - flags |= (aopbase != 0x00FF) << 0x05; - flags |= (symid != 0xFFFF) << 0x06; - flags |= (fixup > 0x0000) << 0x06; - flags |= (islabel ) << 0x07; - flags |= (issym ) << 0x07; - flags |= (am != 0x00FF) << 0x08; - flags |= (cm != 0x00FF) << 0x09; - flags |= (str != 0xFFFF) << 0x0A; - - if (dbg) { - printf("update_addr(): "); - printf("flags: $%04X\n", flags); - } - if (!flags || flags == 0x40) { - if (dbg) { - printf("update_addr(): "); - puts("This line only contains a comment, so don't update the address."); - } - return address; - } - if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) { - if (fixup && symid == 0xFFFF && (opcodes[mne][IMPL] == 0xFF)) { - value = address; - } else if (opcodes[mne][IMPL] != 0xFF && symid == 0xFFFF) { - value = 0; - } else { - value = use_symbol("", symid, address, 1, dbg); - } - } else { - value = ln[l].op; - } - if (flags & 0x220) { - switch (cm) { - case 0: value += ln[l].aop; break; - case 1: value -= ln[l].aop; break; + line *l = lines; + for (; l && l->linenum != ln; l = l->next); + /*if (dbg) { + if (l->linenum == ln) { + printf("find_line(): Found line number %u, at line index %X.\n", ln, i); } - } - if (dbg) { - printf("update_addr(): value: $%"PRIX64"\n", value); - } - switch (dir) { - case DIR_ORG: - address = value; + printf("find_line(): linenum: %u, i: %X\n", l->linenum, i); + }*/ + if (l != NULL) { + if (l->linenum == ln) { if (dbg) { - printf("update_addr(): "); - printf("Set the Program Counter's Origin to $%"PRIX64".\n", address); - } - break; - case DIR_BYTE: - if (flags & 0x400) { - for (; string[str][i] != '\0'; i++, j++, address++) { - i += string[str][i] == '\\'; - } - j++; - address++; - if (dbg) { - printf("update_addr(): "); - printf("Increment Program Counter by $%04X", j); - puts(", to make room for the string."); - } - } else { - address += 1; + printf("find_line(): Found line number %u.\n", ln); } - break; - case DIR_WORD: address += 2; break; - case DIR_DWORD: address += 4; break; - case DIR_QWORD: address += 8; break; - } - if (flags & 0x01) { - if (dbg) { - printf("update_addr(): "); - puts("This line contains a directive, so skip everything else."); - } - return address; - } - if ((flags & 0x15B) == 0x02 || (opcodes[mne][IMPL] != 0xFF && am == 0xFF && opbase == 0xFF && symid == 0xFFFF)) { - ln[l].am = IMPL; - am = IMPL; - if (dbg) { - printf("update_addr(): "); - puts("Addressing Mode has been set to Implied."); - } - } - if (am == IMPL) { - opsize = 0; - } else if (am == IMM) { - switch (rs) { - case 3: address += 8; break; - case 2: address += 4; break; - case 1: address += 2; break; - default: address += 1; break; + return l; } + } else { if (dbg) { - if (!(flags & 0x04)) { - rs = 0; - } - printf("update_addr(): "); - printf("Increment Program Counter by $%02X", 1 << rs); - puts(", to make room for the operand."); - } - } else if ((flags & 0x158) && (!(flags & 0x80))) { - opsize = 0; - opsize = (value <= 0x00000000000000FF) ? 1 : opsize; - opsize = (value > 0x00000000000000FF) ? 2 : opsize; - opsize = (value > 0x000000000000FFFF) ? 3 : opsize; - opsize = (value > 0x0000000000FFFFFF) ? 4 : opsize; - opsize = (value > 0x00000000FFFFFFFF) ? 5 : opsize; - opsize = (value > 0x000000FFFFFFFFFF) ? 6 : opsize; - opsize = (value > 0x0000FFFFFFFFFFFF) ? 7 : opsize; - opsize = (value > 0x00FFFFFFFFFFFFFF) ? 8 : opsize; - if (opsize) { - switch (opsize-1) { - case 0: - case 2: - case 5: - case 3: - if (!(flags & 0x100)) { - am = ZM; - ln[l].am = am; - if (dbg) { - printf("update_addr(): "); - puts("Addressing Mode has been set to Zero Matrix."); - } - } - break; - case 1: - case 4: - case 6: - case 7: - if (!(flags & 0x100)) { - am = ABS; - ln[l].am = am; - if (dbg) { - printf("update_addr(): "); - puts("Addressing Mode has been set to Absolute."); - } - } - break; - } - address += opsize; - if (dbg) { - printf("update_addr(): "); - printf("Increment Program Counter by $%02X", opsize); - puts(", to make room for the address."); - } - } - } - if (dbg) { - printf("update_addr(): "); - printf("Address: $%"PRIX64"\n", address); - } - return address; -} - -uint16_t find_line(struct line *l, uint16_t ln, uint8_t dbg) { - uint16_t i = 0; - for (; i < lineidx && l[i].linenum != ln; i++); - if (dbg) { - if (l[i].linenum == ln) { - printf("find_line(): Found line number %u, at line index %X.\n", ln, i); + printf("find_line(): oof, could not find line number %u.\n", ln); } - printf("find_line(): linenum: %u, i: %X\n", l[i].linenum, i); + return NULL; } - return i; + return l; } -uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { +uint64_t lex(char *str, uint64_t address, uint8_t dbg) { char sym[0x100]; uint16_t i = 0; uint16_t j = 0; uint16_t comid = 0; uint16_t strid = 0; uint16_t symid = 0; - uint16_t line = 0; + uint64_t value = 0; lex_type = 0xFF; uint8_t k = 0; @@ -436,6 +271,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { uint8_t isstart = 1; uint8_t fall = 0; uint8_t done = 0; + line *l = NULL; + token *st = NULL; + token *t = NULL; + token *lt = NULL; while (isdigit(str[i]) && !isspace(str[i])) { lnum[j++] = str[i++]; @@ -448,25 +287,18 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { } else { ln = linenum; } - line = find_line(l, ln, dbg); - if (line != lineidx) { - address = l[line].addr; + l = find_line(ln, dbg); + if (l) { + address = l->addr; + } else { + l = malloc(sizeof(line)); + (last_line) ? (last_line->next = l) : (lines = l); + l->tok = NULL; + l->next = NULL; + l->count = 0; + last_line = l; + } - l[line].dir = 0xFF; - l[line].mne = 0xFF; - l[line].rs = 0xFF; - l[line].am = 0xFF; - l[line].cm = 0xFF; - l[line].opbase = 0xFF; - l[line].aopbase = 0xFF; - l[line].islabel = 0; - l[line].issym = 0; - l[line].str = 0xFFFF; - l[line].com = 0xFFFF; - l[line].sym = 0xFFFF; - l[line].op = 0; - l[line].aop = 0; - l[line].addr = address; while (str[i] != '\0' && str[i] != '\n') { base = 0; space = 0; @@ -481,10 +313,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { printf("lex(): tab: %u, space: %u\n", tab, space); } if (isstart) { - l[line].stab = tab; - l[line].sspace = space; + l->stab = tab; + l->sspace = space; if (dbg) { - printf("lex(): starting tabs: %u, starting spaces: %u\n", l[line].stab, l[line].sspace); + printf("lex(): starting tabs: %u, starting spaces: %u\n", l->stab, l->sspace); } } if (isspace(str[i])) { @@ -506,7 +338,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { break; } } - l[line].dir = k; + l->count++; + t = make_token(lex_type, k, 0, ""); } else { lex_type = TOK_RS; switch (tolower(lexeme[j-1])) { @@ -523,8 +356,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { rs = 3; break; } - address++; - l[line].rs = rs; + l->count++; + t = make_token(lex_type, rs, 0, ""); isop = 0; } break; @@ -535,59 +368,45 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { } strid = get_string(lexeme, dbg); if (strid == 0xFFFF) { - if (line != lineidx && l[line].str != 0xFFFF) { - strid = l[line].str; - } else { - strid = stridx; - } + strid = stridx; string[strid] = malloc(j+1); memcpy(string[strid], lexeme, j+1); - l[line].str = strid; - stridx += (line == lineidx); + stridx++; } else { - l[line].str = strid; } if (dbg) { printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); } - if (l[line].dir == DIR_INCLUDE) { - l[line].incl = strid; + if (lt->id == TOK_DIR && lt->type == DIR_INCLUDE) { incl[inc_file++] = strid; } lex_type = TOK_STRING; + l->count++; + t = make_token(lex_type, 0, 0, string[strid]); break; - if (str[i] == '$') { - case '$': base = 16; - } else if (str[i] == '%') { - case '%': base = 2; - } + case '$': + case '%': + value = 0; + base = (str[i] == '$') ? 16 : 2; i++; - while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n')) { + while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n' && str[i] != ',')) { lexeme[j++] = str[i++]; } lexeme[j] = '\0'; - switch (lex_type) { - default: - if (l[line].cm != 0xFF) { - case TOK_PLUS : - case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, base); - l[line].aopbase = (base & 16) ? BASE_HEX : BASE_BIN; - } else { - case TOK_SYM: l[line].op = strtoull(lexeme, NULL, base); - l[line].opbase = (base & 16) ? BASE_HEX : BASE_BIN; - } - if (lex_type == TOK_SYM) { - mksymbol(sym, l[line].op, 1, 0, 0, dbg); - l[line].sym = get_symid(sym, address, line, dbg); - isfixup += (l[line].sym == 0xFFFF); - if (dbg) { - printf("lex(): isfixup: %u\n", isfixup); - } - } - break; + lex_type = (base == 16) ? TOK_HEX : TOK_BIN; + value = strtoull(lexeme, NULL, base); + if (lt->id == TOK_SYM) { + mksymbol(sym, value, 1, 0, 0, dbg); + if (lt) { + lt->word = get_symid(sym, address, lt, dbg); + } + isfixup += (lt->word == 0xFFFF); + if (dbg) { + printf("lex(): isfixup: %u\n", isfixup); + } } - - lex_type = (base & 16) ? TOK_HEX : TOK_BIN; + l->count++; + t = make_token(lex_type, 0, value, ""); break; case '\'': i++; @@ -611,37 +430,35 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { break; default: ch = lexeme[k]; } - switch (lex_type) { - case TOK_PLUS : - case TOK_MINUS: - l[line].aop = ch; - l[line].aopbase = BASE_CHAR; - break; - default: - l[line].op = ch; - l[line].opbase = BASE_CHAR; - break; - } lex_type = TOK_CHAR; + l->count++; + t = make_token(lex_type, 0, ch, ""); break; - case '(': - if (str[i] == '#' || str[i] == '(') { - if (str[i] == '#') { - case '#': lex_type = TOK_IMM; - } - l[line].am = (str[i] == '#') ? IMM : IND; - } else { + case '(': l->tok->type = IND; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; + case '#': l->tok->type = IMM; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; case '+': - case '-': l[line].cm = (str[i] == '-'); - lex_type = (str[i] == '-') ? TOK_MINUS : TOK_PLUS; + case '-': + case '>': + case '<': + lex_type = TOK_EXPR; + switch (str[i]) { + case '+': value = EXPR_PLUS ; break; + case '-': value = EXPR_MINUS; break; + case '>': value = EXPR_LOW ; break; + case '<': value = EXPR_HIGH ; break; } + l->count++; + t = make_token(lex_type, value, 0, ""); + memset(lexeme, 0, strlen(lexeme)+1); + lexeme[j++] = str[i]; + break; + case '=': + i++; + lex_type = TOK_SYM; + l->count++; + t = make_token(lex_type, 0, 0, ""); memset(lexeme, 0, strlen(lexeme)+1); lexeme[j] = str[i]; - if (str[i] == '=') { - case '=': i++; - l[line].issym = 1; - lex_type = TOK_SYM; - } break; case ')': i++; @@ -650,9 +467,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { while (isspace(str[i])) { lexeme[j++] = str[i++]; } - if (l[line].am == IND && tolower(str[i]) == 'y') { + if (l->tok->type == IND && tolower(str[i]) == 'y') { lexeme[j++] = 'y'; - l[line].am = INDY; + l->tok->type = INDY; } lexeme[j] = '\0'; } else { @@ -666,20 +483,21 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { while (isspace(str[i])) { lexeme[j++] = str[i++]; } - if (l[line].am == IND && tolower(str[i]) == 'x') { - l[line].am = INDX; + if (l->tok->type == IND && tolower(str[i]) == 'x') { + l->tok->type = INDX; lexeme[j++] = 'x'; i++; } else { switch (tolower(str[i])) { case 'x': - l[line].am = ZMX; + l->tok->type = ZMX; lexeme[j++] = 'x'; break; case 'y': - l[line].am = ZMY; + l->tok->type = ZMY; lexeme[j++] = 'y'; break; + default: lex_type = TOK_COMMA; i--; break; } } lexeme[j] = '\0'; @@ -689,13 +507,14 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { lexeme[j] = ':'; lexeme[j+1] = '\0'; lex_type = TOK_LABEL; - l[line].islabel = 1; + l->count++; + t = make_token(lex_type, 0, 0, ""); mksymbol(sym, address, 1, 0, 0, dbg); if (isfixup) { - isfixup = reslv_fixups(l, dbg); + isfixup = reslv_fixups(dbg); } - l[line].sym = get_symid(sym, address, line, dbg); - isfixup += (l[line].sym == 0xFFFF); + t->word = get_symid(sym, address, t, dbg); + isfixup += (t->word == 0xFFFF); if (dbg) { printf("lex(): isfixup: %u\n", isfixup); } @@ -708,22 +527,23 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { lexeme[j] = '\0'; comid = get_comment(lexeme, dbg); if (comid == 0xFFFF) { - if (line != lineidx && l[line].com != 0xFFFF) { + /*if (line != lineidx && l[line].com != 0xFFFF) { comid = l[line].com; } else { comid = comidx; - } + }*/ + comid = comidx; comment[comid] = malloc(j+1); memcpy(comment[comid], lexeme, j+1); - l[line].com = comid; - comidx += (line == lineidx); + comidx++; } else { - l[line].com = comid; } if (dbg) { printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]); } lex_type = TOK_COMMENT; + l->count++; + t = make_token(lex_type, 0, 0, comment[comid]); break; default: if (isalnum(str[i]) || str[i] == '_') { @@ -733,6 +553,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { case ',': case '.': case '+': + case '<': + case '>': case '-': case ':': case '=': @@ -759,8 +581,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { if (!strcasecmp(lexeme, mne[k])) { lex_type = TOK_OPCODE; isop = 1; - l[line].mne = k; - address++; + l->count++; + t = make_token(lex_type, 0xFF, k, ""); break; } } @@ -774,6 +596,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { case '.': case '+': case '-': + case '<': + case '>': case ':': case ';': case '=': @@ -800,29 +624,25 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { } if (lexeme[k] == '\0') { if (num) { - switch (lex_type) { - default: - if (l[line].cm != 0xFF) { - case TOK_PLUS : - case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, 10); - l[line].aopbase = BASE_DEC; - } else { - case TOK_SYM: l[line].op = strtoull(lexeme, NULL, 10); - l[line].opbase = BASE_DEC; - } - if (lex_type == TOK_SYM) { - mksymbol(sym, l[line].op, 1, 0, 0, dbg); - l[line].sym = get_symid(sym, address, line, dbg); - isfixup += (l[line].sym == 0xFFFF); - if (dbg) { - printf("lex(): isfixup: %u\n", isfixup); - } - } - break; + value = 0; + value = strtoull(lexeme, NULL, 10); + if (lt->id == TOK_SYM) { + mksymbol(sym, value, 1, 0, 0, dbg); + if (lt) { + lt->word = get_symid(sym, address, lt, dbg); + } + isfixup += (lt->word == 0xFFFF); + if (dbg) { + printf("lex(): isfixup: %u\n", isfixup); + } } lex_type = TOK_DEC; + l->count++; + t = make_token(lex_type, 0, value, ""); } else if (isch && lex_type != TOK_HEX && lex_type != TOK_BIN) { lex_type = TOK_SYM; + l->count++; + t = make_token(lex_type, 0, 0, ""); memcpy(sym, lexeme, j+1); uint8_t spaces = 0; for (; isspace(str[i+spaces]); spaces++); @@ -830,8 +650,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { printf("lex(): spaces: %u\n", spaces); } if (str[i+spaces] != ':' && str[i+spaces] != '=') { - l[line].sym = get_symid(lexeme, address, line, dbg); - isfixup += l[line].sym == 0xFFFF; + t->word = get_symid(lexeme, address, t, dbg); + isfixup += (t->word == 0xFFFF); if (dbg) { printf("lex(): isfixup: %u\n", isfixup); } @@ -842,6 +662,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { } break; } + if (!l->tok && t) { + l->tok = tokens; + } if (dbg) { printf("lex(): lexeme: %s, lex_type: %s\n", lexeme, (lex_type != 0xFF) ? lex_tok[lex_type] : "TOK_NONE"); } @@ -850,7 +673,7 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { if (lex_type == TOK_OPCODE && !isop) { j = 0; } else { - if (lex_type == TOK_PLUS || lex_type == TOK_MINUS) { + if (lex_type == TOK_EXPR) { i++; } else { switch (str[i]) { @@ -859,6 +682,8 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { case '.': case '+': case '-': + case '<': + case '>': case ':': case ';': case '=': @@ -875,10 +700,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { } if (lex_type == TOK_COMMENT) { if (!isstart) { - l[line].etab = tab; - l[line].espace = space; + l->etab = tab; + l->espace = space; if (dbg) { - printf("lex(): ending tabs: %u, ending spaces: %u\n", l[line].etab, l[line].espace); + printf("lex(): ending tabs: %u, ending spaces: %u\n", l->etab, l->espace); } } } @@ -886,48 +711,29 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { memset(lexeme, 0, strlen(lexeme)+1); lex_type = 0xFF; } + if (t) { + lt = t; + t = t->next; + } } if (i) { - address = update_addr(l, address, isfixup, line, dbg); + l->tok = tokens; + tokens = NULL; + last_tok = NULL; + bytecount dummy; + address = parse_tokens(l->tok, &dummy, 0, address, dbg); if (dbg) { printf("lex(): Next address: $%"PRIX64"\n", address); - printf( - "lex(): " - "address: $%"PRIX64 - ", dir: %u" - ", mne: $%02X" - ", rs: %u" - ", am: %u" - ", cm: %u" - ", opbase: %u" - ", com: $%04X" - ", sym: $%04X" - ", op: $%016"PRIX64 - ", aop: $%016"PRIX64 - ", ln: %u\n" - , l[line].addr - , l[line].dir - , l[line].mne - , l[line].rs - , l[line].am - , l[line].cm - , l[line].opbase - , l[line].com - , l[line].sym - , l[line].op - , l[line].aop - , line); } if (ln > linenum || islinenum) { - l[line].linenum = ln; + l->linenum = ln; if (ln > linenum) { linenum+=(10+(ln & 10)); } } else if (!islinenum) { - l[line].linenum = linenum; + l->linenum = linenum; linenum += 10; } - lineidx += (line == lineidx); } return address; } diff --git a/programs/subasm-2.s b/programs/subasm-2.s deleted file mode 100644 index f10dac8..0000000 --- a/programs/subasm-2.s +++ /dev/null @@ -1,323 +0,0 @@ -; SuBAsm -; The Sux Bootstrapped Assembler. -; -; by mr b0nk 500 <b0nk@b0nk.xyz> - -.org incl -; String Constants. -prg_name: - .byte "SuBAsm" -ver_txt: - .byte ", version " -ver_num: - .byte "0.1" - -; Directives. -dir: - .byte "org" - .byte "byte" - .byte "word" - .byte "dword" - .byte "qword" - .byte "include" - -; Short form Commands. -sh_cmds: - .byte "vlahirs" - -; Commands. -cmds: - .byte "viewmem" - .byte "list" - .byte "asm" - .byte "help" - .byte "inst" - .byte "run" - .byte "set" - -; Instruction Mnemonics. -mne: - .byte "AAB" - .byte "ABA" - .byte "ADC" - .byte "AND" - .byte "ARB" - .byte "ASR" - .byte "BCC" - .byte "BCS" - .byte "BEQ" - .byte "BNE" - .byte "BNG" - .byte "BPO" - .byte "BRK" - .byte "BVC" - .byte "BVS" - .byte "CAB" - .byte "CLC" - .byte "CLI" - .byte "CLV" - .byte "CMP" - .byte "CPB" - .byte "CPS" - .byte "CPX" - .byte "CPY" - .byte "DAB" - .byte "DEB" - .byte "DEC" - .byte "DEX" - .byte "DEY" - .byte "DIV" - .byte "ENT" - .byte "INB" - .byte "INC" - .byte "INX" - .byte "INY" - .byte "JMP" - .byte "JSL" - .byte "JSR" - .byte "LDA" - .byte "LDB" - .byte "LDX" - .byte "LDY" - .byte "LLB" - .byte "LRB" - .byte "LSL" - .byte "LSR" - .byte "MAB" - .byte "MUL" - .byte "NOP" - .byte "OAB" - .byte "ORA" - .byte "PHA" - .byte "PHB" - .byte "PHP" - .byte "PHX" - .byte "PHY" - .byte "PLA" - .byte "PLB" - .byte "PLP" - .byte "PLX" - .byte "PLY" - .byte "RLB" - .byte "ROL" - .byte "ROR" - .byte "RRB" - .byte "RTI" - .byte "RTL" - .byte "RTS" - .byte "SAB" - .byte "SBC" - .byte "SEC" - .byte "SEI" - .byte "STA" - .byte "STB" - .byte "STT" - .byte "STX" - .byte "STY" - .byte "TAB" - .byte "TAX" - .byte "TAY" - .byte "TBA" - .byte "TSX" - .byte "TXA" - .byte "TXS" - .byte "TXY" - .byte "TYA" - .byte "TYX" - .byte "WAI" - .byte "XAB" - .byte "XOR" - -; Command subroutine table. -cmd_srt: - .word viewmem - .word list - .word asm - .word help - .word inst - .word run - .word set - -; Hex character table. -hex_char: - .byte "0123456789ABCDEF" - - -.org $4400 -; Subroutine pointer. -sub_ptr: - .word 0 - -; Indecies. -idx0: - .word 0 -idx1: - .word 0 -idx2: - .word 0 - -; Program Counter. -prg_cnt: - .qword 0 - -; Start of program code. -.org parser -subasm: - ldb #0 ; Set the first pointer - lda.w #cmd_buf ; to the command buffer. - jsl set_ptr ; - tba ; Reset A. - tax ; Reset X. - jsl chk_shcmd ; Did we get a shortend command? - bne parse_cmd ; Yes, so skip everything else. - jsl chk_cmd ; No, but did we get a full command? - bne parse_cmd ; Yes, so skip everything else. - jsl lexer ; No, so start lexing this line. -subasm_end: - rtl ; End of subasm. - -parse_cmd: - inb ; Set the second pointer - lda.w #cmd_srt ; to the command subroutine table. - jsl set_ptr ; - deb ; Reset B. - tba ; Reset A. - lda f ; Get the command ID. - cmp #8 ; Is the command ID greater than the command count? - bcs subasm_end ; Yes, so we're done. - lsl #1 ; No, so multiply the command ID by two. - phy #2 ; Preserve the screen buffer position. - tay ; Set the index to the offset that we just calculated. - lda.w (ptr2), y ; Get the command subroutine, from the command subroutine table. - ply #2 ; Get back the screen buffer position. - ldb #2 ; Save it in the third pointer. - jsl set_ptr ; - ldb #0 ; Reset B. - jsr (ptr3) ; Run the command's subroutine. - jmp subasm_end ; We are done. - -chk_shcmd: - inb ; Set the second pointer - lda.w #sh_cmds ; to the shortend command table. - jsl set_ptr ; - deb ; Reset B. - tba ; Reset A. - phy #2 ; Preserve the screen buffer position. - txy ; Set our index to zero. - lda (ptr), y ; Is there nothing in the command buffer? - beq shcmd_fail ; Yes, so return that we failed. - cmp #' ' ; No, but is this character, a space? - beq shcmd_fail ; Yes, so return that we failed. -shcmd_loop: - ldb (ptr2), y ; Are we at the end of the table? - beq shcmd_fail ; Yes, so return that we failed. - cab ; No, so did the character match? - beq shcmd_fnd ; Yes, so check if there are any arguments. - iny ; No, so check the next command. - jmp shcmd_loop ; Keep looping. -shcmd_fnd: - sty f ; Save the command ID. - ldy #1 ; Check the next character in the command buffer. - lda (ptr), y ; Is this the end of the buffer? - beq shcmd_true ; Yes, so return that we succeded. - cmp #' ' ; No, but is this a space? - beq shcmd_true ; Yes, so return that we succeded. - jmp shcmd_fail ; No, so return that we failed. -shcmd_true: - lda #1 ; Return true. - jmp shcmd_end ; We are done. -shcmd_fail: - tba ; Return false. - tax ; Reset X. -shcmd_end: - ldb #0 ; Reset B. - ply #2 ; Get back the screen buffer position. - rtl ; End of chk_shcmd. - -print_hex: - pha #8 ; Preserve the hex value. - ldb #1 ; Set the second pointer - lda.w hex_char ; to the start of hex character table. - jsl set_ptr ; - ldb #0 ; Reset B. - pla #8 ; Get the hex value back. -pnthex_lp: - pha #8 ; Preserve the hex value. - and #$F ; Mask the lowest nibble. - phx #2 ; Preserve the digit count. - phy #2 ; Preserve the screen buffer position. - tay ; Get the index for the hex digit. - lda (ptr2), y ; Get the hex digit. - ply #2 ; Get back the screen buffer position. - jsl print_char ; Print the hex digit. - plx #2 ; Get the digit count back. - pla #8 ; Get the hex value back. -pnthex_lp1: - cpx #1 ; Is the digit count less than one? - bcc pnthex_lp2 ; Yes, so don't decrement the digit count. - dex ; No, but was the digit count zero, when decremented? - beq pnthex_end ; Yes, so we're done. - jmp pnthex_lp3 ; No, so get the next nibble. -pnthex_lp2: - ldb #1 ; Enable auto digit count. -pnthex_lp3: - lsr #4 ; No, but is the next nibble, a zero? - beq pnthex_lp4 ; Yes, so check if auto digit count is enabled. - jmp pnthex_lp ; No, so print the next digit. -pnthex_lp4: - cpb #1 ; Is auto digit count enabled? - beq pnthex_end ; Yes, so we're done. - jmp pnthex_lp ; No, so keep printing more digits. -pnthex_end: - ldb #0 ; Reset B. - rtl ; End of print_hex. - -print_space: - lda #' ' ; Set the character to a space. - phb #1 ; Preserve the spacing count. - ldb #1 ; Enable replace mode. - stb b ; - jsl print_char ; Print the space. - plb #1 ; Get the spacing count back. - deb ; Have we printed all of the spacing? - beq pntsp_end ; Yes, so we're done. - jmp print_space ; No, so keep printing spaces. -pntsp_end: - rtl ; End of print_space. - -viewmem: - pha #8 ; Preserve the address. - lda #'\n' ; Print a newline. - jsl print_char ; - ldb #19 ; Print 19 spaces. - jsl print_space ; -vmem_lp: - pla #8 ; Get the address back. - nop ; -vmem_end: - rts ; End of viewmem. - -list: - nop ; -list_end: - rts ; End of list. -asm: - nop ; -asm_end: - rts ; End of asm. -help: - nop ; -help_end: - rts ; End of help. -inst: - nop ; -inst_end: - rts ; End of inst. -run: - nop ; -run_end: - rts ; End of run. -set: - nop ; -set_end: - rts ; End of set. diff --git a/programs/subasm.s b/programs/subasm.s index 50f2e8d..350e105 100644 --- a/programs/subasm.s +++ b/programs/subasm.s @@ -3,576 +3,471 @@ ; ; by mr b0nk 500 <b0nk@b0nk.xyz> -; Variables -.org $1000 -prg_name: +MAX_SYM = $800 ; Max symbol size. + +.org incl +; String Constants. +asm_name: .byte "SuBAsm" -ver_txt: - .byte ", version " -ver_num: +asm_ver: .byte "0.1" ; Directives. dir: - .byte "org" + .byte "org", .byte "byte" .byte "word" .byte "dword" .byte "qword" + .byte "include" + +; Short form Commands. +sh_cmds: + .byte "vlahirs" + +; Commands. +cmds: + .byte "viewmem" + .byte "list" + .byte "asm" + .byte "help" + .byte "inst" + .byte "run" + .byte "set" + +; Instruction mnemonics, and opcodes. + +; Legend. +; mne = Mnemonic. +; imm = Immediate data. +; zm = Zero Matrix. +; zmx = Zero Matrix, indexed with X. +; zmy = Zero Matrix, indexed with Y. +; ind = Indirect. +; idx = Indexed Indirect. +; idy = Indirect Indexed. +; abs = Absolute. +; imp = Implied. -; Instruction mnemonics. mne: - .byte "CPS" - .byte "ADC" - .byte "AAB" - .byte "PHB" - .byte "PHP" - .byte "PHA" - .byte "PHY" - .byte "TAY" - .byte "PHX" - .byte "TAX" - .byte "TYX" - .byte "JMP" - .byte "SBC" - .byte "SAB" - .byte "PLB" - .byte "PLP" - .byte "PLA" - .byte "PLY" - .byte "TYA" - .byte "PLX" - .byte "TXA" - .byte "TXY" - .byte "JSR" - .byte "AND" - .byte "ABA" - .byte "STT" - .byte "TAB" - .byte "TSX" - .byte "BPO" - .byte "ORA" - .byte "OAB" - .byte "TBA" - .byte "SEI" - .byte "TXS" - .byte "BNG" - .byte "XOR" - .byte "XAB" - .byte "CLI" - .byte "BCS" - .byte "LSL" - .byte "LLB" - .byte "STB" - .byte "SEC" - .byte "STA" - .byte "STY" - .byte "STX" - .byte "BCC" - .byte "LSR" - .byte "LRB" - .byte "LDB" - .byte "CLC" - .byte "LDA" - .byte "LDY" - .byte "LDX" - .byte "BEQ" - .byte "ROL" - .byte "RLB" - .byte "SSP" - .byte "BNE" - .byte "ROR" - .byte "RRB" - .byte "CSP" - .byte "BVS" - .byte "MUL" - .byte "MAB" - .byte "SEV" - .byte "BVC" - .byte "DIV" - .byte "DAB" - .byte "CLV" - .byte "RTS" - .byte "CMP" - .byte "CAB" - .byte "CPY" - .byte "CPX" - .byte "CPB" - .byte "ENT" - .byte "RTI" - .byte "INC" - .byte "IAB" - .byte "INY" - .byte "INX" - .byte "DEC" - .byte "DBA" - .byte "DEY" - .byte "DEX" - .byte "WAI" - .byte "JSL" - .byte "ASR" - .byte "ARB" - .byte "NOP" - .byte "RTL" - .byte "BRK" - - -scr_row: - .byte $0 -scr_col: - .byte $0 -a: - .word $0 -b: - .word $0 -c: - .word $0 -d: - .word $0 - -str_buf: - -; Input buffer. -.org $2000 -buf: - -.org $2400 -ptr1: - .qword $2500 - -ptr2: - .qword $2900 - -; Control Register. -.org $C000 -ctrl_reg: - -; Screen. -.org $C001 -scr: - -; Keyboard. -.org $C002 -kbd: - -; Main program. -.org $0 -reset: - cps - ldx.w #$FFFF - txs - ldy #0 - jsr clr_buf - ldx.w #0 ; Reset x. - ldy #0 ; Reset y. - jmp print_title - -read: - lda ctrl_reg ; Is the keyboard ready? - beq read ; Loop until the keyboard is ready. - lda #0 ; Start resetting the control register. - sta ctrl_reg ; Reset the control register. - jmp getchar ; We got a key. - -rset_x: - - ldx #0 ; Reset x. - stx.w x - rts - -print_title: - lda prg_name, x - beq print_ver ; Did we find a null terminator? - sta ; Print character. - inx ; Increment offset. - inc x - jmp print_title ; Keep printing more characters. - -print_ver - jsr rset_x - lda ver_txt, x - beq print_num ; Did we find a null terminator? - sta scr ; Print character. - inx ; Increment offset. - jmp print_ver ; Keep printing more characters. - -print_num: - lda ver_num, x - beq getline ; Did we find a null terminator? - sta scr ; Print character. - inx ; Increment offset. - jmp print_num ; Keep printing more characters. -getline: - lda #$A - sta scr ; Print newline - inc scr_row - lda #0 - sta scr_col - inc y - jsr rset_x - jmp read - -getchar: - lda kbd ; Get typed character. - cmp #$1B ; Did the user type an escape? - beq esc ; Yes, so start getting the escape code. - cmp #$A ; Did the user type a newline? - beq nl ; Yes, so start parsing the input. - cmp #8 ; Did the user type a backspace? - beq bs ; Yes, so start checking the buffer. - jsr echo ; Print character to screen. - -store_char: - sta buf, y ; Store typed character into the input buffer. - iny ; Increment buffer offset. - jmp read ; Get another character. - -esc: - lda ctrl_reg ; Skip the '['. - lda ctrl_reg ; Get the next character. - beq read ; We have an error, so discard it, and go back to getting user input. - lda kbd ; Get the escape code. - sta c ; Store the escape code, until we need it. - jsr isup ; Check if the user pressed up. - lda d - cmp #0 - bne esc_end - jsr isdown ; Check if the user pressed down. - lda d - cmp #0 - bne esc_end - lda #0 - jsr isleft ; Check if the user pressed left. - lda d - cmp #0 - bne esc_end - jsr isright ; Check if the user pressed right. -esc_end: - lda #$0 - sta d - jmp rset_a ; Go back to getting user input. - -isup: - lda scr_row ; Is the cursor at the top of the screen? - beq isup_done ; Yes, so return. - lda c ; No, so load the escape code back into the accumulator. - cmp #$41 ; Did the user press the up arrow key? - beq up ; Yes, so move the cursor up. -isup_done: - rts ; End of isup. - -isdown: - lda scr_row ; Start checking the y coordinate of the cursor. - cmp #$17 ; Is the cursor at the bottom of the screen? - beq isdown_done ; Yes, so return. - lda c ; No, so load the escape code back into the accumulator. - cmp #$42 ; Did the user press the down arrow key? - beq down ; Yes, so move the cursor down. -isdown_done: - rts ; End of isdown. - -isright: - lda scr_col ; Start checking the x coordinate of the cursor. - cmp #$4F ; Is the cursor at the far right of the screen? - beq isright_end ; Yes, so return. - lda c ; No, so load the escape code back into the accumulator. - cmp #$43 ; Did the user press the right arrow key? - beq right ; Yes, so move the cursor right. -isright_end: - rts ; End of isright. - -isleft: - lda scr_col ; Is the cursor at the far left of the screen? - beq isleft_done ; Yes, so return. - lda c ; No, so load the escape code back into the accumulator. - cmp #$44 ; Did the user press the left arrow key? - beq left ; Yes, so move the cursor left. -isleft_done: - rts ; End of isleft. - -up: - dec scr_row - jsr update_pos - lda #1 - sta d - jmp isup_done -down: - inc scr_row - jsr update_pos - lda #1 - sta d - jmp isdown_done -right: - inc scr_col - jsr update_pos - jmp isright_end -left: - dec scr_col - jsr update_pos - lda #1 - sta d - jmp isleft_done - -update_pos: - lda #$1B ; Print an escape character - sta scr ; to the screen. - lda #$5B ; Print '[' - sta scr ; to the screen, and start the escape sequence. - jsr getrow ; Start printing the row number to the screen. - jsr getcol ; Start printing the column number to the screen. - lda #$48 ; Print 'H' - sta scr ; to the screen. - rts ; End of update_pos. -getrow: - lda scr_row ; Get the cursor's y coordinate. - div #$A ; Divide A by 10. - adc #$30 ; Convert it to ascii, and - sta scr ; print to the screen. - tba ; Get the remainder. - adc #$30 ; Convert it to ascii, and - sta scr ; print to the screen. - rts ; End of getrow. -getcol: - lda #$3B ; Print ';' - sta scr ; to the screen. - lda scr_col ; Get the cursor's x coordinate. - div #$A ; Divide A by 10. - adc #$30 ; Convert it to ascii, and - sta scr ; print to the screen. - tba ; Get the remainder. - adc #$30 ; Convert it to ascii, and - sta scr ; print to the screen. - rts ; End of getrow. - - - -nl: - sta scr ; Print newline. - inc scr_row ; Move the cursor down one line. - lda #0 ; Put a null terminator, in place of the newline. - sta scr_col ; Move the cursor back to column 0. - sta buf, y ; Place it into the input buffer. - ldy.w #0 ; Reset y, to parse the input. - jsr parse ; Start parsing input. - -back: - sta scr ; Print backspace. - lda #0 ; Put a null terminator, in place of the backspace. - sta buf, y ; Place it into the input buffer. - dey ; Decrement buffer offset. - dec scr_col - jmp read ; Get next character. - -bs: - cpy #0 ; Are we at the start of the buffer? - beq read ; We are, so do not store the backspace into the buffer. - jmp back ; We are not, so add the backspace to the buffer. - -parse: - jsr getdir - jsr - rts - -getdir: - iny ; Increment offset. - lda buf, y - jsr iswhite - bcs getdir ; Reset y, if we hit the null terminator. - cmp #$2E ; Is this character a '.'? - bne getdir_exit ; No, so return. - jsr clr_ptr - -getdir_end: - iny ; Increment offset. - lda buf, y - jsr iswhite - bcs getdir_cmp - ora #%00100000 ; Make character lower case. - sta (ptr1), y - jmp getdir_end -gettok: - ply #1 - iny -gettok2: - lda buf, y - jsr istoken - bcs gettok3 - jmp gettok2 -gettok3: - cmp #$ - cmp #$24 ; Is this character, a '$'? - beq getaddr ; Yes, so start getting the address. - - - -getdir_cmp: - phy #1 - ldy.w #0 - tyx -getdir_cpl: - ldb dir, x ; Start checking if the directive we're using, is "org". - stb (ptr2), y - beq getdir_scmp - inx - iny - jmp getdir_cpl -getdir_scmp: - ldy #0 - jsr strcmp - cpx #0 - beq getdir_tok -getdir_exit: - rts ; End of getdir. - - -istoken: - cmp #$20 ; Is this character a space? - beq istoken_f ; Yes, so return false. - cmp #$09 ; Is this character a tab? - beq istoken_f ; Yes, so return false. - cmp #$A ; Is this character a newline? - beq istoken_f ; Yes, so return false. - cmp #$3B ; Is this character a ';'? - beq istoken_f ; Yes, so return false. - cmp #0 ; Is this character a null terminator? - beq istoken_f ; Yes, so return false. - sec ; Return true. - rts ; End of istoken. -istoken_f - clc ; Return false. - rts ; End of istoken_f. - -iswhite: - cmp #$20 ; Is this character a space? - beq iswhite_t ; Yes, so return true. - cmp #9 ; Is this character a tab? - beq iswhite_t ; Yes, so return true. - clc ; No, so return false. - rts ; End of iswhite. -iswhite_t: - sec ; Return true. - rts ; End of iswhite_t. - -rset_y: - ldy.w #0 - jmp print_buf ; Print the input buffer. - -print_buf: - lda buf, y ; Get a character from the input buffer. - beq fin ; Are we done with printing the buffer? - sta scr ; Print said character. - iny - jmp print_buf ; Keep printing the buffer. - -spin: - nop - nop - nop - jmp spin - -clr_buf: - lda #0 - cpy.w #$3FF - beq clr_end - sta buf, y - iny - jmp clr_buf -clr_sbuf: - lda #0 - cpy.w #$1FF - beq clr_end - sta str_buf, y - iny - jmp clr_sbuf - -clr_end: - rts - -echo: - tab - ldx scr_col - cpx #$4F - bne echo_print - cmp #$A - beq linewrap -linewrap: - inc scr_row - ldx #0 - stx scr_col - jsr update_pos -echo_print: - tba - sta scr ; Echo typed character. - inc scr_col ; Increment the cursor's x coordinate. - sta buf, y ; Store typed character into the input buffer. - iny ; Increment the buffer offset. - rts ; Return. - -clr_ptr: - lda #0 - cpy.w #$3FF - beq ptr_end - sta (ptr1), y - sta (ptr2), y - iny - jmp clr_ptr -ptr_end: - rts - -strcmp: - lda (ptr1), y - cmp (ptr2), y - bne strcmp_l1 - tax - beq strcmp_l3 - iny - bne strcmp - jmp strcmp - - -strcmp_l1: - bcs strcmp_l2 - ldx #0 - dex - rts - -strcmp_l2: - ldx #1 -strcmp_l3: - rts - - -.org $FFC0 -.qword reset - -.org $FF50 -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin - -.org $FFA0 -.qword irq_routine -.org $0 -v -.org $100 -v -.org $200 -v -.org $300 -v -.org $1000 -v -.org $1100 -v -.org $1200 -v -.org $1300 -v -.org $1400 -v -q - +; mne imm, zm, zmx, zmy, ind, idx, idy, abs, imp + .byte "CPS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00 + .byte "ADC", $01, $06, $FF, $FF, $FF, $FF, $FF, $04, $FF + .byte "AAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $02 + .byte "PHP", $08, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "CPB", $09, $2D, $FF, $FF, $55, $AD, $AC, $2C, $FF + .byte "PHB", $0A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "DEC", $FF, $0D, $FF, $FF, $FF, $FF, $FF, $0C, $E5 + .byte "JMP", $FF, $0E, $FF, $FF, $CE, $FF, $FF, $10, $FF + .byte "SBC", $11, $16, $FF, $FF, $FF, $FF, $FF, $14, $FF + .byte "SAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $12 + .byte "ENT", $18, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "CPY", $19, $3D, $FF, $FF, $85, $FF, $FF, $4C, $FF + .byte "PLB", $1A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "INC", $FF, $1D, $FF, $FF, $FF, $FF, $FF, $1C, $F5 + .byte "JSR", $FF, $1E, $FF, $FF, $BE, $FF, $FF, $FF, $FF + .byte "JSL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $20, $FF + .byte "AND", $21, $26, $FF, $FF, $FF, $FF, $FF, $24, $FF + .byte "ABA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $22 + .byte "PLP", $28, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "CPX", $29, $4D, $FF, $FF, $B5, $FF, $FF, $3C, $FF + .byte "PHY", $2A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "BPO", $FF, $2E, $FF, $FF, $FF, $FF, $FF, $30, $FF + .byte "ORA", $31, $36, $FF, $FF, $FF, $FF, $FF, $34, $FF + .byte "OAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $32 + .byte "STT", $38, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "PLY", $3A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "BNG", $FF, $3E, $FF, $FF, $FF, $FF, $FF, $40, $FF + .byte "XOR", $41, $46, $FF, $FF, $FF, $FF, $FF, $44, $FF + .byte "XAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $42 + .byte "PHA", $48, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "PHX", $4A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "BCS", $FF, $4E, $FF, $FF, $FF, $FF, $FF, $50, $FF + .byte "LSL", $51, $56, $FF, $FF, $FF, $FF, $FF, $54, $FF + .byte "LLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $52 + .byte "CLC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $58 + .byte "PLX", $5A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "BCC", $FF, $5E, $FF, $FF, $FF, $FF, $FF, $60, $FF + .byte "LSR", $61, $66, $FF, $FF, $FF, $FF, $FF, $64, $FF + .byte "LRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $62 + .byte "PLA", $68, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "TAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $6A + .byte "BEQ", $FF, $6E, $FF, $FF, $FF, $FF, $FF, $70, $FF + .byte "ROL", $71, $76, $FF, $FF, $FF, $FF, $FF, $74, $FF + .byte "RLB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $72 + .byte "SEC", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $78 + .byte "TBA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $7A + .byte "BNE", $FF, $7E, $FF, $FF, $FF, $FF, $FF, $80, $FF + .byte "ROR", $81, $86, $FF, $FF, $FF, $FF, $FF, $84, $FF + .byte "RRB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $82 + .byte "DEY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $88 + .byte "TAY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $8A + .byte "BVS", $FF, $8E, $FF, $FF, $FF, $FF, $FF, $90, $FF + .byte "MUL", $91, $96, $FF, $FF, $FF, $FF, $FF, $94, $FF + .byte "MAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $92 + .byte "CLI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $98 + .byte "TYA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $9A + .byte "BVC", $FF, $9E, $FF, $FF, $FF, $FF, $FF, $A0, $FF + .byte "DIV", $A1, $A6, $FF, $FF, $FF, $FF, $FF, $A4, $FF + .byte "DAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A2 + .byte "INY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $A8 + .byte "TAX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AA + .byte "RTS", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $AE + .byte "RTL", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B0 + .byte "CMP", $B1, $B6, $FF, $FF, $25, $7D, $7C, $B4, $FF + .byte "CAB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B2 + .byte "SEI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $B8 + .byte "LDX", $B9, $BD, $FF, $C9, $95, $FF, $FF, $BC, $FF + .byte "TXA", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $BA + .byte "RTI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C0 + .byte "LDA", $C1, $C6, $79, $39, $05, $5D, $5C, $C4, $FF + .byte "DEX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C5 + .byte "CLV", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $C8 + .byte "TYX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $CA + .byte "STA", $FF, $CD, $89, $49, $15, $6D, $6C, $CC, $FF + .byte "TSX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D0 + .byte "LDB", $D1, $D6, $99, $59, $35, $8D, $8C, $D4, $FF + .byte "INX", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D5 + .byte "WAI", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $D8 + .byte "TXY", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $DA + .byte "STB", $FF, $DD, $A9, $69, $45, $9D, $9C, $DC, $FF + .byte "TXS", $E0, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte "LDY", $E1, $E6, $E9, $FF, $65, $FF, $FF, $E4, $FF + .byte "BRK", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $E8 + .byte "NOP", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EA + .byte "STY", $FF, $ED, $F9, $FF, $75, $FF, $FF, $EC, $FF + .byte "DEB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $EE + .byte "ASR", $F1, $F6, $FF, $FF, $FF, $FF, $FF, $F4, $FF + .byte "ARB", $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $F2 + .byte "STX", $FF, $FD, $FF, $D9, $A5, $FF, $FF, $FC, $FF + .byte "INB" $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FE + +; Command subroutine table. +cmd_srt: + .word viewmem + .word list + .word asm + .word help + .word inst + .word run + .word set + +; Hex character table. +hex_char: + .byte "0123456789ABCDEF" + + +; Token table. +.org $20000 +tokline: + +.org cmd_buf+$400 +; Program Counter. +prg_cnt: + .qword 0 +; Hex digit string buffer. +hex_str: + .qword 0, 0 +; String buffer. +strbuf: + +.org strbuf+$80 +; Subroutine pointer. +sub_ptr: + .word 0 + +; Indecies. +idx0: + .qword 0 +idx1: + .qword 0 +idx2: + .qword 0 +idx3: + .qword 0 + +; Lexeme string. +lexeme: + +; Symbol tables. +.org lexeme+$100 +sym_val: +.org sym_val+$4000 +sym_id: +.org sym_id+$1000 +sym_def: +.org sym_def+$100 +sym_name: + +; Fixup table. +; Fixups are unresolved symbols. +.org sym_name+$1000 +fix_sym: +.org fix_sym+$1000 +fix_ln: +.org fix_ln+$1000 +fix_val: + + +; Start of program code. +.org parser +subasm: + ldb #0 ; Set the first pointer + lda.d #cmd_buf ; to the command buffer. + jsl set_ptr ; + tba ; Reset A. + tax ; Reset X. + jsl chk_shcmd ; Did we get a shortend command? + bne parse_cmd ; Yes, so skip everything else. + jmp subasm_end ; + jsl chk_cmd ; No, but did we get a full command? + bne parse_cmd ; Yes, so skip everything else. + jsl lexer ; No, so start lexing this line. +subasm_end: + rtl ; End of subasm. + +parse_cmd: + ldb #1 ; Set the second pointer + lda.d #cmd_srt ; to the command subroutine table. + jsl set_ptr ; + deb ; Reset B. + tba ; Reset A. + lda f ; Get the command ID. + cmp #8 ; Is the command ID greater than the command count? + bcs subasm_end ; Yes, so we're done. + lsl #1 ; No, so multiply the command ID by two. + phy #2 ; Preserve the screen buffer position. + tay ; Set the index to the offset that we just calculated. + lda.w (ptr2), y ; Get the command subroutine, from the command subroutine table. + ply #2 ; Get back the screen buffer position. + ldb #2 ; Save it in the third pointer. + jsl set_ptr ; + ldb #0 ; Reset B. + jsr (ptr3) ; Run the command's subroutine. + jmp subasm_end ; We are done. + +chk_shcmd: + tba ; Reset A. + inb ; Set the second pointer + lda.w #sh_cmds ; to the shortend command table. + jsl set_ptr ; + deb ; Reset B. + tba ; Reset A. + phy #2 ; Preserve the screen buffer position. + txy ; Set our index to zero. + lda (ptr), y ; Is there nothing in the command buffer? + beq shcmd_fail ; Yes, so return that we failed. + cmp #' ' ; No, but is this character, a space? + beq shcmd_fail ; Yes, so return that we failed. +shcmd_loop: + ldb (ptr2), y ; Are we at the end of the table? + beq shcmd_fail ; Yes, so return that we failed. + cab ; No, so did the character match? + beq shcmd_fnd ; Yes, so check if there are any arguments. + iny ; No, so check the next command. + jmp shcmd_loop ; Keep looping. +shcmd_fnd: + sty f ; Save the command ID. + ldy #1 ; Check the next character in the command buffer. + lda (ptr), y ; Is this the end of the buffer? + beq shcmd_true ; Yes, so return that we succeded. + cmp #' ' ; No, but is this a space? + beq shcmd_true ; Yes, so return that we succeded. + jmp shcmd_fail ; No, so return that we failed. +shcmd_true: + lda #1 ; Return true. + jmp shcmd_end ; We are done. +shcmd_fail: + ldb #0 ; Reset B. + tba ; Return false. + tax ; Reset X. +shcmd_end: + ply #2 ; Get back the screen buffer position. + rtl ; End of chk_shcmd. + +print_hex: + pha #8 ; Preserve the hex value. + and #0 ; Reset A. + ldb #1 ; Set the second pointer + lda.w #hex_char ; to the start of hex character table. + jsl set_ptr ; + inb ; Set the third pointer + lda.d #hex_str ; to the end of hex string buffer. + clc ; Do a non carrying add. + adc #$10 ; + jsl set_ptr ; + ldb #0 ; Reset B. + pla #8 ; Get the hex value back. +pnthex_lp: + pha #8 ; Preserve the hex value. + and #$F ; Mask the lowest nibble. + phy #2 ; Preserve the screen buffer position. + tay ; Get the index for the hex digit. + lda (ptr2), y ; Get the hex digit. + dec ptr3 ; Decrement the string pointer. + sta (ptr3) ; Save the hex digit character in the string. + ply #2 ; Get back the screen buffer position. + pla #8 ; Get the hex value back. +pnthex_lp1: + cpx #1 ; Is the digit count less than one? + bcc pnthex_lp2 ; Yes, so don't decrement the digit count. + dex ; No, but was the digit count zero, when decremented? + beq pnthex_end ; Yes, so we're done. + jmp pnthex_lp3 ; No, so get the next nibble. +pnthex_lp2: + ldb #1 ; Enable auto digit count. +pnthex_lp3: + lsr #4 ; No, but is the next nibble, a zero? + beq pnthex_lp4 ; Yes, so check if auto digit count is enabled. + jmp pnthex_lp ; No, so print the next digit. +pnthex_lp4: + cpb #1 ; Is auto digit count enabled? + beq pnthex_end ; Yes, so we're done. + jmp pnthex_lp ; No, so keep printing more digits. +pnthex_end: + rtl ; End of print_hex. + +charcpy: + ldx idx3 ; Get the string index. + sta strbuf, x ; Save it in the string buffer. + inc idx3 ; Increment the string index. + rtl ; End of charcpy. + +print_hi: + and #0 ; Reset A. + sta idx3 ; Clear the string index. + lda #'$' ; Print the hex delimiter. + jsl charcpy ; + lda.q idx0 ; Get the masked address. + ldx #$10 ; Set digit count to 16. + jsl print_hex ; Print the address. + lda.q hex_str ; Get the lower half of the string. + sta.q strbuf+1 ; Save it in the string buffer. + lda.q hex_str+8 ; Get the upper half of the string. + sta.q strbuf+9 ; Save it in the string buffer. + ldx #$11 ; Add 16 to the index. + stx idx3 ; + lda #':' ; Print a colon. + jsl charcpy ; + lda # ' ' ; Print a space. + jsl charcpy ; + rtl ; End of print_hi. + +print_lo: + lda #0 ; Reset A. + sta idx3 ; Clear the string index. +pntlo_lp: + ldx #2 ; Set digit count to 2. + pha #1 ; Preserve the nibble offset. + jsl print_hex ; Print the low nibble offset. + lda.w (ptr3) ; Get the two digits. + jsl charcpy ; Copy the first digit. + lsr #8 ; Copy the next digit. + jsl charcpy ; + pla #1 ; Get the nibble offset back. + inc ; Increment the offset. + cmp #$10 ; Are we at the last offset? + bcs pntlo_end ; Yes, so we're done. +pntlo_lp1: + pha #1 ; No, so preserve the nibble offset. + lda #' ' ; Add a space to the string buffer. + jsl charcpy ; + pla #1 ; Get the nibble offset back. + jmp pntlo_lp ; Keep looping. +pntlo_end: + inx ; Increment the index by one. + lda #0 ; Null terminate the string buffer. + sta strbuf, x ; + tax ; Reset X. + lda.d #strbuf ; Print the string buffer. + jsl print_str ; + rtl ; End of print_lo. + +print_chunk: + ldx #0 ; Reset X. + phy #2 ; Preserve the screen buffer index. + txy ; Copy the byte index to it. +pntchnk_lp: + and #0 ; Reset A. + ldx #2 ; Set the digit count to 2. + lda (idx0), y ; Get the byte at that address. + jsl print_hex ; Print the byte. + lda.w (ptr3) ; Get the two digits. + jsl charcpy ; Copy the first digit. + lsr #8 ; Copy the next digit. + jsl charcpy ; + iny ; Increment the byte index. + cpy #$10 ; Have we read 16 bytes? + beq pntchnk_end ; Yes, so we're done. + lda #' ' ; No, so add a soace to the string buffer. + jsl charcpy ; + jmp pntchnk_lp ; Keep looping. +pntchnk_end: + ply #2 ; Get the screen buffer index back. + inx ; Increment the index by one. + and #0 ; Null terminate the string. + sta strbuf, x ; + tax ; Reset X. + sta idx3 ; Clear the string index. + rtl ; End of print_chunk. + +viewmem: + lda.q prg_cnt ; Get the program counter. + sta.q idx0 ; Save the address in the first index. + and #$F0 ; Clear the first four bits of the address. + sta idx0 ; Overwrite the first byte, with the masked byte. + lda #19 ; Move the cursor to the right, by 19 columns. + sta scr_col ; + jsl update_pos ; + jsl print_lo ; Print the low nibble offsets. + ldx #0 ; Reset X. + ldb #0 ; Reset B. + stb idx1 ; Reset the byte count. +vmem_lp0: + lda #'\n' ; Print a newline. + jsl print_char ; + jsl print_hi ; Place the address in the string buffer. + jsl print_chunk ; Place the next 16 bytes in the string buffer. + lda.d #strbuf ; Print the string buffer. + jsl print_str ; + inc idx1 ; Increment the chunk count. + ldb idx1 ; Get the chunk count. + cpb #$10 ; Did we print 16 chunks? + beq vmem_end ; Yes, so we're done. + lda.q idx0 ; No, so get the address index. + clc ; Prepare for a non carrying add. + adc #$10 ; Add 16 to the address. + sta.q idx0 ; Put it back into the address. + and #0 ; Reset A. + jmp vmem_lp0 ; Keep looping. +vmem_end: + lda #'\n' ; Print a newline. + jsl print_char ; + and #0 ; Reset A. + rts ; End of viewmem. + + +list: + nop ; +list_end: + rts ; End of list. +asm: + nop ; +asm_end: + rts ; End of asm. +help: + nop ; +help_end: + rts ; End of help. +inst: + nop ; +inst_end: + rts ; End of inst. +run: + nop ; +run_end: + rts ; End of run. +set: + nop ; +set_end: + rts ; End of set. diff --git a/programs/subeditor.s b/programs/subeditor.s index bdd3a11..e344588 100644 --- a/programs/subeditor.s +++ b/programs/subeditor.s @@ -4,17 +4,17 @@ ; mr b0nk 500 <b0nk@b0nk.xyz> ; I/O constants. -status = $C000 ; Keyboard status. -scr = $C001 ; Character that is to be printed. -kbd = $C002 ; Character from the Keyboard. -step = $C010 ; Enables clock stepping, when set. +status = $100 ; Keyboard status. +scr = $101 ; Character that is to be printed. +kbd = $102 ; Character from the Keyboard. +step = $110 ; Enables clock stepping, when set. ; Screen constants. maxrow = 23 ; Screen's row count. maxcol = 79 ; Screen's column count. ; Include SuBAsm. -.include "subasm-2.s" +.include "subasm.s" .org $A000 ; String Literals/Constants. @@ -22,36 +22,49 @@ tok: .byte "dab" msg: .byte "oof, you divided a, and b on me.\n" -string: - .byte "Please, type something.\n" + +ed_name: + .byte "SuBEditor" +ed_ver: + .byte "1" +ed_sver: + .byte ".0.0" + +ver_str: + .byte ", version " +made: + .byte "Created by, " + +author: + .byte "mr b0nk 500" + +;sub_name: +; .byte "SuB Suite" +;sub_ver: +; .byte "0.9" + string2: .byte "You typed, " ; Linewrap bitmask table. bits: - .byte $80 - .byte $40 - .byte $20 - .byte $10 - .byte $08 - .byte $04 - .byte $02 - .byte $01 + .byte $80, $40, $20, $10, $08, $04, $02, $01 ; This label is for any included files. incl: ; Linewrap table. -.org $1000 +.org $30000 bitabl: .qword 0 .qword 0 -; Input buffer. -.org $2000 +; SCreen buffer. +.org bitabl+$1000 buffer: -.org $4000 +; Command buffer. +.org buffer+$2000 cmd_buf: @@ -93,7 +106,7 @@ zero: ; End of pseudo registers. end: - .word 0 + .qword 0 bitmask: .byte 0 scr_str: @@ -129,8 +142,9 @@ reset: inc end ; lda.w #$1FFF ; Set the clear count to $1FFF. sta.w scr_ptr ; - lda.w #buffer ; Set the array to be cleared to the screen buffer. + lda.d #buffer ; Set the array to be cleared to the screen buffer. jsl clr_arr ; Clear the screen buffer. + jsl pnt_strt ; Print the starting message. jmp start ; Goto the start of the main program. clr_arr: @@ -163,6 +177,25 @@ clr_arr_end: plb #1 ; Get whatever was in the B register, back. rtl ; End of clr_arr. +pnt_strt: + lda.w #ed_name ; Print the name of the editor. + jsl print_str ; + lda.w #ver_str ; Print the version text. + jsl print_str ; + lda.w #ed_ver ; Print the version number. + jsl print_str ; + lda.w #ed_sver ; Print the sub version number. + jsl print_str ; + lda #'\n' ; Print a newline. + jsl print_char ; + lda.w #made ; Print the "Created by" text. + jsl print_str ; + lda.w #author ; Print the name of the author. + jsl print_str ; + lda #'\n' ; Print a newline. + jsl print_char ; + rtl ; End of pnt_strt. + start: lda #0 ; TODO: Update this for the Super VIA. sta status ; Clear the control register of the I/O adapter. @@ -171,12 +204,10 @@ start: tay ; Reset the cursor index. lda.w #$3FF ; Set the clear count to $3FF. sta.w scr_ptr ; - lda.w #cmd_buf ; Set the array to be cleared to the command buffer. + lda.d #cmd_buf ; Set the array to be cleared to the command buffer. jsl clr_arr ; Clear the command buffer. ply #2 ; Get back the cursor index. - lda.w #string ; Print the startup message. - jsl print_str ; - lsr #$10 ; Reset the Accumulator. + and #0 ; Reset the Accumulator. sta end ; jmp read ; Start reading the keyboard. @@ -191,19 +222,20 @@ read: jmp read ; No, so keep looping. print_str: - sta.w end ; Save the parameter. + ldx #0 ; Reset X. + sta.q end ; Save the parameter. print_str2: - lda.w end ; Get the parameter. + lda.q end ; Get the parameter. ldb #0 ; Clear the B register. jsl set_ptr ; Set the first pointer to the parameter. tba ; Clear the Accumulator. - inb ; Enable replace mode. - stb b ; pntstr_lp: - lda.w ptr ; Get the first pointer. - cmp.w end ; Did the pointer change? + ldb #1 ; Enable replace mode. + stb b ; + lda.q ptr ; Get the first pointer. + cmp.q end ; Did the pointer change? bne print_str2 ; Yes, so set it back. - lsr #$10 ; No, reset the accumulator. + and #0 ; No, reset the accumulator. phy #2 ; Save the cursor index. txy ; Copy the string index into Y. lda (ptr), y ; Are we at the end of the string? @@ -230,7 +262,7 @@ getbt0: getbt1: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.w #bitabl ; Set the second pointer to the linewrap table. + lda.d #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; lsr #$10 ; Clear the Accumulator. pla #1 ; Get the return byte back. @@ -246,9 +278,9 @@ getbt1: clrbit: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.w #bitabl ; Set the second pointer to the linewrap table. + lda.d #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; - lsr #$10 ; Clear the Accumulator. + and #0 ; Clear the Accumulator. pla #1 ; Get the return byte back. jsl bitpos ; Get the bit, and byte position. xor #$FF ; Invert the bitmask. @@ -266,9 +298,9 @@ bitout: setbit: pha #1 ; Save the parameter. ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.w #bitabl ; Set the second pointer to the linewrap table. + lda.d #bitabl ; Set the second pointer to the linewrap table. jsl set_ptr ; - lsr #$10 ; Clear the Accumulator. + and #0 ; Clear the Accumulator. pla #1 ; Get the return byte back. jsl bitpos ; Get the bit, and byte position. phy #2 ; Save the screen index. @@ -282,7 +314,7 @@ bitpos: ldb #0 ; Make sure that set_ptr sets the first pointer. lda.w #bits ; Set the first pointer to the bitmask table. jsl set_ptr ; - lsr #$10 ; Clear the Accumulator. + and #0 ; Clear the Accumulator. pla #1 ; Get the parameter back. stx bitmask ; Make the line number the bitmask. txa ; Copy it to the Accumulator. @@ -361,10 +393,10 @@ cmd_cpy3: tay ; Place it into the index. ldx.w #0 ; Reset the X register. ldb #0 ; Make sure that set_ptr sets the first pointer. - lda.w #buffer ; Set the first pointer to the start of the screen buffer. + lda.d #buffer ; Set the first pointer to the start of the screen buffer. jsl set_ptr ; inb ; Make sure that set_ptr sets the second pointer. - lda.w #cmd_buf ; Set the second pointer to the start of the command buffer. + lda.d #cmd_buf ; Set the second pointer to the start of the command buffer. jsl set_ptr ; deb ; Set B back to zero. tba ; Set the accumulator to zero. @@ -403,26 +435,26 @@ cmd_cpy_nd: findst: - lda #0 ; + lda #0 ; Reset A. findst_lp: - pha #1 ; - jsl getbit ; - pla #1 ; - bcc findst_done ; - inc ; - dec scr_row ; - bpo findst_lp ; - dec ; - inc scr_row ; + pha #1 ; Save the current line number. + jsl getbit ; Is this the start of the line? + pla #1 ; Get the current line number back. + bcc findst_done ; Yes, so we're done. + inc ; No, so check the next physical line. + dec scr_row ; Are we at the top of the screen? + bpo findst_lp ; No, so keep looping. + dec ; Yes, so move back one line. + inc scr_row ; Put the row postiion back to zero. findst_done: - cmp #0 ; - rtl ; + cmp #0 ; Update all the flags. + rtl ; End of findst. fndend: phb #1 ; Save the contents of the B register. ldb #0 ; Make sure that set_ptr sets the first pointer. - lda.w #buffer ; Set the first pointer to the start of the screen buffer. + lda.d #buffer ; Set the first pointer to the start of the screen buffer. jsl set_ptr ; tba ; Set the Accumulator to zero. plb #1 ; Restore the contents of the B register. @@ -446,16 +478,13 @@ findend: parse: lda #0 ; tax ; - jsl dabbed ; - beq start ; - lda #0 ; - tax ; - jmp result ; + jsl subasm ; + jmp start ; print_char: sta a ; Save the typed character for now. ldb #2 ; Make sure that set_ptr sets the third pointer. - lda.w #buffer ; Set the third pointer to the start of the screen buffer. + lda.d #buffer ; Set the third pointer to the start of the screen buffer. jsl set_ptr ; ldb #0 ; Set B to zero. tba ; Set the Accumulator to zero. @@ -482,25 +511,25 @@ printc: lda b ; No, but was the flag set? bne printc_save ; Yes, so don't shift the line. sty.w scr_ptr ; No, so save the cursor index for later. - jsl fndend ; - jmp prntc_movln ; + jsl fndend ; Find the end of the line. + jmp prntc_movln ; Start shifting the line right. prntc_updt: - lda scr_col ; + lda scr_col ; Save the current column position for later. sta scr_tcol ; prntc_updt2: - jsl findend ; - sta e ; - sta scr_row ; - jsl findst ; - lda scr_row ; + jsl findend ; Find the end of the line. + sta e ; Use it for redrawing the line. + sta scr_row ; Set the row position to to the end of the line. + jsl findst ; Find the start of the line. + lda scr_row ; Get the start of the line. prntc_updt3: - sta f ; - jsl rdrw_ln ; - lda scr_trow ; + sta f ; Set the starting line, to the start of the line. + jsl rdrw_ln ; Redraw the line. + lda scr_trow ; Get the real row position back. sta scr_row ; - lda scr_tcol ; + lda scr_tcol ; Get the real column position back. sta scr_col ; - jsl update_pos ; + jsl update_pos ; Update the cursor's position. dec d ; jmp printc_sav1 ; prntc_movln: @@ -574,22 +603,22 @@ printc_end: rtl ; nl: - lda #0 ; - ldb (ptr3), y ; - bne nl1 ; - sta (ptr3), y ; Store said terminator into the input buffer. + lda #0 ; Reset A. + ldb (ptr3), y ; Is this character not a null terminator? + bne nl1 ; Yes, so don't overwrite it. + sta (ptr3), y ; No, so overwrite it. nl1: - sta scr_col ; - lda scr_row ; - cmp #maxrow ; - bcc nl_inc ; - jsl scrl_down ; - jmp nl_end ; + sta scr_col ; Move the cursor to the start of the next line. + lda scr_row ; Get the row position. + cmp #maxrow ; Are we at the bottom of the screen? + bcc nl_inc ; No, so move down one line. + jsl scrl_down ; Yes, so scroll down one line. + jmp nl_end ; We are done. nl_inc: - inc scr_row ; - jsl update_pos ; + inc scr_row ; Move the cursor down by one line. + jsl update_pos ; Update the cursor's position. nl_end: - lda #'\n' ; + lda #'\n' ; Print the newline. sta a ; jmp printc_end ; @@ -603,12 +632,12 @@ clr_scr: tay ; lda.w #$1FFF ; Set the clear count to $1FFF. sta.w scr_ptr ; - lda.w #buffer ; Set the array to be cleared to the command buffer. + lda.d #buffer ; Set the array to be cleared to the screen buffer. jsl clr_arr ; Clear the screen buffer. tay ; lda.w #$3FF ; Set the clear count to $3FF. sta.w scr_ptr ; - lda.w #buffer ; Set the array to be cleared to the command buffer. + lda.d #cmd_buf ; Set the array to be cleared to the command buffer. jsl clr_arr ; Clear the screen buffer. sta scr_col ; sta scr_row ; @@ -636,18 +665,18 @@ step_dis: jmp printc_end ; back: - ldb #0 ; + ldb #0 ; Reset B, and some flags. stb e ; stb f ; - lda scr_row ; + lda scr_row ; Save the current row position for later. sta scr_trow ; - jsl findend ; - sta scr_row ; + jsl findend ; Find the end of the line. + sta scr_row ; Set our row position to the end of the line. back0: - jsl findst ; - beq back1 ; - bcs back_updt ; - lda scr_trow ; + jsl findst ; Does this line take up more than one real line? + beq back1 ; No, so skip updating any other lines. + bcs back_updt ; Yes, so update the other lines. + lda scr_trow ; Get the real row position back. sta scr_row ; back1: dey ; Decrement the buffer's offset. @@ -655,32 +684,32 @@ back1: sta (ptr3), y ; into the buffer. tyx ; Copy the current cursor index to X. iny ; Increment cursor index. - ldb #0 ; + ldb #0 ; Set shifting direction to left. stb d ; jsl shftln ; Shift line back by one character. lda #$7F ; Print a backspace to the screen. sta scr ; - lda e ; - beq back3 ; + lda e ; Are we updating more than one line? + beq back3 ; No, so skip to the next step. back2: - jsl findend ; - sta e ; - lda scr_col ; + jsl findend ; Yes, so find the end of the line. + sta e ; Set the end parameter to it. + lda scr_col ; Save the current column position for now. sta scr_tcol ; - jsl rdrw_ln ; - lda scr_tcol ; + jsl rdrw_ln ; Start redrawing the line. + lda scr_tcol ; Get the real column position back. sta scr_col ; back3: - lda scr_trow ; + lda scr_trow ; Get the real row position bac. sta scr_row ; dec scr_col ; Move the cursor back by one column, jsl update_pos ; and update it's position. jmp printc_end ; We are done. back_updt: - lda scr_row ; + lda scr_row ; Set the line to start redrawing, to the start of the line. sta f ; - inc e ; - jmp back1 ; + inc e ; Set the redraw flag to true. + jmp back1 ; Start shifting the line back. bs: lda scr_col ; Are we at the far left of the screen? @@ -1155,62 +1184,6 @@ rdrow_end: rdrow_done: rtl ; -result: - lda.w #string2 ; - ldx.w zero ; - jsl print_str ; -rset_x: - lda #0 ; Reset a. - tax ; Reset x. - jmp print_buf ; Print the input buffer. - -dabbed: - ldb #0 ; Make sure that set_ptr is setting the first pointer. - lda.w #cmd_buf ; Set the first pointer to the start of the command buffer. - jsl set_ptr ; - inb ; Make set_ptr set the second pointer. - lda.w #tok ; Set the second pointer to the start of the token string. - jsl set_ptr ; - deb ; Set B back to zero. - tba ; Also set the accumulator back to zero. -dab_st: - phy #2 ; - txy ; - lda (ptr), y ; Are we at the end of the string? - beq dab_pend ; Yes, so return false. - cmp (ptr2), y ; No, but is this character the same as the character in the token string? - beq chk_str ; Yes, so increment the character count. - jmp dab_pend ; No, so return false. -chk_str: - ply #2 ; - inx ; - cpx #3 ; - bne dab_st ; - ldx #0 ; -pnt_msg: - lda.w #msg ; - ldx #0 ; - jsl print_str ; - jmp dab_peqnd ; -dab_pend: - ply #2 ; - lda #1 ; - jmp dab_end ; -dab_peqnd: - lda #0 ; - jmp dab_end ; -dab_end: - rtl ; - -print_buf: - lda.w #cmd_buf ; - jsl print_str ; - lsr #$10 ; Clear the Accumulator. -cmd_clr: - lda #'\n' ; - jsl print_char ; - jmp start ; - rdrw_ln: lda scr_row ; pha #1 ; @@ -1246,12 +1219,15 @@ set_ptr: cpb #2 ; No, but are we setting the third pointer? beq set_ptr3 ; Yes, so start setting it. set_ptr1: + stb.q ptr ; Reset the first pointer. sta.q ptr ; No, so set the first pointer. jmp setptr_end ; We are done. set_ptr2: + stb.q ptr2 ; Reset the second pointer. sta.q ptr2 ; Set the second pointer. jmp setptr_end ; We are done. set_ptr3: + stb.q ptr3 ; Reset the third pointer. sta.q ptr3 ; Set the third pointer. setptr_end: rtl ; End of set_ptr. @@ -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 @@ -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; |