summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-11-20 15:10:24 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2020-11-20 15:10:24 -0500
commit83ce1151ee1f06ae6b1c5c1018cc2489494e5ea4 (patch)
treeba4edade46c57ec5119d01ab8a7ad9f7943c6804
parentdc7ebb9d424bb39d59f09b8498746beb871c46f4 (diff)
- Implemented support for Sux's base extension.
This is the biggest milestone I've reached for this project, since the base extension changes alot about what Sux can do by default, and now makes it a viable instruction set for modern day use, when compared with other instruction sets.
-rw-r--r--asmmon.c23
-rw-r--r--asmmon.h274
-rw-r--r--assemble.c261
-rw-r--r--disasm.c96
-rw-r--r--disasm.h168
-rw-r--r--enums.h370
-rw-r--r--lexer.c36
-rw-r--r--lexer.h38
-rw-r--r--opcode.h3
-rw-r--r--programs/sub-suite/print_char.s147
-rw-r--r--programs/sub-suite/subeditor-new.s1119
-rw-r--r--sux.c405
-rw-r--r--sux.h804
-rw-r--r--tables.h168
-rw-r--r--test/base-ext.s19
15 files changed, 3177 insertions, 754 deletions
diff --git a/asmmon.c b/asmmon.c
index 6796ebb..0890076 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -149,6 +149,7 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
uint8_t am_done = 1;
uint8_t op_done = 1;
uint16_t bline = s->bline;
+ const char *inst_name;
for (; bline; bline--) {
putchar('\n');
}
@@ -169,7 +170,6 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
case INDY: putchar('('); am_done = 0; break;
case ZMY :
case ZMX : am_done = 0; break;
- case BREG: putchar('b'); am_done = 1; break;
}
am = (am_done) ? 0xFF : am;
}
@@ -188,9 +188,14 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
switch (t->id) {
case TOK_DIR : printf(".%s", dir_t[t->type]); break;
case TOK_RS : printf("%s", rs_t[t->type]); break;
+ case TOK_EXTOP :
case TOK_OPCODE:
+ switch (t->id) {
+ case TOK_EXTOP : inst_name = ext_mne[t->byte]; break;
+ case TOK_OPCODE: inst_name = /**/mne[t->byte]; break;
+ }
for (; j < 3; j++) {
- mne_lower[j] = tolower(mne[t->byte][j]);
+ mne_lower[j] = tolower(inst_name[j]);
}
mne_lower[j] = '\0';
j = 0;
@@ -300,6 +305,12 @@ 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) {
+ switch (am) {
+ case EIND: putchar('('); am_done = 0; break;
+ case BREG: putchar('b'); am_done = 1; break;
+ }
+ }
if (am != 0xFF && !am_done && op_done) {
switch (am) {
case INDX:
@@ -309,12 +320,18 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
break;
}
/* Falls Through. */
+ case EIND:
+ if (am == EIND) {
+ putchar('e');
+ }
+ /* Falls Through. */
case INDY:
case IND :
putchar(')');
- if (am == IND) {
+ if (am == IND || am == EIND) {
break;
}
+ /* Falls Through. */
case ZMY : printf(", y"); break;
}
am = 0xFF;
diff --git a/asmmon.h b/asmmon.h
index a031e7d..6f4e5f5 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -68,7 +68,7 @@ struct sym {
};
struct inst {
- uint16_t am; /* Addressing modes. */
+ uint32_t am; /* Addressing modes. */
uint8_t op; /* Base value used to get the actual opcode. */
};
@@ -117,6 +117,7 @@ enum token {
TOK_IMM,
TOK_BREG,
TOK_OPCODE,
+ TOK_EXTOP,
TOK_RS,
TOK_OF,
TOK_COMMENT,
@@ -144,6 +145,7 @@ enum pre_token {
PTOK_RBRACK,
PTOK_COMMA,
PTOK_B,
+ PTOK_E,
PTOK_X,
PTOK_Y,
PTOK_S,
@@ -183,7 +185,14 @@ enum addrmode {
AM_BREG = (1 << 9),
AM_IMPL = (1 << 10),
AM_INDX2 = (1 << 11),
- AM_ZM2 = (1 << 12)
+ AM_ZM2 = (1 << 12),
+ AM_EIND = (1 << 13),
+ AM_EIND2 = (1 << 14),
+ AM_ABY = (1 << 15),
+ AM_ABX = (1 << 16),
+ AM_AIND = (1 << 17),
+ AM_AINDY = (1 << 18),
+ AM_AINDX = (1 << 19),
};
enum ind {
@@ -209,33 +218,59 @@ enum ind {
STY_IND = 19
};
+enum eind {
+ DEC_EIND,
+ INC_EIND,
+ STY_EIND,
+ STA_EIND,
+ STB_EIND,
+ LDX_EIND,
+ STX_EIND,
+ CPB_EIND,
+ CPX_EIND,
+ CPY_EIND
+};
+
static const uint8_t ind_ops[20] = {
- [CMP_IND] = 0x8C,
- [CMP_IDY] = 0xF9,
- [CMP_IDX] = 0xAA,
- [CPB_IND] = 0x7C,
- [CPB_IDY] = 0xFA,
- [CPB_IDX] = 0xBA,
- [JMP_IND] = 0xEC,
- [JSR_IND] = 0xDC,
- [LDA_IND] = 0xC4,
- [LDA_IDY] = 0xD9,
- [LDB_IND] = 0xE4,
- [LDB_IDY] = 0xE9,
- [LDX_IND] = 0xBC,
- [LDY_IND] = 0xAC,
- [STA_IND] = 0xD4,
- [STA_IDY] = 0xCA,
- [STB_IND] = 0xF4,
- [STB_IDY] = 0xDA,
- [STX_IND] = 0xCC,
- [STY_IND] = 0x9C
+ [CMP_IND] = CMP_IN,
+ [CMP_IDY] = CMP_IY,
+ [CMP_IDX] = CMP_IX,
+ [CPB_IND] = CPB_IN,
+ [CPB_IDY] = CPB_IY,
+ [CPB_IDX] = CPB_IX,
+ [JMP_IND] = JMP_IN,
+ [JSR_IND] = JSR_IN,
+ [LDA_IND] = LDA_IN,
+ [LDA_IDY] = LDA_IY,
+ [LDB_IND] = LDB_IN,
+ [LDB_IDY] = LDB_IY,
+ [LDX_IND] = LDX_IN,
+ [LDY_IND] = LDY_IN,
+ [STA_IND] = STA_IN,
+ [STA_IDY] = STA_IY,
+ [STB_IND] = STB_IN,
+ [STB_IDY] = STB_IY,
+ [STX_IND] = STX_IN,
+ [STY_IND] = STY_IN
+};
+
+static const uint8_t eind_base_ops[10] = {
+ [DEC_EIND] = DEC_E,
+ [INC_EIND] = INC_E,
+ [STY_EIND] = STY_E,
+ [STA_EIND] = STA_E,
+ [STB_EIND] = STB_E,
+ [LDX_EIND] = LDX_E,
+ [STX_EIND] = STX_E,
+ [CPB_EIND] = CPB_E,
+ [CPX_EIND] = CPX_E,
+ [CPY_EIND] = CPY_E
};
static const instruction inst[OPNUM] = {
- [ADC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x01},
- [AND] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x41},
- [ASR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x62},
+ [ADC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x01},
+ [AND] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x41},
+ [ASR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x62},
[BCC] = {(AM_REL), 0xA0},
[BCS] = {(AM_REL), 0x90},
[BEQ] = {(AM_REL), 0xB0},
@@ -249,31 +284,31 @@ static const instruction inst[OPNUM] = {
[CLC] = {(AM_IMPL), 0x09},
[CLI] = {(AM_IMPL), 0x29},
[CLV] = {(AM_IMPL), 0x49},
- [CMP] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_BREG|AM_INDX2), 0x82},
- [CPB] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_INDX2), 0x04},
+ [CMP] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_BREG|AM_INDX2|AM_EIND), 0x82},
+ [CPB] = {(AM_IMM|AM_ZM|AM_IND|AM_INDY|AM_ABS|AM_INDX2|AM_EIND2), 0x04},
[CPS] = {(AM_IMPL), 0x00},
- [CPX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS), 0x24},
- [CPY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS), 0x44},
+ [CPX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x24},
+ [CPY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x44},
[DEB] = {(AM_IMPL), 0x99},
- [DEC] = {(AM_IMPL|AM_ZM|AM_ABS), 0x84},
+ [DEC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2), 0x84},
[DEX] = {(AM_IMPL), 0xB9},
[DEY] = {(AM_IMPL), 0x79},
- [DIV] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x42},
+ [DIV] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x42},
[INB] = {(AM_IMPL), 0xA9},
- [INC] = {(AM_IMPL|AM_ZM|AM_ABS), 0xA4},
+ [INC] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND2), 0xA4},
[INX] = {(AM_IMPL), 0xC9},
[INY] = {(AM_IMPL), 0x89},
- [JMP] = {(AM_ABS|AM_IND|AM_ZM2), 0x00},
- [JSR] = {(AM_ABS|AM_IND|AM_ZM2), 0x20},
- [LDA] = {(AM_IMM|AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS), 0xC2},
- [LDB] = {(AM_IMM|AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS), 0xE2},
- [LDX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS), 0x64},
- [LDY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS), 0xA2},
- [LSL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0xA1},
- [LSR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0xC1},
- [MUL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x22},
+ [JMP] = {(AM_ABS|AM_IND|AM_ZM2|AM_EIND), 0x00},
+ [JSR] = {(AM_ABS|AM_IND|AM_ZM2|AM_EIND), 0x20},
+ [LDA] = {(AM_IMM|AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND), 0xC2},
+ [LDB] = {(AM_IMM|AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND), 0xE2},
+ [LDX] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x64},
+ [LDY] = {(AM_IMM|AM_ZM|AM_IND|AM_ABS|AM_EIND), 0xA2},
+ [LSL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xA1},
+ [LSR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xC1},
+ [MUL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x22},
[NOP] = {(AM_IMPL), 0xEA},
- [ORA] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x61},
+ [ORA] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x61},
[PHA] = {(AM_IMPL), 0x8E},
[PHB] = {(AM_IMPL), 0xAE},
[PHP] = {(AM_IMPL), 0x6E},
@@ -284,29 +319,81 @@ static const instruction inst[OPNUM] = {
[PLP] = {(AM_IMPL), 0x7E},
[PLX] = {(AM_IMPL), 0xFE},
[PLY] = {(AM_IMPL), 0xDE},
- [ROL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0xE1},
- [ROR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x02},
+ [ROL] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0xE1},
+ [ROR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x02},
[RTI] = {(AM_IMPL), 0x60},
[RTS] = {(AM_IMPL), 0x50},
- [SBC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x21},
+ [SBC] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x21},
[SEC] = {(AM_IMPL), 0x19},
[SEI] = {(AM_IMPL), 0x39},
- [STA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS), 0x28},
- [STB] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS), 0x48},
- [STX] = {(AM_ZM|AM_IND|AM_ABS), 0x68},
- [STY] = {(AM_ZM|AM_IND|AM_ABS), 0x08},
+ [STA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND2), 0x28},
+ [STB] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_EIND2), 0x48},
+ [STX] = {(AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x68},
+ [STY] = {(AM_ZM|AM_IND|AM_ABS|AM_EIND2), 0x08},
[TAB] = {(AM_IMPL), 0x0A},
[TAX] = {(AM_IMPL), 0x4A},
[TAY] = {(AM_IMPL), 0x2A},
[TBA] = {(AM_IMPL), 0x1A},
[TSX] = {(AM_IMPL), 0x8A},
[TXA] = {(AM_IMPL), 0x5A},
- [TXS] = {(AM_IMPL|AM_IMM), 0x9A},
+ [TXS] = {(AM_IMPL), 0x9A},
[TXY] = {(AM_IMPL), 0x7A},
[TYA] = {(AM_IMPL), 0x3A},
[TYX] = {(AM_IMPL), 0x6A},
[WAI] = {(AM_IMPL), 0x59},
- [XOR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x81}
+ [XOR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG|AM_EIND), 0x81}
+};
+
+static const instruction ext_inst[EXT_OPNUM] = {
+ [LEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY), 0x03},
+ [PEA] = {(AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_ABX|AM_ABY|AM_AIND|AM_AINDX|AM_AINDY), 0x23},
+ [ADD] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x06},
+ [SUB] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x26},
+ [ADE] = {(AM_IMM|AM_ZM|AM_ABS), 0x46},
+ [SBE] = {(AM_IMM|AM_ZM|AM_ABS), 0x66},
+ [ADS] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x86},
+ [SBS] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0xA6},
+ [NOT] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND), 0xC6},
+ [LLM] = {(AM_ZM|AM_ABS|AM_EIND), 0x48},
+ [LRM] = {(AM_ZM|AM_ABS|AM_EIND), 0x68},
+ [RLM] = {(AM_ZM|AM_ABS|AM_EIND), 0x88},
+ [RRM] = {(AM_ZM|AM_ABS|AM_EIND), 0xA8},
+ [ARM] = {(AM_ZM|AM_ABS|AM_EIND), 0xC8},
+ [PHE] = {(AM_IMPL), 0x6B},
+ [PLE] = {(AM_IMPL), 0x7B},
+ [CPE] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x08},
+ [ICE] = {(AM_ZM|AM_ABS|AM_EIND), 0x28},
+ [LDS] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x40},
+ [DEE] = {(AM_IMPL), 0x8B},
+ [INE] = {(AM_IMPL), 0x9B},
+ [DES] = {(AM_IMPL), 0xAB},
+ [INS] = {(AM_IMPL), 0xBB},
+ [STS] = {(AM_ZM|AM_ABS|AM_EIND), 0xA0},
+ [STE] = {(AM_ZM|AM_ABS), 0xC0},
+ [STZ] = {(AM_ZM|AM_ABS|AM_EIND), 0xE0},
+ [SCO] = {(AM_IMM|AM_ZM|AM_ABS|AM_EIND), 0x60},
+ [ECO] = {(AM_ZM|AM_ABS|AM_EIND), 0x80},
+ [CLZ] = {(AM_ZM|AM_ABS|AM_EIND), 0x05},
+ [CLO] = {(AM_ZM|AM_ABS|AM_EIND), 0x25},
+ [BIT] = {(AM_ZM|AM_ABS|AM_EIND), 0x45},
+ [MMV] = {(AM_IMPL), 0xCB},
+ [SWP] = {(AM_IMPL|AM_ZM|AM_ABS|AM_EIND), 0xE6},
+ [PCN] = {(AM_ZM|AM_ABS|AM_EIND), 0xE8},
+ [REP] = {(AM_REL), 0xBD},
+ [REQ] = {(AM_REL), 0xCD},
+ [RNE] = {(AM_REL), 0xDD},
+ [LNG] = {(AM_IMM|AM_EIND2), 0x0D},
+ [LPO] = {(AM_IMM|AM_EIND2), 0x2D},
+ [LCS] = {(AM_IMM|AM_EIND2), 0x4D},
+ [LCC] = {(AM_IMM|AM_EIND2), 0x6D},
+ [LEQ] = {(AM_IMM|AM_EIND2), 0x8D},
+ [LNE] = {(AM_IMM|AM_EIND2), 0xAD},
+ [SNG] = {(AM_EIND2), 0x1D},
+ [SPO] = {(AM_EIND2), 0x3D},
+ [SCS] = {(AM_EIND2), 0x5D},
+ [SCC] = {(AM_EIND2), 0x7D},
+ [SEQ] = {(AM_EIND2), 0x9D},
+ [SNE] = {(AM_EIND2), 0xBD}
};
static const char *dir_t[11] = {
@@ -330,7 +417,7 @@ static const char *rs_t[4] = {
[3] = ".q"
};
-static const char *lex_tok[22] = {
+static const char *lex_tok[23] = {
[TOK_DIR ] = "TOK_DIR",
[TOK_LOCAL ] = "TOK_LOCAL",
[TOK_LABEL ] = "TOK_LABEL",
@@ -343,6 +430,7 @@ static const char *lex_tok[22] = {
[TOK_IMM ] = "TOK_IMM",
[TOK_BREG ] = "TOK_BREG",
[TOK_OPCODE ] = "TOK_OPCODE",
+ [TOK_EXTOP ] = "TOK_EXTOP",
[TOK_RS ] = "TOK_RS",
[TOK_OF ] = "TOK_OF",
[TOK_COMMENT] = "TOK_COMMENT",
@@ -355,18 +443,24 @@ static const char *lex_tok[22] = {
[TOK_MEMBER ] = "TOK_MEMBER"
};
-static const char *adrmode[11] = {
- [IMM ] = "IMM",
- [ZM ] = "ZM",
- [ZMX ] = "ZMX",
- [ZMY ] = "ZMY",
- [IND ] = "IND",
- [INDX] = "INDX",
- [INDY] = "INDY",
- [ABS ] = "ABS",
- [REL ] = "REL",
- [BREG] = "BREG",
- [IMPL] = "IMPL"
+static const char *adrmode[] = {
+ [IMM ] = "IMM",
+ [ZM ] = "ZM",
+ [ZMX ] = "ZMX",
+ [ZMY ] = "ZMY",
+ [IND ] = "IND",
+ [INDX ] = "INDX",
+ [INDY ] = "INDY",
+ [ABS ] = "ABS",
+ [REL ] = "REL",
+ [BREG ] = "BREG",
+ [IMPL ] = "IMPL",
+ [ABSX ] = "ABSX",
+ [ABSY ] = "ABSY",
+ [AIND ] = "AIND",
+ [AINDX] = "AINDX",
+ [AINDY] = "AINDY",
+ [EIND ] = "EIND"
};
static const char *mne[OPNUM] = {
@@ -446,6 +540,58 @@ static const char *mne[OPNUM] = {
[XOR] = "XOR"
};
+static const char *ext_mne[EXT_OPNUM] = {
+ [LEA] = "LEA",
+ [PEA] = "PEA",
+ [ADD] = "ADD",
+ [SUB] = "SUB",
+ [ADE] = "ADE",
+ [SBE] = "SBE",
+ [ADS] = "ADS",
+ [SBS] = "SBS",
+ [NOT] = "NOT",
+ [LLM] = "LLM",
+ [LRM] = "LRM",
+ [RLM] = "RLM",
+ [RRM] = "RRM",
+ [ARM] = "ARM",
+ [PHE] = "PHE",
+ [PLE] = "PLE",
+ [CPE] = "CPE",
+ [ICE] = "ICE",
+ [LDS] = "LDS",
+ [DEE] = "DEE",
+ [INE] = "INE",
+ [DES] = "DES",
+ [INS] = "INS",
+ [STS] = "STS",
+ [STE] = "STE",
+ [STZ] = "STZ",
+ [SCO] = "SCO",
+ [ECO] = "ECO",
+ [CLZ] = "CLZ",
+ [CLO] = "CLO",
+ [BIT] = "BIT",
+ [MMV] = "MMV",
+ [SWP] = "SWP",
+ [PCN] = "PCN",
+ [REP] = "REP",
+ [REQ] = "REQ",
+ [RNE] = "RNE",
+ [LNG] = "LNG",
+ [LPO] = "LPO",
+ [LCS] = "LCS",
+ [LCC] = "LCC",
+ [LEQ] = "LEQ",
+ [LNE] = "LNE",
+ [SNG] = "SNG",
+ [SPO] = "SPO",
+ [SCS] = "SCS",
+ [SCC] = "SCC",
+ [SEQ] = "SEQ",
+ [SNE] = "SNE"
+};
+
static const char *instdesc[OPNUM] = {
[ADC] = "ADd accumulator, with operand, Carry if needed.",
[AND] = "Bitwise AND accumulator, with operand.",
diff --git a/assemble.c b/assemble.c
index 8d7eb85..297be87 100644
--- a/assemble.c
+++ b/assemble.c
@@ -1,5 +1,13 @@
#include "asmmon.h"
+#define AM_ADDR (AM_ZM | AM_ZMX | AM_ZMY | \
+ AM_IND | AM_INDX | AM_INDY | \
+ AM_ABS | AM_ABX | AM_ABY | \
+ AM_AIND | AM_AINDX | AM_AINDY | \
+ AM_INDX2 | AM_ZM2)
+
+static const uint64_t mem_size = 0x04000000; /* Size of address space. */
+
token *tok_global;
uint8_t isexpr(uint8_t type, uint8_t dbg) {
@@ -58,6 +66,38 @@ uint8_t get_ind(uint8_t mne, uint8_t am, uint8_t dbg) {
return base_idx + offset;
}
+uint8_t get_eind(uint8_t mne, uint8_t dbg) {
+ switch (mne) {
+ case DEC: return DEC_EIND;
+ case INC: return INC_EIND;
+ case STY: return STY_EIND;
+ case STA: return STA_EIND;
+ case STB: return STB_EIND;
+ case LDX: return LDX_EIND;
+ case STX: return STX_EIND;
+ case CPB: return CPB_EIND;
+ case CPX: return CPX_EIND;
+ case CPY: return CPY_EIND;
+ }
+ return 0xFF;
+}
+
+static void write_value(uint64_t value, uint64_t address, uint8_t size) {
+ if (address < mem_size) {
+ size = (size > 7) ? 7 : size;
+ #if 1
+ if (size < 7) {
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ *(uint64_t *)(addr+address) = (*(uint64_t *)(addr+address) & ~mask) | (value & mask);
+ } else {
+ *(uint64_t *)(addr+address) = value;
+ }
+ #else
+ memcpy(addr+address, &value, size+1);
+ #endif
+ }
+}
+
uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
uint64_t value = 0;
uint64_t tmp_val = 0;
@@ -232,34 +272,14 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre
case TOK_LABEL:
val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg);
switch (type) {
- case DIR_QWORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+7] = val.u8[7];
- addr[tmpaddr+6] = val.u8[6];
- addr[tmpaddr+5] = val.u8[5];
- addr[tmpaddr+4] = val.u8[4];
- }
- tmp += 4;
- case DIR_DWORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+3] = val.u8[3];
- addr[tmpaddr+2] = val.u8[2];
- }
- tmp += 2;
- case DIR_WORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+1] = val.u8[1];
- }
- tmp++;
- case DIR_BYTE:
- if (isasm) {
- addr[tmpaddr ] = val.u8[0];
- }
- tmp++;
- tmpaddr += tmp;
- bc->datasize += tmp;
- break;
+ case DIR_QWORD: tmp = 8; break;
+ case DIR_DWORD: tmp = 4; break;
+ case DIR_WORD : tmp = 2; break;
+ case DIR_BYTE : tmp = 1; break;
}
+ write_value(val.u64, tmpaddr, tmp-1);
+ tmpaddr += tmp;
+ bc->datasize += tmp;
if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) {
t = skip_expr(t, dbg);
}
@@ -303,21 +323,47 @@ 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) {
+ uint8_t inst_size = 0;
+ union reg ins;
+ if (prefix & 3) {
+ ins.u8[inst_size++] = prefix;
+ }
+ if ((ext_prefix & 0x0D) == 0x0D) {
+ ins.u8[inst_size++] = ext_prefix;
+ }
+ ins.u8[inst_size++] = opcode;
+ if (isasm) {
+ write_value(ins.u64, address, inst_size-1);
+ if (size) {
+ write_value(value, address+inst_size, size-1);
+ }
+ }
+ inst_size += size;
+ return inst_size;
+}
+
uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
union reg val;
uint8_t opsize;
+ uint8_t id;
uint8_t instr;
uint8_t opcode;
+ uint8_t ext_prefix = 0;
uint8_t type;
- uint16_t am = 0;
+ uint32_t am = 0;
uint8_t tmp = 0;
uint8_t prefix = 0;
uint8_t rs = 0;
uint8_t of = 0;
uint8_t tmp_prefix = 0;
+ uint8_t inst_size = 0;
+ val.u64 = 0;
+ instruction ins;
for (; t; t = t->next) {
- if (t->id == TOK_OPCODE) {
+ if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) {
+ id = t->id;
instr = t->byte;
type = t->type;
} else {
@@ -340,51 +386,47 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
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));
- am = inst[instr].am;
+ uint8_t isimplied = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF);
+ ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr];
+ am = ins.am;
+ if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) {
+ ext_prefix = 0x0D;
+ }
if ((am & AM_IMPL) && isimplied) {
type = IMPL;
} else {
- if (inst[instr].am & AM_REL) {
+ if (ins.am & AM_REL) {
type = REL;
}
if (t->next) {
t = t->next;
}
- val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
- }
- /* Special case for TXS. */
- if (instr == TXS) {
- if (type == IMM) {
- rs = 1;
- } else {
- type = IMPL;
+ if (type != BREG && type != EIND) {
+ val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
}
}
- opcode = inst[instr].op;
+ opcode = ins.op;
uint64_t saveaddr = address;
uint64_t max_val = 0;
uint8_t i = 0;
uint8_t j = 1;
+ uint8_t type2 = 0xFF;
switch (type) {
case BREG:
case IMPL:
- if (instr == CPS) {
+ case EIND:
+ if (id == TOK_OPCODE && instr == CPS) {
rs = 0;
}
- if ((am & (AM_IMPL|AM_BREG))) {
- if ((am & AM_IMPL) && (prefix)) {
- if (isasm) {
- addr[address] = prefix;
+ 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;
}
- address++;
- bc->progsize++;
}
- if (isasm) {
- addr[address] = (am & AM_BREG) ? opcode+0x14 : opcode;
- }
- address++;
- bc->progsize++;
+ opcode = (am & AM_BREG) ? opcode+0x14 : opcode;
}
break;
case REL:
@@ -417,21 +459,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
val.u64 = tmp_val;
}
- if (prefix) {
- if (isasm) {
- addr[address] = prefix;
- }
- address++;
- bc->progsize++;
- }
- if (isasm) {
- addr[address] = opcode;
- }
- address++;
- bc->progsize++;
- if (isasm) {
- setreg(addr, +, address, val.u8, +, 0, tmp-1);
- }
}
break;
default:
@@ -453,14 +480,32 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
}
}
- if (type == 0xFF) {
+ type2 = type;
+ if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) {
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 (type2) {
+ case ZMX : type = (type == ABS) ? ABSX : type2; break;
+ case ZMY : type = (type == ABS) ? ABSY : type2; break;
+ case IND : type = (type == ABS) ? AIND : type2; break;
+ case INDX: type = (type == ABS) ? AINDX : type2; break;
+ case INDY: type = (type == ABS) ? AINDY : type2; break;
+ }
if (opsize) {
- if (type != ABS) {
+ uint8_t is_abs = 0;
+ switch (type) {
+ case ABS :
+ case ABSX :
+ case ABSY :
+ case AIND :
+ case AINDX:
+ case AINDY: is_abs = 1; break;
+
+ }
+ if (!is_abs || (type2 != 0xFF && type == type2)) {
switch (opsize) {
case 2: opsize = 3; break;
case 5: opsize = 6; break;
@@ -468,7 +513,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
prefix |= amp[opsize-1];
}
- if (am & (AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_INDX2|AM_ZM2)) {
+ if (am & AM_ADDR) {
switch (type) {
case ZM:
if (am & AM_ZM) {
@@ -479,7 +524,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
break;
case ZMX:
if (am & AM_ZMX) {
- opcode += 0x06;
+ opcode += (id == TOK_OPCODE) ? 0x06 : 0x54;
}
break;
case ZMY:
@@ -487,54 +532,59 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
opcode += 0x14;
}
break;
- case ABS:
- if (am & AM_ABS) {
- opcode += 0x10;
- }
- break;
case INDX:
if (am & AM_INDX) {
- opcode += 0x16;
+ opcode += (id == TOK_OPCODE) ? 0x16 : 0x94;
break;
}
/* Falls Through. */
case IND:
case INDY:
- if (am & (AM_IND|AM_INDY|AM_INDX2)) {
+ if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) {
opcode = ind_ops[get_ind(instr, type, dbg)];
+ } else {
+ opcode += (type == IND) ? 0x44 : 0x84;
}
break;
- }
- if (prefix) {
- if (isasm) {
- addr[address] = prefix;
- }
- address++;
- bc->progsize++;
- }
- if (isasm) {
- addr[address] = opcode;
- }
- address++;
- bc->progsize++;
- if (isasm) {
- switch (opsize-1) {
- case 7: addr[address+7] = val.u8[7];
- case 6: addr[address+6] = val.u8[6];
- case 5: addr[address+5] = val.u8[5];
- case 4: addr[address+4] = val.u8[4];
- case 3: addr[address+3] = val.u8[3];
- case 2: addr[address+2] = val.u8[2];
- case 1: addr[address+1] = val.u8[1];
- case 0: addr[address ] = val.u8[0];
- }
+ case ABS:
+ if (am & AM_ABS) {
+ opcode += 0x10;
+ }
+ break;
+ case ABSX:
+ if (am & AM_ABX) {
+ opcode += 0x50;
+ }
+ break;
+ case ABSY:
+ if (am & AM_ABY) {
+ opcode += 0x00;
+ }
+ break;
+ case AIND:
+ if (am & AM_AIND) {
+ opcode += 0x40;
+ }
+ break;
+ case AINDX:
+ if (am & AM_AINDX) {
+ opcode += 0x90;
+ }
+ break;
+ case AINDY:
+ if (am & AM_AINDY) {
+ opcode += 0x80;
+ }
+ break;
+
}
tmp = opsize;
}
break;
}
- address += tmp;
- bc->progsize += tmp;
+ inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg);
+ address += inst_size;
+ bc->progsize += inst_size;
}
return address;
}
@@ -554,6 +604,7 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t
case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break;
}
break;
+ case TOK_EXTOP :
case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;
case TOK_COMMENT: break;
}
diff --git a/disasm.c b/disasm.c
index ff326d4..8c16db6 100644
--- a/disasm.c
+++ b/disasm.c
@@ -10,10 +10,11 @@ void print_regs(struct sux *cpu, uint8_t lines, uint8_t thread) {
wmove(scr, lines, 1);
wclrtoeol(scr);
wprintw(scr, "pc: $%04"PRIX64 , cpu->pc);
- wprintw(scr, ", a: $%016"PRIX64, cpu->a);
- wprintw(scr, ", b: $%016"PRIX64, cpu->b);
- wprintw(scr, ", x: $%016"PRIX64, cpu->x);
- wprintw(scr, ", y: $%016"PRIX64, cpu->y);
+ wprintw(scr, ", a: $%08"PRIX64, cpu->a);
+ wprintw(scr, ", b: $%08"PRIX64, cpu->b);
+ wprintw(scr, ", x: $%08"PRIX64, cpu->x);
+ wprintw(scr, ", y: $%08"PRIX64, cpu->y);
+ wprintw(scr, ", e: $%08"PRIX64, cpu->e);
wprintw(scr, ", sp: $%"PRIX64, cpu->sp);
wprintw(scr, ", ps: %c%c---%c%c%c", cpu->ps.u8[thread] & N ? 'N' : '-'
, cpu->ps.u8[thread] & V ? 'V' : '-'
@@ -23,9 +24,9 @@ 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 thread) {
+void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t prefix2, uint8_t thread) {
uint64_t value;
- uint64_t address = get_addr(cpu, opcode, prefix, 0, 0, thread);
+ uint64_t address = get_addr(cpu, opcode, prefix, ext_prefix, 0, 0, thread);
uint8_t rs = (prefix >> 4) & 3;
char *postfix;
char *of;
@@ -35,7 +36,17 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
uint8_t tmp = 0;
union reg mask;
mask.u64 = 0;
- memcpy(op, opname[opcode], 3);
+ const char *inst_name;
+ uint8_t inst_type;
+ if ((ext_prefix & 0xD) == 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;
@@ -53,28 +64,33 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
}
uint8_t addrsize = 0;
char *idx;
- switch (optype[opcode]) {
- case IND : idx = ")"; break;
- case INDX: idx = ", x)"; break;
- case INDY: idx = "), y"; break;
- case ZMX : idx = ", x"; break;
- case ZMY : idx = ", y"; break;
- default : idx = ""; break;
+ 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 (optype[opcode]) {
- case ZM :
- case ZMX :
- case ZMY :
- case IND :
- case INDX:
- case INDY: addrsize = get_addrsize(prefix, ZM); break;
- case ABS : addrsize = get_addrsize(prefix, ABS); break;
- case IMM :
- case REL : addrsize = (1 << rs)-1; 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 || optype[opcode] == REL) {
+ 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;
@@ -87,18 +103,24 @@ void disasm(struct sux *cpu, uint8_t lines, uint8_t opcode, uint8_t prefix, uint
}
value = (sign[0] == '-') ? (~value + 1) & mask.u64 : value;
}
- switch (optype[opcode]) {
- case BREG:
- case IMPL: wprintw(scr, "%s%s" , opname[opcode], postfix); break;
- case IMM : wprintw(scr, "%s%s #$%0*"PRIX64 , op, postfix, (addrsize+1) << 1, value); break;
- case IND :
- case INDX:
- case INDY: ind = "("; /* Falls through. */
- case ZMX :
- case ZMY :
- 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 EIND :
+ case BREG :
+ case IMPL : wprintw(scr, "%s%s" , inst_name, 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;
}
if (address == TX_ADDR || address == RX_ADDR) {
diff --git a/disasm.h b/disasm.h
index e56007f..6f978ce 100644
--- a/disasm.h
+++ b/disasm.h
@@ -102,7 +102,7 @@ static const char *opname[0x100] = {
[XOR_B ] = "XOR B",
[CMP_B ] = "CMP B",
[DEB_IMP ] = "DEB",
- [TXS_IMM ] = "TXS #",
+ [TXS_IMP ] = "TXS",
[STY_IN ] = "STY ind",
[PLA_IMP ] = "PLA",
[BCC_REL ] = "BCC rel",
@@ -169,3 +169,169 @@ static const char *opname[0x100] = {
[CPB_IY ] = "CPB indy",
[PLX_IMP ] = "PLX"
};
+
+static const char *ext_opname[0x100] = {
+ [LEA_AY ] = "LEA a, y",
+ [ADD_IMM] = "ADD #",
+ [LEA_Z ] = "LEA zm",
+ [CPE_IMM] = "CPE #",
+ [CLZ_Z ] = "CLZ zm",
+ [ADD_Z ] = "ADD zm",
+ [STB_E ] = "STB (E)",
+ [CPE_Z ] = "CPE zm",
+ [LNG_IMM] = "LNG #",
+ [LNG_E ] = "LNG (E)",
+ [JMP_E ] = "JMP (E)",
+ [ADC_E ] = "ADC (E)",
+ [ROR_E ] = "ROR (E)",
+ [LEA_AB ] = "LEA a",
+ [CLZ_AB ] = "CLZ a",
+ [ADD_AB ] = "ADD a",
+ [LEA_ZY ] = "LEA zm, y",
+ [CPE_AB ] = "CPE a",
+ [CLZ_E ] = "CLZ (E)",
+ [ADD_E ] = "ADD (E)",
+ [LDX_E ] = "LDX (E)",
+ [SNG_E ] = "SNG (E)",
+ [PEA_AY ] = "PEA a, y",
+ [SUB_IMM] = "SUB #",
+ [PEA_Z ] = "PEA zm",
+ [CLO_Z ] = "CLO zm",
+ [SUB_Z ] = "SUB zm",
+ [STX_E ] = "STX (E)",
+ [ICE_Z ] = "ICE (E)",
+ [LPO_IMM] = "LPO #",
+ [LPO_E ] = "LPO (E)",
+ [JSR_E ] = "JSR (E)",
+ [SBC_E ] = "SBC (E)",
+ [MUL_E ] = "MUL (E)",
+ [PEA_AB ] = "PEA a",
+ [CLO_AB ] = "CLO a",
+ [SUB_AB ] = "SUB a",
+ [PEA_ZY ] = "PEA zm, y",
+ [ICE_AB ] = "ICE a",
+ [CLO_E ] = "CLO (E)",
+ [SUB_E ] = "SUB (E)",
+ [CPB_E ] = "CPB (E)",
+ [ICE_E ] = "ICE (E)",
+ [SPO_E ] = "SPO (E)",
+ [LDS_IMM] = "LDS #",
+ [LEA_AI ] = "LEA (a)",
+ [LDS_Z ] = "LDS zm",
+ [ADE_IMM] = "ADE #",
+ [LEA_IN ] = "LEA (zm)",
+ [BIT_Z ] = "BIT zm",
+ [ADE_Z ] = "ADE zm",
+ [CPX_E ] = "CPX (E)",
+ [LLM_Z ] = "LLM zm",
+ [LCS_IMM] = "LCS #",
+ [LCS_E ] = "LCS (E)",
+ [LDS_AB ] = "LDS a",
+ [AND_E ] = "AND (E)",
+ [DIV_E ] = "DIV (E)",
+ [LEA_AX ] = "LEA a, x",
+ [LDS_E ] = "LDS (E)",
+ [BIT_AB ] = "BIT a",
+ [ADE_AB ] = "ADE a",
+ [LEA_ZX ] = "LEA zm, x",
+ [LLM_AB ] = "LLM a",
+ [BIT_E ] = "BIT (E)",
+ [CPY_E ] = "CPY (E)",
+ [LLM_E ] = "LLM (E)",
+ [SCS_E ] = "SCS (E)",
+ [SCO_IMM] = "SCO #",
+ [PEA_AI ] = "PEA (a)",
+ [SCO_Z ] = "SCO zm",
+ [SBE_IMM] = "SBE #",
+ [PEA_IN ] = "PEA (zm)",
+ [SBE_Z ] = "SBE zm",
+ [PHE_IMP] = "PHE",
+ [LRM_Z ] = "LRM zm",
+ [LCC_IMM] = "LCC #",
+ [LCC_E ] = "LCC (E)",
+ [SCO_AB ] = "SCO a",
+ [ORA_E ] = "ORA (E)",
+ [ASR_E ] = "ASR (E)",
+ [PEA_AX ] = "PEA a, x",
+ [SCO_E ] = "SCO (E)",
+ [SBE_AB ] = "SBE a",
+ [PEA_ZX ] = "PEA zm, x",
+ [LRM_AB ] = "LRM a",
+ [PLE_IMP] = "PLE",
+ [LRM_E ] = "LRM (E)",
+ [SCC_E ] = "SCC (E)",
+ [ECO_IMM] = "ECO #",
+ [DEC_E ] = "DEC (E)",
+ [LEA_AIY] = "LEA (a), y",
+ [ECO_Z ] = "ECO zm",
+ [ADS_IMM] = "ADS #",
+ [LEA_IY ] = "LEA (zm), y",
+ [ADS_Z ] = "ADS zm",
+ [DEE_IMP] = "DEE",
+ [RLM_Z ] = "RLM zm",
+ [LEQ_IMM] = "LEQ #",
+ [LEQ_E ] = "LEQ (E)",
+ [ECO_AB ] = "ECO a",
+ [XOR_E ] = "XOR (E)",
+ [CMP_E ] = "CMP (E)",
+ [LEA_AIX] = "LEA (a, x)",
+ [ECO_E ] = "ECO (E)",
+ [ADS_AB ] = "ADS a",
+ [LEA_IX ] = "LEA (zm, x)",
+ [RLM_AB ] = "RLM a",
+ [ADS_E ] = "ADS (E)",
+ [INE_IMP] = "INE",
+ [RLM_E ] = "RLM (E)",
+ [SEQ_E ] = "SEQ (E)",
+ [INC_E ] = "INC (E)",
+ [PEA_AIY] = "PEA (a), y",
+ [STS_Z ] = "STS zm",
+ [SBS_IMM] = "SBS #",
+ [PEA_IY ] = "PEA (zm), y",
+ [SBS_Z ] = "SBS zm",
+ [DES_IMP] = "DES",
+ [RRM_Z ] = "RRM zm",
+ [LNE_IMM] = "LNE #",
+ [LNE_E ] = "LNE (E)",
+ [STS_AB ] = "STS a",
+ [LSL_E ] = "LSL (E)",
+ [LDY_E ] = "LDY (E)",
+ [PEA_AIX] = "PEA (a, x)",
+ [STS_E ] = "STS (E)",
+ [SBS_AB ] = "SBS a",
+ [PEA_IX ] = "PEA (zm, x)",
+ [RRM_AB ] = "RRM a",
+ [SBS_E ] = "SBS (E)",
+ [INS_IMP] = "INS",
+ [RRM_E ] = "RRM (E)",
+ [REP_REL] = "REP rel",
+ [SNE_E ] = "SNE (E)",
+ [STY_E ] = "STY (E)",
+ [STE_Z ] = "STE zm",
+ [NOT_A ] = "NOT A",
+ [NOT_Z ] = "NOT zm",
+ [MMV_IMP] = "MMV",
+ [ARM_Z ] = "ARM zm",
+ [REQ_REL] = "REQ rel",
+ [STE_AB ] = "STE a",
+ [LSR_E ] = "LSR (E)",
+ [LDA_E ] = "LDA (E)",
+ [NOT_AB ] = "NOT a",
+ [ARM_AB ] = "ARM a",
+ [NOT_E ] = "NOT (E)",
+ [ARM_E ] = "ARM (E)",
+ [RNE_REL] = "RNE rel",
+ [STA_E ] = "STA (E)",
+ [STZ_Z ] = "STZ zm",
+ [SWP_A ] = "SWP A",
+ [SWP_Z ] = "SWP zm",
+ [PCN_Z ] = "PCN zm",
+ [STZ_AB ] = "STZ a",
+ [ROL_E ] = "ROL (E)",
+ [LDB_E ] = "LDB (E)",
+ [STZ_E ] = "STZ (E)",
+ [SWP_AB ] = "SWP a",
+ [PCN_AB ] = "PCN a",
+ [SWP_E ] = "SWP (E)",
+ [PCN_E ] = "PCN (E)"
+};
diff --git a/enums.h b/enums.h
index 2670397..bca5010 100644
--- a/enums.h
+++ b/enums.h
@@ -1,26 +1,23 @@
enum am {
/* Part of Base ISA. */
- IMM, /* Immediate Data. */
- ZM, /* Zero Matrix. */
- ZMX, /* Zero Matrix, indexed with X. */
- ZMY, /* Zero Matrix, indexed with Y. */
- IND, /* Indirect. */
- INDX, /* Indexed Indirect. */
- INDY, /* Indirect Indexed. */
- ABS, /* Absolute. */
- REL, /* Relative to Program Counter. */
- BREG, /* B Register. */
- IMPL, /* Implied. */
+ IMM, /* Immediate Data. */
+ ZM, /* Zero Matrix. */
+ ZMX, /* Zero Matrix, indexed with X. */
+ ZMY, /* Zero Matrix, indexed with Y. */
+ IND, /* Indirect. */
+ INDX, /* Indexed Indirect. */
+ INDY, /* Indirect Indexed. */
+ ABS, /* Absolute. */
+ REL, /* Relative to Program Counter. */
+ BREG, /* B Register. */
+ IMPL, /* Implied. */
/* Part of Base Extension. */
- ABSX, /* Absolute, Indexed with X. */
- ABSY, /* Absolute, Indexed with Y. */
- SPI, /* Stack Pointer, Immediate Offset. */
- SPX, /* Stack Pointer, Offset with X. */
- SPY, /* Stack Pointer, Offset with Y. */
- INA, /* Absolute Indirect. */
- INAX, /* Absolute Indexed Indirect. */
- INAY, /* Absolute Indirect Indexed. */
- EIND, /* Effective Address Register, Indirect. */
+ ABSX, /* Absolute, Indexed with X. */
+ ABSY, /* Absolute, Indexed with Y. */
+ AIND, /* Absolute Indirect. */
+ AINDX, /* Absolute Indexed Indirect. */
+ AINDY, /* Absolute Indirect Indexed. */
+ EIND, /* Effective Address Register, Indirect. */
};
enum mne {
@@ -100,6 +97,58 @@ enum mne {
XOR
};
+enum ext_mne {
+ LEA,
+ PEA,
+ ADD,
+ SUB,
+ ADE,
+ SBE,
+ ADS,
+ SBS,
+ NOT,
+ LLM,
+ LRM,
+ RLM,
+ RRM,
+ ARM,
+ PHE,
+ PLE,
+ CPE,
+ ICE,
+ LDS,
+ DEE,
+ INE,
+ DES,
+ INS,
+ STS,
+ STE,
+ STZ,
+ SCO,
+ ECO,
+ CLZ,
+ CLO,
+ BIT,
+ MMV,
+ SWP,
+ PCN,
+ REP,
+ REQ,
+ RNE,
+ LNG,
+ LPO,
+ LCS,
+ LCC,
+ LEQ,
+ LNE,
+ SNG,
+ SPO,
+ SCS,
+ SCC,
+ SEQ,
+ SNE
+};
+
enum base_isa {
CPS_IMP = 0x00, /* Clear Processor Status. */
ADC_IMM = 0x01, /* ADd with Carry. */
@@ -204,7 +253,7 @@ enum base_isa {
XOR_B = 0x95, /* XOR B Register. */
CMP_B = 0x96, /* CMP B Register. */
DEB_IMP = 0x99, /* Decrement B register. */
- TXS_IMM = 0x9A, /* Transfer X to Stack pointer. */
+ TXS_IMP = 0x9A, /* Transfer X to Stack pointer. */
STY_IN = 0x9C, /* STY Indirect */
PLA_IMP = 0x9E, /* PuLl Accumulator from stack. */
BCC_REL = 0xA0, /* Branch if Carry Clear. */
@@ -273,122 +322,167 @@ enum base_isa {
};
enum base_ext {
- ADC_E = 0x01, /* ADC E Indirect. */
- LEA_ZX = 0x02, /* LEA Zero Matrix, indexed with X. */
- LEA_SX = 0x03, /* LEA Stack Pointer, offset with X. */
- ADD = 0x04, /* ADD without carry. */
- LLM = 0x05, /* Logical shift Left, on Memory. */
- PHE = 0x08, /* PusH Effective address register to stack. */
- CPB_E = 0x09, /* CPB E Indirect. */
- DEC_E = 0x0C, /* DEC E Indirect. */
+ LEA_AY = 0x03, /* LEA Absolute, indexed with Y. */
+ ADD_IMM = 0x06, /* ADD without carry. */
+ LEA_Z = 0x07, /* Load Effective Address. */
+ CPE_IMM = 0x08, /* ComPare Effective address register. */
+ CLZ_Z = 0x09, /* Count Leading Zeros. */
+ ADD_Z = 0x0A, /* ADD Zero Matrix. */
+ STB_E = 0x0B, /* STB E Indirect. */
+ CPE_Z = 0x0C, /* CPE Zero Matrix. */
+ LNG_IMM = 0x0D, /* Load accumulator, if NeGative. */
+ LNG_E = 0x0E, /* LNG E Indirect. */
JMP_E = 0x10, /* JMP E Indirect. */
- SBC_E = 0x11, /* SBC E Indirect. */
- LEA_ZY = 0x12, /* LEA Zero Matrix, indexed with Y. */
- LEA_SY = 0x13, /* LEA Stack Pointer, offset with Y. */
- ADD_E = 0x14, /* ADD E Indirect. */
- LLM_Z = 0x15, /* LLM Zero Matrix. */
- CPY_E = 0x19, /* CPY E Indirect. */
- INC_E = 0x1C, /* INC E Indirect. */
- JSR_E = 0x20, /* JSR E Indirect. */
- AND_E = 0x21, /* AND E Indirect. */
- PEA_ZX = 0x22, /* PEA Zero Matrix, indexed with X. */
- PEA_SX = 0x23, /* PEA Stack Pointer, offset with X. */
- SUB = 0x24, /* SUBtract without carry. */
- LLM_E = 0x25, /* LLM E Indirect. */
- PLE = 0x28, /* PuLl Effective address register from stack. */
- CPX_E = 0x29, /* CPX E Indirect. */
- DEE = 0x2C, /* DEcrement Effective address register. */
- BPO_E = 0x30, /* BPO E Indirect. */
- ORA_E = 0x31, /* ORA E Indirect. */
- PEA_ZY = 0x32, /* PEA Zero Matrix, indexed with Y. */
- PEA_SY = 0x33, /* PEA Stack Pointer, offset with Y. */
- SUB_E = 0x34, /* SUB E Indirect. */
- LRM = 0x35, /* Logical shift Right, on Memory. */
- CPE = 0x39, /* ComPare Effective address register. */
- INE = 0x3C, /* INcrement Effective address register. */
- BNG_E = 0x40, /* BNG E Indirect. */
- XOR_E = 0x41, /* XOR E Indirect. */
- LEA_AX = 0x42, /* LEA Absolute, indexed with X. */
- LEA_SI = 0x43, /* LEA Stack Pointer, Immediate offset. */
- ADE = 0x44, /* ADd Effective address register. */
- LRM_Z = 0x45, /* LRM Zero Matrix. */
- CPE_AB = 0x49, /* CPE Absolute. */
- DES = 0x4C, /* DEcrement Stack pointer. */
- BCS_E = 0x50, /* BCS E Indirect. */
- LSL_E = 0x51, /* LSL E Indirect. */
- LEA_AY = 0x52, /* LEA Absolute, indexed with Y. */
- LEA_RE = 0x53, /* LEA Relative. */
- ADE_A = 0x54, /* ADE with Accumulator. */
- LRM_E = 0x55, /* LRM E Indirect. */
- CPE_Z = 0x59, /* CPE Zero Matrix. */
- INS = 0x5C, /* INcrement Stack pointer. */
- BCC_E = 0x60, /* BCC E Indirect. */
- LSR_E = 0x61, /* LSR E Indirect. */
- PEA_AX = 0x62, /* PEA Absolute, indexed with X. */
- PEA_SI = 0x63, /* PEA Stack Pointer, Immediate offset. */
- SBE = 0x64, /* SuBtract Effective address register. */
- RLM = 0x65, /* Rotate Left, on Memory. */
- ICE = 0x69, /* Interlocked Compare, and Exchange. */
- BEQ_E = 0x70, /* BEQ E Indirect. */
- ROL_E = 0x71, /* ROL E Indirect. */
- PEA_AY = 0x72, /* PEA Absolute, indexed with Y. */
- PEA_RE = 0x73, /* PEA Relative. */
- RLM_Z = 0x75, /* RLM Zero Matrix. */
- ICE_Z = 0x79, /* ICE Zero Matrix. */
- STE = 0x7C, /* STore Effective address register. */
- BNE_E = 0x80, /* BNE E Indirect. */
- ROR_E = 0x81, /* ROR E Indirect. */
- LEA_IX = 0x82, /* LEA Indexed Indirect. */
- LEA_IN = 0x83, /* LEA Indirect. */
- ADS = 0x84, /* ADd Stack pointer. */
- RLM_E = 0x85, /* RLM E Indirect. */
- ICE_E = 0x89, /* ICE E Indirect. */
- STE_Z = 0x8C, /* STE Zero Matrix. */
- BVS_E = 0x90, /* BVS E Indirect. */
- MUL_E = 0x91, /* MUL E Indirect. */
- LEA_IY = 0x92, /* LEA Indirect Indexed. */
- LEA_AI = 0x93, /* LEA Absolute Indirect. */
- ADS_A = 0x94, /* ADS with Accumulator. */
- RRM = 0x95, /* Rotate Right, on Memory. */
- STZ = 0x9C, /* STore Zero. */
- BVC_E = 0xA0, /* BVC E Indirect. */
- DIV_E = 0xA1, /* DIV E Indirect. */
- PEA_IX = 0xA2, /* PEA Indexed Indirect. */
- PEA_IN = 0xA3, /* PEA Indirect. */
- SBS = 0xA4, /* SuBtract Stack pointer. */
- RRM_ZM = 0xA5, /* RRM Zero Matrix. */
- STZ_ZM = 0xAC, /* STZ Zero Matrix. */
- CMP_E = 0xB1, /* CMP E Indirect. */
- PEA_IY = 0xB2, /* PEA Indirect Indexed. */
- PEA_AI = 0xB3, /* PEA Absolute Indirect. */
- SBS_A = 0xB4, /* SBS with Accumulator. */
- RRM_E = 0xB5, /* RRM E Indirect. */
- LDX_E = 0xB9, /* LDX E Indirect. */
- STZ_E = 0xBC, /* STZ E Indirect. */
- LDA_E = 0xC1, /* LDA E Indirect. */
- LEA_AIX = 0xC2, /* LEA Absolute Indexed Indirect. */
- LEA_Z = 0xC3, /* LEA Zero Matrix. */
- NOT = 0xC4, /* bitwise NOT with accumulator. */
- ARM = 0xC5, /* Arithmetic shift Right, on Memory. */
- LDE = 0xC9, /* LoaD Effective address register. */
- STA_E = 0xCC, /* STA E Indirect. */
- LDB_E = 0xD1, /* LDB E Indirect. */
- LEA_AIY = 0xD2, /* LEA Absolute Indirect Indexed. */
- LEA = 0xD3, /* Load Effective Address. */
- NOT_AB = 0xD4, /* NOT Absolute. */
- ARM_Z = 0xD5, /* ARM Zero Matrix. */
- LDE_AB = 0xD9, /* LDE Absolute. */
- STB_E = 0xDC, /* STB E Indirect. */
- LDY_E = 0xE1, /* LDY E Indirect. */
- PEA_AIX = 0xE2, /* PEA Absolute Indexed Indirect. */
- PEA_Z = 0xE3, /* PEA Zero Matrix. */
- NOT_Z = 0xE4, /* NOT Zero Matrix. */
- ARM_E = 0xE5, /* ARM E Indirect. */
- LDE_Z = 0xE9, /* LDE Zero Matrix. */
- STY_E = 0xEC, /* STY E Indirect. */
- ASR_E = 0xF1, /* ASR E Indirect. */
- PEA_AIY = 0xF2, /* PEA Absolute Indirect Indexed. */
- PEA = 0xF3, /* Push Effective Address. */
- NOT_E = 0xF4, /* NOT E Indirect. */
- STX_E = 0xFC, /* STX E Indirect. */
+ ADC_E = 0x11, /* ADC E Indirect. */
+ ROR_E = 0x12, /* ROR E Indirect. */
+ LEA_AB = 0x13, /* LEA Absolute. */
+ CLZ_AB = 0x15, /* CLZ Absolute. */
+ ADD_AB = 0x16, /* ADD Absolute. */
+ LEA_ZY = 0x17, /* LEA Zero Matrix, indexed with Y. */
+ CPE_AB = 0x18, /* CPE Absolute. */
+ CLZ_E = 0x19, /* CLZ E Indirect. */
+ ADD_E = 0x1A, /* ADD E Indirect. */
+ LDX_E = 0x1B, /* LDX E Indirect. */
+ SNG_E = 0x1E, /* Store accumulator, if NeGative. */
+ PEA_AY = 0x23, /* PEA Absolute, indexed with Y. */
+ SUB_IMM = 0x26, /* SUBtract without carry. */
+ PEA_Z = 0x27, /* Push Effective Address. */
+ CLO_Z = 0x29, /* Count Leading Ones. */
+ SUB_Z = 0x2A, /* SUB Zero Matrix. */
+ STX_E = 0x2B, /* STX E Indirect. */
+ ICE_Z = 0x2C, /* Interlocked Compare, and Exchange. */
+ LPO_IMM = 0x2D, /* Load accumulator, if POsitive. */
+ LPO_E = 0x2E, /* LPO E Indirect. */
+ JSR_E = 0x30, /* JSR E Indirect. */
+ SBC_E = 0x31, /* SBC E Indirect. */
+ MUL_E = 0x32, /* MUL E Indirect. */
+ PEA_AB = 0x33, /* PEA Absolute. */
+ CLO_AB = 0x34, /* CLO Absolute. */
+ SUB_AB = 0x35, /* SUB Absolute. */
+ PEA_ZY = 0x37, /* PEA Zero Matrix, indexed with Y. */
+ ICE_AB = 0x38, /* ICE Absolute. */
+ CLO_E = 0x39, /* CLO E Indirect. */
+ SUB_E = 0x3A, /* SUB E Indirect. */
+ CPB_E = 0x3B, /* CPB E Indirect. */
+ ICE_E = 0x3C, /* ICE E Indirect. */
+ SPO_E = 0x3E, /* Store accumulator, if POsitive. */
+ LDS_IMM = 0x40, /* LoaD Stack pointer. */
+ LEA_AI = 0x43, /* LEA Absolute Indirect. */
+ LDS_Z = 0x44, /* LDS Zero Matrix. */
+ ADE_IMM = 0x46, /* ADd Effective address register. */
+ LEA_IN = 0x47, /* LEA Indirect. */
+ BIT_Z = 0x49, /* BIt Test. */
+ ADE_Z = 0x4A, /* ADE Zero Matrix. */
+ CPX_E = 0x4B, /* CPX E Indirect. */
+ LLM_Z = 0x4C, /* Logical shift Left, on Memory. */
+ LCS_IMM = 0x4D, /* Load accumulator, if Carry Set. */
+ LCS_E = 0x4E, /* LCS E Indirect. */
+ LDS_AB = 0x50, /* LDS Absolute. */
+ AND_E = 0x51, /* AND E Indirect. */
+ DIV_E = 0x52, /* DIV E Indirect. */
+ LEA_AX = 0x53, /* LEA Absolute, indexed with X. */
+ LDS_E = 0x54, /* LDS E Indirect. */
+ BIT_AB = 0x55, /* BIT Absolute. */
+ ADE_AB = 0x56, /* ADE Absolute. */
+ LEA_ZX = 0x57, /* LEA Zero Matrix, indexed with X. */
+ LLM_AB = 0x58, /* LLM Absolute. */
+ BIT_E = 0x59, /* BIT E Indirect. */
+ CPY_E = 0x5B, /* CPY E Indirect. */
+ LLM_E = 0x5C, /* LLM E Indirect. */
+ SCS_E = 0x5E, /* Store accumulator, if Carry Set. */
+ SCO_IMM = 0x60, /* Start one, or more COre(s). */
+ PEA_AI = 0x63, /* PEA Absolute Indirect. */
+ SCO_Z = 0x64, /* SCO Zero Matrix. */
+ SBE_IMM = 0x66, /* SuBtract Effective address register. */
+ PEA_IN = 0x67, /* PEA Indirect. */
+ SBE_Z = 0x6A, /* SBE Zero Matrix. */
+ PHE_IMP = 0x6B, /* PusH Effective address register to stack. */
+ LRM_Z = 0x6C, /* Logical shift Right, on Memory. */
+ LCC_IMM = 0x6D, /* Load accumulator, if Carry Clear. */
+ LCC_E = 0x6E, /* LCC E Indirect. */
+ SCO_AB = 0x70, /* SCO Absolute. */
+ ORA_E = 0x71, /* ORA E Indirect. */
+ ASR_E = 0x72, /* ASR E Indirect. */
+ PEA_AX = 0x73, /* PEA Absolute, indexed with X. */
+ SCO_E = 0x74, /* SCO E Indirect. */
+ SBE_AB = 0x76, /* SBE Absolute. */
+ PEA_ZX = 0x77, /* PEA Zero Matrix, indexed with X. */
+ LRM_AB = 0x78, /* LRM Absolute. */
+ PLE_IMP = 0x7B, /* PuLl Effective address register from stack. */
+ LRM_E = 0x7C, /* LRM E Indirect. */
+ SCC_E = 0x7E, /* Store accumulator, if Carry Clear. */
+ ECO_IMM = 0x80, /* End one, or more COre(s). */
+ DEC_E = 0x82, /* DEC E Indirect. */
+ LEA_AIY = 0x83, /* LEA Absolute Indirect Indexed. */
+ ECO_Z = 0x84, /* ECO Zero Matrix. */
+ ADS_IMM = 0x86, /* ADd Stack pointer. */
+ LEA_IY = 0x87, /* LEA Indirect Indexed. */
+ ADS_Z = 0x8A, /* ADS Zero Matrix. */
+ DEE_IMP = 0x8B, /* DEcrement Effective address register. */
+ RLM_Z = 0x8C, /* Rotate Left, on Memory. */
+ LEQ_IMM = 0x8D, /* Load accumulator, if EQual. */
+ LEQ_E = 0x8E, /* LEQ E Indirect. */
+ ECO_AB = 0x90, /* ECO Absolute. */
+ XOR_E = 0x91, /* XOR E Indirect. */
+ CMP_E = 0x92, /* CMP E Indirect. */
+ LEA_AIX = 0x93, /* LEA Absolute Indexed Indirect. */
+ ECO_E = 0x94, /* ECO E Indirect. */
+ ADS_AB = 0x96, /* ADS Absolute. */
+ LEA_IX = 0x97, /* LEA Indexed Indirect. */
+ RLM_AB = 0x98, /* RLM Absolute. */
+ ADS_E = 0x9A, /* ADS E Indirect. */
+ INE_IMP = 0x9B, /* INcrement Effective address register. */
+ RLM_E = 0x9C, /* RLM E Indirect. */
+ SEQ_E = 0x9E, /* Store accumulator, if EQual. */
+ INC_E = 0xA2, /* INC E Indirect. */
+ PEA_AIY = 0xA3, /* PEA Absolute Indirect Indexed. */
+ STS_Z = 0xA4, /* STore Stack pointer. */
+ SBS_IMM = 0xA6, /* SuBtract Stack pointer. */
+ PEA_IY = 0xA7, /* PEA Indirect Indexed. */
+ SBS_Z = 0xAA, /* SBS Zero Matrix. */
+ DES_IMP = 0xAB, /* DEcrement Stack pointer. */
+ RRM_Z = 0xAC, /* Rotate Right, on Memory. */
+ LNE_IMM = 0xAD, /* Load accumulator, if Not Equal. */
+ LNE_E = 0xAE, /* LNE E Indirect. */
+ STS_AB = 0xB0, /* STS Absolute. */
+ LSL_E = 0xB1, /* LSL E Indirect. */
+ LDY_E = 0xB2, /* LDY E Indirect. */
+ PEA_AIX = 0xB3, /* PEA Absolute Indexed Indirect. */
+ STS_E = 0xB4, /* STS E Indirect. */
+ SBS_AB = 0xB6, /* SBS Absolute. */
+ PEA_IX = 0xB7, /* PEA Indexed Indirect. */
+ RRM_AB = 0xB8, /* RRM Absolute. */
+ SBS_E = 0xBA, /* SBS E Indirect. */
+ INS_IMP = 0xBB, /* INcrement Stack pointer. */
+ RRM_E = 0xBC, /* RRM E Indirect. */
+ REP_REL = 0xBD, /* REPeat until counter is zero. */
+ SNE_E = 0xBE, /* Store accumulator, if Not Equal. */
+ STY_E = 0xC2, /* STY E Indirect. */
+ STE_Z = 0xC4, /* STore Effective address register. */
+ NOT_A = 0xC6, /* bitwise NOT with accumulator. */
+ NOT_Z = 0xCA, /* NOT Zero Matrix. */
+ MMV_IMP = 0xCB, /* Memory MoVe. */
+ ARM_Z = 0xCC, /* Arithmetic shift Right, on Memory. */
+ REQ_REL = 0xCD, /* Repeat until either counter is zero, or zero flag isn't set. */
+ STE_AB = 0xD0, /* STE Absolute. */
+ LSR_E = 0xD1, /* LSR E Indirect. */
+ LDA_E = 0xD2, /* LDA E Indirect. */
+ NOT_AB = 0xD6, /* NOT Absolute. */
+ ARM_AB = 0xD8, /* ARM Absolute. */
+ NOT_E = 0xDA, /* NOT E Indirect. */
+ ARM_E = 0xDC, /* ARM E Indirect. */
+ RNE_REL = 0xDD, /* Repeat until either counter is zero, or zero flag is set. */
+ STA_E = 0xE2, /* STA E Indirect. */
+ STZ_Z = 0xE4, /* STore Zero. */
+ SWP_A = 0xE6, /* SWaP lower half, with upper half. */
+ SWP_Z = 0xEA, /* SWP Zero Matrix. */
+ PCN_Z = 0xEC, /* Population CouNt. */
+ STZ_AB = 0xF0, /* STZ Absolute. */
+ ROL_E = 0xF1, /* ROL E Indirect. */
+ LDB_E = 0xF2, /* LDB E Indirect. */
+ STZ_E = 0xF4, /* STZ E Indirect. */
+ SWP_AB = 0xF6, /* SWP Absolute. */
+ PCN_AB = 0xF8, /* PCN Absolute. */
+ SWP_E = 0xFA, /* SWP E Indirect. */
+ PCN_E = 0xFC /* PCN E Indirect. */
};
diff --git a/lexer.c b/lexer.c
index 7cc9b87..f8280a0 100644
--- a/lexer.c
+++ b/lexer.c
@@ -242,6 +242,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
lex_type = 0xFF;
uint8_t k = 0;
+ uint8_t k2 = 0;
union reg ch;
ch.u64 = 0;
uint8_t rs = 0;
@@ -324,12 +325,13 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
offset++;
}
switch (get_ptok(str[i+offset], dbg)) {
- case PTOK_B :
- case PTOK_X :
- case PTOK_Y :
- case PTOK_S :
- case PTOK_P :
- case PTOK_ALPHA :
+ case PTOK_B :
+ case PTOK_E :
+ case PTOK_X :
+ case PTOK_Y :
+ case PTOK_S :
+ case PTOK_P :
+ case PTOK_ALPHA :
case PTOK_NUMBER: ptok = PTOK_ALPHA; break;
}
if ((ptok == PTOK_S && toupper(str[i+1]) != 'P') || (ptok == PTOK_P && toupper(str[i+1]) != 'C')) {
@@ -584,6 +586,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
(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++];
@@ -593,8 +596,9 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
break;
}
switch (ptok) {
- case PTOK_X: l->tok->type = (lex_type == TOK_IND) ? INDX : ZMX; break;
- case PTOK_Y: l->tok->type = (lex_type == TOK_IND) ? INDY : ZMY; break;
+ case PTOK_E: l->tok->type = (lex_type == TOK_IND) ? EIND : l->tok->type; break;
+ case PTOK_X: l->tok->type = (lex_type == TOK_IND) ? INDX : ZMX; break;
+ case PTOK_Y: l->tok->type = (lex_type == TOK_IND) ? INDY : ZMY; break;
}
break;
case PTOK_S:
@@ -697,13 +701,17 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
isch = 0;
isop = 0;
if (j == 3 && str[i] != ':' && !is_struct) {
- for (k = 0; k < OPNUM; k++) {
- if (toupper(lexeme[0]) == mne[k][0]) {
- if (!strcasecmp(lexeme, mne[k])) {
- lex_type = TOK_OPCODE;
+ for (k = 0, k2 = 0; k < OPNUM || k2 < EXT_OPNUM; k++, k2++) {
+ int find_ext = (k2 < EXT_OPNUM);
+ int upper = toupper(lexeme[0]);
+ if (upper == mne[k][0] || (find_ext && upper == ext_mne[k2][0])) {
+ 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;
isop = 1;
l->count++;
- t = make_token(lex_type, 0xFF, space, tab, k, "", NULL);
+ t = make_token(lex_type, 0xFF, space, tab, (is_base && !is_ext) ? k : k2, "", NULL);
break;
}
}
@@ -791,7 +799,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
printf("lex(): lexeme: %s, lex_type: %s\n", lexeme, (lex_type != 0xFF) ? lex_tok[lex_type] : "TOK_NONE");
}
j = 0;
- if (lex_type == TOK_OPCODE && !isop) {
+ if ((lex_type == TOK_OPCODE || lex_type == TOK_EXTOP) && !isop) {
j = 0;
} else if (lex_type == TOK_EXPR || (lex_type != TOK_MEMBER && !isdelm2(str[i], dbg))) {
i++;
diff --git a/lexer.h b/lexer.h
index 3a9951e..dc478cd 100644
--- a/lexer.h
+++ b/lexer.h
@@ -34,28 +34,29 @@ static inline uint8_t isdelm2(char c, uint8_t dbg) {
static inline uint8_t get_ptok(char c, uint8_t dbg) {
switch (c) {
- case '.' : return PTOK_DOT ;
- case '@' : return PTOK_AT ;
- case ':' : return PTOK_COLON ;
- case '=' : return PTOK_EQU ;
- case '+' : return PTOK_PLUS ;
- case '-' : return PTOK_MINUS ;
- case '>' : return PTOK_GT ;
- case '<' : return PTOK_LT ;
- case '|' : return PTOK_PIPE ;
- case '(' : return PTOK_LBRACK ;
- case ')' : return PTOK_RBRACK ;
- case ',' : return PTOK_COMMA ;
- case 'B': case 'b' : return PTOK_B ;
+ case '.' : return PTOK_DOT ;
+ case '@' : return PTOK_AT ;
+ case ':' : return PTOK_COLON ;
+ case '=' : return PTOK_EQU ;
+ case '+' : return PTOK_PLUS ;
+ case '-' : return PTOK_MINUS ;
+ case '>' : return PTOK_GT ;
+ case '<' : return PTOK_LT ;
+ case '|' : return PTOK_PIPE ;
+ case '(' : return PTOK_LBRACK ;
+ case ')' : return PTOK_RBRACK ;
+ case ',' : return PTOK_COMMA ;
+ case 'B': case 'b' : return PTOK_B ;
+ case 'E': case 'e' : return PTOK_E ;
case 'X': case 'x' : return PTOK_X ;
case 'Y': case 'y' : return PTOK_Y ;
case 'S': case 's' : return PTOK_S ;
case 'P': case 'p' : return PTOK_P ;
- case '\"': return PTOK_DQUOTE ;
- case '\'': return PTOK_SQUOTE ;
- case '#' : return PTOK_HASH ;
- case ';' : return PTOK_SCOLON ;
- case '$' : return PTOK_DOLLAR ;
+ case '\"': return PTOK_DQUOTE ;
+ case '\'': return PTOK_SQUOTE ;
+ case '#' : return PTOK_HASH ;
+ case ';' : return PTOK_SCOLON ;
+ case '$' : return PTOK_DOLLAR ;
case '%' : return PTOK_PERCENT;
default :
if (isdigit(c)) {
@@ -71,6 +72,7 @@ static inline uint8_t get_ptok(char c, uint8_t dbg) {
static inline uint8_t is_altok(uint8_t ptok, uint8_t dbg) {
switch (ptok) {
case PTOK_B:
+ case PTOK_E:
case PTOK_X:
case PTOK_Y:
case PTOK_S:
diff --git a/opcode.h b/opcode.h
index 4c5d585..40b832f 100644
--- a/opcode.h
+++ b/opcode.h
@@ -10,6 +10,7 @@
#define keypoll 0
#define OPNUM 74
+#define EXT_OPNUM 49
#define C (1 << 0) /* Carry flag. */
#define Z (1 << 1) /* Zero flag. */
@@ -55,10 +56,10 @@ union reg {
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 pc; /* Program counter. */
uint64_t sp; /* Stack pointer. */
uint64_t clk; /* Number of clock cycles. */
- uint8_t crt; /* Current running threads. */
};
extern int asmmon();
diff --git a/programs/sub-suite/print_char.s b/programs/sub-suite/print_char.s
new file mode 100644
index 0000000..e12461c
--- /dev/null
+++ b/programs/sub-suite/print_char.s
@@ -0,0 +1,147 @@
+print_char:
+; sta a ; Save the typed character for now.
+ pha ; Preserve the character.
+; ldb #2 ; Make sure that set_ptr sets the third pointer.
+ lda.d #buffer ; Set the third pointer to the start of the screen buffer.
+ pha.q ; Push the pointer onto the stack.
+ lda sp+9 ; Get the character back.
+; jsr set_ptr ;
+; ldb #0 ; Set B to zero.
+; tba ; Set the Accumulator to zero.
+; lda a ; Get back the character.
+ cmp #$1B ; Did the user type an escape character?
+ beq esc ; Yes, so go check the escape code.
+ cmp #'\n' ; No, but did the user type a newline?
+ beq nl ; Yes, so handle the newline.
+ cmp #$C ; No, but did the user type Ctrl+L?
+ beq clr_scr ; Yes, so clear the screen.
+ cmp #19 ; No, but did the user type Ctrl+S?
+ beq en_step ; Yes, so enable clock/instruction stepping.
+ cmp #18 ; No, but did the user type Ctrl+R?
+ beq dis_step ; Yes, so disable clock/instruction stepping.
+ cmp #'\b' ; No, but did the user type a backspace?
+ beq bs ; Yes, so handle the backspace.
+ cmp #$7F ; No, but did they type Delete?
+ beq bs ; Yes, so treat it as a backspace.
+printc:
+ lda #0 ; No, so start trying to print a character.
+ sta d ;
+ lda (sp+1), y ; Are we at the end of the string?
+ beq @save ; Yes, so just print the character.
+ lda b ; 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.
+ 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 e ; Use it for redrawing the line.
+ sta scr_row ; Set the row position to to the end of the line.
+ jsr findst ; Find the start of the line.
+ lda scr_row ; Get the start of the line.
+@update2:
+ sta f ; Set the starting line, to the start of the line.
+ jsr rdrw_ln ; Redraw the line.
+ lda scr_trow ; Get the real row position back.
+ sta scr_row ;
+ lda scr_tcol ; Get the real column position back.
+ sta scr_col ;
+ jsr update_pos ; Update the cursor's position.
+ dec d ;
+ bra @save1 ;
+@shift:
+ ldy.w scr_ptr3 ;
+ inc scr_ptr3 ;
+ tyx ;
+ dey ;
+ ldb #1 ;
+ stb d ;
+ jsr shftln ;
+ ldb #1 ;
+ stb d ;
+; lda a ;
+ lda sp+9 ;
+ sta (sp+1), y ; store typed character into the input buffer.
+ lda scr_row ;
+ sta scr_trow ;
+ bra @update ;
+@save:
+ ldb d ;
+ bne @update ;
+@save1:
+; lda a ;
+ lda sp+9 ;
+ sta (sp+1), y ; store typed character into the input buffer.
+@incr:
+ inc scr_col ; Increment the cursor's x coordinate.
+ iny ;
+@wrapped:
+ ldb #1 ;
+ stb f ;
+ ldb scr_col ;
+ cpb #maxcol+1 ;
+ bcs @scrolled ;
+@print:
+ sta scr ; Echo typed character.
+ ldb f ;
+ beq @wrap ;
+ bra printc_end ;
+@scrolled:
+ ldb scr_row ;
+ cpb #maxrow ;
+ bcs @scroll ;
+@wrapped2:
+ ldb #0 ;
+ stb f ;
+ bra @print ;
+@scroll:
+ sta scr ; Echo typed character.
+ clc ;
+ lda #1 ;
+ sta wrapped ;
+ jsr scrl_down ;
+@wrap:
+ ldb #0
+ stb scr_col ;
+ ldb scr_row ;
+ cpb #maxrow ;
+ bcs @wrap2 ;
+@wrap1:
+ inc scr_row ;
+@wrap2:
+ phx.w ;
+ clc ;
+ lda scr_row ;
+ adc scr_str ;
+ tax ;
+ jsr setbit ;
+ plx.w ;
+ jsr update_pos ;
+printc_end:
+ pla.q ; Pull the pointer off the stack.
+ pla ; Pull the character off the stack.
+ and #0 ; Reset A.
+ rts ;
+
+nl:
+ lda #0 ; Reset A.
+ ldb (sp+1), y ; Is this character not a null terminator?
+ bne @scroll ; Yes, so don't overwrite it.
+ sta (sp+1), y ; No, so overwrite it.
+@scroll:
+ sta scr_col ; Move the cursor to the start of the next line.
+ lda scr_row ; Get the row position.
+ cmp #maxrow ; Are we at the bottom of the screen?
+ bcc @incr ; No, so move down one line.
+ jsr scrl_down ; Yes, so scroll down one line.
+ bra @end ; We are done.
+@incr:
+ inc scr_row ; Move the cursor down by one line.
+ jsr update_pos ; Update the cursor's position.
+@end:
+ lda #'\n' ; Print the newline.
+ sta a ;
+ rts ;
diff --git a/programs/sub-suite/subeditor-new.s b/programs/sub-suite/subeditor-new.s
new file mode 100644
index 0000000..6c1cfb1
--- /dev/null
+++ b/programs/sub-suite/subeditor-new.s
@@ -0,0 +1,1119 @@
+; SuBEditor.
+;
+; Writen in Sux assembly by
+; mr b0nk 500 <b0nk@b0nk.xyz>
+
+
+.org $8000
+reset:
+ cps ; Reset the processor status register.
+ ldx.w #$FFFF ; Reset the stack pointer.
+ txs ;
+ ldy #0 ; Reset the Y register.
+ sty end ;
+ tyx ; Reset the X register.
+ lda #maxrow ; Set the end of the screen to the screen's max row count.
+ sta scr_end ;
+ tya ; Reset the Accumulator.
+ sta scr_str ; Set the start of the screen back to zero.
+ sta.q bitabl ; Reset the first half of the linewrap table.
+ sta.q bitabl+8 ; Reset the second half of the linewrap table.
+ inc end ;
+ lda.w #$1FFF ; Set the clear count to $1FFF.
+ pha.w ; Push the clear count to the stack.
+ lda.d #buffer ; Set the array to be cleared to the screen buffer.
+ pha.q ; Push it on to the stack.
+ jsr clr_arr ; Clear the screen buffer.
+ pla.q ; Pull the pointer off of the stack.
+ pla.w ; Pull the clear count off of the stack.
+ and #0 ; Reset A.
+ jsr pnt_strt ; Print the starting message.
+ lda #$C ; Clear the screen.
+ sta scr ;
+ bra start ; Goto the start of the main program.
+
+clr_arr:
+ phb ; Preserve whatever was in B.
+ ldb #0 ; Clear B.
+ clc ; Prepare for a non carrying add.
+ adc #8 ; Set the second pointer to the parameter, plus eight.
+ pha.q ; Push it onto the stack.
+ tba ;
+@loop:
+ cpy.w sp+26 ; Did we clear all of the array?
+ bcs @end ; Yes, so we're done.
+ sta.q (sp+18), y; No, so clear eight bytes.
+ sta.q (sp+1), y ; Clear eight more bytes.
+ tya ; Copy the array index.
+ adc #$10 ; Increment the index by 16.
+ tay ; Update the index.
+ tba ; Reset the Accumulator.
+ sta.q (sp+18), y; Do this one more time, to clear 32 bytes.
+ sta.q (sp+1), y ;
+ tya ;
+ adc #$10 ;
+ tay ;
+ tba ;
+ bra @loop ; Keep looping.
+@end:
+ ldy.w zero ; Set the index back to zero.
+ pla.q ; Move the stack pointer back.
+ tba ; Reset A.
+ plb ; Get whatever was in the B register, back.
+ rts ; End of clr_arr.
+
+pnt_strt:
+ lda.w #ed_name ; Print the name of the editor.
+ jsr print_str ;
+ lda.w #ver_str ; Print the version text.
+ jsr print_str ;
+ lda.w #ed_ver ; Print the version number.
+ jsr print_str ;
+ lda.w #ed_sver ; Print the sub version number.
+ jsr print_str ;
+ lda #'\n' ; Print a newline.
+ jsr print_char ;
+ lda.w #made ; Print the "Created by" text.
+ jsr print_str ;
+ lda.w #author ; Print the name of the author.
+ jsr print_str ;
+ lda #'\n' ; Print a newline.
+ jsr print_char ;
+ rts ; End of pnt_strt.
+
+start:
+ lda #0 ; TODO: Update this for the Super VIA.
+ sta status ; Clear the control register of the I/O adapter.
+ tax ; Reset X.
+ phy.w ; Save the cursor index for later.
+ tay ; Reset the cursor index.
+ lda.w #$3FF ; Set the clear count to $3FF.
+ pha.w ; Push the clear count onto the stack.
+ lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
+ pha.q ; Push the pointer onto the stack.
+ jsr clr_arr ; Clear the command buffer.
+ pla.q ; Pull the pointer off of the stack.
+ pla.w ; Pull the clear count off of the stack.
+ ply.w ; Get back the cursor index.
+ and #0 ; Reset the Accumulator.
+ sta end ;
+ bra read ; Start reading the keyboard.
+
+read:
+ lda #0 ; Reset the Accumulator.
+ sta end ; Disable the dummy flag.
+ inc end ; Enable the dummy flag.
+ lda status ; Did we get a key?
+ beq read ; No, so try again.
+ jsr getchar ; Yes, and was it a newline?
+ beq parse ; Yes, so start parsing the line.
+ bra read ; No, so keep looping.
+
+parse:
+ lda #0 ;
+ tax ;
+ jsr subasm ;
+ bra start ;
+
+
+print_str:
+ ldx #0 ; Reset X.
+ pha.q ; Push the parameter onto the stack.
+@loop:
+ ldb #1 ; Enable replace mode.
+ stb b ;
+ and #0 ; No, reset the accumulator.
+ phy.w ; Save the cursor index.
+ txy ; Copy the string index into Y.
+ lda (sp+3), y ; Are we at the end of the string?
+ ply.w ; Get the cursor index back.
+ beq @end ; Yes, so we're done.
+ inx ; No, so increment the string index.
+ jsr print_char ; Print the character.
+ bra @loop ; Keep looping.
+@end:
+ pla.q ; Pull the parameter off the stack.
+ ldb #0 ; Enable insert mode.
+ stb b ;
+ tba ; Reset A.
+ 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:
+ tab ; Save the parameter.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
+ pha.q ; Push the pointer onto the stack.
+ tba ; Get the parameter back.
+ jsr bitpos ; Get the bit, and byte position.
+ phy.w ; Save the screen index.
+ txy ; Get the byte position.
+ ldb (sp+3), y ; Get one byte of the wrap table.
+ ply.w ; Get the screen index back.
+ aba ; Mask out the bit of the current line number.
+ cmp #1 ; Set the carry flag, if true.
+ bra bitout ; We are done.
+
+clrbit:
+ tab ; Save the parameter.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
+ pha.q ; Push the pointer onto the stack.
+ tba ; Get the parameter 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 (sp+3), y ; Get one byte of the wrap table.
+ aba ; Clear the bit of the current line number.
+bitsav:
+ sta (sp+3), y ; Update the wrap table.
+ ply.w ; Get the screen index back.
+bitout:
+ pla.q ; Pull the pointer off the stack.
+ and #0 ; Reset A.
+ ldx bitmask ; Return the bitmask.
+ rts ; We are done.
+
+setbit:
+ tab ; Save the parameter.
+ lda.d #bitabl ; Set the second pointer to the linewrap table.
+ pha.q ; Push the pointer onto the stack.
+ tba ; Get the parameter back.
+ jsr bitpos ; Get the bit, and byte position.
+ phy.w ; Save the screen index.
+ txy ; Get the byte position.
+ ldb (sp+3), y ; Get one byte of the wrap table.
+ oab ; Set the bit of the current line number.
+ bra bitsav ; Save the bit.
+
+bitpos:
+ tab ; Save the parameter.
+ lda.w #bits ; Set the first pointer to the bitmask table.
+ pha.q ; Push the pointer onto the stack.
+ tba ; 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 (sp+3), 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.
+ tab ; Preserve the bitmask.
+ pla.q ; Pull the pointer off the stack.
+ tba ; Get the bitmask back.
+ rts ; End of bitpos.
+
+getchar:
+ lda kbd ; Get the character that was typed from the keyboard.
+ ldb #0 ; Reset the B register.
+ stb e ; Set the temporary row position to zero, in case we get a newline.
+ stb b ; Enable insert mode.
+ pha ; Save the character.
+ phy.w ; Save the cursor index.
+ cmp #'\n' ; Was the character that was typed, a newline?
+ bne @print ; No, so just print the character.
+ jsr cmd_cpy ; Yes, so start copying the line to the command buffer.
+@print:
+ ply.w ; Get back the cursor index.
+ pla ; Get back the character.
+ ldb e ; Is the temporary row position non zero?
+ bne @row ; Yes, so reset the row positon.
+@print1:
+ jsr print_char ; No, so print the character.
+ lda a ; Get the return value.
+ cmp #'\n' ; Is the return value, a newline?
+ beq @true ; Yes, so return true.
+ bra @false ; No, so return false.
+@row:
+ ldb e ; Get the temporary row position.
+ cpb #maxrow ; Is temporary row position, at, or above the bottom of the screen?
+ beq @row2 ; Yes, so leave it as is.
+ bcs @row1 ; No, so set it to the bottom of the screen.
+ bra @row2 ; Yes, so leave it as is.
+@row1:
+ ldb #maxrow ; Set the row position to the bottom of the screen.
+@row2:
+ stb scr_row ; Set the row position.
+ bra @print1 ; Print the character.
+@true:
+ lda #0 ; Return true.
+ bra @end ; We are done.
+@false:
+ lda #1 ; Return false.
+@end:
+ rts ; End of getchar.
+
+
+cmd_cpy:
+ lda scr_row ; Get the row position.
+ sta scr_trow ; Save it for later.
+ jsr findend ; Find the end of the 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:
+ sec ; Yes, so make sure that we don't subtract by the starting point, plus one.
+ sbc scr_str ; Offset the row position, back by the screen's starting point.
+ clc ; Clear the carry flag, so that nothing odd occurs.
+@start:
+ sta scr_row ; Set the row position to the end of the line.
+ sta e ; Save it into the temporary row posiition.
+ jsr findst ; Find the start of the line.
+ clc ; Clear the carry flag.
+ lda scr_row ; Get the row position.
+ adc scr_str ; Add it with the screen's starting row.
+ mul #maxcol+1 ; Multiply it with the width of the screen, plus one.
+ tay ; Place it into the index.
+ ldx.w #0 ; Reset the X register.
+ ldb #0 ; Make sure that set_ptr sets the first pointer.
+ lda.d #buffer ; Set the first pointer to the start of the screen buffer.
+ pha.q ; Push the pointer onto the stack.
+ lda.d #cmd_buf ; Set the second pointer to the start of the command buffer.
+ pha.q ; Push the pointer onto the stack.
+ tba ; Set the accumulator to zero.
+@loop:
+ ldb #0 ; Reset the B register.
+ lda.q (sp+9), y ; Get eight bytes from the current line.
+@loop1:
+ phy.w ; Save the screen index.
+ txy ; Get the command buffer index.
+ sta (sp+3), y ; Copy one byte from the screen buffer, to the command buffer.
+ inx ; Increment the command buffer index.
+ ply.w ; Get back the screen index.
+ cpx.w #$3FF ; Are we at the end of the command buffer?
+ bcs @end ; Yes, so we're done.
+ iny ; No, so increment the screen index.
+ inb ; Increment the byte count.
+ lsr #8 ; Shift in the next byte.
+ stb g ; Save the byte count.
+ tab ; Save the string buffer.
+ and #$FF ; Is this byte of the buffer, a null terminator?
+ beq @end1 ; Yes, so we're done.
+ tba ; No so get back the string buffer.
+ ldb g ; Get back the byte count.
+ cpb #7 ; Did we shift in eight bytes?
+ beq @loop ; Yes, so get eight more bytes.
+ bra @loop1 ; No, so keep shifting in more bytes.
+@end:
+ ldb #0 ; Reset B.
+ phy.w ; Save the screen index.
+ txy ; Get the command buffer index.
+ stb (sp+3), y ; Terminate the command buffer.
+ ply.w ; Get back the screen index.
+@end1:
+ pla.q ; Pull one of the pointers off the stack.
+ pla.q ; Pull the other pointer off the stack.
+ tba ; The B register is zero, so clear the Accumulator.
+ rts ; End of cmd_cpy.
+
+
+findst:
+ lda #0 ; Reset A.
+@loop:
+ 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.
+ dec scr_row ; Are we at the top of the screen?
+ bpo @loop ; No, so keep looping.
+ dec ; Yes, so move back one line.
+ inc scr_row ; Put the row postiion back to zero.
+@end:
+ cmp #0 ; Update all the flags.
+ rts ; End of findst.
+
+
+fndend:
+ lda.d #buffer ; Set the first pointer to the start of the screen buffer.
+ pha.q ; Push the pointer onto the stack.
+ phb ; Save the contents of the B register.
+ ldb #0 ; Make sure that set_ptr sets the first pointer.
+ tba ; Set the Accumulator to zero.
+ plb ; Restore the contents of the B register.
+ phy.w ;
+@loop:
+ lda (sp+3), y ; Are we at the end of the string?
+ beq @end ; Yes, so we're done.
+ iny ; No, so increment the cursor index.
+ bra @loop ; Keep looping.
+@end:
+ sty.w scr_ptr3 ;
+ ply.w ;
+ pla.q ; Pull the pointer off the stack.
+ and #0 ; Reset A.
+ rts ; End of fndend.
+
+findend:
+ jsr fndend ;
+ lda.w scr_ptr3 ;
+ div #maxcol+1 ;
+ rts ;
+
+
+print_char:
+ sta a ; Save the typed character for now.
+ ldb #2 ; Make sure that set_ptr sets the third pointer.
+ lda.d #buffer ; Set the third pointer to the start of the screen buffer.
+ jsr set_ptr ;
+ ldb #0 ; Set B to zero.
+ tba ; Set the Accumulator to zero.
+ lda a ; Get back the character.
+ cmp #$1B ; Did the user type an escape character?
+ beq esc ; Yes, so go check the escape code.
+ cmp #'\n' ; No, but did the user type a newline?
+ beq nl ; Yes, so handle the newline.
+ cmp #$C ; No, but did the user type Ctrl+L?
+ beq clr_scr ; Yes, so clear the screen.
+ cmp #19 ; No, but did the user type Ctrl+S?
+ beq en_step ; Yes, so enable clock/instruction stepping.
+ cmp #18 ; No, but did the user type Ctrl+R?
+ beq dis_step ; Yes, so disable clock/instruction stepping.
+ cmp #'\b' ; No, but did the user type a backspace?
+ beq bs ; Yes, so handle the backspace.
+ cmp #$7F ; No, but did they type Delete?
+ beq bs ; Yes, so treat it as a backspace.
+printc:
+ lda #0 ; No, so start trying to print a character.
+ sta d ;
+ lda (ptr3), y ; Are we at the end of the string?
+ beq @save ; Yes, so just print the character.
+ lda b ; 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.
+ 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 e ; Use it for redrawing the line.
+ sta scr_row ; Set the row position to to the end of the line.
+ jsr findst ; Find the start of the line.
+ lda scr_row ; Get the start of the line.
+@update2:
+ sta f ; Set the starting line, to the start of the line.
+ jsr rdrw_ln ; Redraw the line.
+ lda scr_trow ; Get the real row position back.
+ sta scr_row ;
+ lda scr_tcol ; Get the real column position back.
+ sta scr_col ;
+ jsr update_pos ; Update the cursor's position.
+ dec d ;
+ bra @save1 ;
+@shift:
+ ldy.w scr_ptr3 ;
+ inc scr_ptr3 ;
+ tyx ;
+ dey ;
+ ldb #1 ;
+ stb d ;
+ jsr shftln ;
+ ldb #1 ;
+ stb d ;
+ lda a ;
+ sta (ptr3), y ; store typed character into the input buffer.
+ lda scr_row ;
+ sta scr_trow ;
+ bra @update ;
+@save:
+ ldb d ;
+ bne @update ;
+@save1:
+ lda a ;
+ sta (ptr3), y ; store typed character into the input buffer.
+@incr:
+ inc scr_col ; Increment the cursor's x coordinate.
+ iny ;
+@wrapped:
+ ldb #1 ;
+ stb f ;
+ ldb scr_col ;
+ cpb #maxcol+1 ;
+ bcs @scrolled ;
+@print:
+ sta scr ; Echo typed character.
+ ldb f ;
+ beq @wrap ;
+ bra printc_end ;
+@scrolled:
+ ldb scr_row ;
+ cpb #maxrow ;
+ bcs @scroll ;
+@wrapped2:
+ ldb #0 ;
+ stb f ;
+ bra @print ;
+@scroll:
+ sta scr ; Echo typed character.
+ clc ;
+ lda #1 ;
+ sta wrapped ;
+ jsr scrl_down ;
+@wrap:
+ ldb #0
+ stb scr_col ;
+ ldb scr_row ;
+ cpb #maxrow ;
+ bcs @wrap2 ;
+@wrap1:
+ inc scr_row ;
+@wrap2:
+ phx.w ;
+ clc ;
+ lda scr_row ;
+ adc scr_str ;
+ tax ;
+ jsr setbit ;
+ plx.w ;
+ jsr update_pos ;
+printc_end:
+ rts ;
+
+nl:
+ lda #0 ; Reset A.
+ ldb (ptr3), y ; Is this character not a null terminator?
+ bne @scroll ; Yes, so don't overwrite it.
+ sta (ptr3), y ; No, so overwrite it.
+@scroll:
+ sta scr_col ; Move the cursor to the start of the next line.
+ lda scr_row ; Get the row position.
+ cmp #maxrow ; Are we at the bottom of the screen?
+ bcc @incr ; No, so move down one line.
+ jsr scrl_down ; Yes, so scroll down one line.
+ bra @end ; We are done.
+@incr:
+ inc scr_row ; Move the cursor down by one line.
+ jsr update_pos ; Update the cursor's position.
+@end:
+ lda #'\n' ; Print the newline.
+ sta a ;
+ rts ;
+
+
+clr_scr:
+ lda #maxrow ;
+ sta scr_end ;
+ lda #0 ;
+ sta scr_str ;
+ sta.q bitabl ;
+ sta.q bitabl+8 ;
+ tay ;
+ lda.w #$1FFF ; Set the clear count to $1FFF.
+ pha.w ; Push the clear count onto the stack.
+; sta.w scr_ptr ;
+ lda.d #buffer ; Set the array to be cleared to the screen buffer.
+ pha.q ; Push the pointer onto the stack.
+ jsr clr_arr ; Clear the screen buffer.
+ tay ;
+ pla.q ; Pull the pointer off of the stack.
+ pla.w ; Pull the clear count off of the stack.
+ lda.w #$3FF ; Set the clear count to $3FF.
+ pha.w ; Push the clear count onto the stack.
+; sta.w scr_ptr ;
+ lda.d #cmd_buf ; Set the array to be cleared to the command buffer.
+ pha.q ;
+ jsr clr_arr ; Clear the screen buffer.
+ pla.q ; Pull the pointer off of the stack.
+ pla.w ; Pull the clear count off of the stack.
+ and #0 ; Reset A.
+ sta scr_col ;
+ sta scr_row ;
+ jsr update_pos ;
+ lda #$C ;
+ sta scr ;
+ rts ;
+
+en_step:
+ lda step ;
+ beq step_en ;
+ rts ;
+step_en:
+ lda #1 ;
+ sta step ;
+ rts ;
+
+dis_step:
+ lda step ;
+ bne step_dis ;
+ rts ;
+step_dis:
+ lda #0 ;
+ sta step ;
+ rts ;
+
+
+bs:
+ lda scr_col ; Are we at the far left of the screen?
+ beq @wrap ; Yes, so check for a wrapped line.
+ bra back ; No, so add the backspace to the buffer.
+@wrap:
+ jsr getbit ; Is this line, a wrapped line?
+ bcs @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?
+ beq @wrap2 ; Yes, so check if the screen is at the top of the buffer.
+ bra @wrap3 ; No, so start clearing the wrap bit.
+@wrap2:
+ lda scr_str ; Are we at the top of the buffer?
+ bne @scroll ; Yes, so scroll up.
+ rts ; No, so we're done.
+@scroll:
+ clc ; Clear the carry flag, so that we don't get odd behaviour.
+ jsr scrl_up ; Scroll up.
+ inc scr_row ; Move down by one row.
+@wrap3:
+ clc ; Clear the carry flag.
+ lda scr_row ; Add the cursor's row position,
+ adc scr_str ; and the screen's starting row.
+ tax ; Transfer that into X.
+@wrap4:
+ dec scr_row ; Move up by one row.
+ ldb #maxcol+1 ; Move the cursor to the absolute right of the screen.
+ stb scr_col ;
+ jsr update_pos ; Update the cursor's position.
+back:
+ ldb #0 ; Reset B, and some flags.
+ stb e ;
+ stb f ;
+ lda scr_row ; Save the current row position for later.
+ sta scr_trow ;
+ jsr findend ; Find the end of the 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?
+ beq @shift ; No, so skip updating any other lines.
+ bcs @update ; Yes, so update the other lines.
+ lda scr_trow ; Get the real row position back.
+ sta scr_row ;
+@shift:
+ dey ; Decrement the buffer's offset.
+ lda #0 ; Place a null terminator
+ sta (ptr3), y ; into the buffer.
+ tyx ; Copy the current cursor index to X.
+ iny ; Increment cursor index.
+ ldb #0 ; Set shifting direction to left.
+ stb d ;
+ jsr shftln ; Shift line back by one character.
+ lda #$7F ; Print a backspace to the screen.
+ sta scr ;
+ lda e ; 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 e ; Set the end parameter to it.
+ lda scr_col ; Save the current column position for now.
+ sta scr_tcol ;
+ jsr rdrw_ln ; Start redrawing the line.
+ lda scr_tcol ; Get the real column position back.
+ sta scr_col ;
+@load:
+ lda scr_trow ; Get the real row position back.
+ sta scr_row ;
+ dec scr_col ; Move the cursor back by one column,
+ jsr update_pos ; and update it's position.
+ rts ; We are done.
+@update:
+ lda scr_row ; Set the line to start redrawing, to the start of the line.
+ sta f ;
+ inc e ; Set the redraw flag to true.
+ bra @shift ; Start shifting the line back.
+
+
+shftln:
+ ldb d ; 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.
+@neg:
+ 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 @neg ; 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.
+@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.
+@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.
+@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 d ; 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 d ; 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.
+
+esc:
+ lda status ; Get the next character.
+ lda kbd ;
+ cmp #$1B ; Is this character an escape character?
+ beq shftesc ; Yes, so check the other set of escape routines.
+ lda status ; No, so wait for the next character.
+ beq @end ; We have an error, so discard it, and go back to getting user input.
+ lda kbd ; Get the escape code.
+ sta c ; Store the escape code, until we need it.
+ lda #0 ; Set the D pseudo register to zero.
+ sta d ;
+ jsr isup ; Check if the user pressed up.
+ lda d ; Did the user press up?
+ bne @end ; Yes, so we're done.
+ jsr isdown ; No, so check if the user pressed down.
+ lda d ; Did the user press down?
+ bne @end ; Yes, so we're done.
+ lda #0 ; No, so check if the user pressed left.
+ jsr isleft ;
+ lda d ; Did the user press left?
+ bne @end ; Yes, so we're done.
+ jsr isright ; No, so check if the user pressed right.
+@end:
+ lda #0 ; Clear the D pseudo register.
+ sta d ;
+ rts ; We are done.
+
+shftesc:
+ lda status ; Skip the '['.
+ lda kbd ;
+ lda status ; Wait for the next character.
+ beq @end ; We have an error, so discard it, and go back to getting user input.
+ lda kbd ; Get the escape code.
+ sta c ; Store the escape code, until we need it.
+ lda #0 ; Use the D pseudo register as a skip flag.
+ sta d ;
+ jsr isshftup ; Check if the user pressed shift+up.
+ lda d ; Was it successful?
+ bne @end ; Yes, so we're done.
+ jsr isshftdown ; No, so check if the user pressed shift+down.
+@end:
+ lda #0 ; Clear the D pseudo register.
+ sta d ;
+ rts ; We are done.
+
+
+isup:
+ lda c ; Load the escape code into the accumulator.
+ cmp #'A' ; Did the user press the up arrow key?
+ bne @end ; No, so we're done.
+ lda scr_row ; Yes, but is the cursor at the top of the screen?
+ beq @scroll ; Yes, so check if we need to scroll.
+@check2:
+ lda c ; No, so load the escape code back into the accumulator.
+ cmp #'A' ; Did the user press the up arrow key?
+ beq @up ; Yes, so move the cursor up.
+ bra @end ; No, so we're done.
+@up:
+ dec scr_row ; Move the cursor up a line.
+ jsr update_pos ; Update it's position.
+ lda #1 ; Tell the escape routine that we succeded.
+ sta d ;
+ rts ; We are done.
+@scroll:
+ lda scr_str ; Are we at the top of the screen buffer?
+ beq @end ; Yes, so we're done.
+ jsr scrl_up ; No, so scroll up.
+ lda #1 ; Tell the escape routine that we were successful.
+ sta d ;
+@end:
+ rts ; End of isup.
+
+
+isdown:
+ lda c ; Load the escape code into the accumulator.
+ cmp #'B' ; Did the user press the down arrow key?
+ bne @end ; No, so we're done.
+ lda scr_row ; Yes, so start checking the y coordinate of the cursor.
+ cmp #maxrow ; Is the cursor at the bottom of the screen?
+ beq @scroll ; Yes, so scroll down.
+ lda c ; No, so load the escape code back into the accumulator.
+ cmp #'B' ; Did the user press the down arrow key?
+ beq @down ; Yes, so move the cursor down.
+ bra @end ; No, so we're done.
+@down:
+ inc scr_row ; Move the cursor down a line.
+ jsr update_pos ; Update it's position.
+ lda #1 ; Tell the escape routine that we succeded.
+ sta d ;
+ rts ; We are done.
+@scroll:
+ lda scr_row ; Save the cursor's row number.
+ sta scr_trow ;
+ lda scr_col ; Save the cursor's column number.
+ sta scr_tcol ;
+ jsr scrl_down ; Scroll down.
+ lda scr_trow ; Load the cursor's row number.
+ sta scr_row ;
+ lda scr_tcol ; Load the cursor's column number.
+ sta scr_col ;
+ lda #1 ; Tell the escape routine that we were successful.
+ sta d ;
+@end:
+ rts ; End of isdown.
+
+
+isright:
+ lda c ; Load the escape code into the accumulator.
+ cmp #'C' ; Did the user press the right arrow key?
+ bne @end2 ; No, so we're done.
+ lda scr_col ; Yes, so start checking the x coordinate of the cursor.
+ cmp #maxcol ; Is the cursor at the far right of the screen?
+ beq @wrap ; Yes, so check if this is a wrapped line.
+ bra @right ; No, so move the cursor right, like normal.
+@wrap:
+ inc scr_row ; Move down a row.
+ jsr getbit ; Is the current line, a wrapped line?
+ bcs @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:
+ lda scr_str ; Are we at the top of the screen buffer?
+ beq @end ; Yes, so we're done.
+ lda #1 ; No, so scroll down.
+ sta wrapped ; Set the wrapped flag.
+ jsr scrl_down ; Scroll down.
+ bra @end ; We are done.
+@incr:
+ lda #0 ; Set the cursor to the far left of the screen.
+ sta scr_col ;
+ lda scr_row ; Get the current row number.
+ cmp #maxrow ; Are we at the bottom of the screen?
+ beq @end1 ; No, so we're done.
+ bcs @scroll ; Yes, so check if we are scrolling down.
+ bra @end1 ; No, so we're done.
+@right:
+ inc scr_col ; Move the cursor right by one character.
+ jsr update_pos ; Update it's position.
+ rts ; End of isright.
+@end:
+ dec scr_row ; Move back up a row.
+@end1:
+ jsr update_pos ; Update the cursor position.
+@end2:
+ lda #0 ; Unset the wrapped flag.
+ sta wrapped ;
+ rts ; End of isright.
+
+
+isleft:
+ lda c ; Load the escape code into the accumulator.
+ cmp #'C' ; Did the user press right?
+ beq @end1 ; Yes, so we're done
+ lda scr_col ; No, but is the cursor at the far left of the screen?
+ beq @wrap ; Yes, so start checking if this is a wrapped line.
+ lda c ; No, so load the escape code back into the accumulator.
+ cmp #'D' ; Did the user press the left arrow key?
+ beq @left ; Yes, so move the cursor left.
+ bra @end1 ; No, so we're done.
+@wrap:
+ jsr getbit ; Is the current line, a wrapped line?
+ bcs @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?
+ beq @decr1 ; Yes, so don't move up a line.
+ lda #1 ; No, so set the wrapped flag.
+ sta wrapped ;
+ dec scr_row ; Move the cursor up one line.
+@decr1:
+ lda #maxcol ; Move the Cursor to the far right of the screen.
+ sta scr_col ;
+ lda #1 ; Tell the escape routine that we were successful.
+ sta d ;
+ lda scr_row ; Are we at the top of the screen?
+ beq @scroll ; Yes, so check if we need to scroll.
+ bra @end ; No, so we're done.
+@scroll:
+ lda wrapped ; Was the wrapped flag set somewhere else?
+ bne @end ; Yes so we're done.
+ lda scr_str ; No, but are we actually at the top of the screen buffer?
+ beq @end1 ; Yes, so we're done.
+ jsr scrl_up ; No, so scroll up.
+ bra @end1 ; We are done.
+@left:
+ dec scr_col ; Move the cursor left a character.
+ jsr update_pos ; Update it's position.
+ lda #1 ; Tell the escape routine that we succeded.
+ sta d ;
+ rts ; We are done
+@end:
+ jsr update_pos ; Update the cursor position.
+@end1:
+ lda #0 ; Unset the wrapped flag.
+ sta wrapped ;
+ rts ; End of isleft.
+
+
+isshftup:
+ lda c ; Load the escape code back into the accumulator.
+ cmp #'A' ; Did the user press the up arrow key?
+ bne @end ;
+ lda #1 ;
+ sta d ;
+ lda scr_str ;
+ beq @end ;
+@shftup:
+ jsr scrl_up ;
+ lda #1 ;
+ sta d ;
+@end:
+ rts ;
+
+
+isshftdown:
+ lda c ; Load the escape code back into the accumulator.
+ cmp #'B' ; Did the user press the down arrow key?
+ bne @end ;
+ lda #1 ;
+ sta d ;
+ lda scr_end ;
+ cmp #71 ;
+ bcs @end ;
+@shftdown:
+ jsr scrl_down ;
+ lda #1 ;
+ sta d ;
+@end:
+ rts ;
+
+
+update_pos:
+ ldb #1 ; Set the F pseudo register to one, to fix some bugs.
+ stb f ;
+ 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.
+ tay ; Place it in the Y regster for now.
+ 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.
+ 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.
+ jsr getrow ; Start printing the row number to the screen.
+ jsr getcol ; Start printing the column number to the screen.
+ lda #'H' ; Print 'H'
+ sta scr ; to the screen.
+ rts ; End of update_pos.
+
+getrow:
+ lda scr_row ; Get the cursor's y coordinate.
+ bra bcd ; Convert it to BCD.
+getcol:
+ lda #';' ; Print ';'
+ sta scr ; to the screen.
+ lda scr_col ; Get the cursor's x coordinate.
+bcd:
+ div #10 ; Divide A by 10.
+ ora #'0' ; Convert it to ascii, and
+ sta scr ; print to the screen.
+ tba ; Get the remainder.
+ ora #'0' ; Convert it to ascii, and
+ sta scr ; print to the screen.
+ rts ; End of bcd.
+
+scrl_down:
+ inc scr_str ; Increment the starting line of the screen.
+ inc scr_end ; Increment the ending line of the screen.
+ lda #$1B ; Print an escape character
+ sta scr ; to the screen.
+ lda #'[' ; Print '['
+ sta scr ; to the screen, and start the escape sequence.
+ lda #'T' ; Print 'T'
+ sta scr ; to the screen, and end the escape sequence.
+ lda scr_row ; Get the cursor's line number.
+ pha ; Save it in the stack.
+ lda wrapped ; Was the wrapped flag set?
+ beq @save ; Yes, so save the cursor position.
+@redraw:
+ 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.
+ bra @end ; No, so we're done.
+@save:
+ lda scr_col ; Get the cursor's column number.
+ pha ; Save it in the stack.
+ bra @redraw ; Start redrawing the current row.
+@load:
+ pla ; Get the cursor's previous column number back.
+ sta scr_col ;
+@end:
+ pla ; Get the cursor's previous line number back.
+ sta scr_row ;
+ jsr update_pos ; Update the cursor's position.
+ lda #0 ; Clear the wrapped flag.
+ sta wrapped ;
+@end1:
+ rts ; End of scrl_down.
+
+scrl_up:
+ dec scr_str ;
+ dec scr_end ;
+ lda #$1B ; Print an escape character
+ sta scr ; to the screen.
+ lda #'[' ; Print '['
+ sta scr ; to the screen, and start the escape sequence.
+ lda #'S' ; Print 'S'
+ sta scr ; to the screen, and end the escape sequence.
+ lda scr_row ;
+ pha ;
+ lda scr_col ;
+ pha ;
+ lda #0 ;
+ sta scr_row ;
+ jsr rdrw_row ;
+ pla ;
+ sta scr_col ;
+ pla ;
+ sta scr_row ;
+ jsr update_pos ;
+@end:
+ rts ;
+
+rdrw_row:
+ lda #0 ;
+ sta scr_col ;
+ jsr update_pos ;
+@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 ;
+@end:
+ lda #0 ;
+ sta scr_col ;
+ jsr update_pos ;
+@end1:
+ rts ;
+
+rdrw_ln:
+ lda scr_row ;
+ pha ;
+ lda f ;
+ sta scr_row ;
+ lda scr_col ;
+ pha ;
+ jsr update_pos ;
+@loop:
+ lda scr_row ;
+ cmp e ;
+ beq @loop1 ;
+ bcs @end ;
+@loop1:
+ jsr rdrw_row ;
+@incr:
+ inc scr_row ;
+ bra @loop ;
+@end:
+ pla ;
+ sta scr_col ;
+ pla ;
+ sta scr_row ;
+ jsr update_pos ;
+ lda #0 ;
+ sta e ;
+ sta f ;
+ rts ;
+
+set_ptr:
+ cpb #1 ; Are we setting the second pointer?
+ beq @ptr2 ; Yes, so start setting it.
+ cpb #2 ; No, but are we setting the third pointer?
+ beq @ptr3 ; Yes, so start setting it.
+@ptr1:
+ stb.q ptr ; Reset the first pointer.
+ sta.q ptr ; No, so set the first pointer.
+ bra @end ; We are done.
+@ptr2:
+ stb.q ptr2 ; Reset the second pointer.
+ sta.q ptr2 ; Set the second pointer.
+ bra @end ; We are done.
+@ptr3:
+ stb.q ptr3 ; Reset the third pointer.
+ sta.q ptr3 ; Set the third pointer.
+@end:
+ rts ; End of set_ptr.
diff --git a/sux.c b/sux.c
index f064cee..4ccd2d5 100644
--- a/sux.c
+++ b/sux.c
@@ -70,11 +70,45 @@ void start_timer(int sec, int usec) {
}
#endif
+uint8_t is_extop(uint8_t opcode, uint8_t dbg) {
+ switch (opcode) {
+ case ADC_E:
+ case SBC_E:
+ case AND_E:
+ case ORA_E:
+ case XOR_E:
+ case LSL_E:
+ case LSR_E:
+ case ROL_E:
+ case ROR_E:
+ case MUL_E:
+ case DIV_E:
+ case ASR_E:
+ case CMP_E:
+ case LDY_E:
+ case LDA_E:
+ case LDB_E:
+ case CPB_E:
+ case CPX_E:
+ case CPY_E:
+ case LDX_E:
+ case DEC_E:
+ case INC_E:
+ case STY_E:
+ case STA_E:
+ case STB_E:
+ case STX_E: return 0;
+ }
+ return 1;
+}
+
void *run(void *args) {
struct suxthr *thr = (void *)args;
struct sux *cpu = &thr->sx;
uint8_t thread = thr->th;
uint8_t prefix = 0;
+ uint8_t ext_prefix = 0;
+ uint8_t prefix2 = 0;
uint8_t opcode = 0;
union reg address;
union reg value;
@@ -141,13 +175,58 @@ void *run(void *args) {
pthread_mutex_unlock(&mutex);
#endif
#endif
- uint16_t instr = read_value(cpu, 0, cpu->pc, 1, 1, 0);
+ uint32_t instr = read_value(cpu, 0, cpu->pc, 3, 1, 0);
uint8_t *tmp_inst = (uint8_t *)&instr;
prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0;
+ ext_prefix = ((*tmp_inst & 0xD) == 0xD) ? *tmp_inst++ : 0;
opcode = *tmp_inst;
- cpu->pc += ((instr & 3) == 3)+1;
+ cpu->pc += ((instr & 3) == 3)+((ext_prefix & 0xD) == 0xD)+1;
address.u64 = cpu->pc;
- uint8_t am = optype[opcode];
+ uint8_t am;
+ uint8_t ext_id = 0;
+ uint8_t tmp_opcode = opcode;
+ uint8_t tmp_ext_prefix = ext_prefix;
+ if (ext_prefix) {
+ ext_id = ((ext_prefix >> 4) & 0xF);
+ switch (ext_id) {
+ case 0x0:
+ am = ext_optype[opcode];
+ if (!is_extop(opcode, 0)) {
+ tmp_ext_prefix = 0;
+ switch (opcode) {
+ case ADC_E: tmp_opcode = ADC_IMM; break;
+ case SBC_E: tmp_opcode = SBC_IMM; break;
+ case AND_E: tmp_opcode = AND_IMM; break;
+ case ORA_E: tmp_opcode = ORA_IMM; break;
+ case XOR_E: tmp_opcode = XOR_IMM; break;
+ case LSL_E: tmp_opcode = LSL_IMM; break;
+ case LSR_E: tmp_opcode = LSR_IMM; break;
+ case ROL_E: tmp_opcode = ROL_IMM; break;
+ case ROR_E: tmp_opcode = ROR_IMM; break;
+ case MUL_E: tmp_opcode = MUL_IMM; break;
+ case DIV_E: tmp_opcode = DIV_IMM; break;
+ case ASR_E: tmp_opcode = ASR_IMM; break;
+ case CMP_E: tmp_opcode = CMP_IMM; break;
+ case LDY_E: tmp_opcode = LDY_IMM; break;
+ case LDA_E: tmp_opcode = LDA_IMM; break;
+ case LDB_E: tmp_opcode = LDB_IMM; break;
+ case CPB_E: tmp_opcode = CPB_IMM; break;
+ case CPX_E: tmp_opcode = CPX_IMM; break;
+ case CPY_E: tmp_opcode = CPY_IMM; break;
+ case LDX_E: tmp_opcode = LDX_IMM; break;
+ case DEC_E: tmp_opcode = DEC_Z; break;
+ case INC_E: tmp_opcode = INC_Z; break;
+ case STY_E: tmp_opcode = STY_Z; break;
+ case STA_E: tmp_opcode = STA_Z; break;
+ case STB_E: tmp_opcode = STB_Z; break;
+ case STX_E: tmp_opcode = STX_Z; break;
+ }
+ }
+ break;
+ }
+ } else {
+ am = optype[opcode];
+ }
uint8_t rs = (prefix >> 4) & 3;
uint8_t size = (/***/1 << rs) - 1;
uint8_t check_io = (am != IMM);
@@ -155,14 +234,14 @@ void *run(void *args) {
#if keypoll
pthread_mutex_lock(&mutex);
#endif
- disasm(cpu, lines, opcode, prefix, thread);
+ disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, thread);
lines+=1;
#if keypoll
pthread_mutex_unlock(&mutex);
#endif
#endif
if (am != IMPL && am != BREG) {
- address.u64 = get_addr(cpu, opcode, prefix, 1, 1, thread);
+ address.u64 = get_addr(cpu, opcode, prefix, ext_prefix, 1, 1, thread);
/*if (address.u64 > mem_size-1) {
addr[STEP_ADDR] = 1;
step = 1;
@@ -172,314 +251,14 @@ void *run(void *args) {
}
}
/*decode_microinst(&uc, &uc_test, prefix, 0);*/
- switch (opcode) {
- case CPS_IMP: /* Clear Processor Status. */
- cpu->ps.u64 = 0;
- break;
- case ADC_B: /* ADC B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case ADC_IMM: /* ADC Immediate. */
- case ADC_AB: /* ADC Absolute. */
- case ADC_Z: /* ADC Zero Matrix. */
- cpu->a = adc(cpu, cpu->a, value.u64, 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. */
- case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */
- case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */
- case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */
- case TAY_IMP: cpu->y = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */
- case TAX_IMP: cpu->x = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */
- case TYX_IMP: cpu->x = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to X. */
- case TYA_IMP: cpu->a = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to Accumulator. */
- case TXA_IMP: cpu->a = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Accumulator. */
- case TXY_IMP: cpu->y = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Y. */
- case TAB_IMP: cpu->b = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to B. */
- case TSX_IMP: cpu->x = transfer(cpu, cpu->sp, value.u64, thread); break; /* Transfer Stack pointer to X. */
- case TBA_IMP: cpu->a = transfer(cpu, cpu->b , value.u64, thread); break; /* Transfer B to Accumulator. */
- case TXS_IMM: cpu->sp = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Stack pointer. */
- case BRA_REL: /* BRA Relative. */
- case JMP_AB: /* JMP Absolute. */
- case JMP_Z: /* JMP Zero Matrix. */
- case JMP_IN: /* JMP Indirect. */
- cpu->pc = address.u64;
- break;
- case SBC_B: /* SBC B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case SBC_IMM: /* SBC Immediate. */
- case SBC_AB: /* SBC Absolute. */
- case SBC_Z: /* SBC Zero Matrix. */
- cpu->a = adc(cpu, cpu->a, ~value.u64, 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. */
- case PLB_IMP: cpu->b = pull(cpu, size, thread); break; /* PuLl B register from stack. */
- case PLY_IMP: cpu->y = pull(cpu, size, thread); break; /* PuLl Y register from stack. */
- case PLX_IMP: cpu->x = pull(cpu, size, thread); break; /* PuLl X register from stack. */
- break;
- case AND_B: /* AND B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case AND_IMM: /* AND Immediate. */
- case AND_AB: /* AND Absolute. */
- case AND_Z: /* AND Zero Matrix. */
- cpu->a = and(cpu, cpu->a, value.u64, thread);
- break;
- case BPO_REL: /* BPO Relative. */
- if (!getflag(N)) {
- cpu->pc = address.u64;
- }
- break;
- case ORA_B: /* ORA B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case ORA_IMM: /* ORA Immediate. */
- case ORA_AB: /* ORA Absolute. */
- case ORA_Z: /* ORA Zero Matrix. */
- cpu->a = or(cpu, cpu->a, value.u64, thread);
- break;
- case SEI_IMP: /* SEt Interrupt. */
- setflag(1, I);
- break;
- case BNG_REL: /* BNG Relative. */
- if (getflag(N)) {
- cpu->pc = address.u64;
- }
- break;
- case XOR_B: /* XOR B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case XOR_IMM: /* XOR Immediate. */
- case XOR_AB: /* XOR Absolute. */
- case XOR_Z: /* XOR Zero Matrix. */
- cpu->a = xor(cpu, cpu->a, value.u64, thread);
- break;
- case CLI_IMP: /* CLear Interrupt. */
- setflag(0, I);
- break;
- case BCS_REL: /* BCS Relative. */
- if (getflag(C)) {
- cpu->pc = address.u64;
- }
- break;
- case LSL_B: /* LSL B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case LSL_IMM: /* LSL Immediate. */
- case LSL_AB: /* LSL Absolute. */
- case LSL_Z: /* LSL Zero Matrix. */
- cpu->a = lsl(cpu, cpu->a, value.u64, thread);
- break;
- case SEC_IMP: /* SEt Carry flag.*/
- setflag(1, C);
- break;
- case STA_AB: /* STA Absolute. */
- case STA_Z: /* STA Zero Matrix. */
- case STA_ZX: /* STA Zero Matrix, Indexed with X. */
- case STA_ZY: /* STA Zero Matrix, Indexed with Y. */
- case STA_IN: /* STA Indirect. */
- case STA_IX: /* STA Indexed Indirect. */
- case STA_IY: /* STA Indirect Indexed. */
- store(cpu, address.u64, cpu->a, prefix, thread);
- break;
- case STY_AB: /* STY Absolute. */
- case STY_Z: /* STY Zero Matrix. */
- case STY_IN: /* STY Indirect. */
- store(cpu, address.u64, cpu->y, prefix, thread);
- break;
- case STX_AB: /* STX Absolute. */
- case STX_Z: /* STX Zero Matrix. */
- case STX_IN: /* STX Indirect. */
- store(cpu, address.u64, cpu->x, prefix, thread);
- break;
- case STB_AB: /* STB Absolute. */
- case STB_Z: /* STB Zero Matrix. */
- case STB_ZX: /* STB Zero Matrix, Indexed with X. */
- case STB_ZY: /* STB Zero Matrix, Indexed with Y. */
- case STB_IN: /* STB Indirect. */
- case STB_IX: /* STB Indexed Indirect. */
- case STB_IY: /* STB Indirect Indexed. */
- store(cpu, address.u64, cpu->b, prefix, thread);
- break;
- case BCC_REL: /* BCC Relative. */
- if (!getflag(C)) {
- cpu->pc = address.u64;
- }
- break;
- case LSR_B: /* LSR B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case LSR_IMM: /* LSR Immediate. */
- case LSR_AB: /* LSR Absolute. */
- case LSR_Z: /* LSR Zero Matrix. */
- cpu->a = lsr(cpu, cpu->a, value.u64, thread);
- break;
- case ASR_B: /* ASR B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case ASR_IMM: /* ASR Immediate. */
- case ASR_AB: /* ASR Absolute. */
- case ASR_Z: /* ASR Zero Matrix. */
- cpu->a = asr(cpu, cpu->a, value.u64, thread);
- break;
- case CLC_IMP: /* CLear Carry flag. */
- setflag(0, C);
- break;
- case LDB_IMM: /* LDB Immediate. */
- case LDB_AB: /* LDB Absolute. */
- case LDB_Z: /* LDB Zero Matrix. */
- case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */
- case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */
- case LDB_IN: /* LDB Indirect. */
- case LDB_IX: /* LDB Indexed Indirect. */
- case LDB_IY: /* LDB Indirect Indexed. */
- cpu->b = load(cpu, cpu->b, address.u64, size, thread);
- break;
- case LDA_IMM: /* LDA Immediate. */
- case LDA_AB: /* LDA Absolute. */
- case LDA_Z: /* LDA Zero Matrix. */
- case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */
- case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */
- case LDA_IN: /* LDA Indirect. */
- case LDA_IX: /* LDA Indexed Indirect. */
- case LDA_IY: /* LDA Indirect Indexed. */
- cpu->a = load(cpu, cpu->a, address.u64, size, thread);
- break;
- case LDY_IMM: /* LDY Immediate. */
- case LDY_AB: /* LDY Absolute. */
- case LDY_Z: /* LDY Zero Matrix. */
- case LDY_IN: /* LDY Indirect. */
- cpu->y = load(cpu, cpu->y, address.u64, size, thread);
- break;
- case LDX_IMM: /* LDX Immediate. */
- case LDX_AB: /* LDX Absolute. */
- case LDX_Z: /* LDX Zero Matrix. */
- case LDX_IN: /* LDX Indirect. */
- cpu->x = load(cpu, cpu->x, address.u64, size, thread);
- break;
- case BEQ_REL: /* BEQ Relative. */
- if (getflag(Z)) {
- cpu->pc = address.u64;
- }
- break;
- case ROL_B: /* ROL B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case ROL_IMM: /* ROL Immediate. */
- case ROL_AB: /* ROL Absolute. */
- case ROL_Z: /* ROL Zero Matrix. */
- cpu->a = rol(cpu, cpu->a, value.u64, thread);
- break;
- case BNE_REL: /* BNE Relative. */
- if (!getflag(Z)) {
- cpu->pc = address.u64;
- }
- break;
- case ROR_B: /* ROR B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case ROR_IMM: /* ROR Immediate. */
- case ROR_AB: /* ROR Absolute. */
- case ROR_Z: /* ROR Zero Matrix. */
- cpu->a = ror(cpu, cpu->a, value.u64, thread);
- break;
- case BVS_REL: /* BVS Relative. */
- if (getflag(V)) {
- cpu->pc = address.u64;
- }
- break;
- case MUL_B: /* MUL B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case MUL_IMM: /* MUL Immediate. */
- case MUL_AB: /* MUL Absolute. */
- case MUL_Z: /* MUL Zero Matrix. */
- cpu->a = mul(cpu, cpu->a, value.u64, thread);
- break;
- case BVC_REL: /* BVC Relative. */
- if (!getflag(V)) {
- cpu->pc = address.u64;
- }
- break;
- case DIV_B: /* DIV B register. */
- case DIV_IMM: /* DIV Immediate. */
- 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.u64, rem, thread);
- break;
- case CLV_IMP: /* CLear oVerflow flag. */
- setflag(0, V);
- break;
- case CPB_IMM: /* CPB Immediate. */
- case CPB_AB: /* CPB Absolute. */
- case CPB_Z: /* CPB Zero Matrix. */
- case CPB_IN: /* CPB Indirect. */
- case CPB_IX: /* CPB Indexed Indirect. */
- case CPB_IY: /* CPB Indirect Indexed. */
- cmp(cpu, value.u64, cpu->b, thread);
- break;
- case CMP_B: /* CMP B register. */
- value.u64 = cpu->b; /* Falls Through. */
- case CMP_IMM: /* CMP Immediate. */
- case CMP_AB: /* CMP Absolute. */
- case CMP_Z: /* CMP Zero Matrix. */
- case CMP_IN: /* CMP Indirect. */
- case CMP_IX: /* CMP Indexed Indirect. */
- case CMP_IY: /* CMP Indirect Indexed. */
- cmp(cpu, value.u64, cpu->a, thread);
- break;
- case CPY_IMM: /* CPY Immediate. */
- case CPY_AB: /* CPY Absolute. */
- case CPY_Z: /* CPY Zero Matrix. */
- cmp(cpu, value.u64, cpu->y, thread);
- break;
- case CPX_IMM: /* CPX Immediate. */
- case CPX_AB: /* CPX Absolute. */
- case CPX_Z: /* CPX Zero Matrix. */
- cmp(cpu, value.u64, cpu->x, 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;
- case INY_IMP: cpu->y = idr(cpu, cpu->y, 1, thread); break;
- case INX_IMP: cpu->x = idr(cpu, cpu->x, 1, thread); break;
- case DEC_IMP: cpu->a = idr(cpu, cpu->a, 0, thread); break;
- case DEB_IMP: cpu->b = idr(cpu, cpu->b, 0, thread); break;
- case DEY_IMP: cpu->y = idr(cpu, cpu->y, 0, thread); break;
- case DEX_IMP: cpu->x = idr(cpu, cpu->x, 0, thread); break;
- case JSR_IN: /* JSR Indirect. */
- case JSR_AB: /* Jump to SubRoutine. */
- case JSR_Z: /* JSR Zero Matrix. */
- push(cpu, cpu->pc, (size) ? size : 7, thread);
- cpu->pc = address.u64;
- break;
- case INC_AB: /* INC Absolute. */
- case INC_Z: /* INC Zero Matrix. */
- idm(cpu, address.u64, prefix, 1, thread);
- break;
- case NOP_IMP: /* No OPeration. */
- break;
- case RTI_IMP: /* ReTurn from Interrupt routine. */
- cpu->ps.u8[thread] = pull(cpu, 0, thread);
- size = 0;
- case RTS_IMP: /* ReTurn from Subroutine. */
- cpu->pc = pull(cpu, (size) ? size : 7, thread);
- break;
- case DEC_AB: /* DEC Absolute. */
- case DEC_Z: /* DEC Zero Matrix. */
- idm(cpu, address.u64, prefix, 0, thread);
- break;
- case BRK_IMP: /* BReaK. */
- case WAI_IMP: /* WAit for Interrupt. */
- if (opcode == WAI_IMP) {
- pthread_mutex_lock(&main_mutex);
- pthread_cond_signal(&main_cond);
- pthread_mutex_unlock(&main_mutex);
- pthread_mutex_lock(&mutex);
- pthread_cond_wait(&cond, &mutex);
- pthread_mutex_unlock(&mutex);
- }
- push(cpu, cpu->pc, 7, thread);
- push(cpu, cpu->ps.u8[thread], 0, thread);
- setflag(1, I);
- setreg(value.u8, +, 0, addr, +, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7);
- if (opcode == WAI_IMP) {
- kbd_rdy &= (uint8_t)~(1 << thread);
- }
- cpu->pc = value.u64;
- default:
- break;
+ ext_prefix = tmp_ext_prefix;
+ opcode = tmp_opcode;
+ if (ext_prefix) {
+ switch (ext_id) {
+ case 0x0: exec_ext_inst(cpu, opcode, prefix, value, address, size, thread); break;
+ }
+ } else {
+ exec_base_inst(cpu, opcode, prefix, value, address, size, thread);
}
#if !IO
ins++;
diff --git a/sux.h b/sux.h
index f719b03..9d7bcb3 100644
--- a/sux.h
+++ b/sux.h
@@ -44,7 +44,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 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);
#endif
/*#define KEYBUF_SIZE 0x40
@@ -59,6 +59,11 @@ static inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
uint8_t id = (prefix & 0x0C) >> 2;
switch (addrmode) {
case ZM:
+ case ZMX:
+ case ZMY:
+ case IND:
+ case INDX:
+ case INDY:
switch (id) {
case 2: return 5;
case 3: return 3;
@@ -67,6 +72,11 @@ static inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
}
break;
case ABS:
+ case ABSX:
+ case ABSY:
+ case AIND:
+ case AINDX:
+ case AINDY:
switch (id) {
case 3: return 7;
case 2: return 6;
@@ -75,7 +85,7 @@ static inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
}
break;
}
- return 0;
+ return 0xFF;
}
static inline uint8_t isrw(uint8_t opcode) {
@@ -269,37 +279,26 @@ static inline uint64_t read_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_cl
return address;
}
-static inline uint64_t zmx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+static inline uint64_t idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg) {
#if getclk
cpu->clk += inc_clk;
#endif
- return read_addr(cpu, prefix, inc_clk, ZM, inc_pc) + cpu->x;
+ return read_addr(cpu, prefix, inc_clk, type, inc_pc) + idx_reg;
}
-static inline uint64_t zmy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
- #if getclk
- cpu->clk += inc_clk;
- #endif
- return read_addr(cpu, prefix, inc_clk, ZM, inc_pc) + cpu->y;
-}
-
-
-static inline uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
- return read_value(cpu, 0, read_addr(cpu, prefix, inc_clk, ZM, inc_pc), 7, inc_clk, 0);
+static inline uint64_t ind_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc) {
+ return read_value(cpu, 0, read_addr(cpu, prefix, inc_clk, type, inc_pc), 7, inc_clk, 0);
}
-static inline uint64_t indx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
+static inline uint64_t ind_idx_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t type, uint8_t inc_pc, uint64_t idx_reg, uint8_t pre_idx) {
#if getclk
cpu->clk += inc_clk;
#endif
- return read_value(cpu, 0, read_addr(cpu, prefix, inc_clk, ZM, inc_pc)+cpu->x, 7, inc_clk, 0);
-}
-
-static inline uint64_t indy_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
- #if getclk
- cpu->clk += inc_clk;
- #endif
- return ind_addr(cpu, prefix, inc_clk, inc_pc) + cpu->y;
+ if (pre_idx) {
+ return read_value(cpu, 0, read_addr(cpu, prefix, inc_clk, type, inc_pc)+idx_reg, 7, inc_clk, 0);
+ } else {
+ return ind_addr(cpu, prefix, inc_clk, type, inc_pc) + idx_reg;
+ }
}
static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk, uint8_t inc_pc) {
@@ -321,12 +320,21 @@ static inline uint64_t rel_addr(struct sux *cpu, uint8_t prefix, uint8_t inc_clk
}
}
-static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) {
+static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix, uint8_t ext_prefix, uint8_t inc_pc, uint8_t inc_clk, uint8_t thread) {
uint64_t address = 0;
- switch (optype[opcode]) {
+ uint8_t type;
+ if ((ext_prefix & 0xD) == 0xD) {
+ switch (ext_prefix >> 4) {
+ case 0x0: type = ext_optype[opcode]; break;
+ }
+ } else {
+ type = optype[opcode];
+ }
+ switch (type) {
case BREG:
case IMPL:
break;
+ case EIND: address = cpu->e; break;
case IMM:
address = imm_addr(cpu);
switch (opcode) {
@@ -335,34 +343,41 @@ static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix,
case ROL_IMM:
case ROR_IMM:
case ASR_IMM:
- if (inc_pc) {
- ++cpu->pc;
+ if ((ext_prefix & 0xD) != 0xD) {
+ if (inc_pc) {
+ ++cpu->pc;
+ }
+ break;
}
- break;
+ /* Falls Through. */
default:
if (inc_pc) {
cpu->pc+=(1 << ((prefix >> 4) & 3));
}
- /* Falls Through. */
- case TXS_IMM: break;
+ break;
}
break;
- case ZM : return read_addr(cpu, prefix, inc_clk, ZM, inc_pc);
- case ABS : return read_addr(cpu, prefix, inc_clk, ABS, inc_pc);
- case ZMX : return zmx_addr(cpu, prefix, inc_clk, /**/ inc_pc);
- case ZMY : return zmy_addr(cpu, prefix, inc_clk, /**/ inc_pc);
- case IND : return ind_addr(cpu, prefix, inc_clk, /**/ inc_pc);
- case INDX: return indx_addr(cpu, prefix, inc_clk, /**/ inc_pc);
- case INDY: return indy_addr(cpu, prefix, inc_clk, /**/ inc_pc);
- case REL : return rel_addr(cpu, prefix, inc_clk, /**/ inc_pc);
+ case ZM : return read_addr(cpu, prefix, inc_clk, ZM, inc_pc);
+ case ZMX : return idx_addr(cpu, prefix, inc_clk, ZM, inc_pc, cpu->x);
+ case ZMY : return idx_addr(cpu, prefix, inc_clk, ZM, inc_pc, cpu->y);
+ case IND : return ind_addr(cpu, prefix, inc_clk, ZM, inc_pc);
+ case INDX : return ind_idx_addr(cpu, prefix, inc_clk, ZM, inc_pc, cpu->x, 1);
+ case INDY : return ind_idx_addr(cpu, prefix, inc_clk, ZM, inc_pc, cpu->y, 0);
+ case ABS : return read_addr(cpu, prefix, inc_clk, ABS, inc_pc);
+ case ABSX : return idx_addr(cpu, prefix, inc_clk, ABS, inc_pc, cpu->x);
+ case ABSY : return idx_addr(cpu, prefix, inc_clk, ABS, inc_pc, cpu->y);
+ case AIND : return ind_addr(cpu, prefix, inc_clk, ABS, inc_pc);
+ case AINDX: return ind_idx_addr(cpu, prefix, inc_clk, ABS, inc_pc, cpu->x, 1);
+ case AINDY: return ind_idx_addr(cpu, prefix, inc_clk, ABS, inc_pc, cpu->y, 0);
+ case REL : return rel_addr(cpu, prefix, inc_clk, /**/ inc_pc);
}
return address;
}
-static inline uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
- uint64_t sum = reg+value+getflag(C);
+static inline uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t carry, uint8_t thread) {
+ uint64_t sum = reg+value+carry;
setflag(sum == 0, Z);
setflag((sum >> 63), N);
setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V);
@@ -406,55 +421,65 @@ static inline uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_
return reg;
}
-static inline uint64_t lsl(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
- uint64_t sum = (value < 64) ? reg << value : 0;
+static inline uint64_t lsl(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 = (value < msb) ? reg << value : 0;
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
- setflag(reg >> (64-value), C);
+ setflag(sum >> (msb-1), N);
+ setflag(reg >> (msb-value), C);
return sum;
}
-static inline uint64_t lsr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
- uint64_t sum = (value < 64) ? reg >> value : 0;
+static inline uint64_t lsr(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 = (value < msb) ? reg >> value : 0;
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
+ setflag(sum >> (msb-1), N);
setflag(reg & 1, C);
return sum;
}
-static inline uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
- uint8_t sign = reg >> 63;
- uint64_t sum = (value < 64) ? (reg >> value) | ((uint64_t)sign << 63) : 0;
+static inline uint64_t asr(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;
+ uint8_t sign = reg >> (msb-1);
+ uint64_t sum = (value < msb) ? (reg >> value) | ((uint64_t)sign << (msb-1)) : 0;
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
+ setflag(sum >> (msb-1), N);
setflag(reg & 1, C);
return sum;
}
-static inline uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static inline uint64_t rol(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;
uint64_t c = getflag(C);
switch (value & 0x3F) {
case 0 : return reg;
case 1 : sum = (reg << 1) | (c & 1); break;
- default: sum = (reg << value) | (c << (value-1)) | (reg >> (65-value)); break;
+ default: sum = (reg << value) | (c << (value-1)) | (reg >> ((msb+1)-value)); break;
}
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
- setflag((reg >> (64-value)) & 1, C);
+ setflag(sum >> (msb-1), N);
+ setflag((reg >> (msb-value)) & 1, C);
return sum;
}
-static inline uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+static inline uint64_t ror(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;
uint64_t c = getflag(C);
switch (value & 0x3F) {
case 0 : return reg;
- case 1 : sum = (reg >> 1) | (c << 63); break;
- default: sum = (reg >> value) | (c << (64-value)) | (reg << (65-value)); break;
+ case 1 : sum = (reg >> 1) | (c << (msb-1)); break;
+ default: sum = (reg >> value) | (c << (msb-value)) | (reg << ((msb+1)-value)); break;
}
setflag(sum == 0, Z);
- setflag(sum >> 63, N);
+ setflag(sum >> (msb-1), N);
setflag((reg >> (value-1)) & 1, C);
return sum;
}
@@ -474,6 +499,7 @@ static inline uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint6
setflag((sum >> 63), N);
return sum;
}
+
static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) {
uint64_t sum = reg-value;
setflag(sum >> 63, N);
@@ -490,6 +516,40 @@ static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t t
return reg;
}
+static inline uint64_t lbcnt(struct sux *cpu, uint64_t value, uint8_t bit, uint8_t size, uint8_t thread) {
+ size = (size > 8) ? 8 : size;
+ uint8_t msb = size*8;
+ if ((!bit && !value) || (bit && value == -1)) {
+ return msb;
+ }
+ uint64_t j = 0;
+ for (int i = msb-1; ((value >> i) & 1) == bit; i--, j++);
+ setflag(j == 0, Z);
+ return j;
+}
+
+static inline void bit_test(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ setflag((value >> 7) & 1, N);
+ setflag((value >> 6) & 1, V);
+ setflag((value & reg) == 0, Z);
+}
+
+static inline uint64_t swap(struct sux *cpu, uint64_t reg, uint8_t size, uint8_t thread) {
+ size = (size > 7) ? 7 : size;
+ uint8_t half = ((size-1)*8) >> 1;
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ uint64_t lo_mask = mask >> half;
+ uint64_t hi_mask = (mask << half) & mask;
+ return (((reg >> half) & lo_mask) | ((reg << half) & hi_mask));
+
+}
+
+static inline uint64_t popcnt(struct sux *cpu, uint64_t value, uint8_t thread) {
+ uint64_t count = 0;
+ for (; value; count++, value &= value - 1);
+ return count;
+}
+
/* Increment, or Decrement memory. */
static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t inc, uint8_t thread) {
uint8_t size = (1 << ((prefix >> 4) & 3))-1;
@@ -508,6 +568,47 @@ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_
write_value(cpu, value, address, size, 1, 1);
}
+static inline void bitshft_mem(struct sux *cpu, uint8_t shft_type, uint64_t shft_cnt, uint64_t address, uint8_t prefix, uint8_t thread) {
+ uint8_t size = (1 << ((prefix >> 4) & 3))-1;
+ uint64_t value = read_value(cpu, 0, address, size, 1, 0);
+ switch (shft_type) {
+ case 0: value = lsl(cpu, value, shft_cnt, size+1, thread); break;
+ case 1: value = lsr(cpu, value, shft_cnt, size+1, thread); break;
+ case 2: value = rol(cpu, value, shft_cnt, size+1, thread); break;
+ case 3: value = ror(cpu, value, shft_cnt, size+1, thread); break;
+ case 4: value = asr(cpu, value, shft_cnt, size+1, thread); break;
+ }
+ write_value(cpu, value, address, size, 1, 1);
+}
+
+static inline void not_mem(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_t thread) {
+ uint8_t size = (1 << ((prefix >> 4) & 3))-1;
+ write_value(cpu, ~read_value(cpu, 0, address, size, 1, 0), address, size, 1, 1);
+}
+
+static inline void lbcnt_mem(struct sux *cpu, uint64_t address, uint8_t bit, uint8_t size, uint8_t thread) {
+ uint64_t value = read_value(cpu, 0, address, size, 1, 0);
+ write_value(cpu, lbcnt(cpu, value, bit, size, thread), address, size, 1, 1);
+}
+
+static inline void swap_mem(struct sux *cpu, uint64_t address, uint8_t size, uint8_t thread) {
+ uint64_t value = read_value(cpu, 0, address, size, 1, 0);
+ write_value(cpu, swap(cpu, value, size, thread), address, size, 1, 1);
+}
+
+static inline uint64_t mem_move(struct sux *cpu, uint64_t n, uint64_t dst, uint64_t src, uint8_t rep, uint8_t size, uint8_t thread) {
+ if (!rep) {
+ uint64_t value = read_value(cpu, 0, src, size, 1, 1);
+ write_value(cpu, value, dst, size, 1, 1);
+ return n-(size+1);
+ } else {
+ if (src < mem_size && dst < mem_size) {
+ memcopy(addr+dst, addr+src, n*(size+1));
+ }
+ return 0;
+ }
+}
+
static inline uint64_t load(struct sux *cpu, uint64_t reg, uint64_t address, uint8_t size, uint8_t thread) {
uint64_t value = read_value(cpu, reg, address, size, 1, 1);
setflag(value == 0, Z);
@@ -519,3 +620,588 @@ static inline void store(struct sux *cpu, uint64_t address, uint64_t reg, uint8_
uint8_t size = (1 << ((prefix >> 4) & 3))-1;
write_value(cpu, reg, address, size, 1, 1);
}
+
+static inline void exec_ext_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, union reg value, union reg address, uint8_t size, uint8_t thread) {
+ uint8_t addr_size = get_addrsize(ext_optype[opcode], prefix);
+ uint8_t tmp = 0;
+ switch (opcode) {
+ case LEA_AB : /* LEA Absolute. */
+ case LEA_AX : /* LEA Absolute, Indexed with X. */
+ case LEA_AY : /* LEA Absolute, Indexed with Y. */
+ case LEA_AI : /* LEA Absolute Indirect. */
+ case LEA_AIX: /* LEA Absolute Indexed Idirect. */
+ case LEA_AIY: /* LEA Absolute Indirect Indexed. */
+ case LEA_Z : /* LEA Zero Matrix. */
+ case LEA_ZX : /* LEA Zero Matrix, Indexed with X. */
+ case LEA_ZY : /* LEA Zero Matrix, Indexed with Y. */
+ case LEA_IN : /* LEA Indirect. */
+ case LEA_IX : /* LEA Indexed Idirect. */
+ case LEA_IY : /* LEA Indirect Indexed. */
+ cpu->e = address.u64;
+ break;
+ case PEA_AB : /* PEA Absolute. */
+ case PEA_AX : /* PEA Absolute, Indexed with X. */
+ case PEA_AY : /* PEA Absolute, Indexed with Y. */
+ case PEA_AI : /* PEA Absolute Indirect. */
+ case PEA_AIX: /* PEA Absolute Indexed Idirect. */
+ case PEA_AIY: /* PEA Absolute Indirect Indexed. */
+ case PEA_Z : /* PEA Zero Matrix. */
+ case PEA_ZX : /* PEA Zero Matrix, Indexed with X. */
+ case PEA_ZY : /* PEA Zero Matrix, Indexed with Y. */
+ case PEA_IN : /* PEA Indirect. */
+ case PEA_IX : /* PEA Indexed Idirect. */
+ case PEA_IY : /* PEA Indirect Indexed. */
+ push(cpu, address.u64, 7, thread);
+ break;
+ case ADD_IMM: /* ADD Immediate. */
+ case ADD_AB : /* ADD Absolute. */
+ case ADD_Z : /* ADD Zero Matrix. */
+ case ADD_E : /* ADD E Indirect. */
+ cpu->a = adc(cpu, cpu->a, value.u64, 0, 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.u64, 1, 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.u64, 0, 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.u64, 1, 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.u64, 0, 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.u64, 1, thread);
+ break;
+ case NOT_A : /* NOT Accumulator. */
+ cpu->a = ~cpu->a;
+ break;
+ case NOT_AB: /* NOT Absolute. */
+ case NOT_Z : /* NOT Zero Matrix. */
+ case NOT_E : /* NOT E Indirect. */
+ not_mem(cpu, address.u64, prefix, thread);
+ break;
+ case LLM_AB: /* LLM Absolute. */
+ case LLM_Z : /* LLM Zero Matrix. */
+ case LLM_E : /* LLM E Indirect. */
+ case LRM_AB: /* LRM Absolute. */
+ case LRM_Z : /* LRM Zero Matrix. */
+ case LRM_E : /* LRM E Indirect. */
+ case RLM_AB: /* RLM Absolute. */
+ case RLM_Z : /* RLM Zero Matrix. */
+ case RLM_E : /* RLM E Indirect. */
+ case RRM_AB: /* RRM Absolute. */
+ case RRM_Z : /* RRM Zero Matrix. */
+ case RRM_E : /* RRM E Indirect. */
+ case ARM_AB: /* ARM Absolute. */
+ case ARM_Z : /* ARM Zero Matrix. */
+ case ARM_E : /* ARM E Indirect. */
+ switch (opcode) {
+ case LLM_AB:
+ case LLM_Z :
+ case LLM_E : tmp = 0; break;
+ case LRM_AB:
+ case LRM_Z :
+ case LRM_E : tmp = 1; break;
+ case RLM_AB:
+ case RLM_Z :
+ case RLM_E : tmp = 2; break;
+ case RRM_AB:
+ case RRM_Z :
+ case RRM_E : tmp = 3; break;
+ case ARM_AB:
+ case ARM_Z :
+ case ARM_E : tmp = 4; break;
+ }
+ bitshft_mem(cpu, tmp, cpu->b, address.u64, prefix, thread);
+ break;
+ case PHE_IMP: push(cpu, cpu->e, size, thread); break; /* PusH E register. */
+ case PLE_IMP: pull(cpu, size, thread); break; /* PuLl E register. */
+ case CPE_IMM: /* CPE Immediate. */
+ case CPE_AB : /* CPE Absolute. */
+ case CPE_Z : /* CPE Zero Matrix. */
+ adc(cpu, cpu->e, ~value.u64, 1, thread);
+ break;
+ case ICE_AB : /* ICE Absolute. */
+ case ICE_Z : /* ICE Zero Matrix. */
+ case ICE_E : /* ICE E Indirect. */
+ break;
+ case LDS_IMM: /* LDS Immediate. */
+ case LDS_AB : /* LDS Absolute. */
+ case LDS_Z : /* LDS Zero Matrix. */
+ case LDS_E : /* LDS E Indirect. */
+ cpu->sp = load(cpu, cpu->sp, address.u64, size, thread);
+ break;
+ case DEE_IMP: cpu->e = idr(cpu, cpu->e, 0, thread); break; /* DEcrement E register. */
+ case INE_IMP: cpu->e = idr(cpu, cpu->e, 1, thread); break; /* INcrement E register. */
+ case DES_IMP: cpu->sp = idr(cpu, cpu->sp, 0, thread); break; /* DEcrement Stack pointer. */
+ case INS_IMP: cpu->sp = idr(cpu, cpu->sp, 1, thread); break; /* INcrement Stack pointer. */
+ case STS_AB: /* STS Absolute. */
+ case STS_Z : /* STS Zero Matrix. */
+ case STS_E : /* STS E Indirect. */
+ store(cpu, address.u64, cpu->sp, prefix, thread);
+ break;
+ case STE_AB: /* STE Absolute. */
+ case STE_Z : /* STE Zero Matrix. */
+ store(cpu, address.u64, cpu->sp, prefix, thread);
+ break;
+ case STZ_AB: /* STZ Absolute. */
+ case STZ_Z : /* STZ Zero Matrix. */
+ case STZ_E : /* STZ E Indirect. */
+ store(cpu, address.u64, 0, prefix, thread);
+ break;
+ case SCO_IMM: /* SCO Immediate. */
+ case SCO_AB : /* SCO Absolute. */
+ case SCO_Z : /* SCO Zero Matrix. */
+ case SCO_E : /* SCO E Indirect. */
+ break;
+ case ECO_IMM: /* ECO Immediate. */
+ case ECO_AB : /* ECO Absolute. */
+ case ECO_Z : /* ECO Zero Matrix. */
+ case ECO_E : /* ECO E Indirect. */
+ break;
+ case CLZ_AB: /* CLZ Absolute. */
+ case CLZ_Z : /* CLZ Zero Matrix. */
+ case CLZ_E : /* CLZ E Indirect. */
+ cpu->a = lbcnt(cpu, value.u64, 0, size, thread);
+ break;
+ case CLO_AB: /* CLO Absolute. */
+ case CLO_Z : /* CLO Zero Matrix. */
+ case CLO_E : /* CLO E Indirect. */
+ cpu->a = lbcnt(cpu, value.u64, 1, size, thread);
+ break;
+ case BIT_AB: /* BIT Absolute. */
+ case BIT_Z : /* BIT Zero Matrix. */
+ case BIT_E : /* BIT E Indirect. */
+ bit_test(cpu, cpu->a, value.u64, thread);
+ break;
+ case MMV_IMP: /* Memory MoVe. */
+ cpu->b = mem_move(cpu, cpu->b, cpu->x, cpu->y, 0, size, thread);
+ break;
+ case SWP_A : /* SWaP lower half, with upper half. */
+ cpu->a = swap(cpu, cpu->a, size, thread);
+ break;
+ case SWP_AB: /* SWP Absolute. */
+ case SWP_Z : /* SWP Zero Matrix. */
+ case SWP_E : /* SWP E Indirect. */
+ swap_mem(cpu, address.u64, size, thread);
+ break;
+ case PCN_AB: /* PCN Absolute. */
+ case PCN_Z : /* PCN Zero Matrix. */
+ case PCN_E : /* PCN E Indirect. */
+ cpu->a = popcnt(cpu, value.u64, thread);
+ break;
+ case REP_REL: /* REP Relative. */
+ if (cpu->b != 0) {
+ cpu->b--;
+ cpu->pc = address.u64;
+ }
+ break;
+ case REQ_REL: /* REQ Relative. */
+ if (cpu->b != 0 && getflag(Z)) {
+ cpu->b--;
+ cpu->pc = address.u64;
+ }
+ break;
+ case RNE_REL: /* RNE Relative. */
+ if (cpu->b != 0 && !getflag(Z)) {
+ cpu->b--;
+ cpu->pc = address.u64;
+ }
+ break;
+ case LNG_IMM: /* LNG Immediate. */
+ case LNG_E : /* LNG E Indirect. */
+ if (getflag(N)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case LPO_IMM: /* LPO Immediate. */
+ case LPO_E : /* LPO E Indirect. */
+ if (!getflag(N)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case LCS_IMM: /* LCS Immediate. */
+ case LCS_E : /* LCS E Indirect. */
+ if (getflag(C)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case LCC_IMM: /* LCC Immediate. */
+ case LCC_E : /* LCC E Indirect. */
+ if (!getflag(C)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case LEQ_IMM: /* LEQ Immediate. */
+ case LEQ_E : /* LEQ E Indirect. */
+ if (getflag(Z)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case LNE_IMM: /* LNE Immediate. */
+ case LNE_E : /* LNE E Indirect. */
+ if (!getflag(Z)) {
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ }
+ break;
+ case SNG_E : /* SNG E Indirect. */
+ if (getflag(N)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+ case SPO_E : /* SPO E Indirect. */
+ if (!getflag(N)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+ case SCS_E : /* SCS E Indirect. */
+ if (getflag(C)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+ case SCC_E : /* SCC E Indirect. */
+ if (!getflag(C)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+ case SEQ_E : /* SEQ E Indirect. */
+ if (getflag(Z)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+ case SNE_E : /* SNE E Indirect. */
+ if (!getflag(Z)) {
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ }
+ break;
+
+ }
+}
+
+static inline void exec_base_inst(struct sux *cpu, uint8_t opcode, uint8_t prefix, union reg value, union reg address, uint8_t size, uint8_t thread) {
+ uint64_t *rem = 0;
+ switch (opcode) {
+ case CPS_IMP: /* Clear Processor Status. */
+ cpu->ps.u8[thread] = 0;
+ break;
+ case ADC_B: /* ADC B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case ADC_IMM: /* ADC Immediate. */
+ case ADC_AB: /* ADC Absolute. */
+ case ADC_Z: /* ADC Zero Matrix. */
+ cpu->a = adc(cpu, cpu->a, value.u64, 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. */
+ case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */
+ case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */
+ case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */
+ case TAY_IMP: cpu->y = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */
+ case TAX_IMP: cpu->x = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */
+ case TYX_IMP: cpu->x = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to X. */
+ case TYA_IMP: cpu->a = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to Accumulator. */
+ case TXA_IMP: cpu->a = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Accumulator. */
+ case TXY_IMP: cpu->y = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Y. */
+ case TAB_IMP: cpu->b = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to B. */
+ case TSX_IMP: cpu->x = transfer(cpu, cpu->sp, value.u64, thread); break; /* Transfer Stack pointer to X. */
+ case TBA_IMP: cpu->a = transfer(cpu, cpu->b , value.u64, thread); break; /* Transfer B to Accumulator. */
+ case TXS_IMP: cpu->sp = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Stack pointer. */
+ case BRA_REL: /* BRA Relative. */
+ case JMP_AB: /* JMP Absolute. */
+ case JMP_Z: /* JMP Zero Matrix. */
+ case JMP_IN: /* JMP Indirect. */
+ cpu->pc = address.u64;
+ break;
+ case SBC_B: /* SBC B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case SBC_IMM: /* SBC Immediate. */
+ case SBC_AB: /* SBC Absolute. */
+ case SBC_Z: /* SBC Zero Matrix. */
+ cpu->a = adc(cpu, cpu->a, ~value.u64, 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. */
+ case PLB_IMP: cpu->b = pull(cpu, size, thread); break; /* PuLl B register from stack. */
+ case PLY_IMP: cpu->y = pull(cpu, size, thread); break; /* PuLl Y register from stack. */
+ case PLX_IMP: cpu->x = pull(cpu, size, thread); break; /* PuLl X register from stack. */
+ break;
+ case AND_B: /* AND B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case AND_IMM: /* AND Immediate. */
+ case AND_AB: /* AND Absolute. */
+ case AND_Z: /* AND Zero Matrix. */
+ cpu->a = and(cpu, cpu->a, value.u64, thread);
+ break;
+ case BPO_REL: /* BPO Relative. */
+ if (!getflag(N)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case ORA_B: /* ORA B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case ORA_IMM: /* ORA Immediate. */
+ case ORA_AB: /* ORA Absolute. */
+ case ORA_Z: /* ORA Zero Matrix. */
+ cpu->a = or(cpu, cpu->a, value.u64, thread);
+ break;
+ case SEI_IMP: /* SEt Interrupt. */
+ setflag(1, I);
+ break;
+ case BNG_REL: /* BNG Relative. */
+ if (getflag(N)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case XOR_B: /* XOR B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case XOR_IMM: /* XOR Immediate. */
+ case XOR_AB: /* XOR Absolute. */
+ case XOR_Z: /* XOR Zero Matrix. */
+ cpu->a = xor(cpu, cpu->a, value.u64, thread);
+ break;
+ case CLI_IMP: /* CLear Interrupt. */
+ setflag(0, I);
+ break;
+ case BCS_REL: /* BCS Relative. */
+ if (getflag(C)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case LSL_B: /* LSL B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case LSL_IMM: /* LSL Immediate. */
+ case LSL_AB: /* LSL Absolute. */
+ case LSL_Z: /* LSL Zero Matrix. */
+ cpu->a = lsl(cpu, cpu->a, value.u64, 8, thread);
+ break;
+ case SEC_IMP: /* SEt Carry flag.*/
+ setflag(1, C);
+ break;
+ case STA_AB: /* STA Absolute. */
+ case STA_Z: /* STA Zero Matrix. */
+ case STA_ZX: /* STA Zero Matrix, Indexed with X. */
+ case STA_ZY: /* STA Zero Matrix, Indexed with Y. */
+ case STA_IN: /* STA Indirect. */
+ case STA_IX: /* STA Indexed Indirect. */
+ case STA_IY: /* STA Indirect Indexed. */
+ store(cpu, address.u64, cpu->a, prefix, thread);
+ break;
+ case STY_AB: /* STY Absolute. */
+ case STY_Z: /* STY Zero Matrix. */
+ case STY_IN: /* STY Indirect. */
+ store(cpu, address.u64, cpu->y, prefix, thread);
+ break;
+ case STX_AB: /* STX Absolute. */
+ case STX_Z: /* STX Zero Matrix. */
+ case STX_IN: /* STX Indirect. */
+ store(cpu, address.u64, cpu->x, prefix, thread);
+ break;
+ case STB_AB: /* STB Absolute. */
+ case STB_Z: /* STB Zero Matrix. */
+ case STB_ZX: /* STB Zero Matrix, Indexed with X. */
+ case STB_ZY: /* STB Zero Matrix, Indexed with Y. */
+ case STB_IN: /* STB Indirect. */
+ case STB_IX: /* STB Indexed Indirect. */
+ case STB_IY: /* STB Indirect Indexed. */
+ store(cpu, address.u64, cpu->b, prefix, thread);
+ break;
+ case BCC_REL: /* BCC Relative. */
+ if (!getflag(C)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case LSR_B: /* LSR B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case LSR_IMM: /* LSR Immediate. */
+ case LSR_AB: /* LSR Absolute. */
+ case LSR_Z: /* LSR Zero Matrix. */
+ cpu->a = lsr(cpu, cpu->a, value.u64, 8, thread);
+ break;
+ case ASR_B: /* ASR B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case ASR_IMM: /* ASR Immediate. */
+ case ASR_AB: /* ASR Absolute. */
+ case ASR_Z: /* ASR Zero Matrix. */
+ cpu->a = asr(cpu, cpu->a, value.u64, 8, thread);
+ break;
+ case CLC_IMP: /* CLear Carry flag. */
+ setflag(0, C);
+ break;
+ case LDB_IMM: /* LDB Immediate. */
+ case LDB_AB: /* LDB Absolute. */
+ case LDB_Z: /* LDB Zero Matrix. */
+ case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */
+ case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */
+ case LDB_IN: /* LDB Indirect. */
+ case LDB_IX: /* LDB Indexed Indirect. */
+ case LDB_IY: /* LDB Indirect Indexed. */
+ cpu->b = load(cpu, cpu->b, address.u64, size, thread);
+ break;
+ case LDA_IMM: /* LDA Immediate. */
+ case LDA_AB: /* LDA Absolute. */
+ case LDA_Z: /* LDA Zero Matrix. */
+ case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */
+ case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */
+ case LDA_IN: /* LDA Indirect. */
+ case LDA_IX: /* LDA Indexed Indirect. */
+ case LDA_IY: /* LDA Indirect Indexed. */
+ cpu->a = load(cpu, cpu->a, address.u64, size, thread);
+ break;
+ case LDY_IMM: /* LDY Immediate. */
+ case LDY_AB: /* LDY Absolute. */
+ case LDY_Z: /* LDY Zero Matrix. */
+ case LDY_IN: /* LDY Indirect. */
+ cpu->y = load(cpu, cpu->y, address.u64, size, thread);
+ break;
+ case LDX_IMM: /* LDX Immediate. */
+ case LDX_AB: /* LDX Absolute. */
+ case LDX_Z: /* LDX Zero Matrix. */
+ case LDX_IN: /* LDX Indirect. */
+ cpu->x = load(cpu, cpu->x, address.u64, size, thread);
+ break;
+ case BEQ_REL: /* BEQ Relative. */
+ if (getflag(Z)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case ROL_B: /* ROL B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case ROL_IMM: /* ROL Immediate. */
+ case ROL_AB: /* ROL Absolute. */
+ case ROL_Z: /* ROL Zero Matrix. */
+ cpu->a = rol(cpu, cpu->a, value.u64, 8, thread);
+ break;
+ case BNE_REL: /* BNE Relative. */
+ if (!getflag(Z)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case ROR_B: /* ROR B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case ROR_IMM: /* ROR Immediate. */
+ case ROR_AB: /* ROR Absolute. */
+ case ROR_Z: /* ROR Zero Matrix. */
+ cpu->a = ror(cpu, cpu->a, value.u64, 8, thread);
+ break;
+ case BVS_REL: /* BVS Relative. */
+ if (getflag(V)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case MUL_B: /* MUL B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case MUL_IMM: /* MUL Immediate. */
+ case MUL_AB: /* MUL Absolute. */
+ case MUL_Z: /* MUL Zero Matrix. */
+ cpu->a = mul(cpu, cpu->a, value.u64, thread);
+ break;
+ case BVC_REL: /* BVC Relative. */
+ if (!getflag(V)) {
+ cpu->pc = address.u64;
+ }
+ break;
+ case DIV_B: /* DIV B register. */
+ case DIV_IMM: /* DIV Immediate. */
+ 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.u64, rem, thread);
+ break;
+ case CLV_IMP: /* CLear oVerflow flag. */
+ setflag(0, V);
+ break;
+ case CPB_IMM: /* CPB Immediate. */
+ case CPB_AB: /* CPB Absolute. */
+ case CPB_Z: /* CPB Zero Matrix. */
+ case CPB_IN: /* CPB Indirect. */
+ case CPB_IX: /* CPB Indexed Indirect. */
+ case CPB_IY: /* CPB Indirect Indexed. */
+ adc(cpu, cpu->b, ~value.u64, 1, thread);
+ break;
+ case CMP_B: /* CMP B register. */
+ value.u64 = cpu->b; /* Falls Through. */
+ case CMP_IMM: /* CMP Immediate. */
+ case CMP_AB: /* CMP Absolute. */
+ case CMP_Z: /* CMP Zero Matrix. */
+ case CMP_IN: /* CMP Indirect. */
+ case CMP_IX: /* CMP Indexed Indirect. */
+ case CMP_IY: /* CMP Indirect Indexed. */
+ adc(cpu, cpu->a, ~value.u64, 1, thread);
+ break;
+ case CPY_IMM: /* CPY Immediate. */
+ case CPY_AB: /* CPY Absolute. */
+ case CPY_Z: /* CPY Zero Matrix. */
+ adc(cpu, cpu->y, ~value.u64, 1, thread);
+ break;
+ case CPX_IMM: /* CPX Immediate. */
+ case CPX_AB: /* CPX Absolute. */
+ case CPX_Z: /* CPX Zero Matrix. */
+ adc(cpu, cpu->x, ~value.u64, 1, 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;
+ case INY_IMP: cpu->y = idr(cpu, cpu->y, 1, thread); break;
+ case INX_IMP: cpu->x = idr(cpu, cpu->x, 1, thread); break;
+ case DEC_IMP: cpu->a = idr(cpu, cpu->a, 0, thread); break;
+ case DEB_IMP: cpu->b = idr(cpu, cpu->b, 0, thread); break;
+ case DEY_IMP: cpu->y = idr(cpu, cpu->y, 0, thread); break;
+ case DEX_IMP: cpu->x = idr(cpu, cpu->x, 0, thread); break;
+ case JSR_IN: /* JSR Indirect. */
+ case JSR_AB: /* Jump to SubRoutine. */
+ case JSR_Z: /* JSR Zero Matrix. */
+ push(cpu, cpu->pc, (size) ? size : 7, thread);
+ cpu->pc = address.u64;
+ break;
+ case INC_AB: /* INC Absolute. */
+ case INC_Z: /* INC Zero Matrix. */
+ idm(cpu, address.u64, prefix, 1, thread);
+ break;
+ case NOP_IMP: /* No OPeration. */
+ break;
+ case RTI_IMP: /* ReTurn from Interrupt routine. */
+ cpu->ps.u8[thread] = pull(cpu, 0, thread);
+ size = 0;
+ case RTS_IMP: /* ReTurn from Subroutine. */
+ cpu->pc = pull(cpu, (size) ? size : 7, thread);
+ break;
+ case DEC_AB: /* DEC Absolute. */
+ case DEC_Z: /* DEC Zero Matrix. */
+ idm(cpu, address.u64, prefix, 0, thread);
+ break;
+ case BRK_IMP: /* BReaK. */
+ case WAI_IMP: /* WAit for Interrupt. */
+ if (opcode == WAI_IMP) {
+ pthread_mutex_lock(&main_mutex);
+ pthread_cond_signal(&main_cond);
+ pthread_mutex_unlock(&main_mutex);
+ pthread_mutex_lock(&mutex);
+ pthread_cond_wait(&cond, &mutex);
+ pthread_mutex_unlock(&mutex);
+ }
+ push(cpu, cpu->pc, 7, thread);
+ push(cpu, cpu->ps.u8[thread], 0, thread);
+ setflag(1, I);
+ value.u64 = read_value(cpu, 0, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7, 1, 0);
+ if (opcode == WAI_IMP) {
+ kbd_rdy &= (uint8_t)~(1 << thread);
+ }
+ cpu->pc = value.u64;
+ default:
+ break;
+ }
+}
diff --git a/tables.h b/tables.h
index 16d5563..b67765d 100644
--- a/tables.h
+++ b/tables.h
@@ -104,7 +104,7 @@ static const uint8_t optype[0x100] = {
[XOR_B ] = BREG,
[CMP_B ] = BREG,
[DEB_IMP ] = IMPL,
- [TXS_IMM ] = IMM,
+ [TXS_IMP ] = IMPL,
[STY_IN ] = IND,
[PLA_IMP ] = IMPL,
[BCC_REL ] = REL,
@@ -171,3 +171,169 @@ static const uint8_t optype[0x100] = {
[CPB_IY ] = INDY,
[PLX_IMP ] = IMPL
};
+
+static const uint8_t ext_optype[0x100] = {
+ [LEA_AY ] = ABSY,
+ [ADD_IMM] = IMM,
+ [LEA_Z ] = ZM,
+ [CPE_IMM] = IMM,
+ [CLZ_Z ] = ZM,
+ [ADD_Z ] = ZM,
+ [STB_E ] = EIND,
+ [CPE_Z ] = ZM,
+ [LNG_IMM] = IMM,
+ [LNG_E ] = EIND,
+ [JMP_E ] = EIND,
+ [ADC_E ] = EIND,
+ [ROR_E ] = EIND,
+ [LEA_AB ] = ABS,
+ [CLZ_AB ] = ABS,
+ [ADD_AB ] = ABS,
+ [LEA_ZY ] = ZMY,
+ [CPE_AB ] = ABS,
+ [CLZ_E ] = EIND,
+ [ADD_E ] = EIND,
+ [LDX_E ] = EIND,
+ [SNG_E ] = EIND,
+ [PEA_AY ] = ABSY,
+ [SUB_IMM] = IMM,
+ [PEA_Z ] = ZM,
+ [CLO_Z ] = ZM,
+ [SUB_Z ] = ZM,
+ [STX_E ] = EIND,
+ [ICE_Z ] = ZM,
+ [LPO_IMM] = IMM,
+ [LPO_E ] = EIND,
+ [JSR_E ] = EIND,
+ [SBC_E ] = EIND,
+ [MUL_E ] = EIND,
+ [PEA_AB ] = ABS,
+ [CLO_AB ] = ABS,
+ [SUB_AB ] = ABS,
+ [PEA_ZY ] = ZMY,
+ [ICE_AB ] = ABS,
+ [CLO_E ] = EIND,
+ [SUB_E ] = EIND,
+ [CPB_E ] = EIND,
+ [ICE_E ] = EIND,
+ [SPO_E ] = EIND,
+ [LDS_IMM] = IMM,
+ [LEA_AI ] = AIND,
+ [LDS_Z ] = ZM,
+ [ADE_IMM] = IMM,
+ [LEA_IN ] = IND,
+ [BIT_Z ] = ZM,
+ [ADE_Z ] = ZM,
+ [CPX_E ] = EIND,
+ [LLM_Z ] = ZM,
+ [LCS_IMM] = IMM,
+ [LCS_E ] = EIND,
+ [LDS_AB ] = ABS,
+ [AND_E ] = EIND,
+ [DIV_E ] = EIND,
+ [LEA_AX ] = ABSX,
+ [LDS_E ] = EIND,
+ [BIT_AB ] = ABS,
+ [ADE_AB ] = ABS,
+ [LEA_ZX ] = ZMX,
+ [LLM_AB ] = ABS,
+ [BIT_E ] = EIND,
+ [CPY_E ] = EIND,
+ [LLM_E ] = EIND,
+ [SCS_E ] = EIND,
+ [SCO_IMM] = IMM,
+ [PEA_AI ] = AIND,
+ [SCO_Z ] = ZM,
+ [SBE_IMM] = IMM,
+ [PEA_IN ] = IND,
+ [SBE_Z ] = ZM,
+ [PHE_IMP] = IMPL,
+ [LRM_Z ] = ZM,
+ [LCC_IMM] = IMM,
+ [LCC_E ] = EIND,
+ [SCO_AB ] = ABS,
+ [ORA_E ] = EIND,
+ [ASR_E ] = EIND,
+ [PEA_AX ] = ABSX,
+ [SCO_E ] = EIND,
+ [SBE_AB ] = ABS,
+ [PEA_ZX ] = ZMX,
+ [LRM_AB ] = ABS,
+ [PLE_IMP] = IMPL,
+ [LRM_E ] = EIND,
+ [SCC_E ] = EIND,
+ [ECO_IMM] = IMM,
+ [DEC_E ] = EIND,
+ [LEA_AIY] = AINDY,
+ [ECO_Z ] = ZM,
+ [ADS_IMM] = IMM,
+ [LEA_IY ] = INDY,
+ [ADS_Z ] = ZM,
+ [DEE_IMP] = IMPL,
+ [RLM_Z ] = ZM,
+ [LEQ_IMM] = IMM,
+ [LEQ_E ] = EIND,
+ [ECO_AB ] = ABS,
+ [XOR_E ] = EIND,
+ [CMP_E ] = EIND,
+ [LEA_AIX] = AINDX,
+ [ECO_E ] = EIND,
+ [ADS_AB ] = ABS,
+ [LEA_IX ] = INDX,
+ [RLM_AB ] = ABS,
+ [ADS_E ] = EIND,
+ [INE_IMP] = IMPL,
+ [RLM_E ] = EIND,
+ [SEQ_E ] = EIND,
+ [INC_E ] = EIND,
+ [PEA_AIY] = AINDY,
+ [STS_Z ] = ZM,
+ [SBS_IMM] = IMM,
+ [PEA_IY ] = INDY,
+ [SBS_Z ] = ZM,
+ [DES_IMP] = IMPL,
+ [RRM_Z ] = ZM,
+ [LNE_IMM] = IMM,
+ [LNE_E ] = EIND,
+ [STS_AB ] = ABS,
+ [LSL_E ] = EIND,
+ [LDY_E ] = EIND,
+ [PEA_AIX] = AINDX,
+ [STS_E ] = EIND,
+ [SBS_AB ] = ABS,
+ [PEA_IX ] = INDX,
+ [RRM_AB ] = ABS,
+ [SBS_E ] = EIND,
+ [INS_IMP] = IMPL,
+ [RRM_E ] = EIND,
+ [REP_REL] = REL,
+ [SNE_E ] = EIND,
+ [STY_E ] = EIND,
+ [STE_Z ] = ZM,
+ [NOT_A ] = IMPL,
+ [NOT_Z ] = ZM,
+ [MMV_IMP] = IMPL,
+ [ARM_Z ] = ZM,
+ [REQ_REL] = REL,
+ [STE_AB ] = ABS,
+ [LSR_E ] = EIND,
+ [LDA_E ] = EIND,
+ [NOT_AB ] = ABS,
+ [ARM_AB ] = ABS,
+ [NOT_E ] = EIND,
+ [ARM_E ] = EIND,
+ [RNE_REL] = REL,
+ [STA_E ] = EIND,
+ [STZ_Z ] = ZM,
+ [SWP_A ] = IMPL,
+ [SWP_Z ] = ZM,
+ [PCN_Z ] = ZM,
+ [STZ_AB ] = ABS,
+ [ROL_E ] = EIND,
+ [LDB_E ] = EIND,
+ [STZ_E ] = EIND,
+ [SWP_AB ] = ABS,
+ [PCN_AB ] = ABS,
+ [SWP_E ] = EIND,
+ [PCN_E ] = EIND
+};
diff --git a/test/base-ext.s b/test/base-ext.s
new file mode 100644
index 0000000..8bf3d45
--- /dev/null
+++ b/test/base-ext.s
@@ -0,0 +1,19 @@
+.org $8000
+reset:
+ cps
+ lds.d #$3FFFF
+loop:
+ lea $10
+ inc (e)
+ lda (e)
+ lea ($FFC0)
+ bra loop
+
+.org $FFC0
+.qword reset
+a
+;l a
+;.org reset
+;v
+;q
+d