summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2021-01-27 13:42:57 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2021-01-27 13:42:57 -0500
commitcd6982e5da1f5facdc1e0154b3a27c01e8b076c9 (patch)
treec8db5ade59d054c6f88ff2ab2cb99df45b250fad
parent1700d8d10453ffe046438de0e6fbd496def915a1 (diff)
- Fixed some bugs in the emulator.
- Started work on implementing the Super VIA emulation. - Added support for disabling disassembly per instruction, when in debug mode. - Did some more work on rewriting the SuB Suite to work with the new calling convention. - Rewrote the symbol handling code in the emulator's assembler, to make it both simpler, and to add support for arbitrarily deep symbol scopes. - Added support for arbitrarily deep local symbol scopes. For example, to declare a symbol of depth 2, you add two '@' characters to the start of the symbol name. In other words, the number of '@' characters before the symbol name is what determines the scope of that symbol. And to use a symbol thats outside the current scope, you would use the same syntax as using a struct member, so you would do `global.local`.
-rw-r--r--asmmon.c10
-rw-r--r--asmmon.h12
-rw-r--r--assemble.c57
-rw-r--r--disasm.c16
-rw-r--r--io.c26
-rw-r--r--lexer.c506
-rw-r--r--programs/sub-suite/declare.s4
-rw-r--r--programs/sub-suite/free-new.s143
-rw-r--r--programs/sub-suite/free-old.s200
-rw-r--r--programs/sub-suite/lexer.s18
-rw-r--r--programs/sub-suite/libc.s499
-rw-r--r--programs/sub-suite/shift_line.c10
-rw-r--r--programs/sub-suite/subasm-syntax56
-rw-r--r--programs/sub-suite/subasm.s361
-rw-r--r--programs/sub-suite/subeditor.s604
-rw-r--r--programs/sub-suite/test-size.s59
-rw-r--r--programs/sub-suite/utils.s312
-rw-r--r--supervia.c18
-rw-r--r--supervia.h25
-rw-r--r--sux.c69
-rw-r--r--sux.h222
-rw-r--r--test/ortho.s20
22 files changed, 1970 insertions, 1277 deletions
diff --git a/asmmon.c b/asmmon.c
index 0890076..81edff2 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -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:
diff --git a/asmmon.h b/asmmon.h
index 7ed879b..de1f732 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -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;
diff --git a/assemble.c b/assemble.c
index 91972eb..f4de278 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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]);
diff --git a/disasm.c b/disasm.c
index b79d55b..1982c17 100644
--- a/disasm.c
+++ b/disasm.c
@@ -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]) {
diff --git a/io.c b/io.c
index e19f194..9848e8d 100644
--- a/io.c
+++ b/io.c
@@ -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 {
diff --git a/lexer.c b/lexer.c
index bb3701a..57a7e14 100644
--- a/lexer.c
+++ b/lexer.c
@@ -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. */
+};
diff --git a/sux.c b/sux.c
index de88b92..59c2168 100644
--- a/sux.c
+++ b/sux.c
@@ -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
diff --git a/sux.h b/sux.h
index 9af8128..c028b84 100644
--- a/sux.h
+++ b/sux.h
@@ -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