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