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