diff options
-rw-r--r-- | asmmon.c | 10 | ||||
-rw-r--r-- | asmmon.h | 12 | ||||
-rw-r--r-- | assemble.c | 57 | ||||
-rw-r--r-- | disasm.c | 16 | ||||
-rw-r--r-- | io.c | 26 | ||||
-rw-r--r-- | lexer.c | 506 | ||||
-rw-r--r-- | programs/sub-suite/declare.s | 4 | ||||
-rw-r--r-- | programs/sub-suite/free-new.s | 143 | ||||
-rw-r--r-- | programs/sub-suite/free-old.s | 200 | ||||
-rw-r--r-- | programs/sub-suite/lexer.s | 18 | ||||
-rw-r--r-- | programs/sub-suite/libc.s | 499 | ||||
-rw-r--r-- | programs/sub-suite/shift_line.c | 10 | ||||
-rw-r--r-- | programs/sub-suite/subasm-syntax | 56 | ||||
-rw-r--r-- | programs/sub-suite/subasm.s | 361 | ||||
-rw-r--r-- | programs/sub-suite/subeditor.s | 604 | ||||
-rw-r--r-- | programs/sub-suite/test-size.s | 59 | ||||
-rw-r--r-- | programs/sub-suite/utils.s | 312 | ||||
-rw-r--r-- | supervia.c | 18 | ||||
-rw-r--r-- | supervia.h | 25 | ||||
-rw-r--r-- | sux.c | 69 | ||||
-rw-r--r-- | sux.h | 222 | ||||
-rw-r--r-- | test/ortho.s | 20 |
22 files changed, 1970 insertions, 1277 deletions
@@ -305,7 +305,7 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u if (t->next && !isopdone(t)) { op_done = isopdone(t->next); } - if (am != 0xFF && op_done && t->id != TOK_RS && !t->next) { + if (am != 0xFF && op_done && t->id != TOK_RS) { switch (am) { case EIND: putchar('('); am_done = 0; break; case BREG: putchar('b'); am_done = 1; break; @@ -418,10 +418,16 @@ int asmmon(const char *fn) { case PTOK_DQUOTE : case PTOK_SQUOTE : case PTOK_B : + case PTOK_E : case PTOK_X : case PTOK_Y : case PTOK_S : case PTOK_P : + case PTOK_A : + case PTOK_C : + case PTOK_D : + case PTOK_F : + case PTOK_R : case PTOK_MINUS : case PTOK_PLUS : is_valid = 1; break; default : is_valid = 0; stop = 1; break; @@ -440,7 +446,7 @@ int asmmon(const char *fn) { case 'h': cmds = (isshcmd || !strcasecmp(cmd, "help" )) << 4; break; case 'i': cmds = (isshcmd || !strcasecmp(cmd, "inst" )) << 5; break; case 'd': cmds = (isshcmd || !strcasecmp(cmd, "done" )) << 6; break; - case 's': cmds = (isshcmd || !strcasecmp(cmd, "set" )) << 7; break; + case 's': cmds = (isshcmd || !strcasecmp(cmd, "sett" )) << 7; break; case ' ': case '\t': default: @@ -4,11 +4,11 @@ #define MAX_TOK 0x1000 -typedef struct tok token ; -typedef struct ln line ; -typedef struct sym symbol ; -typedef struct fix fixup ; -typedef struct inst instruction ; +typedef struct tok token; +typedef struct ln line; +typedef struct sym symbol; +typedef struct fix fixup; +typedef struct inst instruction; struct tok { @@ -59,6 +59,7 @@ struct sym { symbol *prev; symbol *down; symbol *up; + int depth; uint16_t count; uint64_t val; uint8_t isstruct : 1; @@ -88,6 +89,7 @@ extern symbol *locals; extern symbol *last_loc; extern fixup *fixups; extern fixup *last_fix; +extern tmp_symtab *tmp_sym_table; extern uint8_t lex_type; @@ -479,8 +479,10 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t }*/ for (; t && i < 2; t = t->next) { + reg = (old_i != i) ? 0 : reg; + got_value = (old_i != i) ? 0 : got_value; if (t->subtype == TOK_IND) { - brack_done = 1; + brack_done = (t->id == TOK_REG) ? 2 : 1; } switch (t->id) { case TOK_HEX : @@ -544,8 +546,8 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t } else { if (op[i].type == 1) { if (op[i].id == MEM_IND) { - op[i].id = (!brack_done && got_value) ? MEM_ZRIND : MEM_RIND; - op[i].id = (brack_done && got_value) ? MEM_ZINDR : op[i].id; + op[i].id = ((!brack_done || brack_done == 2) && got_value) ? MEM_ZRIND : MEM_RIND; + op[i].id = (brack_done == 1 && got_value) ? MEM_ZINDR : op[i].id; brack_done = 0; } else { op[i].id = (got_value) ? MEM_ZMR : op[i].id; @@ -578,7 +580,6 @@ token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t op[0].cc = t->byte; i = 3; break; - } if (!t) { break; @@ -737,6 +738,13 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, i = 8; for (; i <= 64; i += 8, j++) { max_val |= ((uint64_t)1 << (i-1)); + /*int64_t tmp_val = (int64_t)op[0].value; + int is_pos = (tmp_val >= 0); + int is_neg = (tmp_val < 0); + if ((is_pos && tmp_val <= ~(int64_t)(max_val)) || (is_neg && tmp_val >= (int64_t)(max_val))) { + opsize = j; + break; + }*/ if ((int64_t)op[0].value >= ~(int64_t)(max_val) || (int64_t)op[0].value <= (int64_t)(max_val)) { opsize = j; break; @@ -917,6 +925,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, if (op[0].cc != 0xFF && op[0].cc < 8) { opcode |= (op[0].cc << 5); } + uint8_t tmp_size = 0; for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { int i2 = 0; int j = 0; @@ -936,17 +945,20 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, if (op[i].id != MEM_IND && op[i].id != 0xFF) { max_val = 0; for (i2 = 8, j = 1; i2 <= 64; i2 += 8, j++) { - max_val |= ((uint64_t)1 << (i2-1)); - if ((int64_t)op[i].value >= ~(int64_t)(max_val) || (int64_t)op[i].value <= (int64_t)(max_val)) { + max_val = ((uint64_t)1 << (i2-1)); + int64_t tmp_val = (int64_t)op[i].value; + int is_pos = (tmp_val >= 0); + int is_neg = (tmp_val < 0); + if ((is_pos && tmp_val <= (int64_t)(max_val-1)) || (is_neg && tmp_val >= -(int64_t)(max_val))) { opsize = j; break; } } } else { max_val = 0; - for (i2 = 8, j = 1; i2 <= 64; i2 += 8, j++) { + for (i2 = 0, j = 1; i2 <= 64; i2 += 8, j++) { max_val |= (0xFF << i2); - if (op[0].value <= max_val) { + if (op[i].value <= max_val) { opsize = j; break; } @@ -965,13 +977,14 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } if (opsize) { uint8_t is_abs = (type == ABS); - if (!is_abs) { + /*if (!is_abs) { switch (opsize) { case 2: opsize = 3; break; case 5: opsize = 6; break; } - } + }*/ prefix |= amp[opsize-1]; + /*tmp_size = (opsize >= tmp_size) ? opsize : tmp_size;*/ } op_size[i] = opsize; if (isasm && dbg) { @@ -981,6 +994,11 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } } } + /*if (tmp_size) { + prefix |= amp[tmp_size-1]; + }*/ + /*op_size[0] = tmp_size; + op_size[1] = tmp_size;*/ } inst_size = write_inst(prefix, ext_prefix, opcode, op, address, op_size, isasm, dbg); address += inst_size; @@ -1218,7 +1236,7 @@ void fix_symtree(line *l) { } } -static inline void free_tokens(token *t) { +static void free_tokens(token *t) { token *tok; if (t != NULL) { tok = t; @@ -1257,7 +1275,7 @@ static void free_symbols(symbol *s) { } } -static inline void free_fixups(fixup *f) { +static void free_fixups(fixup *f) { fixup *fix; if (f != NULL) { fix = f; @@ -1268,6 +1286,17 @@ static inline void free_fixups(fixup *f) { } } +static inline void free_tmp_symtab(tmp_symtab *st) { + tmp_symtab *tmp; + if (st != NULL) { + tmp = st; + st = st->next; + free(tmp); + tmp = NULL; + free_tmp_symtab(st); + } +} + uint64_t get_tokmem(token *t) { uint64_t i = 0; for (; t; t = t->next, i++); @@ -1298,6 +1327,10 @@ void cleanup() { free_fixups(fixups); fixups = NULL; } + if (tmp_sym_table) { + free_tmp_symtab(tmp_sym_table); + tmp_sym_table = NULL; + } while (i < stridx || i < comidx) { if (i < stridx && string[i]) { free(string[i]); @@ -59,6 +59,7 @@ static void sub_dbg(struct sux *cpu, WINDOW *w, uint64_t address, uint64_t *orth adr = read_value(cpu, 0, tmpad, 7, 0, 0); tmpad += 8; wmove(w, 1, 0); + wclrtoeol(w); wprintw(w, "scr_row: %02u, scr_col: %02u, scr_str: %02u, scr_end: %02u", addr[0], addr[1], addr[2], addr[3]); wmove(w, 2, 0); wprintw(w, "bitabl: "); @@ -173,11 +174,10 @@ static uint64_t get_offset(uint64_t value, uint8_t size, char **sign) { size = (size > 8) ? 8 : size; uint8_t msb = size*8; uint64_t mask = (-(uint64_t)1 >> ((8 - size) * 8)); - mask &= (1 << (msb-1)); + mask &= ~(1 << (msb-1)); *sign = ((value >> (msb-1)) & 1) ? "-" : "+"; - if (*sign[0] == '-') { - value &= mask; - value = -(value+1); + if (*sign[0] == '-' && value != (1 << (msb-1))) { + value = (-value) & mask; } return value; } @@ -301,10 +301,6 @@ static void disasm_ortho(struct sux *cpu, WINDOW *w, uint8_t opcode, uint8_t pre uint64_t val = 0; if (op[i].type) { uint8_t addr_size = get_ortho_addrsize(prefix, op[i].id); - if (addr_size != 0xFF) { - uint64_t value = get_offset(op[i].value, addr_size+1, &sign[i]); - sprintf(address[i], "$%0*"PRIX64, (addr_size+1)*2, value); - } if (op[i].id == MEM_SIB) { sprintf(scale[i], "%u*", op[i].scale+1); } else if (op[i].id == MEM_IMM) { @@ -321,6 +317,10 @@ static void disasm_ortho(struct sux *cpu, WINDOW *w, uint8_t opcode, uint8_t pre case MEM_SIB : case MEM_RIND : is_rind = 1; break; } + if (addr_size != 0xFF) { + uint64_t value = (is_rind) ? get_offset(op[i].value, addr_size+1, &sign[i]) : op[i].value; + sprintf(address[i], "$%0*"PRIX64, (addr_size+1)*2, value); + } if (is_rind) { for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) { switch (op[i].rind[j]) { @@ -48,6 +48,7 @@ int get_key(WINDOW *scr) { int x, y; int c; int keycode = 0; + int tmp_flag = dbg_print_per_inst; curs_set(1); if ((key == NULL) || (key && key[key_idx] == '\0') || !kbd_rdy) { c = wgetch(scr); @@ -89,12 +90,17 @@ int get_key(WINDOW *scr) { wrefresh(regs); #endif break; + case KEY_F(3): + dbg_print_per_inst = !dbg_print_per_inst; } #if debug && !bench getyx(scr, y, x); wmove(scr, getmaxy(scr)-1, 0); wclrtoeol(scr); wprintw(scr, "keycode: %i", keycode); + if (tmp_flag != dbg_print_per_inst) { + wprintw(scr, ", Disassemble per instruction %s", (dbg_print_per_inst) ? "enabled" : "disabled"); + } wmove(scr, y, x); #endif } @@ -235,10 +241,16 @@ void reset_esc() { void handle_ctrlcode(int c) { int x, y; uint16_t scr_col = 0; + int tmp_flag = 0; #if debug - if (!subdbg) { - scr_col = (addr[TX_ADDR] != 0x0C && addr[TX_ADDR] != '\n' && scr_col < 160) ? (addr[1] << 1)-2 : 0; - wmove(scr, 28, scr_col); + if (subdbg) { + tmp_flag = (addr[TX_ADDR] != 0x0C && addr[TX_ADDR] != '\n' && scr_col < 160); + if (!tmp_flag) { + wmove(scr, 30, 0); + wclrtoeol(scr); + } + scr_col = (tmp_flag) ? (addr[1] << 1)-2 : 0; + wmove(scr, 30, scr_col); } #endif getyx(scr, y, x); @@ -261,11 +273,11 @@ void handle_ctrlcode(int c) { #if !debug wdelch(scr); #else - if (!subdbg) { + if (subdbg) { scr_col++; - wmove(scr, 28, scr_col--); + wmove(scr, 30, scr_col--); wdelch(scr); - wmove(scr, 28, scr_col); + wmove(scr, 30, scr_col); wdelch(scr); } #endif @@ -283,7 +295,7 @@ void handle_ctrlcode(int c) { /*wmove(scr, y, x);*/ waddch(scr, c); #else - if (!subdbg && scr_col < 160) { + if (subdbg && scr_col < 160) { if (c != ' ') { wprintw(scr, "%02X", c); } else { @@ -10,97 +10,193 @@ symbol *last_loc = NULL; symbol *cur_sym = NULL; symbol *struct_sym = NULL; + line *tmp_line = 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) ? symbols : locals; - uint8_t flag = 0; - for (; s; s = s->next, i++) { - if (!useid && name[0] != s->name[0]) { - continue; - } - flag = (useid) ? (id == s->id) : !strcmp(name, s->name); - if (flag) { - if (def) { - if (s->def) { - if (dbg) { - printf("mksymbol(): oof, you cannot redefine the symbol: %s\n", name); +symbol *find_symbol(symbol *root, const char *name, int depth, uint8_t dbg) { + symbol *s = root; + symbol *ret = NULL; + char *tmp = malloc(strlen(name)+1); + memcpy(tmp, name, strlen(name)+1); + char *scope_name = strtok_r(tmp, ".", &tmp); + size_t name_len = strlen(scope_name); + for (; s != NULL; s = s->next) { + size_t sym_name_len = strlen(s->name); + if (name_len == sym_name_len && scope_name[0] == s->name[0] && !strcmp(scope_name, s->name)) { + if (depth) { + if (s->down) { + ret = find_symbol(s->down, (tmp == NULL) ? scope_name : tmp, depth-1, dbg); + if (ret) { + return ret; } - defined = 1; - } else { - defined = 0; - } - s->def = def; - s->val = val; - s->id = i; - if (dbg) { - printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s\n", def, val, name); - printf("mksymbol(): i: $%X, id: $%04X\n", i, s->id); } + } else { + return s; } - return s; } } - size_t str_size = strlen(name)+1; - s = malloc(sizeof(symbol)); - s->down = NULL; - if (!islocal) { - (last_sym) ? (last_sym->next = s) : (symbols = s); - if (last_sym) { - last_sym->next->prev = last_sym; - last_sym->next->up = last_sym->up; - last_sym->next->down = NULL; + return NULL; +} + +int add_symbol(symbol *sym, const char *name, symbol **root, symbol **lsym, symbol **rloc, symbol **lloc, symbol **csym, int csym_depth, int depth, uint8_t dbg) { + symbol *s = (!depth) ? ((*lsym) ? *lsym : *root): ((*lloc) ? *lloc : *rloc); + sym->next = NULL; + sym->up = NULL; + sym->down = NULL; + sym->prev = NULL; + if (depth && depth >= csym_depth) { + //s = *csym; + s = find_symbol(*root, name, depth-1, dbg); + depth -= (!csym_depth) ? depth-1 : csym_depth; + } + int j = 0; + int is_new_scope = 0; + for (int i = 0; i < depth; i++) { + if (s) { + if (s->down != NULL) { + s->down->up = (s->down->up == NULL) ? s : s->down->up; + s = s->down; + } else if (j) { + return 0; + } else { + int is_first_entry = ((s->up == NULL) || (s->next == NULL && s->up)); + is_new_scope = (depth <= 1 && is_first_entry); + j++; + } } else { - symbols->prev = NULL; - symbols->up = NULL; - symbols->down = NULL; + is_new_scope = 1; + /*return 0;*/ } - } else { - (last_loc) ? (last_loc->next = s) : (locals = s); - if (last_loc) { - last_loc->next->prev = last_loc; - last_loc->next->up = last_loc->up; - last_loc->next->down = NULL; + } + for (; s != NULL && s->next != NULL; s = s->next) { + if (dbg) { + printf("s: %p, s->next: %p, s->prev: %p\n", s, s->next, s->prev); + } + } + if ((is_new_scope && *lsym) || *lloc || *csym) { + /* + if (is_new_scope) { + s = *lsym; } else { - locals->prev = NULL; - locals->down = NULL; + s = (!depth) ? *lsym : *lloc; + }*/ + if (is_new_scope && sym->depth > s->depth) { + s->down = sym; + s->down->up = s; + s->down->prev = NULL; + } else { + s->next = sym; + } + if (dbg) { + for (symbol *tmp = s; tmp && tmp->prev; tmp = tmp->prev) { + printf("add_symbol(): s: %p, s->name: %s, s->next: %p, s->prev: %p, s->up: %p, s->down: %p\n", tmp, tmp->name, tmp->next, tmp->prev, tmp->up, tmp->down); + } + } + sym->next = NULL; + if (s->next == sym) { + sym->prev = s; + if (sym->depth) { + sym->up = s->up; + } + } + sym->down = NULL; + + } + + if ((*root && (*root)->prev)) { + (*root)->prev = NULL; + } + + if ((*rloc && (*rloc)->prev)) { + (*rloc)->prev = NULL; + } + if (!depth) { + if (*lsym == NULL) { + *root = sym; + sym->next = NULL; + sym->prev = NULL; + sym->up = NULL; + sym->down = NULL; + } + *lsym = sym; + *rloc = NULL; + *lloc = NULL; + } else { + if (is_new_scope) { + *lloc = NULL; + } + if (*lloc == NULL) { + *rloc = sym; + sym->next = NULL; + sym->prev = NULL; + sym->down = NULL; } + *lloc = sym; } + *csym = sym; + return 1; +} + +char *find_deepest_scope(const char *name) { + int i; + for (i = strlen(name); i >= 0 && name[i] != '.'; i--); + return (char *)name+(i+1); +} + +symbol *mksymbol(const char *name, uint64_t val, uint8_t def, int depth, uint8_t use_scope, uint16_t id, uint8_t dbg) { + uint16_t i = 0; + symbol *s = find_symbol(symbols, (char *)name, depth, dbg); + char *scope_name = (!use_scope) ? find_deepest_scope(name) : (char *)name; + if (s) { + if (def) { + if (s->def) { + if (dbg) { + printf("mksymbol(): oof, you cannot redefine the symbol: %s\n", scope_name); + } + defined = 1; + } else { + defined = 0; + } + s->def = def; + s->val = val; + s->id = i; + if (dbg) { + printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s\n", def, val, scope_name); + printf("mksymbol(): i: $%X, id: $%04X\n", i, s->id); + } + } + return s; + } + size_t str_size = strlen(scope_name)+1; + + s = malloc(sizeof(symbol)); s->name = malloc(str_size); s->def = def; s->val = val; s->count = 0; s->isstruct = 0; - memcpy(s->name, name, str_size); + s->depth = depth; s->next = NULL; + s->up = NULL; + s->down = NULL; + s->prev = NULL; s->id = sym_count++; - (!islocal) ? (last_sym = s) : (last_loc = s); - if (!islocal) { - s->down = NULL; - /*if (def) { - locals = NULL; - last_loc = NULL; - }*/ - } else { - cur_sym->count++; - } + + memcpy(s->name, scope_name, str_size); defined = 0; if (dbg) { - printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s, id: $%04X\n", def, val, name, sym_count-1); + printf("mksymbol(): def: %u, val: $%016"PRIX64", name: %s, id: $%04X\n", def, val, scope_name, sym_count-1); } return s; } uint16_t fixup_cnt = 0; -symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t islocal, uint8_t dbg) { - symbol *s = mksymbol(name, 0, 0, islocal, 0, 0, dbg); +symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t depth, uint8_t use_scope, uint8_t dbg) { + symbol *s = mksymbol(name, val, 0, depth, use_scope, use_scope, dbg); if (dbg) { printf("get_sym(): Symbol ID: $%X.\n", s->id); } - if (s->def) { - return s; - } else { + if (!s->def) { if (dbg) { printf("get_sym(): oof, symbol %s, does not exist, yet.\n", name); } @@ -112,28 +208,8 @@ symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t islocal, uint8 f->next = NULL; last_fix = f; fixup_cnt++; - return NULL; } -} - -symbol *find_member(char *name, symbol* root, uint8_t dbg) { - /*for (; root->up; root = root->up);*/ - symbol *s = root; - if (s->down == NULL && s->up != NULL) { - s = s->up; - } - do { - s = s->down; - for (symbol *m = s; m; m = m->next) { - size_t len1 = strlen(name); - size_t len2 = strlen(m->name); - if (len1 == len2 && name[0] == m->name[0] && !strcmp(name, m->name)) { - return m; - } - } - for (;s && s->next && !s->down; s = s->next); - } while (s && s->down); - return NULL; + return s; } uint16_t reslv_fixups(uint8_t dbg) { @@ -228,16 +304,62 @@ line *find_line(uint32_t ln, uint8_t dbg) { return l; } +char *mk_scope_name(symbol *csym, int depth, const char *name, uint8_t dbg) { + size_t len = strlen(name); + size_t name_len = len; + symbol *s = csym; + char **scopes; + if (depth) { + scopes = malloc(sizeof(char *)*depth); + } + + for (int i = depth; i && s; i--) { + if (dbg) { + printf("mk_scope_name(): s->depth: %i\n", s->depth); + } + s = (s->depth >= i && s->up) ? s->up : s; + //s = (i < 2 && s->up) ? s->up : s; + len += strlen(s->name); + scopes[i-1] = s->name; + } + + len += depth; + char *scope_name = malloc(len+1); + char *tmp = scope_name; + memset(tmp, 0, len+1); + for (int i = 0; i < depth; i++) { + size_t name_len = strlen(scopes[i]); + memcpy(tmp, scopes[i], name_len); + tmp += name_len; + *tmp++ = '.'; + if (dbg) { + printf("mk_scope_name(): scope_name: %s\n", scope_name); + } + } + memcpy(tmp, name, name_len); + if (dbg) { + printf("mk_scope_name(): scope_name: %s\n", scope_name); + } + return scope_name; +} + int is_struct = 0; int is_anon = 0; -void create_struct(symbol *c_sym, line *l, token *t, token *lt, char *name, uint8_t dbg) { - uint8_t ismember = !(is_struct == 1 && lt && lt->id == TOK_DIR); - mksymbol(name, 0, 1, ismember, 0, 0, dbg); +void create_struct(symbol *c_sym, line *l, token *t, token *lt, const char *name, uint8_t dbg) { + int depth = is_struct-is_anon; + uint8_t ismember = !(depth == 1 && lt && lt->id == TOK_DIR); + int is_new_scope = (lt && lt->id == TOK_DIR); + depth -= is_new_scope; + + char *struct_name = mk_scope_name(c_sym, depth, name, dbg); + symbol *s = mksymbol(struct_name, 0, 1, depth, 0, 0, dbg); + int is_sym_added = add_symbol(s, struct_name, &symbols, &last_sym, &locals, &last_loc, &c_sym, 0, depth, dbg); + t->sym = get_sym(struct_name, 0, t, depth, 0, dbg); + if (isfixup) { isfixup = reslv_fixups(dbg); } - t->sym = get_sym(name, 0, t, ismember, dbg); if (lt && lt->id == TOK_DIR) { t->sym->isstruct = 1; t->id = (lt->type == DIR_STRUCT) ? TOK_STRUCT : TOK_UNION; @@ -257,26 +379,24 @@ void create_struct(symbol *c_sym, line *l, token *t, token *lt, char *name, uint } else { c_sym->down = locals; } - } else { - if (lt && lt->id == TOK_DIR) { - if (lt->type == DIR_UNION || lt->type == DIR_STRUCT) { - c_sym->down = locals; - c_sym->down->up = c_sym; - last_loc->up = c_sym; - c_sym = last_loc; - locals = NULL; - last_loc = NULL; - } - } } cur_sym = c_sym; } void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) { int skip = 0; - if (/*s_sym &&*/ is_anon > 0) { + if (is_anon > 0) { if ((c_sym && c_sym->isanon) || (c_sym->up && !c_sym->up->isanon) || (c_sym && s_sym->isanon)) { - is_anon--; + int depth = is_struct-is_anon; + if ((depth > 0 || (is_struct > 1 && is_anon >= is_struct)) && c_sym->depth > depth) { + for (; c_sym->depth > is_struct-is_anon && c_sym->up; c_sym = c_sym->up) { + if (dbg) { + printf("end_struct(): c_sym->depth: %i, is_struct-is_anon: %i\n", c_sym->depth, is_struct-is_anon); + } + } + } else if (c_sym->depth) { + is_anon--; + } } else if (is_struct <= 0) { is_anon = 0; } @@ -289,15 +409,21 @@ void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) { s->up = c_sym; } if (dbg) { - printf("s: %p, s->up: %p, c_sym: %p, last_loc: %p\n", s, s->up, c_sym, last_loc); + printf("end_struct(): s: %p, s->up: %p, c_sym: %p, last_loc: %p\n", s, s->up, c_sym, last_loc); } } - if (c_sym->down == NULL) { - c_sym->down = locals; - } } if ((is_anon <= 0 || is_struct <= 0)) { - for (s_sym = c_sym; /*s_sym &&*/ s_sym->prev && !s_sym->isanon; s_sym = s_sym->prev); + if (dbg) { + for (symbol *s = c_sym; s->next && !s->isanon; s = s->next) { + printf("end_struct(): %p, s->next: %p, s->prev: %p, s->isanon: %i\n", s, s->next, s->prev, s->isanon); + } + } + for (s_sym = c_sym; s_sym->prev && !s_sym->isanon; s_sym = s_sym->prev) { + if (dbg) { + printf("end_struct(): s_sym: %p, s_sym->next: %p, s_sym->prev: %p, s_sym->isanon: %i\n", s_sym, s_sym->next, s_sym->prev, s_sym->isanon); + } + } struct_sym = s_sym; } if ((is_struct-is_anon) > 0 && !skip) { @@ -307,7 +433,7 @@ void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) { s->up = c_sym->up; } if (dbg) { - printf("s: %p, s->up: %p, c_sym->up: %p, last_loc: %p\n", s, s->up, c_sym->up, last_loc); + printf("end_struct(): s: %p, s->up: %p, c_sym->up: %p, last_loc: %p\n", s, s->up, c_sym->up, last_loc); } } if (c_sym->up) { @@ -318,6 +444,74 @@ void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) { } } +fixup *find_fixup(fixup *root, const char *name, int depth, uint8_t dbg) { + size_t name_len = strlen(name); + for (fixup *f = root; f; f = f->next) { + symbol *s = f->s; + if (s && s->name) { + if (s->depth == depth) { + size_t sym_name_len = strlen(s->name); + if (name_len == sym_name_len && name[0] == s->name[0] && !strcmp(name, s->name)) { + if (!s->def) { + return f; + } + } + } + } + } + return NULL; +} + +void resolve_symbol_names(line *l, const char *name, symbol *sym, int depth, uint8_t dbg) { + size_t name_len = strlen(name); + for (token *t = l->tok; t; t = t->next) { + size_t sym_name_len; + switch (t->id) { + case TOK_LABEL: + case TOK_SYM: + if (t->sym) { + sym_name_len = strlen(t->sym->name); + if (name_len == sym_name_len && name[0] == t->sym->name[0] && !strcmp(name, t->sym->name)) { + if (t->sym->depth == depth && !t->sym->def) { + t->sym = sym; + } + } + } + break; + } + } + if (l->next) { + resolve_symbol_names(l->next, name, sym, depth, dbg); + } +} + +void new_symbol(token *t, const char *name, uint64_t value, int depth, uint8_t dbg) { + size_t name_len = strlen(name); + char *scope_name = mk_scope_name(cur_sym, depth, name, dbg); + symbol *s; + fixup *f = find_fixup(fixups, scope_name, depth, dbg); + if (f == NULL) { + s = mksymbol(scope_name, value, 1, depth, 0, 0, dbg); + } else { + s = f->s; + resolve_symbol_names(lines, scope_name, s, depth, dbg); + s->def = 1; + s->val = value; + free(s->name); + s->name = NULL; + s->name = malloc(name_len+1); + memcpy(s->name, name, name_len+1); + } + int is_sym_added = add_symbol(s, scope_name, &symbols, &last_sym, &locals, &last_loc, &cur_sym, 0, depth, dbg); + if (isfixup) { + isfixup = reslv_fixups(dbg); + } + if (t) { + t->sym = get_sym(scope_name, value, t, depth, 0, dbg); + isfixup += (t->sym == NULL); + } +} + uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { char sym[0x100]; uint16_t i = 0; @@ -337,7 +531,9 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { uint8_t of = 0; uint8_t base = 0; - uint8_t islocal = 0; + int depth = 0; + + int is_inst = 0; uint8_t isop = 0; int num = 0; @@ -355,13 +551,11 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { uint8_t done = 0; - /*uint8_t is_newcom = 0;*/ line *l = NULL; token *st = NULL; token *t = NULL; token *lt = NULL; symbol *tmp_sym = NULL; - symbol *tsym = NULL; while (isdigit(str[i]) && isdelm(str[i], dbg) != 16) { lnum[j++] = str[i++]; @@ -412,6 +606,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { if (((ptok == PTOK_S || ptok == PTOK_B) && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C')) { offset++; } + int is_alpha = 0; switch (get_ptok(str[i+offset], dbg)) { case PTOK_B : case PTOK_E : @@ -424,7 +619,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { case PTOK_D : case PTOK_F : case PTOK_R : - case PTOK_ALPHA : ptok = PTOK_ALPHA; break; + case PTOK_ALPHA : ptok = PTOK_ALPHA; is_alpha = 1; break; case PTOK_NUMBER: if (ptok == PTOK_R) { char reg_num[3]; @@ -435,20 +630,28 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { reg_num[isnum] = '\0'; if (isnum == 2) { int regnum = strtoul(reg_num, NULL, 10); - ptok = (regnum < 11 || regnum > 15) ? PTOK_ALPHA : ptok; + if (regnum < 11 || regnum > 15) { + ptok = PTOK_ALPHA; + is_alpha = 1; + } } else { ptok = PTOK_ALPHA; + is_alpha = 1; } } else { ptok = PTOK_ALPHA; + is_alpha = 1; } break; } - if ((ptok == PTOK_S && str[i+1] && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) { + if (ptok == PTOK_P && toupper(str[i+1]) != 'C') { ptok = PTOK_ALPHA; + is_alpha = 1; } + + ptok = (!is_inst && !is_alpha) ? PTOK_ALPHA : ptok; } - /*i = ptok_handler[ptok](str, i, lex_type, l, t, dbg);*/ + switch (ptok) { case PTOK_DOT: i++; @@ -463,9 +666,10 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { uint16_t tmp = j; for (j = 0; isdelm(str[i+j], dbg) & 16; j++); uint8_t ret = get_ptok(str[i+j], dbg); + ret = (is_altok(ret, dbg)) ? PTOK_ALPHA : ret; j = tmp; - if ((k == DIR_STRUCT || k == DIR_UNION) && (ret != PTOK_ALPHA || (is_anon && ret == PTOK_ALPHA))) { + if ((k == DIR_STRUCT || k == DIR_UNION) && ret != PTOK_ALPHA) { is_anon++; } is_struct += (k == DIR_STRUCT || k == DIR_UNION); @@ -556,16 +760,8 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { i += j; value = strtoull(lexeme, NULL, base); if (lt->id == TOK_SYM) { - tsym = mksymbol(sym, value, 1, islocal, 0, 0, dbg); - if (lt) { - lt->sym = get_sym(sym, address, lt, islocal, dbg); - } - if (!islocal) { - cur_sym = last_sym; - } - tsym = NULL; - islocal = 0; - isfixup += (lt->sym == NULL); + new_symbol(lt, sym, value, depth, dbg); + depth = 0; if (dbg) { printf("lex(): isfixup: %u\n", isfixup); } @@ -606,20 +802,17 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { break; case PTOK_LBRACK: case PTOK_HASH : - /*l->tok->type = (ptok == PTOK_LBRACK) ? IND : IMM; - lex_type = (ptok == PTOK_LBRACK) ? TOK_IND : TOK_IMM;*/ lex_type = TOK_MEM; value = (ptok == PTOK_LBRACK) ? MEM_IND : MEM_IMM; l->count++; t = make_token(lex_type, value, space, tab, 0, "", NULL); lex_type = (ptok == PTOK_LBRACK) ? TOK_IND : TOK_IMM; + t->subtype = (t->subtype == 0xFF && lex_subtype != 0xFF) ? lex_subtype : t->subtype; if (lex_subtype != 0xFF) { lex_subtype = 0xFF; } memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; - /*(t) ? (t->subspace = space) : (lt->subspace = space); - (t) ? (t->subtab = tab) : (lt->subtab = tab);*/ break; case PTOK_PLUS: case PTOK_MINUS: @@ -695,7 +888,6 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { lexeme[j+1] = (ptok == PTOK_R || ((ptok == PTOK_S || ptok == PTOK_B) && get_ptok(str[i], dbg) == PTOK_P)) ? str[i++] : '\0'; lexeme[j+2] = (ptok == PTOK_R) ? str[i++] : '\0'; lexeme[j+3] = '\0'; - /*lex_subtype = (lex_type == TOK_CSV && lt && lt->subtype != TOK_CSV) ? lex_type : lex_subtype;*/ lex_type = TOK_REG; switch (ptok) { case PTOK_A: value = REG_A; break; @@ -719,17 +911,11 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { t = make_token(lex_type, value, space, tab, 0, "", NULL); t->subtype = (t->subtype == 0xFF && lex_subtype != 0xFF) ? lex_subtype : t->subtype; lex_subtype = 0xFF; - /*(t) ? (t->subspace = space) : (lt->subspace = space); - (t) ? (t->subtab = tab) : (lt->subtab = tab);*/ break; case PTOK_P: lexeme[j] = str[i++]; lexeme[j+1] = (str[i] != ',') ? str[i++] : '\0'; lexeme[j+2] = '\0'; - /*switch (ptok) { - case PTOK_S: of = 1; break; - case PTOK_P: of = 2; break; - }*/ of = 2; lex_type = TOK_OF; l->count++; @@ -737,8 +923,8 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { break; case PTOK_AT: memset(lexeme, 0, strlen(lexeme)+1); + for (char *tmp = str+i; *tmp++ == '@'; depth++); lexeme[j] = '@'; - islocal = 1; lex_type = TOK_LOCAL; if (lt || t) { (t) ? (t->subspace = space) : (lt->subspace = space); @@ -750,26 +936,12 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { lexeme[j] = ':'; lexeme[j+1] = '\0'; lex_type = TOK_LABEL; - tsym = mksymbol(sym, address, 1, islocal, 0, 0, dbg); - if (isfixup) { - isfixup = reslv_fixups(dbg); - } if (lt) { lt->id = lex_type; - lt->type = islocal; - lt->sym = get_sym(sym, address, t, islocal, dbg); - isfixup += (lt->sym == NULL); - } - if (!islocal) { - cur_sym = last_sym; - locals = NULL; - last_loc = NULL; - } else if (cur_sym->down == NULL && cur_sym == last_sym) { - cur_sym->down = locals; - cur_sym->down->up = cur_sym; + lt->type = depth; } - tsym = NULL; - islocal = 0; + new_symbol(lt, sym, address, depth, dbg); + depth = 0; if (dbg) { printf("lex(): isfixup: %u\n", isfixup); } @@ -812,7 +984,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { break; case PTOK_ALPHA: - for (; !isdelm2(str[i+j], dbg); j++); + for (; !isdelm2(str[i+j], dbg) || (is_inst && str[i+j] == '.'); j++); memcpy(lexeme, str+i, j); lexeme[j] = '\0'; i += j; @@ -836,6 +1008,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { lex_type = (is_ext) ? TOK_EXTOP : lex_type; lex_type = (is_ortho) ? TOK_ORTHO : lex_type; isop = 1; + is_inst = 1; l->count++; t = make_token(lex_type, 0xFF, space, tab, k, "", NULL); break; @@ -860,37 +1033,34 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) { for (; isdelm(str[i+spaces], dbg) == 16; spaces++); uint8_t ret = get_ptok(str[i+spaces], dbg); if (ret == PTOK_COLON || ret == PTOK_EQU) { - islocal = (lex_type == TOK_LOCAL); + depth = (lex_type == TOK_LOCAL); } lex_type = TOK_SYM; l->count++; - t = make_token(lex_type, islocal, space, tab, 0, "", NULL); + t = make_token(lex_type, depth, space, tab, 0, "", NULL); memcpy(sym, lexeme, j+1); if (dbg) { printf("lex(): spaces: %u\n", spaces); } if (is_struct) { create_struct(cur_sym, l, t, lt, sym, dbg); - islocal = 0; + depth = 0; } else if ((str[i+spaces] != ':' && str[i+spaces] != '=')) { - uint8_t sym_struct = 0; symbol *s; - /*tmp_sym = (s && s->isstruct) ? NULL : tmp_sym;*/ - if (tmp_sym) { - t->sym = find_member(lexeme, tmp_sym, dbg); - tmp_sym = NULL; - } else { - t->sym = get_sym(lexeme, address, t, islocal, dbg); - } + int scope_depth; + char *tmp = lexeme; + for (scope_depth = 0; *tmp; scope_depth += (*tmp++ == '.')); + char *scope_name = (!scope_depth) ? mk_scope_name(cur_sym, depth, lexeme, dbg) : lexeme; + t->sym = get_sym(scope_name, address, t, (scope_depth) ? scope_depth : depth, 1, dbg); isfixup += (t && t->sym == NULL); - islocal = 0; + depth = 0; if (dbg) { printf("lex(): isfixup: %u\n", isfixup); } } - if (!is_struct && t && t->sym && t->sym->isstruct) { + /*if (!is_struct && t && t->sym && t->sym->isstruct) { tmp_sym = t->sym; - } + }*/ } } break; diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s index 550228d..36a4f15 100644 --- a/programs/sub-suite/declare.s +++ b/programs/sub-suite/declare.s @@ -2,7 +2,7 @@ ; Structs, and unions. ; Line struct. -.struct ln +.struct line next .qword ; Pointer to next line. tok .qword ; The tokens for this line. @@ -852,7 +852,7 @@ cmd_srt: .word list .word asm .word help - .word inst + .word instruction .word run .word set_val diff --git a/programs/sub-suite/free-new.s b/programs/sub-suite/free-new.s new file mode 100644 index 0000000..dad19d0 --- /dev/null +++ b/programs/sub-suite/free-new.s @@ -0,0 +1,143 @@ +.include "declare.s" + +.org 0 + +; free: Free allocated memory. +; Input: D = Pointer to allocated memory. +; Output: none. +; Caller preserved registers: D. +; Callie preserved registers: A, B, X, Y, E. + +free: + pha.q ; Preserve A. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + phe.q ; Preserve E. + and #0 ; Reset A. + tab ; Reset B. + tax ; Reset X. + tay ; Reset Y. + mov a, d ; Get the passed pointer. + bne @getrealblk ; The pointer isn't NULL, so get the real block. + bra @end ; The pointer is NULL, so we're done. +@getrealblk: + sub #8 ; Get the start of the used block. + mov.q a, (a) ; Get the start of the real block. + mov.q b, (a+ublk.size) ; Get the size of the real block. + lea e, (a+b) ; Add the size of the real block with the start of the real block. + cmp.q e, heapptr ; Is this block on top of the heap? + bne @heapadd ; No, so add it to the free block list. +@dectop: + mov.q heapptr, (a) ; Set the top of the heap to the start of the previous real block. +@chklastblk: + mov.q b, heapl ; Get the last free list entry. + beq @end ; The free list is empty, so we're done. + ldy #fblk.size ; Get the size of the block. + mov.q a, (b+fblk.size) ; Get the size of the block. + lea e, (a+b) ; Add the size of the block, with the address of the block entry. + cmp.q e, heapptr ; Is the last block on top of the heap? + bne @end ; No, so we're done. +@delblk: + mov.q heapptr, b ; Yes, so remove the last block. +@correctblk: + mov.q a, (b+fblk.prev) ; Get the previous block. + sta.q heapl ; Set the last block to the previous block. + bne @delnxtblk ; The previous block isn't NULL, so delete the next block. + sta.q heapf ; The previous block is NULL, so empty the free list. + bra @end ; We are done. +@delnxtblk: + lea e, (a+fblk.next) ; Delete the next block. + stz.q (e) ; +@end: + ple.q ; Restore E. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. + + +@heapadd: + mov.q y, heapf ; Get the first block. + bne @srchflst ; The Free list isn't empty, so start searching the free list. +@empty: + mov.q (a+fblk.next), y ; Clear the next block. + mov.q (a+fblk.prev), y ; Clear the previous block. + sta.q heapf ; Set the first block entry to the current block. + sta.q heapl ; Set the last block entry to the current block. + bra @end ; We are done. +@srchflst: +@loop: + cmp y, a ; Is the right pointer at, or below the current block? + beq @nextright ; Yes, so get the next right pointer. + bcs @chkrmerge ; No, so do the right block merge. +@nextright: + tyx ; Set the left pointer, to the right pointer. + mov.q y, (y+fblk.next) ; Set the current right pointer to the next right pointer. + bne @loop ; The next right pointer isn't NULL, so keep looping. +@st_lmerge2: + mov.q (a+fblk.next), y ; Clear the next block. + sta.q heapl ; Set the last free block entry to it. + bra @chklmerge2 ; Do the left block merge. +@chkrmerge: + lea e, (a+b) ; Add the size of the current block, to the current block. + cmp e, y ; Is the current block the same as the right block? + bne @normerge ; No, so don't merge the right block. +@rmerge: + mov e, b ; Get the size of the current block. + add.q e, (y+fblk.size) ; Add the size of the current block, with the size of the right pointer. + mov.q (a+fblk.size), e ; Set the size of the current block, to the new size. +@rmerge2: + lea fblk.next ; Get the next right pointer. + mov.q (a+e), (y+e) ; Set the next block, to the next right pointer. + mov.q b, (y+e) ; Save the next block. + beq @setheapl ; The next block is NULL, so set the last block. +@setprev: + mov.q (b+fblk.prev), a ; Set the previous block to the current block. + bra @chklmerge ; Do the left block merge. +@setheapl: + sta.q heapl ; Set the last block to the current block. + bra @chklmerge ; Do the left block merge. +@normerge: + mov.q (a+fblk.next), y ; Set the next block to the right pointer. + mov.q (y+fblk.prev), a ; Set the previous right pointer to the current block. +@chklmerge: + and x, x ; Is the left pointer NULL? + bne @chklmerge2 ; No, so keep checking. +@newstart: + mov.q (a+fblk.prev), x ; + sta.q heapf ; Set the first block, to the current block. + bra @end2 ; We are done. +@chklmerge2: + mov.q e, (x+fblk.size) ; Get the size of the left block. + add e, x ; Add the size of the left block, to the left pointer. + cmp e, a ; Is the left block adjacent? + bne @nolmerge ; No, so don't merge the left block. +@lmerge: + lea fblk.size ; Set the offset to the block size. + add.q (x+e), (a+e) ; Add the size of the left block, with the size of the current block. +@lmerge2: + lea fblk.next ; Set the offset to the next block. + mov.q (x+e), (a+e) ; Set the next left pointer, to the next block. + mov.q b, (a+e) ; Get the next block. + beq @newlast ; The next block is NULL, so set the last block. +@lprev: + mov.q (b+fblk.prev), x ; Set the next left pointer's previous pointer to the left pointer. + bra @end2 ; We are done. +@newlast: + stx.q heapl ; Set the last block, to the left pointer. + bra @end2 ; We are done. +@nolmerge: + mov.q (x+fblk.next), a ; Set the next left pointer, to the current block. +@nolmerge2: + mov.q (a+fblk.prev), x ; Set the previous block, to the left pointer. +@end2: + ple.q ; Restore E. + ply.q ; Restore Y. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. + +a +q diff --git a/programs/sub-suite/free-old.s b/programs/sub-suite/free-old.s new file mode 100644 index 0000000..7f75edd --- /dev/null +++ b/programs/sub-suite/free-old.s @@ -0,0 +1,200 @@ +.include "declare.s" + +.org 0 + +; free: Free allocated memory. +; Input: A = Pointer to allocated memory. +; Output: none. +; Caller preserved registers: none. +; Callie preserved registers: A, B, Y. + +free: + pha.q ; Preserve A. + phb.q ; Preserve B. + phy.q ; Preserve Y. + pha.q ; Push the pointer argument to the stack. + and #0 ; Reset A. + tay ; Reset Y. + sbs #$18 ; Allocate 3 local variables onto the stack. + lda.q sp+25 ; Get the passed pointer. + ora.d sp+29 ; Is the passed pointer NULL? + bne @getrealblk ; No, so get the real block. + bra @end ; Yes, so we're done. +@getrealblk: + lda.q sp+25 ; Get the passed pointer. + sec ; Prepare for a non borrowing subtract. + sbc #8 ; Move the passed pointer back by one. + sta.q sp+25 ; Set the first local variable to the start of the used block. + lda.q (sp+25) ; Get the real block address. + sta.q sp+25 ; Set the passed pointer to the start of the real block. + ldy #ublk.size ; Get the size of the real block. + lda.q (sp+25), y; + sta.q sp+17 ; Save the size of the real block. + clc ; Prepare for a non carrying add. + adc.q sp+25 ; Add the size of the real block with the start of the real block. + cmp.q heapptr ; Is this block on top of the heap? + bne @heapadd ; No, so add it to the free block list. +@dectop: + lda.q sp+25 ; Get the block. + sta.q heapptr ; Set the top of the heap to it. +@chklastblk: + lda.q heapl ; Get the last free list entry. + sta.q sp+17 ; Copy it into the second local variable. + ora.d sp+21 ; Is the free list empty? + beq @end ; Yes, so we're done. + lda.q sp+17 ; No, so Get the last free list entry. + ldy #fblk.size ; Get the size of the block. + lda.q (sp+17), y; + clc ; Prepare for a non carrying add. + adc.q sp+17 ; Add the size of the block, with the address of the block entry. + cmp.q heapptr ; Is the last block on top of the heap? + bne @end ; No, so we're done. +@delblk: + lda.q sp+17 ; Yes, so remove the last block. + sta.q heapptr ; +@correctblk: + ldy #fblk.prev ; Get the previous block. + lda.q (sp+17), y; + sta.q sp+25 ; Save the previous block for now. + sta.q heapl ; Set the last block to the previous block. + ora.d sp+29 ; Is the previous block non NULL? + bne @delnxtblk ; Yes, so delete the next block. + sta.q heapf ; No, so empty the free list. + bra @end ; We are done. +@delnxtblk: + and #0 ; Reset A. + ldy #fblk.next ; Delete the next block. + sta.q (sp+25), y; +@end: + ads #$20 ; Clean up the stack frame. + ply.q ; Restore Y. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. + + +@heapadd: + lda.q heapf ; Get the first block. + sta.q sp+9 ; Copy it into the third local variable. + ora.d sp+13 ; Is the free list empty? + bne @srchflst ; No, so start searching the free list. +@empty: + ldy #fblk.next ; Clear the next block. + sta.q (sp+25), y; + ldy #fblk.prev ; Clear the previous block. + sta.q (sp+25), y; + lda.q sp+25 ; Reset A. + sta.q heapf ; Clear the first block entry. + sta.q heapf ; Clear the last block entry. + bra @end ; We are done. +@srchflst: + and #0 ; Reset A. + sta.q sp+1 ; Reset the left pointer. + ldy #fblk.next ; Setup for the loop. +@loop: + lda.q sp+9 ; Get the right pointer. + cmp.q sp+25 ; Is the right pointer at, or below the current block? + beq @nextright ; Yes, so get the next right pointer. + bcs @chkrmerge ; No, so do the right block merge. +@nextright: + sta.q sp+1 ; Set the left pointer, to the right pointer. + lda.q (sp+9), y ; Get the next right pointer. + sta.q sp+9 ; Set the current right pointer to the next right pointer. + ora.d sp+13 ; Is the next right pointer NULL? + bne @loop ; No, so keep looping. +@st_lmerge2: + sta.q (sp+25), y; Clear the next block. + lda.q sp+25 ; Get the current block. + sta.q heapl ; Set the last free block entry to it. + bra @chklmerge2 ; Do the left block merge. +@chkrmerge: + lda.q sp+25 ; Get the current block. + clc ; Prepare for a non carrying add. + adc.q sp+17 ; Add the size of the current block, to the current block. + cmp.q sp+9 ; Is the right pointer NULL? + bne @normerge ; No, so don't merge the right block. +@rmerge: + ldy #fblk.size ; Get the size of the right pointer. + lda.q sp+17 ; Get the size of the current block. + clc ; Prepare for a non carrying add. + adc.q (sp+9), y ; Add the size of the current block, with the size of the right pointer. + sta.q (sp+25), y; Set the size of the current block, to the new size. +@rmerge2: + ldy #fblk.next ; Get the next right pointer. + lda.q (sp+9), y ; + sta.q (sp+25), y; Set the next block, to the next right pointer. + sta.q sp+17 ; Save the next block in the second local variable. + ora.d sp+21 ; Is the next block NULL? + beq @setheapl ; Yes, so set the last block. +@setprev: + lda.q sp+25 ; Get the current block. + ldy #fblk.prev ; Set the previous block to the current block. + sta.q (sp+17), y; + bra @chklmerge ; Do the left block merge. +@setheapl: + lda.q sp+25 ; Get the current block. + sta.q heapl ; Set the last block to the current block. + bra @chklmerge ; Do the left block merge. +@normerge: + lda.q sp+9 ; Get the right pointer. + ldy #fblk.next ; Set the next block to the right pointer. + sta.q (sp+25), y; + lda.q sp+25 ; Get the current block. + ldy #fblk.prev ; Set the previous right pointer to the current block. + lda.q (sp+9), y ; +@chklmerge: + lda.q sp+1 ; Get the left pointer. + ora.d sp+5 ; Is the left pointer NULL? + bne @chklmerge2 ; No, so keep checking. +@newstart: + ldy #fblk.prev ; Clear the previous block. + sta.q (sp+25), y; + lda.q sp+25 ; Get the current block. + sta.q heapf ; Set the first block, to the current block. + bra @end2 ; We are done. +@chklmerge2: + ldy #fblk.size ; Get the size of the left block. + lda.q (sp+1), y ; + clc ; Prepare for a non carrying add. + adc.q sp+1 ; Add the size of the left block, to the left pointer. + cmp.q sp+25 ; Is the left block adjacent? + bne @nolmerge ; No, so don't merge the left block. +@lmerge: + lda.q (sp+1), y ; Get the size of the left block. + clc ; Prepare for a non carrying add. + ldb.q (sp+25), y; Get the size of the current block. + adc b ; Add the size of the left block, with the size of the current block. + sta.q (sp+1), y ; Set the size of the left block to the new size. +@lmerge2: + ldy #fblk.next ; Get the next block. + lda.q (sp+25), y; + sta.q (sp+1), y ; Set the next left pointer, to the next block. + sta.q sp+17 ; Set the second local variable to the next block. + ora.d sp+21 ; Is the next left pointer NULL? + beq @newlast ; Yes, so set the last block. +@lprev: + lda.q sp+1 ; Get the left pointer. + ldy #fblk.prev ; Set the next left pointer's previous pointer to the left pointer. + sta.q (sp+17), y; + bra @end2 ; We are done. +@newlast: + lda.q sp+1 ; Get the left pointer. + sta.q heapl ; Set the last block, to the left pointer. + bra @end2 ; We are done. +@nolmerge: + lda.q sp+25 ; Get the current block. + ldy #fblk.next ; Set the next left pointer, to the current block. + sta.q (sp+1), y ; +@nolmerge2: + lda.q sp+1 ; Get the left pointer. + ldy #fblk.prev ; Set the previous block, to the left pointer. + sta.q (sp+25), y; +@end2: + ads #$20 ; Clean up the stack frame. + ply.q ; Restore Y. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. + +a +q diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s index b2850aa..0d712ff 100644 --- a/programs/sub-suite/lexer.s +++ b/programs/sub-suite/lexer.s @@ -65,7 +65,7 @@ lex: ;@nextlline: ; ldb #1 ; No, so set the second pointer to the last line. ; jsr set_ptr ; -; ldy #ln.next ; Set the next last line to the current line. +; ldy #line.next ; Set the next last line to the current line. ; lda.q cline ; ; sta.q (ptr2), y ; ; bra @initline ; Initialize the line. @@ -76,11 +76,11 @@ lex: ; ldb #1 ; Set the second pointer to the current line. ; jsr set_ptr ; ; and #0 ; Reset A. -; ldy #ln.next ; Reset the next line. +; ldy #line.next ; Reset the next line. ; sta.q (ptr2), y ; -; ldy #ln.tok ; Reset the token. +; ldy #line.tok ; Reset the token. ; sta.q (ptr2), y ; -; ldy #ln.bline ; Reset the number of blank lines. +; ldy #line.bline ; Reset the number of blank lines. ; sta.w (ptr2), y ; ; tay ; Reset Y. @loop: @@ -225,11 +225,10 @@ ptok_dot: beq @found ; Yes, so create a new token. inc idx1 ; No, so increment the directive ID. @getlen: + mov d, a ; Get the string. jsr strlen ; Get the string's length. 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. + add.w idx2, a ; Add the string offset to the current length bra @dir_loop ; Keep looping. @found: lda #TOK_DIR ; Set the lexeme type to TOK_DIR. @@ -443,11 +442,10 @@ ptok_alph: beq @found ; Yes, so create a new token. inc idx1 ; No, so increment the instruction ID. @offset: + mov d, a ; Get the string. jsr strlen ; Get the string's length. 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. + add.w idx2, a ; Add the string offset to the current length bra @isop_loop ; Keep looping. @found: lda #TOK_MNE ; Set the lexeme type to TOK_MNE. diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s index ae35146..53e936a 100644 --- a/programs/sub-suite/libc.s +++ b/programs/sub-suite/libc.s @@ -17,12 +17,10 @@ strtoull: 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. + sub #'a'-10 ; Yes, so 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. + sub #'0' ; Get the numeric value from this digit. @chkbase: cmp sp+25 ; Does the value match the base? bcs @end ; No, so we're done. @@ -30,8 +28,7 @@ strtoull: tab ; Save the digit value. lda.q sp+1 ; Get the value from the value buffer. mul sp+25 ; Multiply the value by the base. - clc ; Prepare for a non carrying add. - adc b ; Add the digit value to the total value. + add a, b ; 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. @@ -44,80 +41,72 @@ strtoull: strlen: - phy.q ; Preserve Y. - pha.q ; Set the temp variable to the argument. and #0 ; Reset A. - tay ; Reset Y. @loop: - lda (sp+1), 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. + inc ; Increment the index. + cmp (d+a-1), #0 ; Are we at the end of the string? + bne @loop ; No, so keep looping. @end: - pla.q ; Get the argument back. - tya ; Get the return value. - ply.q ; Get the preserved value back. + dec ; Decrement the length to not include the terminator. rts ; End of strlen. strcmp: - ldb #0 ; Reset B. - tba ; Reset A. + phb.q ; Preserve B. + phx.q ; Preserve X. phy.q ; Preserve Y. + and #0 ; Reset A. + tab ; Reset B. + tax ; Reset X. tay ; Reset Y. @loop: - ldb #0 ; Set the islong flag to false. - lda (sp+25), y ; Are we at the end of the first string? + ldx #0 ; Set the islong flag to false. + mov a, (d+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+19), y ; Is the character of both strings, the same? + ldx #1 ; No, so set the islong flag to true. + cmp a, (s+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. + phb.q ; Preserve B. + phx.q ; Preserve X. phy.q ; Preserve Y. + and #0 ; Reset A. + tab ; Reset B. + tax ; Reset X. + inx ; Set X to 1. tay ; Reset Y. @loop: - ldb #0 ; Set the islong flag to false. - lda (sp+25), y ; Are we at the end of the first string? + dex ; Set the islong flag to false. + mov a, (d+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. + inx ; 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+19), y ; Get the character of the second string. + tab ; Save the converted character. + mov a, (s+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. cmp b ; 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+17), y ; Are we at the end of the second string? + mov a, (s+y) ; Are we at the end of the second string? beq @islong ; Yes, so check the islong flag. @isshort: - lda (sp+25), 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. + mov a, (d+y) ; No, but are we at the end of the first string? + bne @islong ; No, so check if the islong flag is true. + lda #$FF ; Yes, so return -1. bra @end ; We are done. -@equ: - lda #0 ; Return 0. - bra @end ; We are done. -@short: - lda #$FF ; Return -1. +@islong: + cpx #1 ; Is the islong flag true? + set a, eq ; Return true if it is. @end: - ply.q ; Get the preserved value back. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. rts ; End of cmpr. @@ -195,304 +184,226 @@ toupper: ; malloc: Dynamically allocate memory. -; Input: A = size in bytes to allocate. +; Input: D = size in bytes to allocate. ; Output: A = Pointer to allocated memory. -; Caller preserved registers: none. -; Callie preserved registers: Y. +; Caller preserved registers: D. +; Callie preserved registers: B, X, Y. malloc: - phy.q ; Preserve Y. - pha.q ; Preserve the size. - and #0 ; Reset A. - tay ; Reset Y. - sbs #$10 ; Allocate 2 local variables onto the stack. - lda.q sp+17 ; Get the size. - ora.d sp+21 ; Is the size zero? - beq @end ; Yes, so we're done. - lda.q sp+17 ; No, so get back the size. - clc ; Prepare for a non carrying add. - adc #ublk ; Add the size of a used block struct, to the size. - sta.q sp+17 ; Set the actual size. - lda.q heapf ; Get the first heap entry. - sta.q sp+9 ; Save it in the second local variable. - bra @checkblk ; Check the block. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + xor b, b ; Reset B. + mov x, b ; Reset X. + txy ; Reset Y. + mov a, d ; Get the size. + beq @end ; The size is zero, so we're done. + add #ublk ; Add the size of a used block struct, to the size. + cmp #ublk ; Is the total size smaller than the size of a used block struct? + bcs @getheapf ; No, so get the first heap entry. +@toosmall: + lda #ublk ; Yes, so set the total size to the size of a used block struct. +@getheapf: + mov d, a ; Place the new size into the passed size. + ldb.q heapf ; Get the first heap entry. + bra @checkblk ; Check the block. @findfblk: - ldy #fblk.size ; Get the size of this free block. - lda.q (sp+9), y ; - sec ; Prepare for a non borrowing subtract. - sbc.q sp+17 ; Subtract the size of this free block, with the passed size. - bcs @blkfound ; The result is less than, or equal to the free size, so return the found block. - ldy #fblk.next ; Get the next free block. - lda.q (sp+9), y ; - sta.q sp+9 ; Set the current free block, to the next free block. + mov.q a, (b+fblk.size) ; Get the size of this free block. + sub a, d ; Subtract the size of this free block, with the passed size. + bcs @blkfound ; The result is less than, or equal to the free size, so return the found block. + mov.q b, (b+fblk.next) ; Set the current free block, to the next free block. @checkblk: - ora.d sp+13 ; Is the address of this block, zero? - bne @findfblk ; No, so keep looping. - lda.q heapptr ; Yes, so get the current top of the heap. - clc ; Prepare for a non carrying add. - adc.q sp+17 ; Add the top of the heap, with the passed size. - bcs @outofspace ; The result overflowed, so return zero. - cmp.q heapend ; Is the top of the heap, less than, or equal to the max heap size? - bcc @inctop ; Yes, so increase the current top of the heap. - beq @inctop ; + bne @findfblk ; The address of this block is non NULL, so keep looping. + mov a, d ; Get the passed size. + add.q heapptr ; Add the top of the heap, with the passed size. +; mov d, a ; Save the new size. + bcs @outofspace ; The result overflowed, so return zero. + cmp.q heapend ; Is the top of the heap, less than, or equal to the max heap size? + bcc @inctop ; Yes, so increase the current top of the heap. + beq @inctop ; @outofspace: - and #0 ; Return zero. - bra @end ; We are done. + and #0 ; Return zero. + bra @end ; We are done. @inctop: - pha.q ; Preserve heapptr + size. - lda.q heapptr ; Get the previous top of the heap. - sta.q sp+17 ; Set the current free block to the previous top of the heap. - pla.q ; Restore heapptr + size. - sta.q heapptr ; Increment the current top of the heap by the passed size. - bra @setsize ; Set the size, and start address into the used space of the block. + + ldb.q heapptr ; Set the current free block to the previous top of the heap. + sta.q heapptr ; Increment the current top of the heap by the passed size. + bra @setsize ; Set the size, and start address into the used space of the block. @blkfound: - bne @sliceblk ; The block is big enough to slice. - cmp #fblk ; Is the block big enough to slice? - bcs @sliceblk ; Yes, so slice the block. - ldy #fblk.prev ; No, so get the previous free block. - lda.q (sp+9), y ; - sta.q sp+1 ; Set the third local variable, to the previous free block. - ora.d sp+5 ; Is the previous block, set to zero? - beq @setheapf ; Yes, so set the first block. - ldy #fblk.next ; No, so get the next free block. - lda.q (sp+9), y ; - sta.q (sp+1), y ; Set the previous block's next block, to the next block. - bra @chknxtblk ; Check the next block. + bne @sliceblk ; The block is big enough to slice. + cmp #fblk ; Is the block big enough to slice? + bcs @sliceblk ; Yes, so slice the block. + mov.q x, (b+fblk.prev) ; Get the previous free block. + beq @setheapf ; The previous block is NULL, so set the first block. + ldy #fblk.next ; No, so set the offset to the next free block. + mov.q (x+y), (b+y) ; Set the previous block's next block, to the next block. + bra @chknxtblk ; Check the next block. @setheapf: - lda.q (sp+9), y ; Get the next block. - sta.q heapf ; Set the first heap entry to it. + ldy #fblk.next ; Set the offset to the next block. + mov.q heapf, (b+y) ; Set the first heap entry to the next block. @chknxtblk: - lda.q (sp+9), y ; Get the next free block. - sta.q sp+1 ; Set the third local variable to the next free block. - ora.d sp+5 ; Is the next block, zero? - beq @setheapl ; Yes, so set the least heap entry. - ldy #fblk.prev ; No, so get the current previous block. - lda.q (sp+9), y ; - sta.q (sp+1), y ; Set the next block's previous block to the current previous block. - bra @retptr ; Return the pointer. + mov.q x, (b+y) ; Get the next free block. + beq @setheapl ; The next block is NULL, so set the least heap entry. + ldy #fblk.prev ; Get the current previous block. + mov.q (x+y), (b+y) ; Set the next block's previous block to the current previous block. + bra @retptr ; Return the pointer. @setheapl: - ldy #fblk.prev ; Get the current previous block. - lda.q (sp+9), y ; - sta.q heapl ; Set the last heap entry to the current previous block. - bra @retptr ; Return the pointer. + ldy #fblk.prev ; Get the current previous block. + mov.q heapl, (b+y) ; Set the last heap entry to the current previous block. + bra @retptr ; Return the pointer. @sliceblk: - ldy #fblk.size ; Get the size of the current block. - lda.q (sp+9), y ; - sec ; Prepare for a non borrowing subtract. - sbc.q sp+17 ; Subtract the current block's size from the passed size. - sta.q (sp+9), y ; Set the current block's size to the subtracted size. - clc ; Prepare for a non carrying add. - adc.q sp+9 ; Add the current block's size to the pointer of the current block. - sta.q sp+9 ; Set the current block to the space above it (return value). + ldy #fblk.size ; Get the size of the current block. + sub.q (b+y), d ; Subtract the current block's size from the passed size. + add.q b, (b+y) ; Add the current block's size to the pointer of the current block. @setsize: - ldy #ublk.size ; Start setting the used block's size, to the passed size. - lda.q sp+17 ; Get the passed size. - sta.q (sp+9), y ; Set the used block's size to the passed size. + mov.q (b+ublk.size), d ; Set the used block's size to the passed size. @retptr: - ldy #ublk.start ; Start setting the used block's starting address, to the used block. - lda.q sp+9 ; Get the used block. - sta.q (sp+9), y ; Set the used block's starting address, to the used block. - clc ; Prepare for a non carrying add. - adc #ublk ; Return the pointer to the real memory block. + mov.q (b+ublk.start), b ; Set the used block's starting address, to the used block. + add b, #ublk ; Get the pointer to the real memory block. + tba ; Return the pointer to the real memory block. @end: - ads #$18 ; Clean up the stack frame. - ply.q ; Restore Y. - rts ; End of malloc. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. + rts ; End of malloc. ; free: Free allocated memory. -; Input: A = Pointer to allocated memory. +; Input: D = Pointer to allocated memory. ; Output: none. -; Caller preserved registers: none. -; Callie preserved registers: A, B, Y. +; Caller preserved registers: D. +; Callie preserved registers: A, B, X, Y, E. free: - pha.q ; Preserve A. - phb.q ; Preserve B. - phy.q ; Preserve Y. - pha.q ; Push the pointer argument to the stack. - and #0 ; Reset A. - tay ; Reset Y. - sbs #$18 ; Allocate 3 local variables onto the stack. - lda.q sp+25 ; Get the passed pointer. - ora.d sp+29 ; Is the passed pointer NULL? - bne @getrealblk ; No, so get the real block. - bra @end ; Yes, so we're done. + pha.q ; Preserve A. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + phe.q ; Preserve E. + and #0 ; Reset A. + tab ; Reset B. + tax ; Reset X. + tay ; Reset Y. + mov a, d ; Get the passed pointer. + bne @getrealblk ; The pointer isn't NULL, so get the real block. + bra @end ; The pointer is NULL, so we're done. @getrealblk: - lda.q sp+25 ; Get the passed pointer. - sec ; Prepare for a non borrowing subtract. - sbc #8 ; Move the passed pointer back by one. - sta.q sp+25 ; Set the first local variable to the start of the used block. - lda.q (sp+25) ; Get the real block address. - sta.q sp+25 ; Set the passed pointer to the start of the real block. - ldy #ublk.size ; Get the size of the real block. - lda.q (sp+25), y; - sta.q sp+17 ; Save the size of the real block. - clc ; Prepare for a non carrying add. - adc.q sp+25 ; Add the size of the real block with the start of the real block. - cmp.q heapptr ; Is this block on top of the heap? - bne @heapadd ; No, so add it to the free block list. + sub #8 ; Get the start of the used block. + mov.q a, (a) ; Get the start of the real block. + mov.q b, (a+ublk.size) ; Get the size of the real block. + lea e, (a+b) ; Add the size of the real block with the start of the real block. + cpe.q heapptr ; Is this block on top of the heap? + bne @heapadd ; No, so add it to the free block list. @dectop: - lda.q sp+25 ; Get the block. - sta.q heapptr ; Set the top of the heap to it. + sta.q heapptr ; Set the top of the heap to the start of the current real block. @chklastblk: - lda.q heapl ; Get the last free list entry. - sta.q sp+17 ; Copy it into the second local variable. - ora.d sp+21 ; Is the free list empty? - beq @end ; Yes, so we're done. - lda.q sp+17 ; No, so Get the last free list entry. - ldy #fblk.size ; Get the size of the block. - lda.q (sp+17), y; - clc ; Prepare for a non carrying add. - adc.q sp+17 ; Add the size of the block, with the address of the block entry. - cmp.q heapptr ; Is the last block on top of the heap? - bne @end ; No, so we're done. + ldb.q heapl ; Get the last free list entry. + beq @end ; The free list is empty, so we're done. + ldy #fblk.size ; Get the size of the block. + mov.q a, (b+fblk.size) ; Get the size of the block. + lea e, (a+b) ; Add the size of the block, with the address of the block entry. + cpe.q heapptr ; Is the last block on top of the heap? + bne @end ; No, so we're done. @delblk: - lda.q sp+17 ; Yes, so remove the last block. - sta.q heapptr ; + stb.q heapptr ; Yes, so remove the last block. @correctblk: - ldy #fblk.prev ; Get the previous block. - lda.q (sp+17), y; - sta.q sp+25 ; Save the previous block for now. - sta.q heapl ; Set the last block to the previous block. - ora.d sp+29 ; Is the previous block non NULL? - bne @delnxtblk ; Yes, so delete the next block. - sta.q heapf ; No, so empty the free list. - bra @end ; We are done. + mov.q a, (b+fblk.prev) ; Get the previous block. + sta.q heapl ; Set the last block to the previous block. + bne @delnxtblk ; The previous block isn't NULL, so delete the next block. + sta.q heapf ; The previous block is NULL, so empty the free list. + bra @end ; We are done. @delnxtblk: - and #0 ; Reset A. - ldy #fblk.next ; Delete the next block. - sta.q (sp+25), y; + lea e, (a+fblk.next) ; Delete the next block. + stz.q (e) ; @end: - ads #$20 ; Clean up the stack frame. - ply.q ; Restore Y. - plb.q ; Restore B. - pla.q ; Restore A. - rts ; End of free. + ple.q ; Restore E. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. @heapadd: - lda.q heapf ; Get the first block. - sta.q sp+9 ; Copy it into the third local variable. - ora.d sp+13 ; Is the free list empty? - bne @srchflst ; No, so start searching the free list. + ldy.q heapf ; Get the first block. + bne @srchflst ; The Free list isn't empty, so start searching the free list. @empty: - ldy #fblk.next ; Clear the next block. - sta.q (sp+25), y; - ldy #fblk.prev ; Clear the previous block. - sta.q (sp+25), y; - lda.q sp+25 ; Reset A. - sta.q heapf ; Clear the first block entry. - sta.q heapf ; Clear the last block entry. - bra @end ; We are done. + mov.q (a+fblk.next), y ; Clear the next block. + mov.q (a+fblk.prev), y ; Clear the previous block. + sta.q heapf ; Set the first block entry to the current block. + sta.q heapl ; Set the last block entry to the current block. + bra @end ; We are done. @srchflst: - and #0 ; Reset A. - sta.q sp+1 ; Reset the left pointer. - ldy #fblk.next ; Setup for the loop. @loop: - lda.q sp+9 ; Get the right pointer. - cmp.q sp+25 ; Is the right pointer at, or below the current block? - beq @nextright ; Yes, so get the next right pointer. - bcs @chkrmerge ; No, so do the right block merge. + cmp y, a ; Is the right pointer at, or below the current block? + beq @nextright ; Yes, so get the next right pointer. + bcs @chkrmerge ; No, so do the right block merge. @nextright: - sta.q sp+1 ; Set the left pointer, to the right pointer. - lda.q (sp+9), y ; Get the next right pointer. - sta.q sp+9 ; Set the current right pointer to the next right pointer. - ora.d sp+13 ; Is the next right pointer NULL? - bne @loop ; No, so keep looping. + tyx ; Set the left pointer, to the right pointer. + mov.q y, (y+fblk.next) ; Set the current right pointer to the next right pointer. + bne @loop ; The next right pointer isn't NULL, so keep looping. @st_lmerge2: - sta.q (sp+25), y; Clear the next block. - lda.q sp+25 ; Get the current block. - sta.q heapl ; Set the last free block entry to it. - bra @chklmerge2 ; Do the left block merge. + mov.q (a+fblk.next), y ; Clear the next block. + sta.q heapl ; Set the last free block entry to it. + bra @chklmerge2 ; Do the left block merge. @chkrmerge: - lda.q sp+25 ; Get the current block. - clc ; Prepare for a non carrying add. - adc.q sp+17 ; Add the size of the current block, to the current block. - cmp.q sp+9 ; Is the right pointer NULL? - bne @normerge ; No, so don't merge the right block. + lea e, (a+b) ; Add the size of the current block, to the current block. + cmp e, y ; Is the current block the same as the right block? + bne @normerge ; No, so don't merge the right block. @rmerge: - ldy #fblk.size ; Get the size of the right pointer. - lda.q sp+17 ; Get the size of the current block. - clc ; Prepare for a non carrying add. - adc.q (sp+9), y ; Add the size of the current block, with the size of the right pointer. - sta.q (sp+25), y; Set the size of the current block, to the new size. + mov e, b ; Get the size of the current block. + add.q e, (y+fblk.size) ; Add the size of the current block, with the size of the right pointer. + mov.q (a+fblk.size), e ; Set the size of the current block, to the new size. @rmerge2: - ldy #fblk.next ; Get the next right pointer. - lda.q (sp+9), y ; - sta.q (sp+25), y; Set the next block, to the next right pointer. - sta.q sp+17 ; Save the next block in the second local variable. - ora.d sp+21 ; Is the next block NULL? - beq @setheapl ; Yes, so set the last block. + lea fblk.next ; Get the next right pointer. + mov.q (a+e), (y+e) ; Set the next block, to the next right pointer. + mov.q b, (y+e) ; Save the next block. + beq @setheapl ; The next block is NULL, so set the last block. @setprev: - lda.q sp+25 ; Get the current block. - ldy #fblk.prev ; Set the previous block to the current block. - sta.q (sp+17), y; - bra @chklmerge ; Do the left block merge. + mov.q (b+fblk.prev), a ; Set the previous block to the current block. + bra @chklmerge ; Do the left block merge. @setheapl: - lda.q sp+25 ; Get the current block. - sta.q heapl ; Set the last block to the current block. - bra @chklmerge ; Do the left block merge. + sta.q heapl ; Set the last block to the current block. + bra @chklmerge ; Do the left block merge. @normerge: - lda.q sp+9 ; Get the right pointer. - ldy #fblk.next ; Set the next block to the right pointer. - sta.q (sp+25), y; - lda.q sp+25 ; Get the current block. - ldy #fblk.prev ; Set the previous right pointer to the current block. - lda.q (sp+9), y ; + mov.q (a+fblk.next), y ; Set the next block to the right pointer. + mov.q (y+fblk.prev), a ; Set the previous right pointer to the current block. @chklmerge: - lda.q sp+1 ; Get the left pointer. - ora.d sp+5 ; Is the left pointer NULL? - bne @chklmerge2 ; No, so keep checking. + and x, x ; Is the left pointer NULL? + bne @chklmerge2 ; No, so keep checking. @newstart: - ldy #fblk.prev ; Clear the previous block. - sta.q (sp+25), y; - lda.q sp+25 ; Get the current block. - sta.q heapf ; Set the first block, to the current block. - bra @end2 ; We are done. + mov.q (a+fblk.prev), x ; + sta.q heapf ; Set the first block, to the current block. + bra @end2 ; We are done. @chklmerge2: - ldy #fblk.size ; Get the size of the left block. - lda.q (sp+1), y ; - clc ; Prepare for a non carrying add. - adc.q sp+1 ; Add the size of the left block, to the left pointer. - cmp.q sp+25 ; Is the left block adjacent? - bne @nolmerge ; No, so don't merge the left block. + mov.q e, (x+fblk.size) ; Get the size of the left block. + add e, x ; Add the size of the left block, to the left pointer. + cmp e, a ; Is the left block adjacent? + bne @nolmerge ; No, so don't merge the left block. @lmerge: - lda.q (sp+1), y ; Get the size of the left block. - clc ; Prepare for a non carrying add. - ldb.q (sp+25), y; Get the size of the current block. - adc b ; Add the size of the left block, with the size of the current block. - sta.q (sp+1), y ; Set the size of the left block to the new size. + lea fblk.size ; Set the offset to the block size. + add.q (x+e), (a+e) ; Add the size of the left block, with the size of the current block. @lmerge2: - ldy #fblk.next ; Get the next block. - lda.q (sp+25), y; - sta.q (sp+1), y ; Set the next left pointer, to the next block. - sta.q sp+17 ; Set the second local variable to the next block. - ora.d sp+21 ; Is the next left pointer NULL? - beq @newlast ; Yes, so set the last block. + lea fblk.next ; Set the offset to the next block. + mov.q (x+e), (a+e) ; Set the next left pointer, to the next block. + mov.q b, (a+e) ; Get the next block. + beq @newlast ; The next block is NULL, so set the last block. @lprev: - lda.q sp+1 ; Get the left pointer. - ldy #fblk.prev ; Set the next left pointer's previous pointer to the left pointer. - sta.q (sp+17), y; - bra @end2 ; We are done. + mov.q (b+fblk.prev), x ; Set the next left pointer's previous pointer to the left pointer. + bra @end2 ; We are done. @newlast: - lda.q sp+1 ; Get the left pointer. - sta.q heapl ; Set the last block, to the left pointer. - bra @end2 ; We are done. + stx.q heapl ; Set the last block, to the left pointer. + bra @end2 ; We are done. @nolmerge: - lda.q sp+25 ; Get the current block. - ldy #fblk.next ; Set the next left pointer, to the current block. - sta.q (sp+1), y ; + mov.q (x+fblk.next), a ; Set the next left pointer, to the current block. @nolmerge2: - lda.q sp+1 ; Get the left pointer. - ldy #fblk.prev ; Set the previous block, to the left pointer. - sta.q (sp+25), y; + mov.q (a+fblk.prev), x ; Set the previous block, to the left pointer. @end2: - ads #$20 ; Clean up the stack frame. - ply.q ; Restore Y. - plb.q ; Restore B. - pla.q ; Restore A. - rts ; End of free. + ple.q ; Restore E. + ply.q ; Restore Y. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of free. ; memcpy: memory to memory copy. diff --git a/programs/sub-suite/shift_line.c b/programs/sub-suite/shift_line.c index 255d21b..365666b 100644 --- a/programs/sub-suite/shift_line.c +++ b/programs/sub-suite/shift_line.c @@ -24,6 +24,12 @@ uint8_t bitpos(unsigned int row, uint8_t *mask) { } +uint8_t getbit(unsigned int row, unsigned int offset) { + uint8_t mask; + uint8_t byte = bitpos(row+offset, &mask); + return (bitabl[byte] & mask); +} + void setbit(unsigned int row) { uint8_t mask; uint8_t byte = bitpos(row, &mask); @@ -48,7 +54,7 @@ void shift_line(char *str, int cursor, int left) { if (left) { int i = end-1; int j = end; - for (; i > cursor; i--, j--) { + for (; i >= cursor; i--, j--) { if (i < 0) { i = 0; str[i] = 0; @@ -72,7 +78,7 @@ void shift_line(char *str, int cursor, int left) { str[i] = 0; } end = find_end(str, i); - if ((end % maxcol) == 0 && (end/maxcol) > scr_row) { + if (((end-1) % maxcol) == 0 && ((end-1)/maxcol) > scr_row) { clrbit(end/maxcol); } } diff --git a/programs/sub-suite/subasm-syntax b/programs/sub-suite/subasm-syntax new file mode 100644 index 0000000..1337914 --- /dev/null +++ b/programs/sub-suite/subasm-syntax @@ -0,0 +1,56 @@ +/* Assembly language syntax for SuBAsm. */ + +/* Comments begin with "/*", and end with "*/". + * Directives begin with a `\`. + */ + +/* mnemonic is the instruction name/mnemonic. + * expr is an expression. + * Indirect Indexed means applying the index after the indirection. + * Indexed Indirect means applying the index before the indirection. + */ + +Expression syntax: + /* TODO */ +Instruction syntax: + Base ISA, and Base Extension: + Implied: + <mnemonic> + B register: + <mnemonic> b + Absolute/Zero Matrix: + /* [, <x|y>] means Indexed with x, or y. */ + <mnemonic> <expr>[, <x|y>] + Immediate Data: + <mnemonic> #<expr> + Absolute/Zero Matrix Indirect: + /* Indexing with x means Indexed Indirect. + * Indexing with y means Indirect Indexed. + */ + <mnemonic> (<expr>[, x])[, y] + E Indirect: + <mnemonic> (e) + Orthogonal Extension: + <mnemonic> <operand>[, operand] + Operand syntax: + <\( + /* The operand starts with a register. + * If the statment is inside brackets, then + * it's a register indirect mode. + */ + [(]reg[+<reg>][\(+|-\)<expr>][)] + /* The operand starts with an expression. + * If the statment is inside brackets, then + * it's an indirect mode. + */ + |[(]expr + /* Is the operand using Indirect, or Indirect Indexed? */ + \if (ind || ind_indexed) { + [)] + \} + [\(+|-\)<reg[+<reg>]>] + /* Is the operand using Indexed Indirect? */ + \if (indexed_ind) { + [)] + \} + \)> diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s index 80aaa47..f22ee60 100644 --- a/programs/sub-suite/subasm.s +++ b/programs/sub-suite/subasm.s @@ -3,153 +3,260 @@ ; ; by mr b0nk 500 <b0nk@b0nk.xyz> +;subasm: +; ldb #0 ; Set the first pointer +; lda.q cmd_buf ; to the command buffer. +; jsr set_ptr ; +; tba ; Reset A. +; tax ; Reset X. +; jsr chk_shcmd ; Did we get a shortend command? +; bne @cmd ; Yes, so skip everything else. +; jsr chk_cmd ; No, but did we get a full command? +; bne @cmd ; Yes, so skip everything else. +; jsr lex ; No, so start lexing this line. +; bra @end ; We are done. +;@cmd: +; lda regf ; Get the command ID. +; 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. +; phx.q ; Preserve X. +; tax ; Set the index to the offset that we just calculated. +; lea.w (cmd_srt, x); Get the pointer, from the command subroutine table. +; plx.q ; Restore X. +; and #0 ; Reset A. +; tab ; Reset B. +; jsr (e) ; 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: +; and #0 ; Reset A. +; tab ; Reset B. +;; inb ; Set the second pointer +;; lda.w #sh_cmds ; to the shortend command table. +;; jsr set_ptr ; +;; deb ; Reset B. +;; tba ; Reset A. +; lea sh_cmds ; Get the address of the short command table. +; phy.w ; Preserve the screen buffer position. +; txy ; Set our index to zero. +; lda (ptr), y ; Is there nothing in the command buffer? +; beq @false ; Yes, so return that we failed. +; cmp #' ' ; No, but is this character, a space? +; beq @false ; Yes, so return that we failed. +; jsr tolower ; No, so convert it to lowercase. +;@loop: +;; ldb (ptr2), y ; Are we at the end of the table? +; ldb (e) ; Are we at the end of the table? +; beq @false ; Yes, so return that we failed. +; cmp b ; No, so did the character match? +; beq @found ; Yes, so check if there are any arguments. +; ine ; No, so check the next command. +; iny ; +; bra @loop ; Keep looping. +;@found: +; sty regf ; Save the command ID. +; lea (ptr) ; Get the address of the next character. +; ine ; +;; ldy #1 ; Check the next character in the command buffer. +;; lda (ptr), y ; Is this the end of the buffer? +; lda (e) ; Is this the end of the buffer? +; beq @true ; Yes, so return true. +; cmp #' ' ; No, but is this a space? +; beq @true ; Yes, so return true. +;@false: +; ldb #0 ; Reset B. +; tba ; Return false. +; tax ; Reset X. +; bra @end ; We are done. +;@true: +; lda #1 ; Return true. +;@end: +; ply.w ; Get back the screen buffer position. +; rts ; End of chk_shcmd. +; +; +;chk_cmd: +; and #0 ; Reset A. +; tab ; Reset B. +; tax ; Reset X. +; sta.q idx0 ; Reset the first index. +; sta.q idx1 ; Reset the second index. +; mov.q ptr, d ; Set the first pointer to the command buffer. +;@loop: +; lda.w #cmds ; Get pointer to the start of the command table. +; add.w idx0 ; Offset the pointer, by the length of the previous string. +; pha.q ; Preserve the command string pointer. +; 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. +; cpb #7 ; Have we reached the end of the command table? +; beq @false ; Yes, so return false. +; inc idx1 ; No, so increment the command ID. +;@getlen: +; mov d, a ; Get the string. +; jsr strlen ; Get the string's length. +; inc ; Add one to the length. +; add.w idx0, a ; Add the string offset to the current length +; bra @loop ; Keep looping. +;@true: +; ldb idx1 ; Get the command ID. +; stb regf ; Return the command ID. +; ldb #1 ; Return true. +; bra @end ; We are done. +;@false: +; ldb #0 ; Return false. +;@end: +; rts ; End of chk_cmd. + + subasm: - ldb #0 ; Set the first pointer - lda.q cmd_buf ; to the command buffer. - jsr set_ptr ; - tba ; Reset A. - tax ; Reset X. - jsr chk_shcmd ; Did we get a shortend command? - bne @cmd ; Yes, so skip everything else. - jsr chk_cmd ; No, but did we get a full command? - bne @cmd ; Yes, so skip everything else. - jsr lex ; No, so start lexing this line. - bra @end ; We are done. + pha.q ; Preserve A. + phe.q ; Preserve E. + des ; Make room for the command id. + and #0 ; Reset A. + lea d, (cmd_buf) ; Get the command buffer. + lea s, (sp+1) ; Get the pointer to the command id. + jsr chk_shcmd ; Did we get a shortend command? + bne @cmd ; Yes, so skip everything else. + jsr chk_cmd ; No, but did we get a full command? + bne @cmd ; Yes, so skip everything else. + mov.q ptr, d ; + jsr lex ; No, so start lexing this line. + bra @end ; We are done. @cmd: - lda regf ; Get the command ID. - 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. - phx.q ; Preserve X. - tax ; Set the index to the offset that we just calculated. - lea.w (cmd_srt, x); Get the pointer, from the command subroutine table. - plx.q ; Restore X. - and #0 ; Reset A. - tab ; Reset B. - jsr (e) ; Run the command's subroutine. + mov s, (s) ; Get the command ID. + cmp s, #7 ; Is the command ID greater than the command count? + bcs @end ; Yes, so we're done. + lsl s, #1 ; No, so multiply the command ID by two. + lea.w e, (cmd_srt+s) ; Get the pointer, from the command subroutine table. + and #0 ; Reset A. + tab ; Reset B. + jsr (e) ; 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. + and #0 ; Reset A. + jsr update_ptr ; Get the screen buffer index. + tay ; Save it in Y. + ins ; Cleanup the stack frame. + ple.q ; Restore E. + pla.q ; Restore A. + rts ; End of subasm. + chk_shcmd: - and #0 ; Reset A. - tab ; Reset B. -; inb ; Set the second pointer -; lda.w #sh_cmds ; to the shortend command table. -; jsr set_ptr ; -; deb ; Reset B. -; tba ; Reset A. - lea sh_cmds ; Get the address of the short command table. - phy.w ; Preserve the screen buffer position. - txy ; Set our index to zero. - lda (ptr), y ; Is there nothing in the command buffer? - beq @false ; Yes, so return that we failed. - cmp #' ' ; No, but is this character, a space? - beq @false ; Yes, so return that we failed. - jsr tolower ; No, so convert it to lowercase. + phb.q ; Preserve B. + lea b, sh_cmds ; Get the address of the short command table. + mov a, (d) ; Is the string empty? + beq @false ; Yes, so return that we failed. + cmp #' ' ; No, but is this character, a space? + beq @false ; Yes, so return that we failed. + jsr tolower ; No, so convert it to lowercase. @loop: -; ldb (ptr2), y ; Are we at the end of the table? - ldb (e) ; Are we at the end of the table? - beq @false ; Yes, so return that we failed. - cmp b ; No, so did the character match? - beq @found ; Yes, so check if there are any arguments. - ine ; No, so check the next command. - iny ; - bra @loop ; Keep looping. + cmp (b), #0 ; Are we at the end of the table? + beq @false ; Yes, so return that we failed. + cmp a, (b) ; No, so did the character match? + beq @found ; Yes, so check if there are any arguments. + inb ; No, so check the next command. + bra @loop ; Keep looping. @found: - sty regf ; Save the command ID. - lea (ptr) ; Get the address of the next character. - ine ; -; ldy #1 ; Check the next character in the command buffer. -; lda (ptr), y ; Is this the end of the buffer? - lda (e) ; Is this the end of the buffer? - beq @true ; Yes, so return true. - cmp #' ' ; No, but is this a space? - beq @true ; Yes, so return true. + sub.w b, #sh_cmds ; Get the command ID. + mov (s), b ; Save the command ID. + mov a, (d+1) ; Is this the end of the string? + beq @true ; Yes, so return true. + cmp #' ' ; No, but is this a space? + beq @true ; Yes, so return true. @false: - ldb #0 ; Reset B. - tba ; Return false. - tax ; Reset X. - bra @end ; We are done. + and #0 ; Return false. + bra @end ; We are done. @true: - lda #1 ; Return true. + lda #1 ; Return true. @end: - ply.w ; Get back the screen buffer position. - rts ; End of chk_shcmd. + plb.q ; Restore B. + rts ; End of chk_shcmd. chk_cmd: - tba ; Reset A. - tax ; Reset X. - sta.q idx0 ; Reset the first index. - sta.q idx1 ; Reset the second index. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + and #0 ; Reset A. + tab ; Reset B. + mov x, s ; Preserve the command ID pointer. + mov y, d ; Preserve the string pointer. + lea s, cmds ; Get pointer to the start of the command table. @loop: - lda.w #cmds ; Get pointer to the start of the command table. - 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 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. - cpb #7 ; Have we reached the end of the command table? - beq @false ; Yes, so return false. - inc idx1 ; No, so increment the command ID. + jsr strcasecmp ; Is the command buffer, the same as the command string? + beq @true ; Yes, so return true. + inb ; No, so increment the command ID. + cpb #7 ; Have we reached the end of the command table? + bcs @false ; Yes, so return false. @getlen: - jsr strlen ; Get the string's length. - 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. - bra @loop ; Keep looping. + mov d, s ; Get the command table string. + jsr strlen ; Get the string's length. + mov d, y ; Restore the string pointer. + inc ; Add one to the length. + add s, a ; Add the string offset to the current length + bra @loop ; Keep looping. @true: - ldb idx1 ; Get the command ID. - stb regf ; Return the command ID. - ldb #1 ; Return true. - bra @end ; We are done. + lda #1 ; Return true. + bra @end ; We are done. @false: - ldb #0 ; Return false. + lda #0 ; Return false. @end: - rts ; End of chk_cmd. + mov s, x ; Restore the command ID pointer. + mov (s), b ; Save the command ID. + and a, a ; Set the flags accordingly. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. + rts ; End of chk_cmd. + viewmem: - lda.q prg_cnt ; Get the program counter. - sta.q idx0 ; Save the address in the first index. - and #$F0 ; Clear the first four bits of the address. - sta idx0 ; Overwrite the first byte, with the masked byte. - lda #19 ; Move the cursor to the right, by 19 columns. - sta scr_col ; - jsr update_pos ; - jsr print_lo ; Print the low nibble offsets. - ldx #0 ; Reset X. - ldb #0 ; Reset B. - stb idx1 ; Reset the byte count. + pha.q ; Preserve A. + phb.q ; Preserve B. + phx.q ; Preserve X. + sbs #$50 ; Make room for the string buffer. + and #0 ; Reset A. + tab ; Reset B. + ldx.q prg_cnt ; Get the program counter. + lda #19 ; Move the cursor to the right, by 19 columns. + sta scr_col ; + jsr update_pos ; + jsr print_lo ; Print the low nibble offsets. @loop: - lda #'\n' ; Print a newline. - jsr print_char ; - jsr print_hi ; Place the address in the string buffer. - jsr print_chunk ; Place the next 16 bytes in the string buffer. - lea strbuf ; Print the string buffer. -; jsr print_str ; - jsr print_sfast ; - inc idx1 ; Increment the chunk count. - ldb idx1 ; Get the chunk count. - cpb #$10 ; Did we print 16 chunks? - beq @end ; Yes, so we're done. - lda.q idx0 ; No, so get the address index. - clc ; Prepare for a non carrying add. - adc #$10 ; Add 16 to the address. - sta.q idx0 ; Put it back into the address. - and #0 ; Reset A. - bra @loop ; Keep looping. + lda #'\n' ; Print a newline. + jsr print_char ; + lea d, (sp+1) ; Get the address of the string buffer. + mov s, x ; Get the program counter. + jsr print_hi ; Print the address to the string buffer. + mov d, a ; Get the string buffer pointer after the printed address. + mov s, x ; Get the program counter. + jsr print_chunk ; Print the next 16 bytes to the string buffer. + lea d, (sp+1) ; Get the address of the string buffer. + lea s, (buffer)+y ; Get the address of the screen buffer, at the current cursor position. +; jsr print_str ; Print the string buffer. + jsr print_sfast ; + inb ; Increment the chunk count. + cpb #$10 ; Did we print 16 chunks? + beq @end ; Yes, so we're done. + add x, #$10 ; No, so add 16 to the address. + and #0 ; Reset A. + bra @loop ; Keep looping. @end: - lda #'\n' ; Print a newline. - jsr print_char ; - and #0 ; Reset A. - rts ; End of viewmem. + lda #'\n' ; Print a newline. + jsr print_char ; + ads #$50 ; Cleanup the stack frame. + plx.q ; Restore X. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of viewmem. list: @@ -164,10 +271,10 @@ help: nop ; @end: rts ; End of help. -inst: +instruction: nop ; @end: - rts ; End of inst. + rts ; End of instruction. run: nop ; @end: diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s index 387b5db..f6b647f 100644 --- a/programs/sub-suite/subeditor.s +++ b/programs/sub-suite/subeditor.s @@ -11,8 +11,8 @@ reset: ldy #0 ; Reset Y. tyx ; Reset X. jsr init_heap ; Initialize the heap. - tax ; Set the stack pointer to the end of RAM. - txs ; + mov sp, a ; Set the stack pointer to the end of RAM. +; txs ; sub.d #STKSIZE ; Subtract the stack size, from the end of RAM. sta.q heapend ; Save the end of the heap. and #0 ; Reset A. @@ -28,45 +28,39 @@ reset: init_heap: lea HEAPORG ; Get the heap's starting point. ste.q heapptr ; + mov d, e ; jsr findramend ; Find the end of the heap. rts ; End of init_heap. init_tables: - and #0 ; Reset A. - lda.w #SCRSIZE ; Allocate SCRSIZE bytes of RAM for the screen buffer. + lea d, SCRSIZE ; Allocate SCRSIZE bytes of RAM for the screen buffer. jsr malloc ; sta.q buffer ; - and #0 ; Reset A. - lda.w #CMDSIZE ; Allocate CMDSIZE bytes of RAM for the command buffer. + lea d, CMDSIZE ; Allocate CMDSIZE bytes of RAM for the command buffer. jsr malloc ; sta.q cmd_buf ; - and #0 ; Reset A. - lda.w #LWSIZE ; Allocate LWSIZE bytes of RAM for the linewrap table. + lea d, LWSIZE ; Allocate LWSIZE bytes of RAM for the linewrap table. jsr malloc ; sta.q bitabl ; - and #0 ; Reset A. rts ; End of init_tables. ;test_free: ; inc step ; -; lda.q bitabl ; +; mov.q d, bitabl ; ; jsr free ; -; lda.q buffer ; +; mov.q d, buffer ; ; jsr free ; -; and #0 ; Reset A. -; lda.w #LWSIZE ; Allocate LWSIZE bytes of RAM for the linewrap table. +; lea d, LWSIZE ; Allocate LWSIZE bytes of RAM for the linewrap table. ; jsr malloc ; ; sta.q bitabl ; -; lda.q cmd_buf ; +; mov.q d, cmd_buf; ; jsr free ; -; and #0 ; Reset A. -; lda.w #SCRSIZE ; Allocate SCRSIZE bytes of RAM for the screen buffer. +; lea d, SCRSIZE ; Allocate SCRSIZE bytes of RAM for the screen buffer. ; jsr malloc ; ; sta.q buffer ; -; and #0 ; Reset A. -; lda.w #CMDSIZE ; Allocate CMDSIZE bytes of RAM for the command buffer. +; lea d, CMDSIZE ; Allocate CMDSIZE bytes of RAM for the command buffer. ; jsr malloc ; ; sta.q cmd_buf ; ; and #0 ; Reset A. @@ -74,33 +68,38 @@ init_tables: clr_arr: - stz.q (e) ; Clear eight bytes. - ade #8 ; Increment the pointer by 8. - stz.q (e) ; Clear eight bytes. - ade #8 ; Increment the pointer by 8. - sub #$10 ; Subtract 16 from the size. + pha.q ; Preserve A. + and #0 ; Reset A. +@loop: + mov.q (d), a ; Clear 16 bytes. + mov.q (d+8), a ; + add d, #$10 ; Increment the pointer by 16. + sub s, #$10 ; Subtract 16 from the size. bcc @end ; We've reached the end of the array, so we're done. beq @end ; - bra clr_arr ; Keep looping. + bra @loop ; Keep looping. @end: + pla.q ; Restore A. rts ; End of clr_arr. pnt_strt: - lea ed_name ; Print the name of the editor. + lea d, ed_name ; Print the name of the editor. jsr print_str ; - lea ver_str ; Print the version text. + lea d, ver_str ; Print the version text. jsr print_str ; - lea ed_ver ; Print the version number. + lea d, ed_ver ; Print the version number. jsr print_str ; - lea ed_sver ; Print the sub version number. + lea d, ed_sver ; Print the sub version number. jsr print_str ; + lea d, '\n' ; Print a newline. lda #'\n' ; Print a newline. jsr print_char ; - lea made ; Print the "Created by" text. + lea d, made ; Print the "Created by" text. jsr print_str ; - lea author ; Print the name of the author. + lea d, author ; Print the name of the author. jsr print_str ; + lea d, '\n' ; Print a newline. lda #'\n' ; Print a newline. jsr print_char ; rts ; End of pnt_strt. @@ -109,8 +108,8 @@ pnt_strt: clr_cmd: and #0 ; Reset A. tay ; Reset Y. - lda.w #CMDSIZE ; Set the clear count to CMDSIZE. - lea (cmd_buf) ; Set the array to be cleared to the command buffer. + lea s, CMDSIZE ; Set the clear count to CMDSIZE. + lea d, (cmd_buf); Set the array to be cleared to the command buffer. jsr clr_arr ; Clear the command buffer. rts ; End of clr_cmd. @@ -149,140 +148,68 @@ getchar: print_str: + pha.q ; Preserve A. + phb.q ; Preserve B. and #0 ; Reset A. tba ; Reset B. @loop: - ldb #1 ; Enable replace mode. - stb regb ; - and #0 ; No, reset the accumulator. - ldb (e) ; Are we at the end of the string? + mov regb, #1 ; Enable replace mode. + and #0 ; Reset A. + mov b, (d) ; 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. - ine ; Increment the string pointer. + inc d ; Increment the string pointer. jsr print_char ; Print the character. bra @loop ; Keep looping. @end: stz regb ; Enable insert mode. and #0 ; Reset A. tab ; Reset B. + pla.q ; Restore A. + plb.q ; Restore B. rts ; End of print_str. -;print_str: -; ldx #0 ; Reset X. -; sta.q end ; Save the parameter. -;@reset: -; lda.q end ; Get the parameter. -; ldb #0 ; Clear the B register. -; jsr set_ptr ; Set the first pointer to the parameter. -; tba ; Clear the Accumulator. -;@loop: -; ldb #1 ; Enable replace mode. -; stb regb ; -; lda.q ptr ; Get the first pointer. -; cmp.q end ; Did the pointer change? -; bne @reset ; Yes, so set it back. -; and #0 ; No, reset the accumulator. -; txy ; Copy the string index into Y. -; 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. -; phx ; Preserve the string index. -; jsr print_char ; Print the character. -; plx ; Get the string index back. -; bra @loop ; Keep looping. -;@end: -; stz regb ; Enable insert mode. -; and #0 ; Reset A. -; tab ; Reset B. -; rts ; End of print_str. - getbit: - clc ; Clear the carry flag. - lda scr_str ; Has the screen been scrolled? - bne getbt0 ; Yes, so add the screen offset to the current line number. - ldx scr_row ; No, so just use the current line number. - bra getbt1 ; Start getting the bit. -getbt0: - lda scr_row ; Get the current line number. - adc scr_str ; Add the screen offset to it. - tax ; Use it as the wrap index. -getbt1: - pha ; Save the parameter. - ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.q bitabl ; Set the second pointer to the linewrap table. - jsr set_ptr ; - lsr #$10 ; Clear the Accumulator. - pla ; Get the return byte back. - jsr bitpos ; Get the bit, and byte position. - phy.w ; Save the screen index. - txy ; Get the byte position. - ldb (ptr2), y ; Get one byte of the wrap table. - ply.w ; Get the screen index back. - and b ; Mask out the bit of the current line number. - cmp #1 ; Set the carry flag, if true. - bra bitout ; We are done. + des ; Create the stack frame. + add d, s ; Add the row position with the row offset position. + lea s, (sp+1) ; Get the address of the bitmask. + jsr bitpos ; Get the bit, and byte position. + ins ; Cleanup the stack frame. + mov a, (bitabl)+a ; Get the bit of the row position. + and a, (s) ; Return the masked bit. + rts ; End of getbit. + clrbit: - pha ; Save the parameter. - ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.q bitabl ; Set the second pointer to the linewrap table. - jsr set_ptr ; - and #0 ; Clear the Accumulator. - pla ; Get the return byte back. - jsr bitpos ; Get the bit, and byte position. - xor #$FF ; Invert the bitmask. - phy.w ; Save the screen index. - txy ; Get the byte position. - ldb (ptr2), y ; Get one byte of the wrap table. - and b ; Clear the bit of the current line number. -bitsav: - sta (ptr2), y ; Update the wrap table. - ply.w ; Get the screen index back. -bitout: - ldx bitmask ; Return the bitmask. - rts ; We are done. + pha.q ; Preserve A. + des ; Create the stack frame. + lea s, (sp+1) ; Get the address of the bitmask. + jsr bitpos ; Get the bit, and byte position. + ins ; Cleanup the stack frame. + not (s) ; Invert the bitmask. + and (bitabl)+a, (s) ; Set the bit of the current row number to zero. + pla.q ; Restore A. + rts ; End of clrbit. setbit: - pha ; Save the parameter. - ldb #1 ; Make sure that set_ptr sets the second pointer. - lda.q bitabl ; Set the second pointer to the linewrap table. - jsr set_ptr ; - and #0 ; Clear the Accumulator. - pla ; Get the return byte back. - jsr bitpos ; Get the bit, and byte position. - phy.w ; Save the screen index. - txy ; Get the byte position. - ldb (ptr2), y ; Get one byte of the wrap table. - ora b ; Set the bit of the current line number. - bra bitsav ; Save the bit. + pha.q ; Preserve A. + des ; Create the stack frame. + lea s, (sp+1) ; Get the address of the bitmask. + jsr bitpos ; Get the bit, and byte position. + ins ; Cleanup the stack frame. + or (bitabl)+a, (s) ; Set the bit of the current row number to one. + pla.q ; Restore A. + rts ; End of setbit. bitpos: - pha ; Save the parameter. - ldb #0 ; Make sure that set_ptr sets the first pointer. - lda.w #bits ; Set the first pointer to the bitmask table. - jsr set_ptr ; - and #0 ; Clear the Accumulator. - pla ; Get the parameter back. - stx bitmask ; Make the line number the bitmask. - txa ; Copy it to the Accumulator. - and #7 ; Get the bit position. - phy.w ; Save the cursor index. - tay ; Use the bit position as the index. - tax ; Copy it into X. - lda (ptr), y ; Get the bitmask. - ply.w ; Get back the cursor index. - pha ; Save the bitmask. - lda bitmask ; Get the line number. - lsr #3 ; Get the byte position. - tax ; Copy it into X. - pla ; Get back the bitmask. - rts ; End of bitpos. + mov a, d ; Preserve the row number. + and d, #7 ; Get the bit position. + lsr #3 ; Return the byte position. + mov (s), (d+bits) ; Place the bitmask into the mask argument. + rts ; End of bitpos. handle_char: @@ -328,7 +255,10 @@ handle_char: cmd_cpy: lda scr_row ; Get the row position. sta scr_trow ; Save it for later. - jsr findend ; Find the end of the line. + lea d, (buffer) ; Get the screen buffer. + mov s, y ; Get the cursor index. + jsr find_end ; Find the end of the line. + div #maxcol+1 ; Get the ending line. ldb scr_str ; Has the screen been scrolled? beq @start ; No, so don't subtract the screen's starting point from the line number. @offset: @@ -388,48 +318,45 @@ cmd_cpy: findst: - lda #0 ; Reset A. +; lda #0 ; Reset A. +; xor d, d ; Reset D. +; xor s, s ; Reset S. + mov d, scr_row ; Get the row position. + mov s, scr_str ; Get the row offset. @loop: - pha ; Save the current line number. +; pha ; Save the current line number. jsr getbit ; Is this the start of the line? - pla ; Get the current line number back. - bcc @end ; Yes, so we're done. - inc ; No, so check the next physical line. +; pla ; Get the current line number back. + beq @end ; Yes, so we're done. + inc d ; No, so check the next physical line. dec scr_row ; Are we at the top of the screen? bpo @loop ; No, so keep looping. - dec ; Yes, so move back one line. + dec d ; Yes, so move back one line. inc scr_row ; Put the row postiion back to zero. @end: - cmp #0 ; Update all the flags. + cmp d, #0 ; Update all the flags. rts ; End of findst. -fndend: - phb ; Save the contents of the B register. - ldb #0 ; Make sure that set_ptr sets the first pointer. - lda.q buffer ; Set the first pointer to the start of the screen buffer. - jsr set_ptr ; - tba ; Set the Accumulator to zero. - plb ; Restore the contents of the B register. - phy.w ; +find_end: + mov a, s ; Set the loop counter. @loop: - lda (ptr), y ; Are we at the end of the string? - beq @end ; Yes, so we're done. - iny ; No, so increment the cursor index. - bra @loop ; Keep looping. + inc ; Increment the loop counter. + cmp (d+a-1), #0 ; Did we hit the null terminator? + bne @loop ; No, so keep looping. @end: - sty.w scr_ptr3 ; - ply.w ; - rts ; End of fndend. - -findend: - jsr fndend ; - lda.w scr_ptr3 ; - div #maxcol+1 ; - rts ; + rts ; End of find_end. + + +get_endrow: + jsr find_end ; Find the end of the line. + div #maxcol+1 ; Get the ending row. + rts ; End of get_endrow print_char: + phb.q ; Preserve B. + phx.q ; Preserve X. phe.q ; Preserve E. sta rega ; Preserve the character. ldb #2 ; Make sure that set_ptr sets the third pointer. @@ -441,15 +368,13 @@ print_char: lda rega ; Get the character back. jsr get_ctrlidx ; Get the control code jump table index. lsl #1 ; Multiply the return value by two, to get the index. - tax ; - lea.w (ct_jtb, x); Get the address of the control code handler. -; pha.q ; -; ple.q ; -; jsr set_ptr ; Set the second pointer to the control code handler. + lea.w e, (ct_jtb+a); Get the address of the control code handler. deb ; Reset B. tba ; Reset A. jsr (e) ; Jump to the handler for that control code. ple.q ; Restore E. + plx.q ; Restore X. + plb.q ; Restore B. rts printc: lda #0 ; start trying to print a character. @@ -458,18 +383,20 @@ printc: beq @save ; Yes, so just print the character. lda regb ; No, but was the flag set? bne @save ; Yes, so don't shift the line. - sty.w scr_ptr ; No, so save the cursor index for later. - jsr fndend ; Find the end of the line. +; sty.w scr_ptr ; No, so save the cursor index for later. +; jsr fndend ; Find the end of the line. bra @shift ; Start shifting the line right. @update: lda scr_col ; Save the current column position for later. sta scr_tcol ; @update1: - jsr findend ; Find the end of the line. - sta rege ; Use it for redrawing the line. + lea d, (buffer) ; Get the screen buffer. + mov s, y ; Get the cursor index. + jsr get_endrow ; Get the ending line. + mov d, a ; + mov s, scr_trow ; Get the current row position. lda scr_trow ; Get the current row position. @update2: - sta regf ; Set the starting line, to the current row position. jsr rdrw_ln ; Redraw the line. lda scr_trow ; Get the real row position back. sta scr_row ; @@ -479,12 +406,15 @@ printc: dec regd ; bra @save1 ; @shift: - ldy.w scr_ptr3 ; - inc scr_ptr3 ; - tyx ; - dey ; - ldb #1 ; - stb regd ; +; ldy.w scr_ptr3 ; +; inc scr_ptr3 ; +; tyx ; +; dey ; +; ldb #1 ; +; stb regd ; + lea d, (buffer) ; Get the screen buffer. + mov.w s, scr_ptr; Get the cursor index. + mov f, #1 ; Set the left flag to true. jsr shftln ; ldb #1 ; stb regd ; @@ -501,6 +431,7 @@ printc: sta (ptr3), y ; store typed character into the input buffer. @incr: inc scr_col ; Increment the cursor's x coordinate. + inc.w scr_ptr ; Increment the screen index. iny ; @wrapped: ldb #1 ; @@ -536,13 +467,15 @@ printc: @wrap1: inc scr_row ; @wrap2: - phx.w ; - clc ; - lda scr_row ; - adc scr_str ; - tax ; - jsr setbit ; - plx.w ; +; phx.w ; +; clc ; +; lda scr_row ; +; adc scr_str ; +; tax ; + mov d, scr_row ; Get the row position. + add d, scr_str ; Add the row offset to the row position. + jsr setbit ; Set the bit of that row. +; plx.w ; jsr update_pos ; printc_end: rts ; @@ -573,11 +506,11 @@ clr_scr: sta scr_end ; stz scr_str ; tay ; - lda.w #LWSIZE ; Set the clear count to LWSIZE. - lea (bitabl) ; Set the array to be cleared to the linewrap table. + lea s, LWSIZE ; Set the clear count to LWSIZE. + lea d, (bitabl) ; Set the array to be cleared to the linewrap table. jsr clr_arr ; Clear the linewrap table. - lda.w #SCRSIZE ; Set the clear count to SCRSIZE. - lea (buffer) ; Set the array to be cleared to the screen buffer. + lea s, SCRSIZE ; Set the clear count to SCRSIZE. + lea d, (buffer) ; Set the array to be cleared to the screen buffer. jsr clr_arr ; Clear the screen buffer. ; lda.w #CMDSIZE ; Set the clear count to CMDSIZE. ; lea (cmd_buf) ; Set the array to be cleared to the command buffer. @@ -613,8 +546,10 @@ bs: beq @wrap ; Yes, so check for a wrapped line. bra back ; No, so add the backspace to the buffer. @wrap: + mov d, scr_row ; Get the row position. + mov s, scr_str ; Get the row offset. jsr getbit ; Is this line, a wrapped line? - bcs @wrap1 ; Yes, so check if the cursor is at the top. + bne @wrap1 ; Yes, so check if the cursor is at the top. rts ; No, so we're done. @wrap1: lda scr_row ; Are we at the top of the screen? @@ -644,7 +579,9 @@ back: stb regf ; lda scr_row ; Save the current row position for later. sta scr_trow ; - jsr findend ; Find the end of the line. + lea d, (buffer) ; Get the screen buffer. + mov s, y ; Get the cursor index. + jsr get_endrow ; Get the ending line. sta scr_row ; Set our row position to the end of the line. @find_st: jsr findst ; Does this line take up more than one real line? @@ -660,14 +597,20 @@ back: iny ; Increment cursor index. ldb #0 ; Set shifting direction to left. stb regd ; + lea d, (buffer) ; Get the screen buffer. + mov s, y ; Get the cursor index. + mov f, #0 ; Set the left flag to false. jsr shftln ; Shift line back by one character. lda #$7F ; Print a backspace to the screen. sta scr ; lda rege ; Are we updating more than one line? beq @load ; No, so skip to the next step. @find_end: - jsr findend ; Yes, so find the end of the line. - sta rege ; Set the end parameter to it. + lea d, (buffer) ; Get the screen buffer. + mov s, y ; Get the cursor index. + jsr get_endrow ; Yes, so Get the ending line. + mov d, a ; + mov s, scr_trow ; Get the current row position. lda scr_col ; Save the current column position for now. sta scr_tcol ; jsr rdrw_ln ; Start redrawing the line. @@ -683,88 +626,73 @@ back: lda (ptr3), y ; Are we at the end of the line? beq @shift ; Yes, so skip redrawing. lda scr_trow ; No, so set the line to start redrawing, to the line that the cursor is on. - sta regf ; inc rege ; Set the redraw flag to true. bra @shift ; Start shifting the line back. shftln: - ldb regd ; Is the flag not set? - beq @dec_loop ; Yes, so shift, and decrement. - ldb #0 ; Clear the B register. - bra @inc_loop ; No, so shift, and increment. + pha.q ; Preserve A. + phb.q ; Preserve B. + and f, f ; Is the left flag not set? + beq @right ; Yes, so shift the line to the right. +; txa ; Get the end of the line. + jsr find_end ; Find the end of the line. + dec ; Decrement the source position. + bra @left ; No, so shift the line to the left. @minus: - ldy.w zero ; Set the source poition to 0. - stb (ptr3), y ; Clear the character that is in the source. - bra @end ; We are done. -@inc_loop: - sty.w scr_ptr2 ; Save the source position for later. - ldy.w scr_ptr ; Get the previous cursor index. - cpy.w scr_ptr2 ; Is the source position, at, or below the cursor index? - beq @inc_loop1 ; Yes, so keep looping. - bcs @end ; No, so we're done. -@inc_loop1: - ldy.w scr_ptr2 ; Get the source position. - lda (ptr3), y ; Get the character from the source position. - phy.w ; Save the source position for later. - txy ; Set our position to the destination. - sta (ptr3), y ; Place the character from the source position, to the destination position. - ply.w ; Set our position back to the source. - stb (ptr3), y ; Clear the character that is in the source. - bng @minus ; The source underflowed, so set it back to zero, - dey ; Decrement the source position. - dex ; Decrement the destination position. - bra @inc_loop ; Keep looping. -@dec_loop: - stx.w scr_ptr2 ; Save the destination position for later. - lda (ptr3), y ; Is the character at the source position, a null terminator? - beq @end3 ; Yes, so we're done. - phy.w ; No, so save the source position for later. - txy ; Set our position to the destination. - sta (ptr3), y ; Place the character from the source position, to the destination position. - inx ; Increment the destination position. - ply.w ; Set our position back to the source. - stb (ptr3), y ; Clear the character that is in the source. - iny ; Increment the source position. - bra @dec_loop ; Keep looping. + and #0 ; Set the source poition to 0. + mov (d), a ; Clear the character that is in the source. + bra @lend ; We are done. +@left: + cmp s, a ; Is the cursor index, at, or below the source position? + beq @left1 ; Yes, so keep looping. + bcs @lend ; No, so we're done. +@left1: + cmp #0 ; Is the source position less than 0? + bcc @minus ; Yes, so set the source position to zero. + mov (d+a+1), (d+a) ; No, so shift the current character to the left by one. + mov (d+a), #0 ; Clear the current character. + dec ; Decrement the source position. + bra @left ; Keep looping. +@right: + cmp (d+s), #0 ; Is this character a null terminator? + beq @rend ; Yes, so we're done. + mov (d+s-1), (d+s) ; No, so shift the current character to the right by one. + mov (d+s), #0 ; Clear the current character. + inc s ; Increment the source position. + bra @right ; Keep looping. @wrap: - tax ; Use the ending line as a parameter for setbit. - jsr setbit ; Set the wrap bit of the ending line. - bra @end5 ; We are done. + mov d, a ; Get the ending line. + jsr setbit ; Set the wrap bit of the ending line. + bra @end ; We are done. @wrap1: - tax ; Use the ending line as a parameter for clrbit. - jsr clrbit ; Clear the wrap bit of the ending line. - bra @end5 ; We are done. + mov d, a ; Get the ending line. + jsr clrbit ; Clear the wrap bit of the ending line. + bra @end ; We are done. +@lend: + lea s, (a+2) ; Add 2 to the source position. + jsr find_end ; Find the end of the line. + dec ; Decrement the end of line position. + div #maxcol+1 ; Get the ending line. +@lend2: + cmp scr_row ; Is the ending line greater than the starting line? + beq @end ; No, so we're done. + bcs @wrap ; Yes, so set the wrap bit. + bra @end ; No, so we're done. +@rend: + jsr find_end ; Find the end of the line. + dec ; Decrement the end of line position. + div #maxcol+1 ; Get the ending line. + cpb #0 ; Is the remainder zero? + bne @end ; No, so we're done. +@rend2: + cmp scr_row ; Is the ending line greater than the starting line? + beq @end ; No, so we're done. + bcs @wrap1 ; Yes, so clear the wrap bit. @end: - lda (ptr3), y ; Is this character a null terminator? - bne @end1 ; No, so just find the end of the line. - lda #$20 ; Yes, so convert it to a space for now. - sta (ptr3), y ; -@end1: - jsr findend ; Find the ending line. - sta regd ; Save ending line for later. - lda (ptr3), y ; Is this character a space? - cmp #$20 ; - bne @end5 ; No, so skip the conversion. - lda #0 ; Yes, so convert it back to zero. - sta (ptr3), y ; -@end2: - lda regd ; Get the ending line. - cmp scr_row ; Is the ending line greater than the starting line? - beq @end5 ; No, so we're done. - bcs @wrap ; Yes, so set the wrap bit. - bra @end5 ; No, so we're done. -@end3: - jsr findend ; Find the ending line. - cpb #0 ; Is the remainder zero? - beq @end4 ; Yes, so check if the ending line is greater than the starting line. - bra @end5 ; No, so we're done. -@end4: - cmp scr_row ; Is the ending line greater than the starting line? - beq @end5 ; No, so we're done. - bcs @wrap1 ; Yes, so clear the wrap bit. -@end5: - rts ; End of shftln. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of shftln. esc: @@ -883,8 +811,10 @@ isright: bra @right ; No, so move the cursor right, like normal. @wrap: inc scr_row ; Move down a row. + mov d, scr_row ; Get the row position. + mov s, scr_str ; Get the row offset. jsr getbit ; Is the current line, a wrapped line? - bcs @incr ; Yes, so leave the cursor where it is. + bne @incr ; Yes, so leave the cursor where it is. dec scr_row ; No, so move the cursor back up a row. bra @end2 ; We are done. @scroll: @@ -927,8 +857,10 @@ isleft: beq @left ; Yes, so move the cursor left. bra @end1 ; No, so we're done. @wrap: + mov d, scr_row ; Get the row position. + mov s, scr_str ; Get the row offset. jsr getbit ; Is the current line, a wrapped line? - bcs @decr ; Yes, so wrap back up a line. + bne @decr ; Yes, so wrap back up a line. bra @end1 ; No, so we're done. @decr: lda scr_row ; Is the cursor at the top of the screen? @@ -999,12 +931,11 @@ isshftdown: 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. + add scr_str ; with the starting line number to get the absolute line number. 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. + add scr_col ; Add the cursor's column number to get the screen index. + sta.w scr_ptr ; Save the screen index. ; cmp.w #$2000 ; Is the index greater than, or equal to the end of the screen buffer? ; bcc @end ; No, so we're done. ;@wrap: @@ -1021,22 +952,21 @@ update_ptr: update_pos: + phb.q ; Preserve B. + and #0 ; Reset A. + tab ; Reset B. ldb #1 ; Set the F pseudo register to one, to fix some bugs. stb regf ; 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 - sta scr ; to the screen. - lda #'[' ; Print '[' - sta scr ; to the screen, and start the escape sequence. + mov scr, #$1B ; Print an escape character to the screen. + mov scr, #'[' ; Print '[' to the screen, and start the escape sequence. jsr getrow ; Start printing the row number to the screen. - lda #';' ; Print ';' - sta scr ; to the screen. + mov scr, #';' ; Print ';' to the screen. jsr getcol ; Start printing the column number to the screen. - lda #'H' ; Print 'H' - sta scr ; to the screen. - ;inc step ; + mov scr, #'H' ; Print 'H' to the screen. + plb.q ; Restore B. rts ; End of update_pos. getrow: @@ -1068,6 +998,7 @@ scrl_down: lda wrapped ; Was the wrapped flag set? beq @save ; Yes, so save the cursor position. @redraw: + lea d, (buffer) ; Get the screen buffer. jsr rdrw_row ; No, so redraw this row. lda wrapped ; Was the wrapped flag set? beq @load ; Yes, so load the previous cursor position back. @@ -1103,6 +1034,7 @@ scrl_up: pha ; lda #0 ; sta scr_row ; + lea d, (buffer) ; Get the screen buffer. jsr rdrw_row ; pla ; sta scr_col ; @@ -1112,64 +1044,54 @@ scrl_up: @end: rts ; + rdrw_row: - lda #0 ; - sta scr_col ; - jsr update_pos ; + pha.q ; Preserve A. + phb.q ; Preserve B. + stz scr_col ; Reset the column position. + jsr update_pos ; Update the cursor position. + xor b, b ; Reset B. + tya ; Get the screen index. + tab ; + add b, #maxcol+1; Get the end of the row plus one. @loop: - lda (ptr3), y ; - beq @incr ; - sta scr ; -@incr: - inc scr_col ; - lda (ptr3), y ; - beq @skip ; -@incr1: - iny ; -@incr2: - lda scr_col ; - cmp #maxcol+1 ; - bcs @end ; - bra @loop ; -@skip: - lda #' ' ; - sta scr ; to the screen. - bra @incr1 ; + cmp (d+a), #0 ; Is this a null terminator? + mne scr, (d+a) ; No, so print the character. + meq scr, #' ' ; Yes, so print a space. + inc ; Increment the screen index. + cmp b ; Is the column position at, or above the maximum column count? + bcc @loop ; No, so keep looping. @end: - lda #0 ; - sta scr_col ; - jsr update_pos ; -@end1: - rts ; + stz scr_col ; Reset the column position. + jsr update_pos ; Update the cursor position. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of rdrw_row. + rdrw_ln: - lda scr_row ; - pha ; - lda regf ; - sta scr_row ; - lda scr_col ; - pha ; - jsr update_pos ; + pha.q ; Preserve A. + psh scr_row ; Preserve the row position. + psh scr_col ; Preserve the column position. + mov scr_row, s ; Set the row position to the starting position. + jsr update_pos ; Update the cursor position. + mov a, d ; Get the ending position. + lea d, (buffer) ; Get the address of the screen buffer. @loop: - lda scr_row ; - cmp rege ; - beq @loop1 ; - bcs @end ; -@loop1: - jsr rdrw_row ; + cmp scr_row, a ; Is the row position at, or below the ending position? + beq @redraw ; Yes, so redraw the row. + bcs @end ; No, so we're done. +@redraw: + jsr rdrw_row ; Redraw the line. @incr: - inc scr_row ; - bra @loop ; + inc scr_row ; Increment the row position. + bra @loop ; Keep looping @end: - pla ; - sta scr_col ; - pla ; - sta scr_row ; - jsr update_pos ; - lda #0 ; - sta rege ; - sta regf ; - rts ; + pul scr_col ; Restore the column position. + pul scr_row ; Restore the row position. + jsr update_pos ; Update the cursor position. + pla.q ; Restore A. + rts ; End of rdrw_ln. set_ptr: diff --git a/programs/sub-suite/test-size.s b/programs/sub-suite/test-size.s new file mode 100644 index 0000000..b543a36 --- /dev/null +++ b/programs/sub-suite/test-size.s @@ -0,0 +1,59 @@ +MAGIC = $AA + + +.org 0 +findramend: + and #0 ; Reset A. +; lda #MAGIC ; Set A to a magic number. +@loop: + mov a, (d) ; Preserve the value. + mov (d), #MAGIC ; Write the magic number to the current end of RAM. + cmp (d), #MAGIC ; Is the value in RAM, the same as the magic number we wrote? + bne @moveback ; No, so move back until we find the last writable memory location. + mov (d), a ; Yes, so restore the previous value. + add.w d, #$4000 ; Increment the end of RAM pointer by 16K. + bra @loop ; Keep looping. +@moveback: + dec d ; Decrement the end of RAM pointer. + mov a, (d) ; Preserve the value. + mov (d), #MAGIC ; Write the magic number to the current end of RAM. + cmp (d), #MAGIC ; Is the value in RAM, the same as the magic number we wrote? + bne @moveback ; No, so keep looping. + mov (d), a ; Yes, so restore the previous value. +@end: + mov a, d ; Return the end of RAM pointer. +; ple.q ; Restore E. + rts ; End of findramend. + + +;findramend: +; phe.q ; Preserve E. +; phb.q ; Preserve B. +; mov e, d ; Set E to the RAM pointer. +; and #0 ; Reset A. +; lda #MAGIC ; Set A to a magic number. +;@loop: +; ldb (e) ; Preserve the value. +; sta (e) ; Write the magic number to the current end of RAM. +; cmp (e) ; Is the value in RAM, the same as the magic number we wrote? +; bne @moveback ; No, so move back until we find the last writable memory location. +; stb (e) ; Yes, so restore the previous value. +; ade.w #$4000 ; Increment the end of RAM pointer by 16K. +; bra @loop ; Keep looping. +;@moveback: +; dee ; Decrement the end of RAM pointer. +; ldb (e) ; Preserve the value. +; sta (e) ; Write the magic number to the current end of RAM. +; cmp (e) ; Is the value in RAM, the same as the magic number we wrote? +; bne @moveback ; No, so keep looping. +; stb (e) ; Yes, so restore the previous value. +;@end: +; mov a, e ; Return the end of RAM pointer. +; ple.q ; Restore E. +; plb.q ; Restore B. +; rts ; End of findramend. + +a +.org findramend +v +q diff --git a/programs/sub-suite/utils.s b/programs/sub-suite/utils.s index 3813a05..6479099 100644 --- a/programs/sub-suite/utils.s +++ b/programs/sub-suite/utils.s @@ -1,141 +1,125 @@ ; Utility subroutines for SuBAsm. print_hi: - and #0 ; Reset A. - sta idx3 ; Clear the string index. - tax ; Reset X. - lda #'$' ; Print the hex delimiter. - sta strbuf, x ; Save it in the string buffer. - lda.q idx0 ; Get the masked address. - ldx #$10 ; Set digit count to 16. - jsr print_hex ; Print the address. - lda.q hex_str ; Get the lower half of the string. - sta.q strbuf+1 ; Save it in the string buffer. - lda.q hex_str+8 ; Get the upper half of the string. - sta.q strbuf+9 ; Save it in the string buffer. - ldx #$11 ; Add 16 to the index. - stx idx3 ; - lda.w #': ' ; Print a space. - sta.w strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index twice. - inc idx3 ; - and #0 ; Reset A. - rts ; End of print_hi. + phb.q ; Preserve B. + sbs #$10 ; Make room for the hex string buffer. + and #0 ; Reset A. + mov b, d ; Get the string buffer pointer. + mov (b), #'$' ; Print the hex delimiter to the string buffer. + inb ; Increment the string buffer pointer. + lea d, (sp+1) ; Get the address of the hex string buffer. + mov f, #$10 ; Set digit count to 16. + jsr print_hex ; Print the address. + mov.q (b), (a) ; Print the lower half of the hex string to the string buffer. + mov.q (b+8), (a+8) ; Print the upper half of the hex string to the string buffer. + add b, #$10 ; Add 16 to the index. + mov.w (b), #': ' ; Print a colon, and space to the string buffer. + add b, #2 ; Add two to the string buffer pointer. + tba a ; Return the string buffer pointer after the printed string. + ads #$10 ; Cleanup the stack frame. + plb.q ; Restore B. + rts ; End of print_hi. print_lo: - and #0 ; Reset A. - sta idx3 ; Clear the string index. + pha.q ; Preserve A. + phb.q ; Preserve B. + phx.q ; Preserve X. + sbs #$33 ; Make room for the hex string buffer, and the normal string buffer. + and #0 ; Reset A. + tab ; Reset B. + lea d, (sp+1) ; Get the address of the hex string buffer. + lea x, (sp+3) ; Get the address of the string buffer. @loop: - ldx #2 ; Set digit count to 2. - pha ; Preserve the nibble offset. - jsr print_hex ; Print the low nibble offset. - lda.w (ptr3) ; Get the two digits. - ldx idx3 ; Get the string index. - sta.w strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index twice. - inc idx3 ; - ldx idx3 ; Get the string index. - pla ; Get the nibble offset back. - inc ; Increment the offset. - cmp #$10 ; Are we at the last offset? - bcs @end ; Yes, so we're done. + lea f, 2 ; Set the digit count to two. + mov s, b ; Get the low nibble offset. + jsr print_hex ; Print the low nibble offset. + mov.w (x), (a) ; Place the hex digits in the string buffer. + add x, #2 ; Add two to the string buffer pointer. + inb ; Increment the nibble offset. + cpb #$10 ; Are we at the last offset? + bcs @end ; Yes, so we're done. @loop1: - pha ; No, so preserve the nibble offset. - lda #' ' ; Add a space to the string buffer. - sta strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index. - pla ; Get the nibble offset back. - bra @loop ; Keep looping. + mov (x), #' ' ; No, so add a space to the string buffer. + inx ; Increment the string buffer pointer. + bra @loop ; Keep looping. @end: - and #0 ; Reset A. - sta strbuf, x ; Null terminate the string buffer. - tax ; Reset X. - lea strbuf ; Print the string buffer. -; jsr print_str ; - jsr print_sfast ; Use the faster, but less robust print string routine. - rts ; End of print_lo. -;@end: -; lda #0 ; Null terminate the string buffer. -; sta strbuf, x ; -; tax ; Reset X. -; lea strbuf ; Print the string buffer. -; jsr print_str ; -; rts ; End of print_lo. + mov (x), #0 ; Null terminate the string buffer. + lea d, (sp+3) ; Get the address of the string buffer. + lea s, (buffer)+y ; Get the address of the screen buffer, at the current cursor position. +; jsr print_str ; Print the string buffer. + jsr print_sfast ; Use the faster, but less robust print string routine. + ads #$33 ; Cleanup the stack frame. + plx.q ; Restore X. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of print_lo. print_chunk: - ldx #0 ; Reset X. - phy.w ; Preserve the screen buffer index. - txy ; Copy the byte index to it. + pha.q ; Preserve A. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + sbs #2 ; Make room for the hex string buffer. + and #0 ; Reset A. + tab ; Reset B. + mov x, d ; Get the address of the string buffer. + mov y, s ; Get the starting address. + lea d, (sp+1) ; Get the address of the hex string buffer. + xor s, s ; Reset S. @loop: - and #0 ; Reset A. - ldx #2 ; Set the digit count to 2. - lda (idx0), y ; Get the byte at that address. - jsr print_hex ; Print the byte. - lda.w (ptr3) ; Get the two digits. - ldx idx3 ; Get the string index. - sta.w strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index twice. - inc idx3 ; - ldx idx3 ; Get the string index. - iny ; Increment the byte index. - cpy #$10 ; Have we read 16 bytes? - beq @end ; Yes, so we're done. - lda #' ' ; No, so add a soace to the string buffer. - sta strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index. - bra @loop ; Keep looping. + lea f, 2 ; Set the digit count to two. + mov s, (y+b) ; Get the byte at that address. + jsr print_hex ; Print the byte. + mov.w (x), (a) ; Print the hex string to the string buffer. + add x, #2 ; Add two to the string buffer pointer. + inb ; Increment the byte index. + cpb #$10 ; Have we read 16 bytes? + beq @end ; Yes, so we're done. + mov (x), #' ' ; No, so print a space to the string buffer. + inx ; Increment the string buffer pointer. + bra @loop ; Keep looping. @end: - ply.w ; Get the screen buffer index back. - inx ; Increment the index by one. - and #0 ; Null terminate the string. - sta strbuf, x ; - tax ; Reset X. - sta idx3 ; Clear the string index. - rts ; End of print_chunk. + mov (x), #0 ; Null terminate the string. + ads #2 ; Cleanup the stack frame. + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. + pla.q ; Restore A. + rts ; End of print_chunk. print_hex: - pha.q ; Preserve the hex value. - and #0 ; Reset A. - ldb #1 ; Set the second pointer - lda.w #hex_char ; to the start of hex character table. - jsr set_ptr ; - inb ; Set the third pointer - lda.d #hex_str ; to the end of hex string buffer. - clc ; Do a non carrying add. - adc #$10 ; - jsr set_ptr ; - ldb #0 ; Reset B. - pla.q ; Get the hex value back. + phb.q ; Preserve B. + phx.q ; Preserve X. + phy.q ; Preserve Y. + lea b, hex_char ; Get the address of the hex character table. + and f, f ; Is the digit count zero? + set x, eq ; Set the auto digit count flag if so. + mne f, #$10 ; Also set the digit count to 16 if the digit count is zero. + mov a, f ; Get the digit count. + add a, d ; Add the string pointer with the digit count. @loop: - pha.q ; Preserve the hex value. - and #$F ; Mask the lowest nibble. - phy.w ; Preserve the screen buffer position. - tay ; Get the index for the hex digit. - lda (ptr2), y ; Get the hex digit. - dec ptr3 ; Decrement the string pointer. - sta (ptr3) ; Save the hex digit character in the string. - ply.w ; Get back the screen buffer position. - pla.q ; Get the hex value back. + mov y, s ; No, so mask the low nibble of the value. + and y, #$F ; + dec ; Decrement the string pointer. + mov (a), (b+y) ; Place the hex digit character in the string. + lsr s, #4 ; Is the next nibble zero? + bne @loop1 ; No, so decrement the digit count. @isauto: - cpx #1 ; Is the digit count less than one? - bcc @auto ; Yes, so don't decrement the digit count. - dex ; No, but was the digit count zero, when decremented? - beq @end ; Yes, so we're done. - bra @next ; No, so get the next nibble. -@auto: - ldb #1 ; Enable auto digit count. -@next: - lsr #4 ; Is the next nibble, a zero? - beq @isauto1 ; Yes, so check if auto digit count is enabled. - bra @loop ; No, so print the next digit. -@isauto1: - cpb #1 ; Is auto digit count enabled? - beq @end ; Yes, so we're done. - bra @loop ; No, so keep printing more digits. + and x, x ; Is the auto digit count flag set? + bne @end ; Yes, so we're done. +@loop1: + cpx #1 ; Is the auto digit count flag set? + sbc f, #0 ; Decrement the digit count if not. + mov y, f ; Get the digit count. + or y, x ; Are both the digit count, and the auto digit count flag zero? + bne @loop ; No, so keep looping. @end: + ply.q ; Restore Y. + plx.q ; Restore X. + plb.q ; Restore B. rts ; End of print_hex. @@ -147,26 +131,18 @@ charcpy: strcmpg: - ldb.w #strcmp ; Get the address of strcmp. - phb.q ; Use it for an indirect call. - ldb.q ptr ; Get the first pointer. + lea strcmp ; Get the address of strcmp. + mov.q d, 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. + lea strcasecmp ; Get the address of strcasecmp. + mov.q d, 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. + mov s, a ; Use the value in A as the second arg. + and #0 ; Reset a. + tab ; Reset b. + jsr (e) ; Call the pushed routine. rts ; End of gargs. @@ -310,11 +286,6 @@ get_ptok: get_ctrlidx: -; phe.q ; Preserve E. -; cmp #$7F ; Is this a delete character? -; beq @del ; Yes, so return the same value as backspace. -; sec ; Do a non borrowing subtract. -; sbc #8 ; Subtract 8 from the character, to get the index. sub #8 ; Subtract 8 from the character, to get the index. tax ; Copy the index to X. and #0 ; Reset A. @@ -324,62 +295,41 @@ get_ctrlidx: leq (e) ; cmp #$7F ; Is this a delete character? leq #2 ; Return 2 if this is the delete character. -; bcc @get_rtval ; Yes, so get the return value from the table. -; beq @get_rtval ; -; ple.q ; Restore E. rts ; End of get_ctrlidx. -;@get_rtval: -; lda ct_rtb, x ; Get the return value from the table. -; rts ; End of get_ctrlidx. -;@del: -; lda #2 ; Return 2. -; rts ; End of get_ctrlidx. findramend: - phx.q ; Preserve X. and #0 ; Reset A. - lda #MAGIC ; Set A to a magic number. @loop: - ldx (e) ; Preserve the value. - sta (e) ; Write the magic number to the current end of RAM. - cmp (e) ; Is the value in RAM, the same as the magic number we wrote? + mov a, (d) ; Preserve the value. + mov (d), #MAGIC ; Write the magic number to the current end of RAM. + cmp (d), #MAGIC ; Is the value in RAM, the same as the magic number we wrote? bne @moveback ; No, so move back until we find the last writable memory location. - stx (e) ; Yes, so restore the previous value. - ade.w #$4000 ; Increment the end of RAM pointer by 16K. + mov (d), a ; Yes, so restore the previous value. + add.w d, #$4000 ; Increment the end of RAM pointer by 16K. bra @loop ; Keep looping. @moveback: - dee ; Decrement the end of RAM pointer. - ldx (e) ; Preserve the value. - sta (e) ; Write the magic number to the current end of RAM. - cmp (e) ; Is the value in RAM, the same as the magic number we wrote? + dec d ; Decrement the end of RAM pointer. + mov a, (d) ; Preserve the value. + mov (d), #MAGIC ; Write the magic number to the current end of RAM. + cmp (d), #MAGIC ; Is the value in RAM, the same as the magic number we wrote? bne @moveback ; No, so keep looping. - stx (e) ; Yes, so restore the previous value. + mov (d), a ; Yes, so restore the previous value. @end: - phe.q ; Return the end of RAM pointer. - pla.q ; - plx.q ; Restore X. + mov a, d ; Return the end of RAM pointer. rts ; End of findramend. print_sfast: -; inc step ; - pea (buffer), y ; Push the address of the cursor's postion in the screen buffer to the stack. + pha.q ; Preserve A. + and #0 ; Reset A. @loop: - lda (e) ; Get the character. - beq @end ; We've hit the end of the string, so we're done. - cmp #'\n' ; Did we get a newline? - beq @nl ; Yes, so move the cursor to the next line. - sta (sp+1) ; Print the character to the screen buffer. - sta scr ; Print the character to the screen. - inc scr_col ; Move the cursor left by one character. - ine ; Increment the string pointer. - inc.q sp+1 ; Increment the screen buffer pointer. - bra @loop ; Keep looping. -@nl: - stz scr_col ; Move the cursor to the start of the line. - inc scr_row ; Move the cursor down by one line. - bra @loop ; Keep looping. + inc ; Increment the index. + cmp (d+a-1), #0 ; Did we hit the end of the string? + beq @end ; Yes, so we're done. + mov (s+a-1), (d+a-1) ; No, so print the character to the buffer. + mov scr, (d+a-1) ; Print the character to the screen. + bra @loop ; Keep looping. @end: - ads #8 ; Cleanup the stack frame. - rts ; End of print_sfast. + pla.q ; Restore A. + rts ; End of print_sfast. diff --git a/supervia.c b/supervia.c new file mode 100644 index 0000000..23e44e9 --- /dev/null +++ b/supervia.c @@ -0,0 +1,18 @@ +void init_supervia(struct supervia *sv) { + memset(sv, 0, sizeof(struct supervia)); +} + +/* Shifts out one bit from each output byte of the shift register into + * the serial output lines of those output bytes. + */ +void shift_out8(struct supervia *sv, int id) { + uint8_t bitpos = 7-sv->sr[id].ocount; + for (int i = 0; i < 8; i++) { + if (sv->sr[id].dir & (1 << i)) { + uint8_t bit = (sv->sr[id].data.u8[i] >> bitpos) & 1; + sv->sr[id].bits |= (bit << i); + } + } + sv->sr[id].ocount++; + sv->sr[id].ocount %= 8; +} diff --git a/supervia.h b/supervia.h new file mode 100644 index 0000000..8afc45d --- /dev/null +++ b/supervia.h @@ -0,0 +1,25 @@ + +struct shift_reg { + union reg data; /* Shift Register Data. */ + uint8_t bits; /* Serial data for each byte. */ + uint8_t ocount; /* Shift out counter. */ + uint8_t icount; /* Shift out counter. */ + uint8_t dir; /* Data direction for each byte. */ +}; + + +struct supervia { + union reg pa; /* Port A. */ + union reg pb; /* Port B. */ + union reg ddra; /* Port A Data Direction Register. */ + union reg ddrb; /* Port B Data Direction Register. */ + union reg t[4]; /* Timers 1-4. */ + struct shift_reg sr[4]; /* Shift Registers A-D. */ + union reg acr; /* Auxiliary Control Register. */ + union reg pcr; /* Peripheral Control Register. */ + union reg ifr; /* Interrupt Flags Register. */ + union reg ier; /* Interrupt Enable Register. */ + union reg rng[2]; /* Random Number Generator A, and B. */ + union reg dac[2]; /* DAC A, and B. */ + union reg adc[2]; /* ADC A, and B. */ +}; @@ -33,6 +33,7 @@ uint8_t step = 0; uint8_t *addr; uint8_t kbd_rdy; +uint8_t dbg_print_per_inst = 0; uint8_t end = 0; @@ -107,6 +108,21 @@ uint8_t is_extop(uint8_t opcode, uint8_t dbg) { return 1; } +int is_wait_kbd(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t *op_type, uint8_t *op_id, uint8_t op_len, uint8_t thread) { + uint64_t address = 0; + operand ortho_op[2]; + uint64_t ortho_addr[2] = {0, 0}; + uint64_t tmp_pc = cpu->pc; + cpu->pc += op_len; + if (ext_prefix != 0x1D) { + address = get_addr(cpu, opcode, prefix, ext_prefix, 0, 0, thread); + } else { + get_ortho_addr(cpu, prefix, cpu->pc, ortho_op, ortho_addr, op_type, op_id, 0, 0, thread); + } + cpu->pc = tmp_pc; + return (address == CTRL_ADDR || ortho_addr[0] == CTRL_ADDR || ortho_addr[1] == CTRL_ADDR); +} + void *run(void *args) { struct suxthr *thr = (void *)args; struct sux *cpu = &thr->sx; @@ -169,19 +185,6 @@ void *run(void *args) { #endif address.u64 = 0; value.u64 = 0; - #if debug && !bench - if (lines > 24*(thread+1)) { - lines = (24*thread)+2; - } - #if keypoll - pthread_mutex_lock(&mutex); - #endif - print_info(cpu, inst_win, lines, thread); - print_regs(cpu, regs); - #if keypoll - pthread_mutex_unlock(&mutex); - #endif - #endif uint32_t inst = read_value(cpu, 0, cpu->pc, 4, 1, 0); uint8_t *tmp_inst = (uint8_t *)&inst; uint8_t inst_len = 0; @@ -190,8 +193,6 @@ void *run(void *args) { opcode = tmp_inst[inst_len++]; op_id = (ext_prefix == 0x1D) ? tmp_inst[inst_len++] : 0; - cpu->pc += inst_len; - address.u64 = cpu->pc; uint8_t operand_type[2]; uint8_t am; uint8_t ortho_id[2]; @@ -253,16 +254,34 @@ void *run(void *args) { uint8_t rs = (prefix >> 4) & 3; uint8_t size = (/***/1 << rs) - 1; uint8_t check_io = (am != IMM); - #if debug && !bench - #if keypoll - pthread_mutex_lock(&mutex); - #endif - disasm(cpu, inst_win, lines, opcode, prefix, ext_prefix, prefix2, operand_type, ortho_id, thread); - lines+=1; - #if keypoll - pthread_mutex_unlock(&mutex); + cpu->pc += inst_len; + address.u64 = cpu->pc; + #if debug && !bench + cpu->pc -= inst_len; + if (!dbg_print_per_inst) { + kbd_rdy = is_wait_kbd(cpu, opcode, prefix, ext_prefix, prefix2, operand_type, ortho_id, inst_len, thread); + } else { + kbd_rdy = 0; + } + if (lines > 24*(thread+1)) { + lines = (24*thread)+2; + } + if (step | kbd_rdy | dbg_print_per_inst) { + #if keypoll + pthread_mutex_lock(&mutex); + #endif + print_info(cpu, inst_win, lines, thread); + print_regs(cpu, regs); + cpu->pc = address.u64; + disasm(cpu, inst_win, lines, opcode, prefix, ext_prefix, prefix2, operand_type, ortho_id, thread); + lines+=1; + #if keypoll + pthread_mutex_unlock(&mutex); + #endif + } else { + cpu->pc = address.u64; + } #endif - #endif if (am != IMPL && am != BREG) { address.u64 = get_addr(cpu, opcode, prefix, ext_prefix, 1, 1, thread); /*if (address.u64 > mem_size-1) { @@ -285,7 +304,7 @@ void *run(void *args) { } else { exec_base_inst(cpu, opcode, prefix, value.u64, address.u64, size, thread); } - //usleep(1); + /*usleep(1);*/ #if !IO ins++; #endif @@ -22,6 +22,7 @@ #define copy64 1 extern uint8_t kbd_rdy; +extern uint8_t dbg_print_per_inst; extern WINDOW *scr; extern WINDOW *regs; @@ -292,6 +293,18 @@ static /*inline*/ uint8_t isread(uint8_t opcode, uint8_t ext_prefix) { } } +static int is_ind(uint8_t type) { + switch (type) { + case MEM_AIND : + case MEM_IND : + case MEM_ARIND: + case MEM_ZRIND: + case MEM_AINDR: + case MEM_ZINDR: return 1; + } + return 0; +} + static void *memcopy(void *restrict dst, const void *restrict src, unsigned int n) { #if copy64 uint64_t *d = dst; @@ -510,7 +523,20 @@ static /*inline*/ uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t pre return address; } +static /*inline*/ uint64_t ortho_ind_addr(struct sux *cpu, uint8_t prefix, uint64_t address, uint8_t inc_clk) { + return read_value(cpu, 0, address, 7, inc_clk, 0); +} + +static /*inline*/ uint64_t ortho_ind_idx_addr(struct sux *cpu, uint8_t prefix, uint64_t address, uint8_t inc_clk, uint64_t idx_reg, uint8_t pre_idx) { + if (pre_idx) { + return read_value(cpu, 0, address+idx_reg, 7, inc_clk, 0); + } else { + return ortho_ind_addr(cpu, prefix, address, inc_clk) + idx_reg; + } +} + static /*inline*/ uint64_t get_ortho_addr(struct sux *cpu, uint8_t prefix, uint64_t address, operand *op, uint64_t *value, uint8_t *op_type, uint8_t *op_id, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) { + uint64_t tmp_addr = address; for (int i = 0; i < 2; i++) { union reg tmp; tmp.u64 = 0; @@ -526,10 +552,8 @@ static /*inline*/ uint64_t get_ortho_addr(struct sux *cpu, uint8_t prefix, uint6 int is_rind = (op[i].id != MEM_ABS && op[i].id != MEM_ZM && op[i].id != MEM_AIND && op[i].id != MEM_IND && op[i].id != MEM_IMM); if (is_rind) { inst_size = (op[i].id == MEM_SIB)+1; - tmp.u64 = read_value(cpu, 0, address, inst_size-1, 0, 0); - if (inc_pc) { - address += inst_size; - } + tmp.u64 = read_value(cpu, 0, tmp_addr, inst_size-1, 0, 0); + tmp_addr += inst_size; op[i].rind[0] = (tmp.u8[inst_size-1] & 0x0F); op[i].rind[1] = (tmp.u8[inst_size-1] >> 4); if (op[i].rind[1] == op[i].rind[0]) { @@ -539,18 +563,15 @@ static /*inline*/ uint64_t get_ortho_addr(struct sux *cpu, uint8_t prefix, uint6 } if (addr_size != 0xFF) { inst_size = addr_size+1; - op[i].value = read_value(cpu, 0, address, inst_size-1, inc_clk, 0); + op[i].value = read_value(cpu, 0, tmp_addr, inst_size-1, inc_clk, 0); value[i] = op[i].value; - if (inc_pc) { - address += inst_size; - } + tmp_addr += inst_size; } if (rs && op[i].id == MEM_IMM) { - value[i] = address; - if (inc_pc) { - address += rs; - } + value[i] = tmp_addr; + tmp_addr += rs; } + uint64_t tmp_val = 0; if (is_rind) { for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) { uint64_t reg; @@ -572,17 +593,42 @@ static /*inline*/ uint64_t get_ortho_addr(struct sux *cpu, uint8_t prefix, uint6 case REG_R14: reg = cpu->r14; break; case REG_R15: reg = cpu->r15; break; } - value[i] += reg; + tmp_val += reg; } if (op[i].id == MEM_SIB) { - value[i] *= op[i].scale+1; + tmp_val *= op[i].scale+1; + } else if (addr_size != 0xFF) { + switch (addr_size) { + case 0: value[i] = (int8_t )value[i]; break; + case 1: value[i] = (int16_t)value[i]; break; + case 2: + case 3: value[i] = (int32_t)value[i]; break; + case 4: + case 5: + case 6: + case 7: value[i] = (int64_t)value[i]; break; + } } + value[i] += (!is_ind(op[i].id)) ? tmp_val : 0; #if getclk cpu->clk += inc_clk; #endif } + if (is_ind(op[i].id)) { + uint8_t pre_idx = 0; + uint8_t type = op[i].id; + switch (type) { + case MEM_AIND : + case MEM_IND : value[i] = ortho_ind_addr(cpu, prefix, value[i], inc_clk); break; + case MEM_ARIND: + case MEM_ZRIND: pre_idx = 1; /* Falls through. */ + case MEM_AINDR: + case MEM_ZINDR: value[i] = ortho_ind_idx_addr(cpu, prefix, value[i], inc_clk, tmp_val, pre_idx); break; + } + } } } + address = (inc_pc) ? tmp_addr : address; return address; } @@ -859,6 +905,11 @@ static /*inline*/ uint64_t mov(struct sux *cpu, uint64_t src, uint64_t size, uin return dst; } +static /*inline*/ uint64_t cmov(struct sux *cpu, uint64_t src, uint64_t size, uint64_t dst, int flag, int *allow_io, uint8_t thread) { + *allow_io = flag; + return (flag) ? mov(cpu, src, size, thread) : dst; +} + static /*inline*/ uint64_t set(struct sux *cpu, uint8_t flag, uint8_t thread) { setflag(flag == 0, Z); return (flag != 0); @@ -908,10 +959,30 @@ static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t uint64_t rem = 0; uint64_t address[2] = {0, 0}; int isdiv = 0; + int allow_io[2] = {1, 1}; + int is_lea = ((opcode & ~0x18) == LEA_RR); + int is_write = 1; operand op[2]; cpu->pc = get_ortho_addr(cpu, prefix, cpu->pc, op, address, op_type, op_id, 1, 1, thread); + for (int i = 0; i < 2; i++) { + if (op[i].type) { + if (is_lea) { + switch (op[i].id) { + case MEM_RIND: + case MEM_ABS : + case MEM_ZM : + case MEM_ABSR: + case MEM_ZMR : + case MEM_SIB : + case MEM_IMM : allow_io[i] = 0; break; + } + } else { + allow_io[i] = (op[i].id != MEM_IMM); + } + } + } if (op[1].type) { - src = read_value(cpu, 0, (op[1].id != MEM_IMM) ? op[1].value : address[1], size, 1, 1); + src = read_value(cpu, 0, address[1], size, 1, allow_io[1]); } else { switch (op[1].id) { case REG_A : src = cpu->a; break; @@ -934,7 +1005,7 @@ static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t } if (op[0].type) { if (op[0].id != MEM_IMM) { - dst = read_value(cpu, 0, op[0].value, size, 1, 1); + dst = read_value(cpu, 0, address[0], size, 1, allow_io[0]); } } else { switch (op[0].id) { @@ -957,47 +1028,15 @@ static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t } } switch (opcode) { - case ORTHO_2OP(MNG): - if (getflag(N)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MPO): - if (!getflag(N)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MCS): - if (getflag(C)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MCC): - if (!getflag(C)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MEQ): - if (getflag(Z)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MNE): - if (!getflag(Z)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MVS): - if (getflag(V)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MVC): - if (!getflag(V)) { - dst = mov(cpu, src, size, thread); - } - break; - case ORTHO_2OP(MOV): dst = mov(cpu, src, size, thread); break; + case ORTHO_2OP(MNG): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, getflag(N), &allow_io[0], thread); break; + case ORTHO_2OP(MPO): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, !getflag(N), &allow_io[0], thread); break; + case ORTHO_2OP(MCS): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, getflag(C), &allow_io[0], thread); break; + case ORTHO_2OP(MCC): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, !getflag(C), &allow_io[0], thread); break; + case ORTHO_2OP(MEQ): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, getflag(Z), &allow_io[0], thread); break; + case ORTHO_2OP(MNE): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, !getflag(Z), &allow_io[0], thread); break; + case ORTHO_2OP(MVS): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, getflag(V), &allow_io[0], thread); break; + case ORTHO_2OP(MVC): dst = cmov(cpu, src, (op[0].type) ? size : 7, dst, !getflag(V), &allow_io[0], thread); break; + case ORTHO_2OP(MOV): dst = mov(cpu, src, (op[0].type) ? size : 7, thread); break; case ORTHO_2OP(ADC): dst = adc(cpu, dst, src, getflag(C), (op[0].type) ? size+1 : 8, thread); break; case ORTHO_2OP(SBC): dst = adc(cpu, dst, ~src, getflag(C), (op[0].type) ? size+1 : 8, thread); break; case ORTHO_2OP(ADD): dst = adc(cpu, dst, src, 0, (op[0].type) ? size+1 : 8, thread); break; @@ -1012,34 +1051,35 @@ static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t case ORTHO_2OP(ASR): dst = asr(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; case ORTHO_2OP(MUL): dst = mul(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; case ORTHO_2OP(DIV): dst = divd(cpu, dst, src, &rem, (op[0].type) ? size+1 : 8, thread); isdiv = 1; break; - case ORTHO_2OP(CMP): adc(cpu, dst, ~src, 1, (op[0].type) ? size+1 : 8, thread); break; + case ORTHO_2OP(CMP): adc(cpu, dst, ~src, 1, (op[0].type) ? size+1 : 8, thread); is_write = 0; break; case ORTHO_2OP(PCN): dst = popcnt(cpu, src, thread); break; case ORTHO_2OP(IML): dst = imul(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break; case ORTHO_2OP(IDV): dst = idiv(cpu, dst, src, &rem, (op[0].type) ? size+1 : 8, thread); isdiv = 1; break; case ORTHO_2OP(LEA): do { - uint64_t address; + uint64_t tmp_addr; uint64_t mask; if (op[1].type) { uint8_t addr_size = get_ortho_addrsize(prefix, op[1].id); - size = (!size) ? addr_size : size; - address = op[1].value; + size = (!size) ? 7 : size; + tmp_addr = address[1]; } else { - address = src; + tmp_addr = src; } mask = (-(uint64_t)1 >> ((7 - size) * 8)); - dst = (address & mask); + dst = (tmp_addr & mask); } while (0); break; case ORTHO_1OP(PEA): do { - uint64_t address = (op[0].type) ? op[0].value : dst; - push(cpu, address, 7, thread); + uint64_t tmp_addr = (op[0].type) ? address[0] : dst; + push(cpu, tmp_addr, 7, thread); + is_write = 0; } while (0); break; case ORTHO_1OP(INC): dst = inc_dec(cpu, dst, (op[0].type) ? size+1 : 8, 1, thread); break; case ORTHO_1OP(DEC): dst = inc_dec(cpu, dst, (op[0].type) ? size+1 : 8, 0, thread); break; - case ORTHO_1OP(PSH): push(cpu, dst, size, thread); break; + case ORTHO_1OP(PSH): push(cpu, dst, size, thread); is_write = 0; break; case ORTHO_1OP(PUL): dst = pull(cpu, size, thread); break; case ORTHO_1OP(NOT): dst = ~dst; break; case ORTHO_1OP(CLZ): dst = lbcnt(cpu, src, 0, size, thread); break; @@ -1056,34 +1096,36 @@ static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t case ORTHO_1CC(SET, VC): dst = set(cpu, !getflag(V), thread); break; } - if (op[0].type) { - if (op[0].id != MEM_IMM) { - write_value(cpu, dst, op[0].value, size, 1, 1); - } - } else { - switch (op[0].id) { - case REG_A : cpu->a = dst; break; - case REG_B : cpu->b = dst; break; - case REG_X : cpu->x = dst; break; - case REG_Y : cpu->y = dst; break; - case REG_E : cpu->e = dst; break; - case REG_C : cpu->c = dst; break; - case REG_D : cpu->d = dst; break; - case REG_S : cpu->s = dst; break; - case REG_F : cpu->f = dst; break; - case REG_SP : cpu->sp = dst; break; - case REG_BP : cpu->bp = dst; break; - case REG_R11: cpu->r11 = dst; break; - case REG_R12: cpu->r12 = dst; break; - case REG_R13: cpu->r13 = dst; break; - case REG_R14: cpu->r14 = dst; break; - case REG_R15: cpu->r15 = dst; break; + if (is_write) { + if (op[0].type) { + if (op[0].id != MEM_IMM) { + write_value(cpu, dst, address[0], size, 1, allow_io[0]); + } + } else { + switch (op[0].id) { + case REG_A : cpu->a = dst; break; + case REG_B : cpu->b = dst; break; + case REG_X : cpu->x = dst; break; + case REG_Y : cpu->y = dst; break; + case REG_E : cpu->e = dst; break; + case REG_C : cpu->c = dst; break; + case REG_D : cpu->d = dst; break; + case REG_S : cpu->s = dst; break; + case REG_F : cpu->f = dst; break; + case REG_SP : cpu->sp = dst; break; + case REG_BP : cpu->bp = dst; break; + case REG_R11: cpu->r11 = dst; break; + case REG_R12: cpu->r12 = dst; break; + case REG_R13: cpu->r13 = dst; break; + case REG_R14: cpu->r14 = dst; break; + case REG_R15: cpu->r15 = dst; break; + } } } if (isdiv) { if (op[1].type) { - if (op[0].id != MEM_IMM) { - write_value(cpu, dst, op[1].value, size, 1, 1); + if (op[1].id != MEM_IMM) { + write_value(cpu, src, address[1], size, 1, 1); } } else { switch (op[1].id) { diff --git a/test/ortho.s b/test/ortho.s index 312c8eb..c7cdd83 100644 --- a/test/ortho.s +++ b/test/ortho.s @@ -4,6 +4,10 @@ count: .org $40000 mem: .res 256 +bitabl: + .res 8 +bits: + .res 8 .org $8000 reset: @@ -18,6 +22,16 @@ reset: cmp.qo (count), y lea.o (count), y lea mem + nop + lea d, $2000 + nop + lea d, (mem+d) + lea bitabl, mem +; mov (bitabl)+a, 0 + mov (d-128), #0 + lea s, count + mov (e), #0 + mov a, (e) loop: inc b inc.q count @@ -31,7 +45,7 @@ loop: .qword reset a -;.org reset -;v -;q +.org reset +v +q d |