summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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