summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-12-08 10:42:10 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2020-12-08 11:16:13 -0500
commit673efacc37efa90e61eba224efadbb4be863c77b (patch)
tree9b22d4c8b12a5d5b07329df121a13116cb98c4a1
parent96393257a43ac52f2b911594d106741245dec5f0 (diff)
- Implemented support for the Orthogonal extension into
both the assembler, and the emulator. I finally figured out how I could get support for the Ortho extension implemented into the old assembler. The only reason for doing this, is to buy me some while I start work on the new assembler, and to help me get an idea for how to do the same in the new assembler.
-rw-r--r--asmmon.h64
-rw-r--r--assemble.c587
-rw-r--r--disasm.c429
-rw-r--r--disasm.h71
-rw-r--r--enums.h79
-rw-r--r--lexer.c210
-rw-r--r--lexer.h12
-rw-r--r--opcode.h14
-rw-r--r--programs/sub-suite/declare.s6
-rw-r--r--programs/sub-suite/lexer.s2
-rw-r--r--programs/sub-suite/libc.s4
-rw-r--r--programs/sub-suite/subasm.s8
-rw-r--r--programs/sub-suite/subeditor.s4
-rw-r--r--programs/sub-suite/subsuite.s2
-rw-r--r--sux.c28
-rw-r--r--sux.h436
-rw-r--r--test/ortho.s35
-rw-r--r--test/struct.s7
18 files changed, 1695 insertions, 303 deletions
diff --git a/asmmon.h b/asmmon.h
index 8fbec35..7ed879b 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -4,17 +4,18 @@
#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 {
- token *next; /* Pointer to the next token. */
- uint8_t id; /* Token ID. */
- uint8_t type; /* Token type ID. */
+ token *next; /* Pointer to the next token. */
+ uint8_t id; /* Token ID. */
+ uint8_t type; /* Token type ID. */
+ uint8_t subtype; /* Token subtype ID. */
uint8_t tab; /* Number of tabs. */
uint8_t space; /* Number of spaces. */
@@ -120,6 +121,9 @@ enum token {
TOK_EXTOP,
TOK_ORTHO,
TOK_REG,
+ TOK_MEM,
+ TOK_CC,
+ TOK_OS,
TOK_RS,
TOK_OF,
TOK_COMMENT,
@@ -130,7 +134,6 @@ enum token {
TOK_STRUCT,
TOK_UNION,
TOK_MEMBER
-
};
enum pre_token {
@@ -176,6 +179,7 @@ enum expr {
EXPR_OR,
EXPR_LSHFT,
EXPR_RSHFT,
+ EXPR_MUL,
EXPR_NONE
};
@@ -240,6 +244,30 @@ enum eind {
CPY_EIND
};
+enum baseext_ortho {
+ OP_LEA,
+ OP_PEA,
+ OP_ADD,
+ OP_SUB,
+ OP_NOT,
+ OP_CLZ,
+ OP_CLO,
+ OP_SWP,
+ OP_PCN
+};
+
+static const uint8_t ext_ortho_ops[9] = {
+ [OP_LEA] = 0x63,
+ [OP_PEA] = 0x0C,
+ [OP_ADD] = 0x03,
+ [OP_SUB] = 0x23,
+ [OP_NOT] = 0x44,
+ [OP_CLZ] = 0xC4,
+ [OP_CLO] = 0xE4,
+ [OP_SWP] = 0x2C,
+ [OP_PCN] = 0x43
+};
+
static const uint8_t ind_ops[20] = {
[CMP_IND] = CMP_IN,
[CMP_IDY] = CMP_IY,
@@ -461,6 +489,9 @@ static const char *lex_tok[] = {
[TOK_EXTOP ] = "TOK_EXTOP",
[TOK_ORTHO ] = "TOK_ORTHO",
[TOK_REG ] = "TOK_REG",
+ [TOK_MEM ] = "TOK_MEM",
+ [TOK_CC ] = "TOK_CC",
+ [TOK_OS ] = "TOK_OS",
[TOK_RS ] = "TOK_RS",
[TOK_OF ] = "TOK_OF",
[TOK_COMMENT] = "TOK_COMMENT",
@@ -646,6 +677,17 @@ static const char *ortho_mne[ORTHO_OPNUM] = {
[SET] = "SET"
};
+static const char *set_cc[8] = {
+ "NG",
+ "PO",
+ "CS",
+ "CC",
+ "EQ",
+ "NE",
+ "VS",
+ "VC"
+};
+
static const char *instdesc[OPNUM] = {
[ADC] = "ADd accumulator, with operand, Carry if needed.",
[AND] = "Bitwise AND accumulator, with operand.",
@@ -762,8 +804,8 @@ extern uint8_t isfixup;
extern line *find_line(uint32_t ln, uint8_t dbg);
extern uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg);
-extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg);
-extern token *skip_expr(token *t, uint8_t dbg);
+extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg);
+extern token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg);
extern uint64_t parse_tokens(token *tm, line **l, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg);
extern token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t value, char *str, symbol *s);
extern void assemble(line *ln, bytecount *bc, uint8_t dbg);
diff --git a/assemble.c b/assemble.c
index 27da287..87d0464 100644
--- a/assemble.c
+++ b/assemble.c
@@ -82,6 +82,21 @@ uint8_t get_eind(uint8_t mne, uint8_t dbg) {
return 0xFF;
}
+uint8_t get_ext_ortho(uint8_t mne, uint8_t dbg) {
+ switch (mne) {
+ case LEA: return OP_LEA;
+ case PEA: return OP_PEA;
+ case ADD: return OP_ADD;
+ case SUB: return OP_SUB;
+ case NOT: return OP_NOT;
+ case CLZ: return OP_CLZ;
+ case CLO: return OP_CLO;
+ case SWP: return OP_SWP;
+ case PCN: return OP_PCN;
+ }
+ return 0xFF;
+}
+
static void write_value(uint64_t value, uint64_t address, uint8_t size) {
if (address < mem_size) {
size = (size > 7) ? 7 : size;
@@ -98,16 +113,23 @@ static void write_value(uint64_t value, uint64_t address, uint8_t size) {
}
}
-uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
+uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) {
uint64_t value = 0;
uint64_t tmp_val = 0;
uint8_t type = EXPR_NONE;
uint8_t isstart = 1;
+ int done = 0;
do {
if (t->id == TOK_EXPR) {
type = t->type;
t = t->next;
}
+ if (stop_comma && t->subtype == TOK_CSV) {
+ done = 1;
+ }
+ if (stop_comma && t->id == TOK_REG) {
+ break;
+ }
switch (t->id) {
case TOK_HEX:
case TOK_DEC:
@@ -119,6 +141,10 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
tmp_val = (t->sym) ? t->sym->val : addr;
t = t->next;
break;
+ default: tmp_val = 0;
+ }
+ if (end_expr != 0xFF && type == end_expr) {
+ break;
}
switch (type) {
case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break;
@@ -150,13 +176,19 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
if (dbg) {
printf("get_val(): Value: $%"PRIX64", Expression type: $%X, Expression Value: $%"PRIX64".\n", value, type, tmp_val);
}
- } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg));
+ } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg));
return value;
}
-token *skip_expr(token *t, uint8_t dbg) {
+token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) {
+ int done = 0;
+ int is_reg = 0;
do {
- t = (t->id == TOK_EXPR) ? t->next : t;
+ is_reg = (t && t->next && t->next->id == TOK_REG);
+ t = (t->id == TOK_EXPR && !is_reg) ? t->next : t;
+ if (is_reg || (stop_comma && (t->subtype == TOK_CSV))) {
+ done = 1;
+ }
switch (t->id) {
case TOK_HEX :
case TOK_DEC :
@@ -165,7 +197,10 @@ token *skip_expr(token *t, uint8_t dbg) {
case TOK_SYM :
case TOK_LABEL: t = t->next; break;
}
- } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg));
+ if (end_expr != 0xFF && t->id == TOK_EXPR && t->type == end_expr) {
+ break;
+ }
+ } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg));
return t;
}
@@ -227,7 +262,7 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg
case DIR_QWORD : member_size = 8; break;
case DIR_UNION :
case DIR_STRUCT: member_size = handle_struct(&l, address, offset, dbg); break;
- case DIR_RES : member_size = get_val(t, address, 3, dbg); t = skip_expr(t, dbg); break;
+ case DIR_RES : member_size = get_val(t, address, 3, 0xFF, 0, dbg); t = skip_expr(t, 0xFF, 0, dbg); break;
}
if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {
member->val = offset;
@@ -270,7 +305,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre
case TOK_CHAR:
case TOK_SYM:
case TOK_LABEL:
- val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg);
+ val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), 0xFF, 0, dbg);
switch (type) {
case DIR_QWORD: tmp = 8; break;
case DIR_DWORD: tmp = 4; break;
@@ -281,7 +316,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre
tmpaddr += tmp;
bc->datasize += tmp;
if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) {
- t = skip_expr(t, dbg);
+ t = skip_expr(t, 0xFF, 0, dbg);
}
break;
case TOK_STRING:
@@ -323,9 +358,13 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre
return tmpaddr;
}
-static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, uint64_t value, uint64_t address, uint8_t size, uint8_t isasm, uint8_t dbg) {
+static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, operand *op, uint64_t address, uint8_t *op_size, uint8_t isasm, uint8_t dbg) {
uint8_t inst_size = 0;
+ uint8_t op_ins_size[2];
union reg ins;
+ union reg op_ins[2];
+ memset(op_ins_size, 0, sizeof(op_ins_size));
+ memset(op_ins, 0, sizeof(op_ins_size));
if (prefix & 3) {
ins.u8[inst_size++] = prefix;
}
@@ -333,16 +372,216 @@ static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, ui
ins.u8[inst_size++] = ext_prefix;
}
ins.u8[inst_size++] = opcode;
+ if (ext_prefix == 0x1D) {
+ for (int i = 0; i < 2 && op[i].type != 0xFF; i++) {
+ ins.u8[inst_size] |= (op[i].id << (!i*4));
+ }
+ inst_size++;
+ for (int i = 0; i < 2 && op[i].type != 0xFF; i++) {
+ int is_sib = 0;
+ if (op[i].type == 1) {
+ int reg = 0;
+ switch (op[i].id) {
+ case MEM_SIB : op_ins[i].u8[op_ins_size[i]++] = op[i].scale; /* Falls through. */
+ case MEM_ABSR :
+ case MEM_ARIND:
+ case MEM_AINDR:
+ case MEM_ZMR :
+ case MEM_ZRIND:
+ case MEM_ZINDR:
+ case MEM_RIND :
+ op_ins[i].u8[op_ins_size[i]] = op[i].rind[reg];
+ reg = (op[i].rind[1] != 0xFF);
+ op_ins[i].u8[op_ins_size[i]++] |= op[i].rind[reg] << 4;
+ break;
+ }
+ }
+ }
+ }
if (isasm) {
+ if (dbg) {
+ printf("$%04"PRIX64":\t", address);
+ for (int i = 0; i < inst_size; i++) {
+ printf("%02X", ins.u8[i]);
+ if (i < inst_size-1) {
+ putchar(' ');
+ }
+ }
+ }
write_value(ins.u64, address, inst_size-1);
- if (size) {
- write_value(value, address+inst_size, size-1);
+ }
+ for (int i = 0; i < 2 && op[i].type != 0xFF; i++) {
+ if (op[i].type == 1) {
+ if (ext_prefix == 0x1D && op_ins_size[i]) {
+ if (isasm) {
+ if (dbg) {
+ putchar(' ');
+ for (int j = 0; j < op_ins_size[i]; j++) {
+ printf("%02X", op_ins[i].u8[j]);
+ if (j < op_ins_size[i]-1) {
+ putchar(' ');
+ }
+ }
+ }
+ write_value(op_ins[i].u64, address+inst_size, op_ins_size[i]-1);
+ }
+ inst_size += op_ins_size[i];
+ }
+ if (op_size[i] && (ext_prefix != 0x1D || (ext_prefix == 0x1D && op[i].id != MEM_SIB && op[i].id != MEM_RIND))) {
+ if (isasm) {
+ if (dbg) {
+ uint8_t *tmp = (uint8_t *)&op[i].value;
+ putchar(' ');
+ for (int j = 0; j < op_size[i]; j++) {
+ printf("%02X", tmp[j]);
+ if (j < op_size[i]-1) {
+ putchar(' ');
+ }
+ }
+ }
+ write_value(op[i].value, address+inst_size, op_size[i]-1);
+ }
+ inst_size += op_size[i];
+ }
}
}
- inst_size += size;
+ if (isasm && dbg) {
+ putchar('\n');
+ }
return inst_size;
}
+token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t dbg) {
+ uint8_t op_type;
+ uint8_t op_inst;
+ /*switch (t->id) {
+ case TOK_OPCODE:
+ case TOK_EXTOP :
+ case TOK_ORTHO :
+ op_type = t->id;
+ op_inst = t->byte;
+ t = t->next;
+ break;
+ }*/
+ int i = 0;
+ int old_i = -1;
+ uint8_t expr_type = 0xFF;
+ uint8_t stop_comma = 0;
+ uint64_t value = 0;
+ uint8_t reg = 0;
+ uint8_t got_value = 0;
+ uint8_t is_sib = 0;
+ uint8_t brack_done = 0;
+ uint8_t is_comma = 0;
+ token *tmp = t;
+ /*for (; tmp; tmp = tmp->next) {
+ printf("t: %p, t->id: $%X, t->id: %s, t->subtype: $%X, t->subtype: %s\n", tmp, tmp->id, (tmp->id <= TOK_MEMBER) ? lex_tok[tmp->id] : "TOK_NONE", tmp->subtype, (tmp->subtype == TOK_IND || tmp->subtype == TOK_CSV) ? lex_tok[tmp->subtype] : "TOK_NONE");
+ }*/
+
+ for (; t && i < 2; t = t->next) {
+ if (t->subtype == TOK_IND) {
+ brack_done = 1;
+ }
+ switch (t->id) {
+ case TOK_HEX :
+ case TOK_DEC :
+ case TOK_BIN :
+ case TOK_SYM :
+ case TOK_CHAR :
+ case TOK_LABEL:
+ if (!got_value) {
+ expr_type = (expr_type == 0xFF && t->next && t->next->id == TOK_EXPR) ? t->next->type : expr_type;
+ switch (expr_type) {
+ default : stop_comma = 1; break;
+ case EXPR_MUL : stop_comma = 0; break;
+ }
+ is_sib = (!stop_comma && op[i].type && op[i].id == MEM_IND);
+ value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg);
+ op[i].value = (!is_sib) ? value : op[i].value;
+ got_value = 1;
+ } else {
+ op[i].value = (!is_sib) ? value : op[i].value;
+ got_value = 0;
+ }
+ if ((op[i].type == 1 && op[i].id == MEM_RIND) || (!op[i].type)) {
+ op[i].is_ind = (op[i].type == 1 && op[i].id == MEM_RIND);
+ op[i].type = 1;
+ op[i].rind[0] = (op[i].rind[0] == 0xFF) ? op[i].id : op[i].rind[0];
+ op[i].id = MEM_ZMR;
+ }
+ is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV)));
+ is_comma = (is_comma >= 2) ? 0 : is_comma;
+ /* Falls Through. */
+ case TOK_MEM:
+ is_comma = (t->id == TOK_MEM) ? 0 : is_comma;
+ if (old_i != i) {
+ op[i].type = 1; /* Set type to memory. */
+ op[i].id = (t->id == TOK_MEM) ? t->type : 0xFF;
+ op[i].id = (is_sib) ? MEM_SIB : op[i].id;
+ op[i].scale = (is_sib) ? value : op[i].scale;
+ old_i = i;
+ } else {
+ if (!op[i].type && !is_sib) {
+ op[i].type = 1;
+ op[i].id = MEM_ZMR;
+ }
+ }
+ if (got_value && !is_comma) {
+ if (t && t->subtype != TOK_CSV) {
+ t = skip_expr(t, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg);
+ }
+ }
+ i += is_comma;
+ if (old_i != i) {
+ got_value = 0;
+ }
+ break;
+ case TOK_REG:
+ if (old_i != i) {
+ op[i].type = 0; /* Set type to register. */
+ op[i].id = t->type;
+ old_i = i;
+ } 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;
+ brack_done = 0;
+ } else {
+ op[i].id = (got_value) ? MEM_ZMR : op[i].id;
+ }
+ op[i].rind[reg] = t->type;
+ reg++;
+ reg = (reg > 1) ? 0 : reg;
+ }
+ }
+ is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV)));
+ is_comma = (is_comma >= 2) ? 0 : is_comma;
+ i += is_comma;
+ break;
+ case TOK_EXPR:
+ expr_type = t->type;
+ switch (expr_type) {
+ default : stop_comma = 1; break;
+ case EXPR_MUL : stop_comma = 0; break;
+ }
+ if (!got_value) {
+ if (t->next && t->next->id != TOK_REG) {
+ value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg);
+ got_value = 1;
+ }
+ } else {
+ got_value = 0;
+ }
+ break;
+ }
+ if (!t) {
+ break;
+ }
+ }
+ return t;
+}
+
uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
union reg val;
uint8_t opsize;
@@ -352,44 +591,66 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
uint8_t ext_prefix = 0;
uint8_t type;
uint32_t am = 0;
- uint8_t tmp = 0;
+ uint8_t op_size[2];
uint8_t prefix = 0;
uint8_t rs = 0;
uint8_t of = 0;
uint8_t tmp_prefix = 0;
uint8_t inst_size = 0;
+ int is_ortho = 0;
val.u64 = 0;
instruction ins;
-
- for (; t; t = t->next) {
- if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) {
+ operand op[2];
+ memset(op, 0xFF, sizeof(op));
+ op_size[0] = 0;
+ op_size[1] = 0;
+ if (t) {
+ if (t->id == TOK_OPCODE || t->id == TOK_EXTOP || t->id == TOK_ORTHO) {
id = t->id;
instr = t->byte;
type = t->type;
} else {
- break;
+ return address;
}
- tmp = 0;
+ /*tmp = 0;*/
opsize = 1;
opcode = 0;
if (t->next) {
rs = get_rs(t->next, dbg);
t = (rs != 0xFF) ? t->next : t;
if (t->next) {
- of = get_of(t->next, dbg);
- t = (of != 0xFF) ? t->next : t;
+ is_ortho = (t->next->id == TOK_OS);
+ t = (is_ortho) ? t->next : t;
+ if (t->next) {
+ of = get_of(t->next, dbg);
+ t = (of != 0xFF) ? t->next : t;
+ }
}
}
+ get_operands(t, op, address, rs, dbg);
+ if (dbg) {
+ for (int i = 0; i < 2 && op[i].type != 0xFF; i++) {
+ printf("%i: op.type: %u, op.id: $%X, op.scale; $%X, op.rind[0]: $%X, op.rind[1]: $%X, op.value: $%"PRIX64"\n", i, op[i].type, op[i].id, op[i].scale, op[i].rind[0], op[i].rind[1], op[i].value);
+ }
+ }
+ uint8_t is_eind = (op[0].type == 1 && op[0].id == MEM_RIND && op[0].rind[0] == REG_E);
+ uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM);
+ uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y));
+ of = (is_mem && (op[0].id == MEM_RIND || op[0].id == MEM_ZMR) && op[0].rind[0] == REG_SP) ? 1 : of;
if (rs != 0xFF || of != 0xFF) {
tmp_prefix = (rs != 0xFF) ? (rs << 0) : tmp_prefix;
tmp_prefix |= (of != 0xFF) ? (of << 2) : tmp_prefix;
}
prefix = (tmp_prefix) ? ((tmp_prefix << 4) | 3) : 0;
uint8_t isincdec = (instr == INC || instr == DEC);
- uint8_t isimplied = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF);
- ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr];
+ uint8_t isimplied = (op[0].type == 0xFF);
+ switch (id) {
+ case TOK_OPCODE: ins = inst[instr]; break;
+ case TOK_EXTOP : ins = ext_inst[instr]; break;
+ case TOK_ORTHO : ins = ortho_inst[instr]; break;
+ }
am = ins.am;
- if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) {
+ if (id == TOK_EXTOP || (id == TOK_OPCODE && is_eind)) {
ext_prefix = 0x0D;
}
if ((am & AM_IMPL) && isimplied) {
@@ -398,12 +659,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
if (ins.am & AM_REL) {
type = REL;
}
- if (t->next) {
- t = t->next;
- }
- if (type != BREG && type != EIND) {
- val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
- }
}
opcode = ins.op;
uint64_t saveaddr = address;
@@ -411,62 +666,73 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
uint8_t i = 0;
uint8_t j = 1;
uint8_t type2 = 0xFF;
- switch (type) {
- case BREG:
- case IMPL:
- case EIND:
- if (id == TOK_OPCODE && instr == CPS) {
- rs = 0;
- }
- if ((am & (AM_IMPL|AM_BREG|AM_EIND|AM_EIND2))) {
- if ((type == EIND) && (am & AM_EIND|AM_EIND2)) {
- int eind_type = ((am & AM_EIND2) != 0);
- switch (eind_type) {
- case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break;
- case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break;
- }
- }
- opcode = ((am & AM_BREG) && type == BREG) ? opcode+0x14 : opcode;
- }
- break;
- case REL:
- case IMM:
- if (am & (AM_IMM|AM_REL)) {
- rs = (rs != 0xFF) ? rs : 0;
- tmp = (1 << rs);
- if (type == REL) {
- uint64_t max_sign = 0;
- uint8_t offset = 1;
- uint64_t tmp_val;
- tmp_val = val.u64;
- offset += (prefix != 0);
- tmp_val -= offset+tmp;
- tmp_val -= address;
- switch (rs) {
- default: max_sign = (int8_t )(1 << 7); break;
- case 1 : max_sign = (int16_t)(1 << 15); break;
- case 2 : max_sign = (int32_t)(1 << 31); break;
- case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break;
- }
- if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) {
- offset += (!rs);
- rs += (rs <= 3);
- tmp = (1 << rs);
- tmp_val = val.u64;
- tmp_val -= offset+tmp;
- tmp_val -= address;
- prefix = ((rs << 4) | 3);
- }
- val.u64 = tmp_val;
+ if (!is_ortho) {
+ is_ortho = (id == TOK_ORTHO);
+ }
+ int is_valid = 1;
+ if (!is_ortho && (is_mem || is_idx)) {
+ switch (op[0].id) {
+ case MEM_AINDR:
+ case MEM_ZINDR:
+ case MEM_ARIND:
+ case MEM_ZRIND:
+ case MEM_SIB : is_valid = 0; break;
+ case MEM_ZMR :
+ case MEM_ABSR :
+ case MEM_RIND :
+ default :
+ if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) {
+ is_valid = 0;
+ } else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) {
+ is_valid = (of != 0xFF || op[0].rind[0] == REG_SP);
+ } else if (is_mem && op[1].type == 1) {
+ is_valid = 0;
}
- }
- break;
- default:
+ break;
+ }
+ } else if (is_ortho) {
+ is_valid = 0;
+ }
+ if (type == IMPL && (am & AM_IMPL)) {
+ if (id == TOK_OPCODE && instr == CPS) {
+ rs = 0;
+ }
+ opcode = opcode;
+ is_ortho = 0;
+ } else if (type == REL) {
+ rs = (rs != 0xFF) ? rs : 0;
+ op_size[0] = (1 << rs);
+ uint64_t max_sign = 0;
+ uint8_t offset = 1;
+ uint64_t tmp_val;
+ tmp_val = op[0].value;
+ offset += (prefix != 0);
+ tmp_val -= offset+op_size[0];
+ tmp_val -= address;
+ switch (rs) {
+ default: max_sign = (int8_t )(1 << 7); break;
+ case 1 : max_sign = (int16_t)(1 << 15); break;
+ case 2 : max_sign = (int32_t)(1 << 31); break;
+ case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break;
+ }
+ if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) {
+ offset += (!rs);
+ rs += (rs <= 3);
+ op_size[0] = (1 << rs);
+ tmp_val = op[i].value;
+ tmp_val -= offset+op_size[0];
+ tmp_val -= address;
+ prefix = ((rs << 4) | 3);
+ }
+ op[0].value = tmp_val;
+ is_ortho = 0;
+ } else if (id != TOK_ORTHO) {
+ if (!is_eind && is_valid && (is_mem || is_idx)) {
if (of != 0xFF) {
i = 8;
for (; i <= 64; i += 8, j++) {
max_val |= ((uint64_t)1 << (i-1));
- if ((int64_t)val.u64 >= ~(int64_t)(max_val) || (int64_t)val.u64 <= (int64_t)(max_val)) {
+ if ((int64_t)op[0].value >= ~(int64_t)(max_val) || (int64_t)op[0].value <= (int64_t)(max_val)) {
opsize = j;
break;
}
@@ -474,12 +740,20 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
} else {
for (; i <= 64; i += 8, j++) {
max_val |= (0xFF << i);
- if (val.u64 <= max_val) {
+ if (op[0].value <= max_val) {
opsize = j;
break;
}
}
}
+ if (is_idx) {
+ switch (op[1].id) {
+ case REG_X: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDX : ZMX; break;
+ case REG_Y: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDY : ZMY; break;
+ }
+ } else {
+ type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? IND : 0xFF;
+ }
type2 = type;
if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) {
switch (opsize-1) {
@@ -520,71 +794,192 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
opcode += 0x04;
} else if (am & AM_ZM2) {
opcode += 0x20;
+ } else {
+ is_ortho = 1;
}
break;
case ZMX:
if (am & AM_ZMX) {
opcode += (id == TOK_OPCODE) ? 0x06 : 0x54;
+ } else {
+ is_ortho = 1;
}
break;
case ZMY:
if (am & AM_ZMY) {
opcode += 0x14;
+ } else {
+ is_ortho = 1;
}
break;
case INDX:
if (am & AM_INDX) {
opcode += (id == TOK_OPCODE) ? 0x16 : 0x94;
break;
+ } else {
+ is_ortho = 1;
}
/* Falls Through. */
case IND:
case INDY:
if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) {
opcode = ind_ops[get_ind(instr, type, dbg)];
- } else {
+ } else if (id = TOK_EXTOP) {
opcode += (type == IND) ? 0x44 : 0x84;
+ } else {
+ is_ortho = 1;
}
break;
case ABS:
if (am & AM_ABS) {
opcode += 0x10;
+ } else {
+ is_ortho = 1;
}
break;
case ABSX:
if (am & AM_ABX) {
opcode += 0x50;
+ } else {
+ is_ortho = 1;
}
break;
case ABSY:
if (am & AM_ABY) {
opcode += 0x00;
+ } else {
+ is_ortho = 1;
}
break;
case AIND:
if (am & AM_AIND) {
opcode += 0x40;
+ } else {
+ is_ortho = 1;
}
break;
case AINDX:
if (am & AM_AINDX) {
opcode += 0x90;
+ } else {
+ is_ortho = 1;
}
break;
case AINDY:
if (am & AM_AINDY) {
opcode += 0x80;
+ } else {
+ is_ortho = 1;
}
break;
}
- tmp = opsize;
+ op_size[0] = opsize;
}
- break;
+
+ } else if (op[1].type == 0xFF) {
+ if (!op[0].type) {
+ if (op[0].id == REG_B && (am & AM_BREG)) {
+ opcode += 0x14;
+ } else if (op[0].id == REG_A && (am & AM_IMPL)) {
+ opcode = opcode;
+ } else {
+ is_ortho = 1;
+ }
+ } else {
+ if (is_eind && (am & AM_EIND|AM_EIND2)) {
+ int eind_type = ((am & AM_EIND2) != 0);
+ switch (eind_type) {
+ case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break;
+ case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break;
+ }
+ } else if ((op[0].id == MEM_IMM) && (am & AM_IMM)) {
+ rs = (rs != 0xFF) ? rs : 0;
+ op_size[0] = (1 << rs);
+ } else {
+ is_ortho = 1;
+ }
+ }
+ } else {
+ is_ortho = 1;
+ }
+ }
+ if (is_ortho) {
+ ext_prefix = 0x1D;
+ if (id == TOK_EXTOP) {
+ opcode = ext_ortho_ops[get_ext_ortho(instr, dbg)];
+ }
+ for (int i = 0; i < 2 && op[i].type != 0xFF; i++) {
+ int i2 = 0;
+ int j = 0;
+ (op[i].type == 1) ? (opcode |= (1 << (3+!i))) : (opcode &= ~(1 << (3+!i)));
+ if (op[i].type == 1 && (am & AM_ORTHO|AM_ORTHO2)) {
+ switch (op[i].id) {
+ case MEM_RIND: break;
+ case MEM_IMM:
+ rs = (rs != 0xFF) ? rs : 0;
+ op_size[i] = (1 << rs);
+ break;
+ case MEM_ZRIND:
+ case MEM_ZINDR:
+ case MEM_ZMR:
+ case MEM_IND:
+ default:
+ if (of != 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)) {
+ opsize = j;
+ break;
+ }
+ }
+ } else {
+ max_val = 0;
+ for (i2 = 0, j = 1; i2 <= 64; i2 += 8, j++) {
+ max_val |= (0xFF << i2);
+ if (op[i].value <= max_val) {
+ opsize = j;
+ break;
+ }
+ }
+ }
+ switch (opsize-1) {
+ case 0: case 2: case 5: case 3: type = ZM ; break;
+ case 1: case 4: case 6: case 7: type = ABS; break;
+ }
+ switch (op[i].id) {
+ case MEM_IND : op[i].id = (type == ABS) ? MEM_AIND : op[i].id; break;
+ case MEM_ZMR : op[i].id = (type == ABS) ? MEM_ABSR : op[i].id; break;
+ case MEM_ZRIND: op[i].id = (type == ABS) ? MEM_ARIND : op[i].id; break;
+ case MEM_ZINDR: op[i].id = (type == ABS) ? MEM_AINDR : op[i].id; break;
+ case 0xFF : op[i].id = (type == ABS) ? MEM_ABS : MEM_ZM; break;
+ }
+ if (opsize) {
+ uint8_t is_abs = (type == ABS);
+ if (!is_abs) {
+ switch (opsize) {
+ case 2: opsize = 3; break;
+ case 5: opsize = 6; break;
+ }
+ }
+ prefix |= amp[opsize-1];
+ }
+ op_size[i] = opsize;
+ if (isasm /*&& dbg*/) {
+ printf("op_size[%i]: %i, opsize: %u\n", i, op_size[i], opsize);
+ }
+ break;
+ }
+ }
+ }
}
- inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg);
+ inst_size = write_inst(prefix, ext_prefix, opcode, op, address, op_size, isasm, /*dbg*/isasm);
address += inst_size;
bc->progsize += inst_size;
+ if (isasm /*&& dbg*/) {
+ printf("inst_size: $%X, bc->progsize: $%"PRIX64"\n", inst_size, bc->progsize);
+ }
}
return address;
}
@@ -596,14 +991,15 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t
switch (t->type) {
case DIR_STRUCT:
case DIR_UNION : handle_struct(l, address, 0, dbg); break;
- case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break;
- case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break;
+ case DIR_RES: t = t->next; address += get_val(t, address, 3, 0xFF, 0, dbg); break;
+ case DIR_ORG: t = t->next; address = get_val(t, address, 3, 0xFF, 0, dbg); break;
case DIR_BYTE:
case DIR_WORD:
case DIR_DWORD:
case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break;
}
break;
+ case TOK_ORTHO :
case TOK_EXTOP :
case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;
case TOK_COMMENT: break;
@@ -618,6 +1014,7 @@ token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t
new_tok->id = id;
new_tok->type = type;
+ new_tok->subtype = 0xFF;
new_tok->tab = tab;
new_tok->space = space;
@@ -806,29 +1203,13 @@ void fix_symtree(line *l) {
if ((!is_structsym) || (isanon && is_structsym)) {
isanon++;
}
- } else if (t->type == DIR_ENDSTRUCT || t->type == DIR_ENDUNION) {
- is_struct--;
- int skip = 0;
- if (isanon > 0) {
- if ((cur_sym->up && !cur_sym->up->isanon) || (sym_struct && sym_struct->isanon)) {
- isanon--;
- }
- skip = (!isanon);
- }
- if ((int)(is_struct-isanon) > 0 && !skip && cur_sym->up) {
- for (sym_struct = s->up; sym_struct->prev && !sym_struct->isanon; sym_struct = sym_struct->prev);
- s = s->up;
- cur_sym = (cur_sym->up != NULL) ? cur_sym->up : s;
- }
}
break;
}
- lt = t;
}
}
}
-
static inline void free_tokens(token *t) {
token *tok;
if (t != NULL) {
diff --git a/disasm.c b/disasm.c
index f9a04a2..74dac5f 100644
--- a/disasm.c
+++ b/disasm.c
@@ -2,6 +2,16 @@
#include "disasm.h"
#include <string.h>
+#define ORTHO_1CC(mne, cc) \
+ mne##_R##cc: case mne##_M##cc
+
+#define ORTHO_1OP(mne) \
+ mne##_R: case mne##_M
+
+#define ORTHO_2OP(mne) \
+ mne##_RR: case mne##_RM: case mne##_MR: case mne##_MM
+
+
void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread) {
for (uint8_t i = (24*thread)+2; i <= 24*(thread+1); i++) {
wmove(scr, i, 0);
@@ -24,9 +34,271 @@ void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread) {
wprintw(scr, ", inst: ");
}
-void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t thread) {
+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));
+ *sign = ((value >> (msb-1)) & 1) ? "-" : "+";
+ if (*sign[0] == '-') {
+ value &= mask;
+ value = -(value+1);
+ }
+ return value;
+}
+
+/* Checks if the opcode, and operands required an ortho suffix. */
+static int is_os(uint8_t opcode, operand *op) {
+ uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM);
+ uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y));
+ int is_valid = 1;
+ int is_sp = 0;
+ if (is_mem || is_idx) {
+ switch (op[0].id) {
+ case MEM_AINDR:
+ case MEM_ZINDR:
+ case MEM_ARIND:
+ case MEM_ZRIND:
+ case MEM_SIB : is_valid = 0; break;
+ case MEM_ZMR :
+ case MEM_ABSR :
+ case MEM_RIND :
+ default :
+ if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) {
+ is_valid = 0;
+ } else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) {
+ is_valid = (op[0].rind[0] == REG_SP);
+ is_sp = (op[0].rind[0] == REG_SP);
+ } else if (is_mem && op[1].type == 1) {
+ is_valid = 0;
+ }
+ break;
+ }
+ }
+ switch (opcode) {
+ case ORTHO_2OP(CMP): return (is_idx && is_valid && ((is_sp && op[0].id == MEM_RIND) || (!is_sp && op[0].id == MEM_IND)));
+ case ORTHO_2OP(LEA): return (is_idx && is_valid);
+ }
+ return 0;
+}
+
+static int is_1cc(uint8_t opcode) {
+ switch (opcode) {
+ case ORTHO_1CC(SET, NG):
+ case ORTHO_1CC(SET, PO):
+ case ORTHO_1CC(SET, CS):
+ case ORTHO_1CC(SET, CC):
+ case ORTHO_1CC(SET, EQ):
+ case ORTHO_1CC(SET, NE):
+ case ORTHO_1CC(SET, VS):
+ case ORTHO_1CC(SET, VC): return 1;
+ }
+ return 0;
+}
+
+static int is_1op(uint8_t opcode) {
+ switch (opcode) {
+ case ORTHO_1OP(PSH):
+ case ORTHO_1OP(PEA):
+ case ORTHO_1OP(PUL):
+ case ORTHO_1OP(SWP):
+ case ORTHO_1OP(NOT):
+ case ORTHO_1OP(NEG):
+ case ORTHO_1OP(DEC):
+ case ORTHO_1OP(INC):
+ case ORTHO_1OP(CLZ):
+ case ORTHO_1OP(CLO): return 1;
+ }
+ return 0;
+}
+
+static int is_2op(uint8_t opcode) {
+ switch (opcode) {
+ case ORTHO_2OP(MNG):
+ case ORTHO_2OP(ADC):
+ case ORTHO_2OP(ROR):
+ case ORTHO_2OP(ADD):
+ case ORTHO_2OP(MPO):
+ case ORTHO_2OP(SBC):
+ case ORTHO_2OP(MUL):
+ case ORTHO_2OP(SUB):
+ case ORTHO_2OP(MCS):
+ case ORTHO_2OP(AND):
+ case ORTHO_2OP(DIV):
+ case ORTHO_2OP(PCN):
+ case ORTHO_2OP(MCC):
+ case ORTHO_2OP(OR ):
+ case ORTHO_2OP(ASR):
+ case ORTHO_2OP(LEA):
+ case ORTHO_2OP(MEQ):
+ case ORTHO_2OP(XOR):
+ case ORTHO_2OP(CMP):
+ case ORTHO_2OP(MNE):
+ case ORTHO_2OP(LSL):
+ case ORTHO_2OP(MOV):
+ case ORTHO_2OP(MVS):
+ case ORTHO_2OP(LSR):
+ case ORTHO_2OP(IML):
+ case ORTHO_2OP(MVC):
+ case ORTHO_2OP(ROL):
+ case ORTHO_2OP(IDV): return 1;
+ }
+ return 0;
+}
+
+static void disasm_ortho(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t prefix2, uint64_t *value, char *inst_name, char *postfix, operand *op, uint8_t rs, uint8_t thread) {
+ char opr[2][256];
+ char address[2][17];
+ char *rind[2] = {"", ""};
+ char *sign[2] = {"", ""};
+ char *ind[2] = {"", ""};
+ char idx[2][33];
+ char scale[2][5];
+ char *reg[2] = {"", ""};
+ memset(opr, 0, sizeof(opr));
+ memset(address, 0, sizeof(address));
+ memset(idx, 0, sizeof(idx));
+ memset(scale, 0, sizeof(scale));
+ for (int i = 0; i < 2; i++) {
+ int is_ind = 0;
+ int is_rind = 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);
+ }
+ switch (op[i].id) {
+ case MEM_ABSR :
+ case MEM_ZMR :
+ case MEM_AINDR:
+ case MEM_AIND :
+ case MEM_ZINDR:
+ case MEM_ARIND:
+ case MEM_ZRIND:
+ case MEM_SIB :
+ case MEM_RIND : is_rind = 1; break;
+ }
+ if (is_rind) {
+ for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) {
+ switch (op[i].rind[j]) {
+ case REG_A : rind[j] = "A"; break;
+ case REG_B : rind[j] = "B"; break;
+ case REG_X : rind[j] = "X"; break;
+ case REG_Y : rind[j] = "Y"; break;
+ case REG_E : rind[j] = "E"; break;
+ case REG_C : rind[j] = "C"; break;
+ case REG_D : rind[j] = "D"; break;
+ case REG_S : rind[j] = "S"; break;
+ case REG_F : rind[j] = "F"; break;
+ case REG_SP : rind[j] = "SP"; break;
+ case REG_BP : rind[j] = "BP"; break;
+ case REG_R11: rind[j] = "R11"; break;
+ case REG_R12: rind[j] = "R12"; break;
+ case REG_R13: rind[j] = "R13"; break;
+ case REG_R14: rind[j] = "R14"; break;
+ case REG_R15: rind[j] = "R15"; break;
+ }
+ }
+ }
+ sprintf(idx[i], "%s%s%s%s", scale[i], rind[0], (op[i].rind[1] != 0xFF) ? "+" : "", rind[1]);
+ switch (op[i].id) {
+ case MEM_AINDR:
+ case MEM_AIND :
+ case MEM_ZINDR:
+ case MEM_IND : is_ind = 1; break;
+ case MEM_ARIND:
+ case MEM_ZRIND:
+ case MEM_SIB :
+ case MEM_RIND : is_ind = 2; break;
+ case MEM_IMM : is_ind = 3; break;
+ }
+ if (!is_rind) {
+ sign[i] = "";
+ }
+ } else {
+ is_ind = 4;
+ switch (op[i].id) {
+ case REG_A : reg[i] = "A"; break;
+ case REG_B : reg[i] = "B"; break;
+ case REG_X : reg[i] = "X"; break;
+ case REG_Y : reg[i] = "Y"; break;
+ case REG_E : reg[i] = "E"; break;
+ case REG_C : reg[i] = "C"; break;
+ case REG_D : reg[i] = "D"; break;
+ case REG_S : reg[i] = "S"; break;
+ case REG_F : reg[i] = "F"; break;
+ case REG_SP : reg[i] = "SP"; break;
+ case REG_BP : reg[i] = "BP"; break;
+ case REG_R11: reg[i] = "R11"; break;
+ case REG_R12: reg[i] = "R12"; break;
+ case REG_R13: reg[i] = "R13"; break;
+ case REG_R14: reg[i] = "R14"; break;
+ case REG_R15: reg[i] = "R15"; break;
+ }
+ }
+ switch (is_ind) {
+ case 0: sprintf(opr[i], "%s%s%s", idx[i], sign[i], address[i]); break;
+ case 1: sprintf(opr[i], "%s%s(%s)", idx[i], sign[i], address[i]); break;
+ case 2: sprintf(opr[i], "(%s%s%s)", idx[i], sign[i], address[i]); break;
+ case 3: sprintf(opr[i], "#$%*"PRIX64, rs*2, op[i].value); break;
+ case 4: sprintf(opr[i], "%s", reg[i]); break;
+ }
+ }
+ char *cc = "";
+ char *op2 = "";
+ int op_count;
+ char *os = ""; /* Ortho Suffix. */
+ if (is_os(opcode, op)) {
+ os = (postfix && postfix[0] == '.') ? "O" : ".O";
+ }
+ if (is_1cc(opcode) || is_2op(opcode)) {
+ op_count = 2;
+ } else if (is_1op(opcode)) {
+ op_count = 1;
+ }
+ if (is_1cc(opcode)) {
+ switch (opcode) {
+ case ORTHO_1CC(SET, NG): cc = "NG"; break;
+ case ORTHO_1CC(SET, PO): cc = "PO"; break;
+ case ORTHO_1CC(SET, CS): cc = "CS"; break;
+ case ORTHO_1CC(SET, CC): cc = "CC"; break;
+ case ORTHO_1CC(SET, EQ): cc = "EQ"; break;
+ case ORTHO_1CC(SET, NE): cc = "NE"; break;
+ case ORTHO_1CC(SET, VS): cc = "VS"; break;
+ case ORTHO_1CC(SET, VC): cc = "VC"; break;
+ }
+ op2 = cc;
+ } else if (is_2op(opcode)) {
+ op2 = opr[1];
+ }
+ wprintw(scr, "%s%s%s %s%s %s", inst_name, postfix, os, opr[0], (op_count == 2) ? "," : "", op2);
+ wmove(scr, 29, 0);
+ wclrtoeol(scr);
+ for (int i = 0; i < 2; i++) {
+ if (op[i].type) {
+ sprintf(address[i], "$%04"PRIX64, value[i]);
+ } else {
+ sprintf(address[i], "none");
+ }
+ }
+ wprintw(scr, "destination address: %s, source address: %s", address[0], address[1]);
+}
+
+
+void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t *op_type, uint8_t *op_id, uint8_t thread) {
uint64_t value;
- uint64_t address = get_addr(cpu, opcode, prefix, ext_prefix, 0, 0, thread);
+ uint64_t address = 0;
+ operand ortho_op[2];
+ uint64_t ortho_addr[2] = {0, 0};
+ 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);
+ }
uint8_t rs = (prefix >> 4) & 3;
char *postfix;
char *of;
@@ -38,15 +310,6 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
mask.u64 = 0;
const char *inst_name;
uint8_t inst_type;
- if ((ext_prefix & 0xF) == 0xD) {
- switch (ext_prefix >> 4) {
- case 0x0: inst_name = ext_opname[opcode]; inst_type = ext_optype[opcode]; break;
- }
- } else {
- inst_name = opname[opcode];
- inst_type = optype[opcode];
- }
- memcpy(op, inst_name, 3);
op[3] = 0;
switch (rs) {
case 0: postfix = ""; break;
@@ -62,74 +325,92 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
case 1 : of = "SP"; break;
case 2 : of = "PC"; break;
}
- uint8_t addrsize = 0;
- char *idx;
- switch (inst_type) {
- case AIND : case IND : idx = ")"; break;
- case AINDX: case INDX: idx = ", x)"; break;
- case AINDY: case INDY: idx = "), y"; break;
- case ABSX : case ZMX : idx = ", x"; break;
- case ABSY : case ZMY : idx = ", y"; break;
- default: idx = ""; break;
- }
- switch (inst_type) {
- case ZM :
- case ZMX :
- case ZMY :
- case IND :
- case INDX :
- case INDY : addrsize = get_addrsize(prefix, ZM); break;
- case ABS :
- case AIND :
- case AINDX:
- case AINDY:
- case ABSX :
- case ABSY : addrsize = get_addrsize(prefix, ABS); break;
- case IMM :
- case REL : addrsize = (1 << rs)-1; break;
- }
- mask.u64 = (-(uint64_t)1 >> ((7 - addrsize) * 8));
- value = read_value(cpu, 0, cpu->pc, addrsize, 0, 0);
- if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || inst_type == REL) {
- switch (addrsize) {
- case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break;
- case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break;
- case 2 :
- case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break;
- case 4 :
- case 5 :
- case 6 :
- case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break;
+ if (ext_prefix != 0x1D) {
+ if ((ext_prefix & 0xF) == 0xD) {
+ switch (ext_prefix >> 4) {
+ case 0x0: inst_name = ext_opname[opcode]; inst_type = ext_optype[opcode]; break;
+ }
+ } else {
+ inst_name = opname[opcode];
+ inst_type = optype[opcode];
+ }
+ memcpy(op, inst_name, 3);
+
+ char *idx;
+ uint8_t addrsize = 0;
+ switch (inst_type) {
+ case AIND : case IND : idx = ")"; break;
+ case AINDX: case INDX: idx = ", x)"; break;
+ case AINDY: case INDY: idx = "), y"; break;
+ case ABSX : case ZMX : idx = ", x"; break;
+ case ABSY : case ZMY : idx = ", y"; break;
+ default: idx = ""; break;
+ }
+ switch (inst_type) {
+ case ZM :
+ case ZMX :
+ case ZMY :
+ case IND :
+ case INDX :
+ case INDY : addrsize = get_addrsize(prefix, ZM); break;
+ case ABS :
+ case AIND :
+ case AINDX:
+ case AINDY:
+ case ABSX :
+ case ABSY : addrsize = get_addrsize(prefix, ABS); break;
+ case IMM :
+ case REL : addrsize = (1 << rs)-1; break;
+ }
+ mask.u64 = (-(uint64_t)1 >> ((7 - addrsize) * 8));
+ value = read_value(cpu, 0, cpu->pc, addrsize, 0, 0);
+ if ((prefix >> 6) == 1 || (prefix >> 6) == 2 || inst_type == REL) {
+ switch (addrsize) {
+ case 0 : sign = ((int8_t )value < 0) ? "-" : "+"; break;
+ case 1 : sign = ((int16_t)value < 0) ? "-" : "+"; break;
+ case 2 :
+ case 3 : sign = ((int32_t)value < 0) ? "-" : "+"; break;
+ case 4 :
+ case 5 :
+ case 6 :
+ case 7 : sign = ((int64_t)value < 0) ? "-" : "+"; break;
+ }
+ value = (sign[0] == '-') ? (~value + 1) & mask.u64 : value;
}
- value = (sign[0] == '-') ? (~value + 1) & mask.u64 : value;
- }
- switch (inst_type) {
- case BREG :
- case IMPL : wprintw(scr, "%s%s" , inst_name, postfix); break;
- case EIND : wprintw(scr, "%s%s (E)" , op, postfix); break;
- case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break;
- case AIND :
- case AINDX:
- case AINDY:
- case IND :
- case INDX :
- case INDY : ind = "("; /* Falls through. */
- case ZMX :
- case ZMY :
- case ABSX :
- case ABSY :
- case ZM :
- case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value, idx); break;
- case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value); break;
+ switch (inst_type) {
+ case BREG :
+ case IMPL : wprintw(scr, "%s%s" , inst_name, postfix); break;
+ case EIND : wprintw(scr, "%s%s (E)" , op, postfix); break;
+ case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break;
+ case AIND :
+ case AINDX:
+ case AINDY:
+ case IND :
+ case INDX :
+ case INDY : ind = "("; /* Falls through. */
+ case ZMX :
+ case ZMY :
+ case ABSX :
+ case ABSY :
+ case ZM :
+ case ABS : wprintw(scr, "%s%s %s%s%s$%0*" PRIX64"%s" , op, postfix, ind, of, sign, (addrsize+1) << 1, value, idx); break;
+ case REL : wprintw(scr, "%s%s %s$%0*"PRIX64 , op, postfix, sign, (addrsize+1) << 1, value); break;
+ }
+ } else {
+ inst_name = ortho_opname[opcode];
+ memcpy(op, inst_name, 3);
+ disasm_ortho(cpu, opcode, prefix, prefix2, ortho_addr, op, postfix, ortho_op, rs, thread);
}
if (address == TX_ADDR || address == RX_ADDR) {
wmove(scr, 27, 0);
wprintw(scr, "TX_ADDR: $%02X, RX_ADDR: $%02X", addr[TX_ADDR], addr[RX_ADDR]);
}
- wmove(scr, 29, 0);
- wclrtoeol(scr);
- wprintw(scr, "address: $%04"PRIX64, address);
+ if (ext_prefix != 0x1D) {
+ wmove(scr, 29, 0);
+ wclrtoeol(scr);
+ wprintw(scr, "address: $%04"PRIX64, address);
+ }
if (subdbg) {
uint8_t ln = 33;
uint16_t line_idx = 0;
@@ -253,3 +534,7 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
}
}
+
+#undef ORTHO_1CC
+#undef ORTHO_1OP
+#undef ORTHO_2OP
diff --git a/disasm.h b/disasm.h
index 6f978ce..3427592 100644
--- a/disasm.h
+++ b/disasm.h
@@ -335,3 +335,74 @@ static const char *ext_opname[0x100] = {
[SWP_E ] = "SWP (E)",
[PCN_E ] = "PCN (E)"
};
+
+#define ORTHO_1CC(mne, cc) \
+ [mne##_R##cc] = #mne " r, " #cc, [mne##_M##cc] = #mne " m, " #cc
+
+#define ORTHO_1OP(mne) \
+ [mne##_R] = #mne " r", [mne##_M] = #mne " m"
+
+#define ORTHO_2OP(mne) \
+ [mne##_RR] = #mne " r, r", [mne##_RM] = #mne " r, m", [mne##_MR] = #mne " m, r", [mne##_MM] = #mne " m, m"
+
+
+static const char *ortho_opname[] = {
+ /* 0x00-0x1C */
+ ORTHO_2OP(MNG/**/), /* Move if NeGative. */
+ ORTHO_2OP(ADC/**/), /* ADC Ortho. */
+ ORTHO_2OP(ROR/**/), /* ROR Ortho. */
+ ORTHO_2OP(ADD/**/), /* ADD Ortho. */
+ ORTHO_1OP(PSH/**/), /* PuSH operand onto the stack. */
+ ORTHO_1CC(SET, NG), /* SET if NeGative. */
+ ORTHO_1OP(PEA/**/), /* PEA Ortho. */
+ /* 0x20-0x3C */
+ ORTHO_2OP(MPO/**/), /* Move if POsitive. */
+ ORTHO_2OP(SBC/**/), /* SBC Ortho. */
+ ORTHO_2OP(MUL/**/), /* MUL Ortho. */
+ ORTHO_2OP(SUB/**/), /* SUB Ortho. */
+ ORTHO_1OP(PUL/**/), /* PuLl operand off of the stack. */
+ ORTHO_1CC(SET, PO), /* SET if POsitive. */
+ ORTHO_1OP(SWP/**/), /* SWP Ortho. */
+ /* 0x40-0x55 */
+ ORTHO_2OP(MCS/**/), /* Move if Carry Set. */
+ ORTHO_2OP(AND/**/), /* AND Ortho. */
+ ORTHO_2OP(DIV/**/), /* DIV Ortho. */
+ ORTHO_2OP(PCN/**/), /* PCN Ortho. */
+ ORTHO_1OP(NOT/**/), /* NOT Ortho. */
+ ORTHO_1CC(SET, CS), /* SET if Carry Set. */
+ /* 0x60-0x75 */
+ ORTHO_2OP(MCC/**/), /* Move if Carry Clear. */
+ ORTHO_2OP(OR /**/), /* Bitwise OR. */
+ ORTHO_2OP(ASR/**/), /* ASR Ortho. */
+ ORTHO_2OP(LEA/**/), /* LEA Ortho. */
+ ORTHO_1OP(NEG/**/), /* NEGate operand. */
+ ORTHO_1CC(SET, CC), /* SET if Carry Clear. */
+ /* 0x80-0x95 */
+ ORTHO_2OP(MEQ/**/), /* Move if EQual. */
+ ORTHO_2OP(XOR/**/), /* XOR Ortho. */
+ ORTHO_2OP(CMP/**/), /* CMP Ortho. */
+ ORTHO_1OP(DEC/**/), /* DEC Ortho. */
+ ORTHO_1CC(SET, EQ), /* SET if EQual. */
+ /* 0xA0-0xB5 */
+ ORTHO_2OP(MNE/**/), /* Move if Not Equal. */
+ ORTHO_2OP(LSL/**/), /* LSL Ortho. */
+ ORTHO_2OP(MOV/**/), /* MOVe data from source, to destination. */
+ ORTHO_1OP(INC/**/), /* INC Ortho. */
+ ORTHO_1CC(SET, NE), /* SET if Not Equal. */
+ /* 0xC0-0xD5 */
+ ORTHO_2OP(MVS/**/), /* Move if oVerflow Set. */
+ ORTHO_2OP(LSR/**/), /* LSR Ortho. */
+ ORTHO_2OP(IML/**/), /* Integer MuLtiply. */
+ ORTHO_1OP(CLZ/**/), /* CLZ Ortho. */
+ ORTHO_1CC(SET, VS), /* SET if oVerflow Set. */
+ /* 0xE0-0xF5 */
+ ORTHO_2OP(MVC/**/), /* Move if oVerflow Clear. */
+ ORTHO_2OP(ROL/**/), /* ROL Ortho. */
+ ORTHO_2OP(IDV/**/), /* Integer DiVide. */
+ ORTHO_1OP(CLO/**/), /* CLO Ortho. */
+ ORTHO_1CC(SET, VC) /* SET if oVerflow Clear. */
+};
+
+#undef ORTHO_1CC
+#undef ORTHO_1OP
+#undef ORTHO_2OP
diff --git a/enums.h b/enums.h
index 07338ee..834566d 100644
--- a/enums.h
+++ b/enums.h
@@ -45,12 +45,15 @@ enum ortho_mem {
MEM_ZM, /* Zero Matrix. */
MEM_ABSR, /* Absolute, Indexed with register. */
MEM_ZMR, /* Zero Matrix, Indexed with register. */
- MEM_ZINDR, /* Zero Matrix, Indirect Indexed Register. */
- MEM_ZRIND, /* Zero Matrix, Indexed Indirect Register. */
+ MEM_AIND, /* Absolute Indirect. */
+ MEM_IND, /* Zero Matrix Indirect. */
MEM_AINDR, /* Absolute, Indirect Indexed Register. */
+ MEM_ZINDR, /* Zero Matrix, Indirect Indexed Register. */
MEM_ARIND, /* Absolute, Indexed Indirect Register. */
+ MEM_ZRIND, /* Zero Matrix, Indexed Indirect Register. */
MEM_RIND, /* Register Indirect. */
- MEM_SIB, /* Scale Index Base. */
+ MEM_IMM, /* Immediate Data. */
+ MEM_SIB = 0xE, /* Scale Index Base. */
};
enum mne {
@@ -538,3 +541,73 @@ enum base_ext {
SWP_E = 0xFA, /* SWP E Indirect. */
PCN_E = 0xFC /* PCN E Indirect. */
};
+
+#define ORTHO_1CC(mne, base, cc) \
+ mne##_R##cc = base, mne##_M##cc = base|0x10
+
+#define ORTHO_1OP(mne, base) \
+ mne##_R = base, mne##_M = base|0x10
+
+#define ORTHO_2OP(mne, base) \
+ mne##_RR = base, mne##_RM = base|0x08, mne##_MR = base|0x10, mne##_MM = base|0x18
+
+enum ortho {
+ /* 0x00-0x1C */
+ ORTHO_2OP(MNG, 0x00/**/), /* Move if NeGative. */
+ ORTHO_2OP(ADC, 0x01/**/), /* ADC Ortho. */
+ ORTHO_2OP(ROR, 0x02/**/), /* ROR Ortho. */
+ ORTHO_2OP(ADD, 0x03/**/), /* ADD Ortho. */
+ ORTHO_1OP(PSH, 0x04/**/), /* PuSH operand onto the stack. */
+ ORTHO_1CC(SET, 0x05, NG), /* SET if NeGative. */
+ ORTHO_1OP(PEA, 0x0C/**/), /* PEA Ortho. */
+ /* 0x20-0x3C */
+ ORTHO_2OP(MPO, 0x20/**/), /* Move if POsitive. */
+ ORTHO_2OP(SBC, 0x21/**/), /* SBC Ortho. */
+ ORTHO_2OP(MUL, 0x22/**/), /* MUL Ortho. */
+ ORTHO_2OP(SUB, 0x23/**/), /* SUB Ortho. */
+ ORTHO_1OP(PUL, 0x24/**/), /* PuLl operand off of the stack. */
+ ORTHO_1CC(SET, 0x25, PO), /* SET if POsitive. */
+ ORTHO_1OP(SWP, 0x2C/**/), /* SWP Ortho. */
+ /* 0x40-0x55 */
+ ORTHO_2OP(MCS, 0x40/**/), /* Move if Carry Set. */
+ ORTHO_2OP(AND, 0x41/**/), /* AND Ortho. */
+ ORTHO_2OP(DIV, 0x42/**/), /* DIV Ortho. */
+ ORTHO_2OP(PCN, 0x43/**/), /* PCN Ortho. */
+ ORTHO_1OP(NOT, 0x44/**/), /* NOT Ortho. */
+ ORTHO_1CC(SET, 0x45, CS), /* SET if Carry Set. */
+ /* 0x60-0x75 */
+ ORTHO_2OP(MCC, 0x60/**/), /* Move if Carry Clear. */
+ ORTHO_2OP(OR , 0x61/**/), /* Bitwise OR. */
+ ORTHO_2OP(ASR, 0x62/**/), /* ASR Ortho. */
+ ORTHO_2OP(LEA, 0x63/**/), /* LEA Ortho. */
+ ORTHO_1OP(NEG, 0x64/**/), /* NEGate operand. */
+ ORTHO_1CC(SET, 0x65, CC), /* SET if Carry Clear. */
+ /* 0x80-0x95 */
+ ORTHO_2OP(MEQ, 0x80/**/), /* Move if EQual. */
+ ORTHO_2OP(XOR, 0x81/**/), /* XOR Ortho. */
+ ORTHO_2OP(CMP, 0x82/**/), /* CMP Ortho. */
+ ORTHO_1OP(DEC, 0x84/**/), /* DEC Ortho. */
+ ORTHO_1CC(SET, 0x85, EQ), /* SET if EQual. */
+ /* 0xA0-0xB5 */
+ ORTHO_2OP(MNE, 0xA0/**/), /* Move if Not Equal. */
+ ORTHO_2OP(LSL, 0xA1/**/), /* LSL Ortho. */
+ ORTHO_2OP(MOV, 0xA2/**/), /* MOVe data from source, to destination. */
+ ORTHO_1OP(INC, 0xA4/**/), /* INC Ortho. */
+ ORTHO_1CC(SET, 0xA5, NE), /* SET if Not Equal. */
+ /* 0xC0-0xD5 */
+ ORTHO_2OP(MVS, 0xC0/**/), /* Move if oVerflow Set. */
+ ORTHO_2OP(LSR, 0xC1/**/), /* LSR Ortho. */
+ ORTHO_2OP(IML, 0xC2/**/), /* Integer MuLtiply. */
+ ORTHO_1OP(CLZ, 0xC4/**/), /* CLZ Ortho. */
+ ORTHO_1CC(SET, 0xC5, VS), /* SET if oVerflow Set. */
+ /* 0xE0-0xF5 */
+ ORTHO_2OP(MVC, 0xE0/**/), /* Move if oVerflow Clear. */
+ ORTHO_2OP(ROL, 0xE1/**/), /* ROL Ortho. */
+ ORTHO_2OP(IDV, 0xE2/**/), /* Integer DiVide. */
+ ORTHO_1OP(CLO, 0xE4/**/), /* CLO Ortho. */
+ ORTHO_1CC(SET, 0xE5, VC) /* SET if oVerflow Clear. */
+};
+
+#undef ORTHO_1CC
+#undef ORTHO_1OP
+#undef ORTHO_2OP
diff --git a/lexer.c b/lexer.c
index 9e9d2e0..873fe6d 100644
--- a/lexer.c
+++ b/lexer.c
@@ -131,8 +131,8 @@ symbol *find_member(char *name, symbol* root, uint8_t dbg) {
return m;
}
}
- for (; s->next && !s->down; s = s->next);
- } while (s->down);
+ for (;s && s->next && !s->down; s = s->next);
+ } while (s && s->down);
return NULL;
}
@@ -274,7 +274,7 @@ void create_struct(symbol *c_sym, line *l, token *t, token *lt, char *name, uint
void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) {
int skip = 0;
- if (is_anon > 0) {
+ if (/*s_sym &&*/ is_anon > 0) {
if ((c_sym && c_sym->isanon) || (c_sym->up && !c_sym->up->isanon) || (c_sym && s_sym->isanon)) {
is_anon--;
} else if (is_struct <= 0) {
@@ -297,7 +297,7 @@ void end_struct(symbol *c_sym, symbol *s_sym, uint8_t dbg) {
}
}
if ((is_anon <= 0 || is_struct <= 0)) {
- for (s_sym = c_sym; s_sym->prev && !s_sym->isanon; s_sym = s_sym->prev);
+ for (s_sym = c_sym; /*s_sym &&*/ s_sym->prev && !s_sym->isanon; s_sym = s_sym->prev);
struct_sym = s_sym;
}
if ((is_struct-is_anon) > 0 && !skip) {
@@ -327,6 +327,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
uint16_t symid = 0;
uint64_t value = 0;
lex_type = 0xFF;
+ uint8_t lex_subtype = 0xFF;
uint8_t k = 0;
uint8_t k2 = 0;
@@ -408,7 +409,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
uint8_t ptok = get_ptok(str[i], dbg);
if (is_altok(ptok, dbg)) {
offset++;
- if (((ptok == PTOK_S && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C'))) {
+ if (((ptok == PTOK_S || ptok == PTOK_B) && toupper(str[i+1]) == 'P') || (ptok == PTOK_P && toupper(str[i+1]) == 'C')) {
offset++;
}
switch (get_ptok(str[i+offset], dbg)) {
@@ -423,10 +424,27 @@ 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 :
- case PTOK_NUMBER: ptok = PTOK_ALPHA; break;
+ case PTOK_ALPHA : ptok = PTOK_ALPHA; break;
+ case PTOK_NUMBER:
+ if (ptok == PTOK_R) {
+ char reg_num[3];
+ int isnum;
+ for (isnum = 0; isdigit(str[i+offset]) && !(isdelm(str[i+offset], dbg) & 0x03) && isnum < 2; offset++, isnum++) {
+ reg_num[isnum] = str[i+offset];
+ }
+ reg_num[isnum] = '\0';
+ if (isnum == 2) {
+ int regnum = strtoul(reg_num, NULL, 10);
+ ptok = (regnum < 11 || regnum > 15) ? PTOK_ALPHA : ptok;
+ } else {
+ ptok = PTOK_ALPHA;
+ }
+ } else {
+ ptok = PTOK_ALPHA;
+ }
+ break;
}
- if ((ptok == PTOK_S && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) {
+ if ((ptok == PTOK_S && str[i+1] && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) {
ptok = PTOK_ALPHA;
}
}
@@ -458,31 +476,41 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
break;
}
}
- l->count++;
if (lex_type != TOK_DIR && lt && lt->id == TOK_SYM) {
lex_type = TOK_MEMBER;
i -= j;
} else {
+ l->count++;
t = make_token(lex_type, k, space, tab, 0, "", NULL);
}
} else {
- lex_type = TOK_RS;
- switch (tolower(lexeme[j-1])) {
- case '2':
- case 'w':
- rs = 1;
- break;
- case '4':
- case 'd':
- rs = 2;
- break;
- case '8':
- case 'q':
- rs = 3;
- break;
+ for (k = 0; !(isdelm(lexeme[k], dbg) & 17); k++) {
+ lex_type = TOK_RS;
+ switch (tolower(lexeme[k])) {
+ case '2':
+ case 'w':
+ rs = 1;
+ break;
+ case '4':
+ case 'd':
+ rs = 2;
+ break;
+ case '8':
+ case 'q':
+ rs = 3;
+ break;
+ case 'o':
+ /* Set Our token type to ortho suffix. */
+ lex_type = TOK_OS;
+ break;
+ }
+ l->count++;
+ t = make_token(lex_type, rs, space, tab, 0, "", NULL);
+ if (t) {
+ lt = t;
+ t = t->next;
+ }
}
- l->count++;
- t = make_token(lex_type, rs, space, tab, 0, "", NULL);
isop = 0;
}
break;
@@ -578,12 +606,20 @@ 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;
+ /*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;
+ 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);
+ /*(t) ? (t->subspace = space) : (lt->subspace = space);
+ (t) ? (t->subtab = tab) : (lt->subtab = tab);*/
break;
case PTOK_PLUS:
case PTOK_MINUS:
@@ -620,51 +656,83 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
lexeme[j] = ')';
lexeme[j+1] = '\0';
lexeme[j+2] = '\0';
+ if (t && t->subtype == 0xFF) {
+ t->subtype = TOK_IND;
+ } else if (lt && lt->subtype == 0xFF) {
+ lt->subtype = TOK_IND;
+ }
+ (t) ? (t->subspace = space) : (lt->subspace = space);
+ (t) ? (t->subtab = tab) : (lt->subtab = tab);
break;
case PTOK_COMMA:
i++;
- if (lex_type != TOK_IND && lex_type != TOK_OF) {
+ if ((lex_type != TOK_IND && lex_type != TOK_OF)) {
lex_type = TOK_CSV;
}
+ lex_subtype = TOK_CSV;
+ if (t && t->subtype == 0xFF) {
+ t->subtype = TOK_CSV;
+ } else if (lt && lt->subtype == 0xFF) {
+ lt->subtype = TOK_CSV;
+ }
+ (t) ? (t->subspace = space) : (lt->subspace = space);
+ (t) ? (t->subtab = tab) : (lt->subtab = tab);
lexeme[j] = ',';
lexeme[j+1] = '\0';
lexeme[j+2] = '\0';
break;
case PTOK_B:
- lexeme[j] = str[i++];
- lexeme[j+1] = '\0';
- lexeme[j+2] = '\0';
- lex_type = TOK_BREG;
- l->tok->type = BREG;
- (t) ? (t->subspace = space) : (lt->subspace = space);
- (t) ? (t->subtab = tab) : (lt->subtab = tab);
- break;
case PTOK_E:
case PTOK_X:
case PTOK_Y:
- lexeme[j] = str[i++];
- lexeme[j+1] = '\0';
- lexeme[j+2] = '\0';
+ case PTOK_S:
+ case PTOK_A:
+ case PTOK_C:
+ case PTOK_D:
+ case PTOK_F:
+ case PTOK_R:
+ lexeme[j+0] = str[i++];
+ 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_E: l->tok->type = (lex_type == TOK_IND) ? EIND : l->tok->type; break;
- case PTOK_X: l->tok->type = (l->tok->type == IND) ? INDX : ZMX; break;
- case PTOK_Y: l->tok->type = (lex_type == TOK_IND) ? INDY : ZMY; break;
+ case PTOK_A: value = REG_A; break;
+ case PTOK_X: value = REG_X; break;
+ case PTOK_Y: value = REG_Y; break;
+ case PTOK_E: value = REG_E; break;
+ case PTOK_C: value = REG_C; break;
+ case PTOK_D: value = REG_D; break;
+ case PTOK_S:
+ case PTOK_B:
+ if (get_ptok(lexeme[j+1], dbg) == PTOK_P) {
+ value = (ptok == PTOK_S) ? REG_SP : REG_BP;
+ } else {
+ value = (ptok == PTOK_S) ? REG_S : REG_B;
+ }
+ break;
+ case PTOK_F: value = REG_F; break;
+ case PTOK_R: value = strtoull(lexeme+j+1, NULL, 10); break;
}
+ l->count++;
+ 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_S:
case PTOK_P:
lexeme[j] = str[i++];
- if (str[i] != ',') {
- lexeme[j+1] = str[i++];
- } else {
- lexeme[j+1] = '\0';
- }
+ lexeme[j+1] = (str[i] != ',') ? str[i++] : '\0';
lexeme[j+2] = '\0';
- switch (ptok) {
+ /*switch (ptok) {
case PTOK_S: of = 1; break;
case PTOK_P: of = 2; break;
- }
+ }*/
+ of = 2;
lex_type = TOK_OF;
+ l->count++;
t = make_token(lex_type, of, space, tab, 0, "", NULL);
break;
case PTOK_AT:
@@ -750,18 +818,26 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
i += j;
isch = 0;
isop = 0;
- if (j == 3 && str[i] != ':' && !is_struct) {
- for (k = 0, k2 = 0; k < OPNUM || k2 < EXT_OPNUM; k++, k2++) {
- int find_ext = (k2 < EXT_OPNUM);
+ if (j > 1 && j <= 3 && str[i] != ':' && !is_struct) {
+ for (k = 0; k < OPNUM; k++) {
+ int find_ext = (k < EXT_OPNUM);
+ int find_ortho = (k < ORTHO_OPNUM);
int upper = toupper(lexeme[0]);
- if (upper == mne[k][0] || (find_ext && upper == ext_mne[k2][0])) {
+ int isbase = (upper == mne[k][0]);
+ int isext = (find_ext && upper == ext_mne[k][0]);
+ int isortho = (find_ortho && upper == ortho_mne[k][0]);
+
+ if (isbase || isext || isortho) {
int is_base = !strcasecmp(lexeme, mne[k]);
- int is_ext = (find_ext && !strcasecmp(lexeme, ext_mne[k2]));
- if (is_base || is_ext) {
- lex_type = (is_base && !is_ext) ? TOK_OPCODE : TOK_EXTOP;
+ int is_ext = (find_ext && !strcasecmp(lexeme, ext_mne[k]));
+ int is_ortho = (find_ortho && !strcasecmp(lexeme, ortho_mne[k]));
+ if (is_base || is_ext || is_ortho) {
+ lex_type = (is_base) ? TOK_OPCODE : lex_type;
+ lex_type = (is_ext) ? TOK_EXTOP : lex_type;
+ lex_type = (is_ortho) ? TOK_ORTHO : lex_type;
isop = 1;
l->count++;
- t = make_token(lex_type, 0xFF, space, tab, (is_base && !is_ext) ? k : k2, "", NULL);
+ t = make_token(lex_type, 0xFF, space, tab, k, "", NULL);
break;
}
}
@@ -769,6 +845,18 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
}
if (!isop) {
uint8_t spaces = 0;
+ if (l->tok && l->tok->type == TOK_ORTHO && l->tok->byte == SET) {
+ for (k = 0; k < 8; k++) {
+ int upper = toupper(lexeme[0]);
+ if (upper == set_cc[k][0]) {
+ if (!strcasecmp(lexeme, set_cc[k])) {
+ lex_type = TOK_CC;
+ l->count++;
+ t = make_token(lex_type, 0xFF, space, tab, k, "", NULL);
+ }
+ }
+ }
+ }
for (; isdelm(str[i+spaces], dbg) == 16; spaces++);
uint8_t ret = get_ptok(str[i+spaces], dbg);
if (ret == PTOK_COLON || ret == PTOK_EQU) {
@@ -845,9 +933,9 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
case TOK_DEC :
case TOK_CHAR:
case TOK_EXPR:
- s->val = get_val(tok, address, 3, dbg);
+ s->val = get_val(tok, address, 3, 0xFF, 0, dbg);
if (tok->next) {
- tok = skip_expr(tok, dbg);
+ tok = skip_expr(tok, 0xFF, 0, dbg);
}
break;
}
diff --git a/lexer.h b/lexer.h
index 356fad0..8775187 100644
--- a/lexer.h
+++ b/lexer.h
@@ -52,6 +52,11 @@ static uint8_t get_ptok(char c, uint8_t dbg) {
case 'Y': case 'y' : return PTOK_Y ;
case 'S': case 's' : return PTOK_S ;
case 'P': case 'p' : return PTOK_P ;
+ case 'A': case 'a' : return PTOK_A ;
+ case 'C': case 'c' : return PTOK_C ;
+ case 'D': case 'd' : return PTOK_D ;
+ case 'F': case 'f' : return PTOK_F ;
+ case 'R': case 'r' : return PTOK_R ;
case '\"': return PTOK_DQUOTE ;
case '\'': return PTOK_SQUOTE ;
case '#' : return PTOK_HASH ;
@@ -76,7 +81,12 @@ static uint8_t is_altok(uint8_t ptok, uint8_t dbg) {
case PTOK_X:
case PTOK_Y:
case PTOK_S:
- case PTOK_P: return 1;
+ case PTOK_P:
+ case PTOK_A:
+ case PTOK_C:
+ case PTOK_D:
+ case PTOK_F:
+ case PTOK_R: return 1;
default : return 0;
}
}
diff --git a/opcode.h b/opcode.h
index f5aeb0d..1e5d820 100644
--- a/opcode.h
+++ b/opcode.h
@@ -58,11 +58,25 @@ struct sux {
union reg ps; /* The processor status register. */
uint64_t a, b, y, x; /* Registers A, B, X, and Y. */
uint64_t e; /* Effective address register. */
+ uint64_t c, d, s, f; /* Registers C, D, S, and F. */;
uint64_t pc; /* Program counter. */
uint64_t sp; /* Stack pointer. */
+ uint64_t bp; /* Base pointer. */
+ uint64_t r11, r12, r13, r14, r15; /* Registers R11-R15. */;
uint64_t clk; /* Number of clock cycles. */
};
+typedef struct op operand;
+
+struct op {
+ uint8_t type; /* Operand Type. 0 = register, 1 = memory. */
+ uint8_t id; /* Operand Type ID 1. 4 bits. */
+ uint8_t rind[2]; /* Register(s) used for register indirect. */
+ uint8_t scale; /* Scale used for SIB. */
+ int is_ind : 1; /* Flag used to determine if this operand is an indirect mode. */
+ uint64_t value; /* Value of operand (used only by memory operands). */
+};
+
extern int asmmon();
enum sw_type {RS, AM, BYTE};
diff --git a/programs/sub-suite/declare.s b/programs/sub-suite/declare.s
index 5828fdb..550228d 100644
--- a/programs/sub-suite/declare.s
+++ b/programs/sub-suite/declare.s
@@ -769,7 +769,7 @@ inst:
.byte $81
; Mnemonic Table.
-mne:
+mnem:
.byte "ADC"
.byte "AND"
.byte "ASR"
@@ -852,9 +852,9 @@ cmd_srt:
.word list
.word asm
.word help
- .word ins
+ .word inst
.word run
- .word set
+ .word set_val
; Return table used by get_ctrlidx.
ct_rtb:
diff --git a/programs/sub-suite/lexer.s b/programs/sub-suite/lexer.s
index 9c3cb87..b2850aa 100644
--- a/programs/sub-suite/lexer.s
+++ b/programs/sub-suite/lexer.s
@@ -434,7 +434,7 @@ ptok_alph:
ldb idx1 ; Get the instruction ID.
cpb #OPNUM ; Have we reached the end of the mnemonic table?
beq @end ; Yes, so we're done.
- lda.w #mne ; No, so get the start of the mnemonic table.
+ lda.w #mnem ; No, so get the start of the mnemonic table.
clc ; Prepare for a non carrying add.
adc.w idx2 ; Offset the pointer, by the length of the previous string.
pha.q ; Preserve the mnemonic string pointer.
diff --git a/programs/sub-suite/libc.s b/programs/sub-suite/libc.s
index 3dc9d63..ae35146 100644
--- a/programs/sub-suite/libc.s
+++ b/programs/sub-suite/libc.s
@@ -277,7 +277,7 @@ malloc:
bra @retptr ; Return the pointer.
@sliceblk:
ldy #fblk.size ; Get the size of the current block.
- lda.q (sp+9). y ;
+ 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.
@@ -412,7 +412,7 @@ free:
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.
+ 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.
diff --git a/programs/sub-suite/subasm.s b/programs/sub-suite/subasm.s
index 7b2b8b9..80aaa47 100644
--- a/programs/sub-suite/subasm.s
+++ b/programs/sub-suite/subasm.s
@@ -164,15 +164,15 @@ help:
nop ;
@end:
rts ; End of help.
-ins:
+inst:
nop ;
@end:
- rts ; End of ins.
+ rts ; End of inst.
run:
nop ;
@end:
rts ; End of run.
-set:
+set_val:
nop ;
@end:
- rts ; End of set.
+ rts ; End of set_val.
diff --git a/programs/sub-suite/subeditor.s b/programs/sub-suite/subeditor.s
index 43768f7..387b5db 100644
--- a/programs/sub-suite/subeditor.s
+++ b/programs/sub-suite/subeditor.s
@@ -693,7 +693,7 @@ shftln:
beq @dec_loop ; Yes, so shift, and decrement.
ldb #0 ; Clear the B register.
bra @inc_loop ; No, so shift, and increment.
-@neg:
+@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.
@@ -711,7 +711,7 @@ shftln:
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 @neg ; The source underflowed, so set it back to zero,
+ 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.
diff --git a/programs/sub-suite/subsuite.s b/programs/sub-suite/subsuite.s
index b276209..7b31c31 100644
--- a/programs/sub-suite/subsuite.s
+++ b/programs/sub-suite/subsuite.s
@@ -17,7 +17,7 @@
.qword reset
a
;l a
-;.org reset+$F50
+;.org reset
;v
;f "subsuite.bin" $8000
;q
diff --git a/sux.c b/sux.c
index ac1f6e2..25bd8c5 100644
--- a/sux.c
+++ b/sux.c
@@ -111,6 +111,7 @@ void *run(void *args) {
uint8_t prefix = 0;
uint8_t ext_prefix = 0;
uint8_t prefix2 = 0;
+ uint8_t op_id = 0;
uint8_t opcode = 0;
union reg address;
union reg value;
@@ -177,17 +178,23 @@ void *run(void *args) {
pthread_mutex_unlock(&mutex);
#endif
#endif
- uint32_t instr = read_value(cpu, 0, cpu->pc, 3, 1, 0);
+ uint32_t instr = read_value(cpu, 0, cpu->pc, 4, 1, 0);
uint8_t *tmp_inst = (uint8_t *)&instr;
- prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0;
- ext_prefix = ((*tmp_inst & 0xF) == 0xD) ? *tmp_inst++ : 0;
- opcode = *tmp_inst;
- cpu->pc += ((instr & 3) == 3)+((ext_prefix & 0xF) == 0xD)+1;
+ uint8_t inst_len = 0;
+ prefix = ((instr & 3) == 3) ? tmp_inst[inst_len++] : 0;
+ ext_prefix = ((tmp_inst[inst_len] & 0xF) == 0xD) ? tmp_inst[inst_len++] : 0;
+ 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];
uint8_t ext_id = 0;
uint8_t tmp_opcode = opcode;
uint8_t tmp_ext_prefix = ext_prefix;
+ int is_ortho = 0;
if (ext_prefix) {
ext_id = (ext_prefix >> 4);
switch (ext_id) {
@@ -227,6 +234,14 @@ void *run(void *args) {
}
}
break;
+ case 0x1:
+ operand_type[0] = ((opcode & 0x10) >> 4);
+ operand_type[1] = ((opcode & 0x08) >> 3);
+ ortho_id[0] = op_id >> 4;
+ ortho_id[1] = op_id & 0x0F;
+ am = IMPL;
+ is_ortho = 1;
+ break;
}
} else {
am = optype[opcode];
@@ -238,7 +253,7 @@ void *run(void *args) {
#if keypoll
pthread_mutex_lock(&mutex);
#endif
- disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, thread);
+ disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, operand_type, ortho_id, thread);
lines+=1;
#if keypoll
pthread_mutex_unlock(&mutex);
@@ -261,6 +276,7 @@ void *run(void *args) {
uint8_t tmp = 0;
switch (ext_id) {
case 0x0: exec_ext_inst(cpu, opcode, prefix, value.u64, address.u64, size, thread); break;
+ case 0x1: exec_ortho_inst(cpu, opcode, prefix, size, operand_type, ortho_id, thread); break;
}
} else {
exec_base_inst(cpu, opcode, prefix, value.u64, address.u64, size, thread);
diff --git a/sux.h b/sux.h
index 5d8ded7..6b8a7f6 100644
--- a/sux.h
+++ b/sux.h
@@ -37,6 +37,15 @@ extern uint8_t end;
#define setflag(flag, bit) ((flag)) ? (cpu->ps.u8[thread] |= bit) : (cpu->ps.u8[thread] &= ~bit)
#define getflag(bit) (cpu->ps.u8[thread] & bit)
+#define ORTHO_1CC(mne, cc) \
+ mne##_R##cc: case mne##_M##cc
+
+#define ORTHO_1OP(mne) \
+ mne##_R: case mne##_M
+
+#define ORTHO_2OP(mne) \
+ mne##_RR: case mne##_RM: case mne##_MR: case mne##_MM
+
extern pthread_mutex_t mutex;
extern pthread_mutex_t main_mutex;
extern pthread_cond_t cond;
@@ -44,7 +53,7 @@ extern pthread_cond_t main_cond;
#if debug
extern void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread);
-extern void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t thread);
+extern void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t *op_type, uint8_t *op_id, uint8_t thread);
#endif
/*#define KEYBUF_SIZE 0x40
@@ -88,6 +97,23 @@ static /*inline*/ uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
return 0xFF;
}
+static /*inline*/ uint8_t get_ortho_addrsize(uint8_t prefix, uint8_t addrmode) {
+ uint8_t type = IMM;
+ switch (addrmode) {
+ case MEM_ABS :
+ case MEM_ABSR :
+ case MEM_AIND :
+ case MEM_AINDR:
+ case MEM_ARIND: type = ABS; break;
+ case MEM_ZM :
+ case MEM_ZMR :
+ case MEM_IND :
+ case MEM_ZINDR:
+ case MEM_ZRIND: type = ZM; break;
+ }
+ return get_addrsize(prefix, type);
+}
+
static /*inline*/ uint8_t isrw(uint8_t opcode, uint8_t ext_prefix) {
if ((ext_prefix & 0xD) == 0xD) {
switch (ext_prefix >> 4) {
@@ -480,12 +506,84 @@ static /*inline*/ uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t pre
return address;
}
+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) {
+ for (int i = 0; i < 2; i++) {
+ union reg tmp;
+ tmp.u64 = 0;
+ op[i].type = op_type[i];
+ op[i].id = op_id[i];
+ op[i].value = 0;
+ op[i].rind[0] = 0xFF;
+ op[i].rind[1] = 0xFF;
+ if (op[i].type) {
+ int inst_size = 0;
+ int addr_size = get_ortho_addrsize(prefix, op[i].id);
+ int rs = (1 << (prefix >> 4));
+ 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;
+ }
+ 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]) {
+ op[i].rind[1] = 0xFF;
+ }
+ op[i].scale = (inst_size == 2) ? tmp.u8[0] : 0;
+ }
+ if (addr_size != 0xFF || (rs && op[i].id == MEM_IMM)) {
+ inst_size = (addr_size != 0xFF) ? addr_size+1 : rs;
+ op[i].value = read_value(cpu, 0, address, inst_size-1, inc_clk, 0);
+ value[i] = op[i].value;
+ if (inc_pc) {
+ address += inst_size;
+ }
+ }
+ if (is_rind) {
+ for (int j = 0; j < 2 && op[i].rind[j] != 0xFF; j++) {
+ uint64_t reg;
+ switch (op[i].rind[j]) {
+ case REG_A : reg = cpu->a; break;
+ case REG_B : reg = cpu->b; break;
+ case REG_X : reg = cpu->x; break;
+ case REG_Y : reg = cpu->y; break;
+ case REG_E : reg = cpu->e; break;
+ case REG_C : reg = cpu->c; break;
+ case REG_D : reg = cpu->d; break;
+ case REG_S : reg = cpu->s; break;
+ case REG_F : reg = cpu->f; break;
+ case REG_SP : reg = cpu->sp; break;
+ case REG_BP : reg = cpu->bp; break;
+ case REG_R11: reg = cpu->r11; break;
+ case REG_R12: reg = cpu->r12; break;
+ case REG_R13: reg = cpu->r13; break;
+ case REG_R14: reg = cpu->r14; break;
+ case REG_R15: reg = cpu->r15; break;
+ }
+ value[i] += reg;
+ }
+ if (op[i].id == MEM_SIB) {
+ value[i] *= op[i].scale+1;
+ }
+ #if getclk
+ cpu->clk += inc_clk;
+ #endif
+ }
+ }
+ }
+ return address;
+}
+
-static /*inline*/ uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t carry, uint8_t thread) {
+static /*inline*/ uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t carry, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
uint64_t sum = reg+value+carry;
setflag(sum == 0, Z);
- setflag((sum >> 63), N);
- setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V);
+ setflag(sum >> (msb-1), N);
+ setflag(((reg^value) >> (msb-1)) && ((reg^sum) >> (msb-1)), V);
setflag((sum < value), C);
return sum;
}
@@ -507,22 +605,28 @@ static /*inline*/ uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) {
return value;
}
-static /*inline*/ uint64_t and(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static /*inline*/ uint64_t and(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
reg &= value;
setflag(reg == 0, Z);
- setflag(reg >> 63, N);
+ setflag(reg >> (msb-1), N);
return reg;
}
-static /*inline*/ uint64_t or(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static /*inline*/ uint64_t or(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
reg |= value;
setflag(reg == 0, Z);
- setflag(reg >> 63, N);
+ setflag(reg >> (msb-1), N);
return reg;
}
-static /*inline*/ uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static /*inline*/ uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
reg ^= value;
setflag(reg == 0, Z);
- setflag(reg >> 63, N);
+ setflag(reg >> (msb-1), N);
return reg;
}
@@ -589,19 +693,23 @@ static /*inline*/ uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, ui
return sum;
}
-static /*inline*/ uint64_t mul(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static /*inline*/ uint64_t mul(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
uint64_t sum = reg*value;
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
- setflag(!((reg^value) >> 63) && ((reg^sum) >> 63), V);
+ setflag(sum >> (msb-1), N);
+ setflag(!((reg^value) >> (msb-1)) && ((reg^sum) >> (msb-1)), V);
return sum;
}
-static /*inline*/ uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint64_t *rem, uint8_t thread) {
+static /*inline*/ uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint64_t *rem, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
uint64_t sum = reg/value;
*rem = reg % value;
setflag(sum == 0, Z);
- setflag((sum >> 63), N);
+ setflag(sum >> (msb-1), N);
return sum;
}
@@ -726,6 +834,264 @@ static /*inline*/ void store(struct sux *cpu, uint64_t address, uint64_t reg, ui
write_value(cpu, reg, address, size, 1, 1);
}
+static /*inline*/ uint64_t mov(struct sux *cpu, uint64_t src, uint64_t size, uint8_t thread) {
+ size = (size > 7) ? 7 : size;
+ uint8_t msb = (size+1)*8;
+ uint64_t dst = 0;
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ if (size < 7) {
+ dst = (dst & ~mask) | (src & mask);
+ } else {
+ dst = src;
+ }
+ setflag(dst == 0, Z);
+ setflag(dst >> (msb-1), N);
+ return dst;
+}
+
+static /*inline*/ uint64_t set(struct sux *cpu, uint8_t flag, uint8_t thread) {
+ return flag;
+}
+
+static /*inline*/ uint64_t inc_dec(struct sux *cpu, uint64_t value, uint8_t size, uint8_t inc, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
+ value += (inc) ? 1 : -1;
+ setflag(value == 0, Z);
+ setflag(value >> (msb-1), N);
+ return value;
+}
+
+static /*inline*/ uint64_t imul(struct sux *cpu, uint64_t dst, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
+ int64_t sum = dst*value;
+ setflag(sum == 0, Z);
+ setflag(sum >> (msb-1), N);
+ setflag(!((dst^value) >> (msb-1)) && ((dst^sum) >> (msb-1)), V);
+ return sum;
+}
+
+static /*inline*/ uint64_t idiv(struct sux *cpu, uint64_t dst, uint64_t value, uint64_t *rem, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
+ int64_t sum = dst/value;
+ *rem = dst % value;
+ setflag(sum == 0, Z);
+ setflag(sum >> (msb-1), N);
+ return sum;
+}
+
+static /*inline*/ uint64_t neg(struct sux *cpu, uint64_t value, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
+ value = -value;
+ setflag(value == 0, Z);
+ setflag(value >> (msb-1), N);
+ return value;
+}
+
+static /*inline*/ void exec_ortho_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t size, uint8_t *op_type, uint8_t *op_id, uint8_t thread) {
+ uint64_t dst = 0;
+ uint64_t src = 0;
+ uint64_t rem = 0;
+ uint64_t address[2] = {0, 0};
+ int isdiv = 0;
+ operand op[2];
+ cpu->pc = get_ortho_addr(cpu, prefix, cpu->pc, op, address, op_type, op_id, 1, 1, thread);
+ if (op[1].type) {
+ src = read_value(cpu, 0, op[1].value, size, 1, 1);
+ } else {
+ switch (op[1].id) {
+ case REG_A : src = cpu->a; break;
+ case REG_B : src = cpu->b; break;
+ case REG_X : src = cpu->x; break;
+ case REG_Y : src = cpu->y; break;
+ case REG_E : src = cpu->e; break;
+ case REG_C : src = cpu->c; break;
+ case REG_D : src = cpu->d; break;
+ case REG_S : src = cpu->s; break;
+ case REG_F : src = cpu->f; break;
+ case REG_SP : src = cpu->sp; break;
+ case REG_BP : src = cpu->bp; break;
+ case REG_R11: src = cpu->r11; break;
+ case REG_R12: src = cpu->r12; break;
+ case REG_R13: src = cpu->r13; break;
+ case REG_R14: src = cpu->r14; break;
+ case REG_R15: src = cpu->r15; break;
+ }
+ }
+ if (op[0].type) {
+ dst = read_value(cpu, 0, op[0].value, size, 1, 1);
+ } else {
+ switch (op[0].id) {
+ case REG_A : dst = cpu->a; break;
+ case REG_B : dst = cpu->b; break;
+ case REG_X : dst = cpu->x; break;
+ case REG_Y : dst = cpu->y; break;
+ case REG_E : dst = cpu->e; break;
+ case REG_C : dst = cpu->c; break;
+ case REG_D : dst = cpu->d; break;
+ case REG_S : dst = cpu->s; break;
+ case REG_F : dst = cpu->f; break;
+ case REG_SP : dst = cpu->sp; break;
+ case REG_BP : dst = cpu->bp; break;
+ case REG_R11: dst = cpu->r11; break;
+ case REG_R12: dst = cpu->r12; break;
+ case REG_R13: dst = cpu->r13; break;
+ case REG_R14: dst = cpu->r14; break;
+ case REG_R15: dst = cpu->r15; break;
+ }
+ }
+ 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(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;
+ case ORTHO_2OP(SUB): dst = adc(cpu, dst, ~src, 1, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(AND): dst = and(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(OR ): dst = or(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(XOR): dst = xor(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(LSL): dst = lsl(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(LSR): dst = lsr(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(ROL): dst = rol(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ case ORTHO_2OP(ROR): dst = ror(cpu, dst, src, (op[0].type) ? size+1 : 8, thread); break;
+ 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(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 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;
+ } else {
+ address = src;
+ }
+ mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ dst = (address & mask);
+ } while (0);
+ break;
+ case ORTHO_1OP(PEA):
+ do {
+ uint64_t address = (op[0].type) ? op[0].value : dst;
+ push(cpu, address, 7, thread);
+ } while (0);
+ break;
+ case ORTHO_1OP(INC): dst = inc_dec(cpu, dst, size, 1, thread); break;
+ case ORTHO_1OP(DEC): dst = inc_dec(cpu, dst, size, 0, thread); break;
+ case ORTHO_1OP(PSH): push(cpu, dst, size, thread); 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;
+ case ORTHO_1OP(CLO): dst = lbcnt(cpu, src, 1, size, thread); break;
+ case ORTHO_1OP(SWP): dst = swap(cpu, dst, size, thread); break;
+ case ORTHO_1OP(NEG): dst = neg(cpu, dst, size, thread); break;
+ case ORTHO_1CC(SET, NG): dst = set(cpu, getflag(N), thread); break;
+ case ORTHO_1CC(SET, PO): dst = set(cpu, !getflag(N), thread); break;
+ case ORTHO_1CC(SET, CS): dst = set(cpu, getflag(C), thread); break;
+ case ORTHO_1CC(SET, CC): dst = set(cpu, !getflag(C), thread); break;
+ case ORTHO_1CC(SET, EQ): dst = set(cpu, getflag(Z), thread); break;
+ case ORTHO_1CC(SET, NE): dst = set(cpu, !getflag(Z), thread); break;
+ case ORTHO_1CC(SET, VS): dst = set(cpu, getflag(V), thread); break;
+ case ORTHO_1CC(SET, VC): dst = set(cpu, !getflag(V), thread); break;
+
+ }
+
+ if (op[0].type) {
+ 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 (isdiv) {
+ if (op[1].type) {
+ write_value(cpu, rem, op[1].value, size, 1, 1);
+ } else {
+ switch (op[1].id) {
+ case REG_A : cpu->a = rem; break;
+ case REG_B : cpu->b = rem; break;
+ case REG_X : cpu->x = rem; break;
+ case REG_Y : cpu->y = rem; break;
+ case REG_E : cpu->e = rem; break;
+ case REG_C : cpu->c = rem; break;
+ case REG_D : cpu->d = rem; break;
+ case REG_S : cpu->s = rem; break;
+ case REG_F : cpu->f = rem; break;
+ case REG_SP : cpu->sp = rem; break;
+ case REG_BP : cpu->bp = rem; break;
+ case REG_R11: cpu->r11 = rem; break;
+ case REG_R12: cpu->r12 = rem; break;
+ case REG_R13: cpu->r13 = rem; break;
+ case REG_R14: cpu->r14 = rem; break;
+ case REG_R15: cpu->r15 = rem; break;
+ }
+ }
+ }
+}
+
static /*inline*/ void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint64_t value, uint64_t address, uint8_t size, uint8_t thread) {
uint8_t addr_size = get_addrsize(prefix, ext_optype[opcode]);
uint8_t tmp = 0;
@@ -767,35 +1133,35 @@ static /*inline*/ void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t pr
case ADD_AB : /* ADD Absolute. */
case ADD_Z : /* ADD Zero Matrix. */
case ADD_E : /* ADD E Indirect. */
- cpu->a = adc(cpu, cpu->a, value, 0, thread);
+ cpu->a = adc(cpu, cpu->a, value, 0, 8, thread);
break;
case SUB_IMM: /* SUB Immediate. */
case SUB_AB : /* SUB Absolute. */
case SUB_Z : /* SUB Zero Matrix. */
case SUB_E : /* SUB E Indirect. */
- cpu->a = adc(cpu, cpu->a, ~value, 1, thread);
+ cpu->a = adc(cpu, cpu->a, ~value, 1, 8, thread);
break;
case ADE_IMM: /* ADE Immediate. */
case ADE_AB : /* ADE Absolute. */
case ADE_Z : /* ADE Zero Matrix. */
- cpu->e = adc(cpu, cpu->e, value, 0, thread);
+ cpu->e = adc(cpu, cpu->e, value, 0, 8, thread);
break;
case SBE_IMM: /* SBE Immediate. */
case SBE_AB : /* SBE Absolute. */
case SBE_Z : /* SBE Zero Matrix. */
- cpu->e = adc(cpu, cpu->e, ~value, 1, thread);
+ cpu->e = adc(cpu, cpu->e, ~value, 1, 8, thread);
break;
case ADS_IMM: /* ADS Immediate. */
case ADS_AB : /* ADS Absolute. */
case ADS_Z : /* ADS Zero Matrix. */
case ADS_E : /* ADS E Indirect. */
- cpu->sp = adc(cpu, cpu->sp, value, 0, thread);
+ cpu->sp = adc(cpu, cpu->sp, value, 0, 8, thread);
break;
case SBS_IMM: /* SBS Immediate. */
case SBS_AB : /* SBS Absolute. */
case SBS_Z : /* SBS Zero Matrix. */
case SBS_E : /* SBS E Indirect. */
- cpu->sp = adc(cpu, cpu->sp, ~value, 1, thread);
+ cpu->sp = adc(cpu, cpu->sp, ~value, 1, 8, thread);
break;
case NOT_A : /* NOT Accumulator. */
cpu->a = ~cpu->a;
@@ -844,7 +1210,7 @@ static /*inline*/ void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t pr
case CPE_IMM: /* CPE Immediate. */
case CPE_AB : /* CPE Absolute. */
case CPE_Z : /* CPE Zero Matrix. */
- adc(cpu, cpu->e, ~value, 1, thread);
+ adc(cpu, cpu->e, ~value, 1, 8, thread);
break;
case ICE_AB : /* ICE Absolute. */
case ICE_Z : /* ICE Zero Matrix. */
@@ -1014,7 +1380,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case ADC_IMM: /* ADC Immediate. */
case ADC_AB: /* ADC Absolute. */
case ADC_Z: /* ADC Zero Matrix. */
- cpu->a = adc(cpu, cpu->a, value, getflag(C), thread);
+ cpu->a = adc(cpu, cpu->a, value, 8, getflag(C), thread);
break;
case PHP_IMP: push(cpu, cpu->ps.u8[thread], 0, thread); break; /* PusH Processor status to stack. */
case PHA_IMP: push(cpu, cpu->a , size, thread); break; /* PusH Accumulator to stack. */
@@ -1042,7 +1408,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case SBC_IMM: /* SBC Immediate. */
case SBC_AB: /* SBC Absolute. */
case SBC_Z: /* SBC Zero Matrix. */
- cpu->a = adc(cpu, cpu->a, ~value, getflag(C), thread);
+ cpu->a = adc(cpu, cpu->a, ~value, 8, getflag(C), thread);
break;
case PLP_IMP: cpu->ps.u8[thread] = pull(cpu, 0, thread); break; /* PuLl Processor status from stack. */
case PLA_IMP: cpu->a = pull(cpu, size, thread); break; /* PuLl Accumulator from stack. */
@@ -1055,7 +1421,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case AND_IMM: /* AND Immediate. */
case AND_AB: /* AND Absolute. */
case AND_Z: /* AND Zero Matrix. */
- cpu->a = and(cpu, cpu->a, value, thread);
+ cpu->a = and(cpu, cpu->a, value, 8, thread);
break;
case BPO_REL: /* BPO Relative. */
if (!getflag(N)) {
@@ -1067,7 +1433,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case ORA_IMM: /* ORA Immediate. */
case ORA_AB: /* ORA Absolute. */
case ORA_Z: /* ORA Zero Matrix. */
- cpu->a = or(cpu, cpu->a, value, thread);
+ cpu->a = or(cpu, cpu->a, value, 8, thread);
break;
case SEI_IMP: /* SEt Interrupt. */
setflag(1, I);
@@ -1082,7 +1448,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case XOR_IMM: /* XOR Immediate. */
case XOR_AB: /* XOR Absolute. */
case XOR_Z: /* XOR Zero Matrix. */
- cpu->a = xor(cpu, cpu->a, value, thread);
+ cpu->a = xor(cpu, cpu->a, value, 8, thread);
break;
case CLI_IMP: /* CLear Interrupt. */
setflag(0, I);
@@ -1218,7 +1584,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case MUL_IMM: /* MUL Immediate. */
case MUL_AB: /* MUL Absolute. */
case MUL_Z: /* MUL Zero Matrix. */
- cpu->a = mul(cpu, cpu->a, value, thread);
+ cpu->a = mul(cpu, cpu->a, value, 8, thread);
break;
case BVC_REL: /* BVC Relative. */
if (!getflag(V)) {
@@ -1230,7 +1596,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case DIV_AB: /* DIV Absolute. */
case DIV_Z: /* DIV Zero Matrix. */
rem = (opcode != DIV_B) ? &cpu->b : &cpu->x;
- cpu->a = divd(cpu, cpu->a, value, rem, thread);
+ cpu->a = divd(cpu, cpu->a, value, rem, 8, thread);
break;
case CLV_IMP: /* CLear oVerflow flag. */
setflag(0, V);
@@ -1241,7 +1607,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case CPB_IN: /* CPB Indirect. */
case CPB_IX: /* CPB Indexed Indirect. */
case CPB_IY: /* CPB Indirect Indexed. */
- adc(cpu, cpu->b, ~value, 1, thread);
+ adc(cpu, cpu->b, ~value, 1, 8, thread);
break;
case CMP_B: /* CMP B register. */
value = cpu->b; /* Falls Through. */
@@ -1251,17 +1617,17 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
case CMP_IN: /* CMP Indirect. */
case CMP_IX: /* CMP Indexed Indirect. */
case CMP_IY: /* CMP Indirect Indexed. */
- adc(cpu, cpu->a, ~value, 1, thread);
+ adc(cpu, cpu->a, ~value, 1, 8, thread);
break;
case CPY_IMM: /* CPY Immediate. */
case CPY_AB: /* CPY Absolute. */
case CPY_Z: /* CPY Zero Matrix. */
- adc(cpu, cpu->y, ~value, 1, thread);
+ adc(cpu, cpu->y, ~value, 1, 8, thread);
break;
case CPX_IMM: /* CPX Immediate. */
case CPX_AB: /* CPX Absolute. */
case CPX_Z: /* CPX Zero Matrix. */
- adc(cpu, cpu->x, ~value, 1, thread);
+ adc(cpu, cpu->x, ~value, 1, 8, thread);
break;
case INC_IMP: cpu->a = idr(cpu, cpu->a, 1, thread); break;
case INB_IMP: cpu->b = idr(cpu, cpu->b, 1, thread); break;
@@ -1315,3 +1681,7 @@ static /*inline*/ void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t p
break;
}
}
+
+#undef ORTHO_1CC
+#undef ORTHO_1OP
+#undef ORTHO_2OP
diff --git a/test/ortho.s b/test/ortho.s
new file mode 100644
index 0000000..bc70d3d
--- /dev/null
+++ b/test/ortho.s
@@ -0,0 +1,35 @@
+.org 0
+count:
+ .res 8
+.org $40000
+mem:
+ .res 256
+
+.org $8000
+reset:
+ cps
+ lds.d #$3FFFF
+ and #0
+ tay
+ xor b, b
+ xor.q count, count
+; cmp.q (count), y
+ cmp.qo (count), y
+ lea.o (count), y
+ lea mem
+loop:
+ inc b
+ inc.q count
+; mov.q e, count
+ mov (b+e), b
+ mov a, (b+e)
+ bra loop
+
+.org $FFC0
+.qword reset
+
+a
+;.org reset
+;v
+;q
+d
diff --git a/test/struct.s b/test/struct.s
index 33de1f1..f8dd71c 100644
--- a/test/struct.s
+++ b/test/struct.s
@@ -57,6 +57,12 @@
ass .word
.endstruct
+.struct token
+ next .byte
+ val .byte
+ id .byte
+
+.endstruct
.org 0
@@ -68,6 +74,7 @@ lda #lol.oof
ldb #lol.asd.aa.lol
ldx #lol.asd.aa.why
ldy #lol.why
+
a
;l a
;v