From aabca199127442c9e094f77fe71c2f295664568a Mon Sep 17 00:00:00 2001 From: Ian C Date: Sat, 30 Nov 2024 11:56:43 +0000 Subject: Added undocumented 6502 opcodes. --- .gitignore | 1 + CHANGELOG | 4 + doc/casm.html | 5 +- src/6502.c | 1078 ++++++++++++++++++++++++++++++++++++++++++++++--------- src/test/6502.1 | 74 ++++ 5 files changed, 985 insertions(+), 177 deletions(-) diff --git a/.gitignore b/.gitignore index a325e0d..332f3ee 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ src/casm *.cdt src/A-Hdrive src/output +.DS_Store diff --git a/CHANGELOG b/CHANGELOG index fe5f189..47dc3de 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,3 +15,7 @@ V1.11 V1.12 ===== * Added VIC-20 PRG output options. + +V1.13 +===== +* Added undocumented 6502 instructions. diff --git a/doc/casm.html b/doc/casm.html index aba9611..aebdf15 100644 --- a/doc/casm.html +++ b/doc/casm.html @@ -1884,7 +1884,10 @@ directive, i.e.

Opcodes

-The 6502 assembler uses the standard Motorola opcodes. +The 6502 assembler uses the standard Motorola opcodes. Undocumented opcodes are +supported and use the opcodes as described at + +www.masswerk.at/nowgobang/2021/6502-illegal-opcodes.

Options

diff --git a/src/6502.c b/src/6502.c index c6c0c33..9a19ef4 100644 --- a/src/6502.c +++ b/src/6502.c @@ -331,59 +331,9 @@ static void CalcAddressMode(int argc, char *argv[], int quoted[], -/* ---------------------------------------- COMMAND HANDLERS +/* ---------------------------------------- COMMAND HANDLERS - LEGAL OPCODES */ -static CommandStatus DUMMY(const char *label, int argc, char *argv[], - int quoted[], char *err, size_t errsize) -{ - address_mode_t mode; - int address; - - CMD_ADDRESS_MODE(mode, address); - - switch(mode) - { - case ACCUMULATOR: - return CMD_OK; - - case IMPLIED: - return CMD_OK; - - case IMMEDIATE: - return CMD_OK; - - case ABSOLUTE: - return CMD_OK; - - case ZERO_PAGE: - return CMD_OK; - - case ABSOLUTE_INDEX_X: - return CMD_OK; - - case ABSOLUTE_INDEX_Y: - return CMD_OK; - - case ZERO_PAGE_INDEX_X: - return CMD_OK; - - case ZERO_PAGE_INDEX_Y: - return CMD_OK; - - case ZERO_PAGE_INDIRECT_X: - return CMD_OK; - - case ZERO_PAGE_INDIRECT_Y: - return CMD_OK; - - default: - snprintf(err, errsize, "%s: unsupported addressing mode %s", - argv[0], address_mode_name[mode]); - return CMD_FAILED; - } -} - static CommandStatus ADC(const char *label, int argc, char *argv[], int quoted[], char *err, size_t errsize) { @@ -1399,165 +1349,929 @@ static CommandStatus STY(const char *label, int argc, char *argv[], } } -/* ---------------------------------------- OPCODE TABLES +/* ---------------------------------------- HANDLERS - UNDOCUMENTED OPCODES */ -typedef struct +static CommandStatus ALR(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) { - const char *op; - int code; -} OpcodeTable; + address_mode_t mode; + int address; -typedef struct -{ - const char *op; - Command cmd; -} HandlerTable; + CMD_ADDRESS_MODE(mode, address); -static const OpcodeTable implied_opcodes[] = -{ - {"NOP", 0xea}, - {"TXS", 0x9a}, - {"TSX", 0xba}, - {"PHA", 0x48}, - {"PLA", 0x68}, - {"PHP", 0x08}, - {"PLP", 0x28}, - {"CLC", 0x18}, - {"SEC", 0x38}, - {"CLI", 0x58}, - {"SEI", 0x78}, - {"CLV", 0xb8}, - {"CLD", 0xd8}, - {"SED", 0xf8}, - {"BRK", 0x00}, - {"TAX", 0xaa}, - {"TXA", 0x8a}, - {"DEX", 0xca}, - {"INX", 0xe8}, - {"TAY", 0xa8}, - {"TYA", 0x98}, - {"DEY", 0x88}, - {"INY", 0xc8}, - {"RTI", 0x40}, - {"RTS", 0x60}, - {NULL} -}; + switch(mode) + { + case IMMEDIATE: + PCWrite(0x4b); + PCWrite(address); + return CMD_OK; + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} -static const OpcodeTable branch_opcodes[] = +static CommandStatus ANC(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) { - {"BPL", 0x10}, - {"BMI", 0x30}, - {"BVC", 0x50}, - {"BVS", 0x70}, - {"BCC", 0x90}, - {"BCS", 0xB0}, - {"BNE", 0xD0}, - {"BEQ", 0xF0}, - {NULL} -}; + address_mode_t mode; + int address; + CMD_ADDRESS_MODE(mode, address); -static const HandlerTable handler_table[] = -{ - {"ADC", ADC}, - {"AND", AND}, - {"ASL", ASL}, - {"BIT", BIT}, - {"CMP", CMP}, - {"CPX", CPX}, - {"CPY", CPY}, - {"DEC", DEC}, - {"EOR", EOR}, - {"INC", INC}, - {"JMP", JMP}, - {"JSR", JSR}, - {"LDA", LDA}, - {"LDX", LDX}, - {"LDY", LDY}, - {"LSR", LSR}, - {"ORA", ORA}, - {"ROL", ROL}, - {"ROR", ROR}, - {"SBC", SBC}, - {"STA", STA}, - {"STX", STX}, - {"STY", STY}, - {NULL} -}; + switch(mode) + { + case IMMEDIATE: + PCWrite(0x0b); + PCWrite(address); + return CMD_OK; + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} +static CommandStatus ANC2(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + CMD_ADDRESS_MODE(mode, address); -/* ---------------------------------------- PUBLIC FUNCTIONS -*/ + switch(mode) + { + case IMMEDIATE: + PCWrite(0x2b); + PCWrite(address); + return CMD_OK; -void Init_6502(void) -{ - option.zp_mode = ZP_AUTO; - SetNeededPasses(3); + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } } - -const ValueTable *Options_6502(void) +static CommandStatus ANE(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) { - return options; -} + address_mode_t mode; + int address; -CommandStatus SetOption_6502(int opt, int argc, char *argv[], - int quoted[], char *err, size_t errsize) -{ - const ValueTable *val; + CMD_ADDRESS_MODE(mode, address); - switch(opt) - { - case OPT_ZP: - CMD_ARGC_CHECK(1); - CMD_TABLE(argv[0], zp_table, val); + printf("Warning: %s is highly unstable and not recommended\n", argv[0]); - option.zp_mode = val->value; - break; + switch(mode) + { + case IMMEDIATE: + PCWrite(0x8b); + PCWrite(address); + return CMD_OK; default: - break; + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; } - - return CMD_OK; } -CommandStatus Handler_6502(const char *label, int argc, char *argv[], - int quoted[], char *err, size_t errsize) +static CommandStatus ARR(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) { - int f; + address_mode_t mode; + int address; - /* Check for simple (implied addressing) opcodes - */ - for(f = 0; implied_opcodes[f].op; f++) + CMD_ADDRESS_MODE(mode, address); + + switch(mode) { - if (CompareString(argv[0], implied_opcodes[f].op)) - { - PCWrite(implied_opcodes[f].code); + case IMMEDIATE: + PCWrite(0x6b); + PCWrite(address); return CMD_OK; - } + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; } +} - /* Check for branch opcodes - */ - for(f = 0; branch_opcodes[f].op; f++) - { - if (CompareString(argv[0], branch_opcodes[f].op)) - { - int offset; +static CommandStatus DCP(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; - CMD_ARGC_CHECK(2); + CMD_ADDRESS_MODE(mode, address); - CMD_EXPR(argv[1], offset); + switch(mode) + { + case ABSOLUTE: + PCWrite(0xcf); + PCWriteWord(address); + return CMD_OK; - offset = offset - (PC() + 2); + case ZERO_PAGE: + PCWrite(0xc7); + PCWrite(address); + return CMD_OK; - if (IsFinalPass() && (offset < -128 || offset > 127)) - { - snprintf(err, errsize, "%s: Branch offset (%d) too big", + case ABSOLUTE_INDEX_X: + PCWrite(0xdf); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0xdb); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0xd7); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0xc3); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0xd3); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus ISC(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0xef); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0xe7); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_X: + PCWrite(0xff); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0xfb); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0xf7); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0xe3); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0xf3); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus LAS(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0xbb); + PCWriteWord(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus LAX(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0xaf); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0xa7); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_Y: + PCWrite(0xb7); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + PCWrite(0xbf); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0xa3); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0xb3); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus LXA(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + printf("Warning: %s is highly unstable and not recommended\n", argv[0]); + + switch(mode) + { + case IMMEDIATE: + PCWrite(0xab); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus RLA(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0x2f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0x27); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_X: + PCWrite(0x3f); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0x3b); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0x37); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0x23); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0x33); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus RRA(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0x6f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0x67); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_X: + PCWrite(0x7f); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0x7b); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0x77); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0x63); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0x73); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SAX(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0x8f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0x87); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_Y: + PCWrite(0x97); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0x83); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SBX(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case IMMEDIATE: + PCWrite(0xcb); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SHA(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + printf("Warning: %s is unstable\n", argv[0]); + + switch(mode) + { + case ABSOLUTE_INDEX_Y: + PCWrite(0x9f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0x93); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SHX(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + printf("Warning: %s is unstable\n", argv[0]); + + switch(mode) + { + case ABSOLUTE_INDEX_Y: + PCWrite(0x9e); + PCWriteWord(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SHY(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + printf("Warning: %s is unstable\n", argv[0]); + + switch(mode) + { + case ABSOLUTE_INDEX_X: + PCWrite(0x9c); + PCWriteWord(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SLO(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0x0f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0x07); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_X: + PCWrite(0x1f); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0x1b); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0x17); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0x03); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0x13); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus SRE(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE: + PCWrite(0x4f); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE: + PCWrite(0x47); + PCWrite(address); + return CMD_OK; + + case ABSOLUTE_INDEX_X: + PCWrite(0x5f); + PCWriteWord(address); + return CMD_OK; + + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0x5b); + PCWriteWord(address); + return CMD_OK; + + case ZERO_PAGE_INDEX_X: + PCWrite(0x57); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_X: + PCWrite(0x43); + PCWrite(address); + return CMD_OK; + + case ZERO_PAGE_INDIRECT_Y: + PCWrite(0x53); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus TAS(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case ABSOLUTE_INDEX_Y: + case ZERO_PAGE_INDEX_Y: + PCWrite(0x9b); + PCWriteWord(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus USBC(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + address_mode_t mode; + int address; + + CMD_ADDRESS_MODE(mode, address); + + switch(mode) + { + case IMMEDIATE: + PCWrite(0xeb); + PCWrite(address); + return CMD_OK; + + default: + snprintf(err, errsize, "%s: unsupported addressing mode %s", + argv[0], address_mode_name[mode]); + return CMD_FAILED; + } +} + +static CommandStatus JAM(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + PCWrite(0x02); + return CMD_OK; +} + +/* ---------------------------------------- OPCODE TABLES +*/ +typedef struct +{ + const char *op; + int code; +} OpcodeTable; + +typedef struct +{ + const char *op; + Command cmd; +} HandlerTable; + +static const OpcodeTable implied_opcodes[] = +{ + {"NOP", 0xea}, + {"TXS", 0x9a}, + {"TSX", 0xba}, + {"PHA", 0x48}, + {"PLA", 0x68}, + {"PHP", 0x08}, + {"PLP", 0x28}, + {"CLC", 0x18}, + {"SEC", 0x38}, + {"CLI", 0x58}, + {"SEI", 0x78}, + {"CLV", 0xb8}, + {"CLD", 0xd8}, + {"SED", 0xf8}, + {"BRK", 0x00}, + {"TAX", 0xaa}, + {"TXA", 0x8a}, + {"DEX", 0xca}, + {"INX", 0xe8}, + {"TAY", 0xa8}, + {"TYA", 0x98}, + {"DEY", 0x88}, + {"INY", 0xc8}, + {"RTI", 0x40}, + {"RTS", 0x60}, + {NULL} +}; + + +static const OpcodeTable branch_opcodes[] = +{ + {"BPL", 0x10}, + {"BMI", 0x30}, + {"BVC", 0x50}, + {"BVS", 0x70}, + {"BCC", 0x90}, + {"BCS", 0xB0}, + {"BNE", 0xD0}, + {"BEQ", 0xF0}, + {NULL} +}; + + +static const HandlerTable handler_table[] = +{ + {"ADC", ADC}, + {"AND", AND}, + {"ASL", ASL}, + {"BIT", BIT}, + {"CMP", CMP}, + {"CPX", CPX}, + {"CPY", CPY}, + {"DEC", DEC}, + {"EOR", EOR}, + {"INC", INC}, + {"JMP", JMP}, + {"JSR", JSR}, + {"LDA", LDA}, + {"LDX", LDX}, + {"LDY", LDY}, + {"LSR", LSR}, + {"ORA", ORA}, + {"ROL", ROL}, + {"ROR", ROR}, + {"SBC", SBC}, + {"STA", STA}, + {"STX", STX}, + {"STY", STY}, + {NULL} +}; + + +static const HandlerTable undocumented_handler_table[] = +{ + {"ALR", ALR}, + {"ASR", ALR}, + {"ANC", ANC}, + {"ANC2", ANC2}, + {"ANE", ANE}, + {"XAA", ANE}, + {"ARR", ARR}, + {"DCP", DCP}, + {"DCM", DCP}, + {"ISC", ISC}, + {"ISB", ISC}, + {"INS", ISC}, + {"LAS", LAS}, + {"LAR", LAS}, + {"LAX", LAX}, + {"LXA", LXA}, + {"RLA", RLA}, + {"RRA", RRA}, + {"SAX", SAX}, + {"AXS", SAX}, + {"AAX", SAX}, + {"SBX", SBX}, + {"ASX", SBX}, + {"SAX", SBX}, + {"SHA", SHA}, + {"AHX", SHA}, + {"AXA", SHA}, + {"SHX", SHX}, + {"SXA", SHX}, + {"XAS", SHX}, + {"SHY", SHY}, + {"SYA", SHY}, + {"SAY", SHY}, + {"SLO", SLO}, + {"ASO", SLO}, + {"SRE", SRE}, + {"TAS", TAS}, + {"XAS", TAS}, + {"SHS", TAS}, + {"USBC", USBC}, + {"SBC", USBC}, + {"JAM", JAM}, + {"KIL", JAM}, + {"HLT", JAM}, + {NULL} +}; + + + + +/* ---------------------------------------- PUBLIC FUNCTIONS +*/ + +void Init_6502(void) +{ + option.zp_mode = ZP_AUTO; + SetNeededPasses(3); +} + + +const ValueTable *Options_6502(void) +{ + return options; +} + +CommandStatus SetOption_6502(int opt, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + const ValueTable *val; + + switch(opt) + { + case OPT_ZP: + CMD_ARGC_CHECK(1); + CMD_TABLE(argv[0], zp_table, val); + + option.zp_mode = val->value; + break; + + default: + break; + } + + return CMD_OK; +} + +CommandStatus Handler_6502(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + int f; + + /* Check for simple (implied addressing) opcodes + */ + for(f = 0; implied_opcodes[f].op; f++) + { + if (CompareString(argv[0], implied_opcodes[f].op)) + { + PCWrite(implied_opcodes[f].code); + return CMD_OK; + } + } + + /* Check for branch opcodes + */ + for(f = 0; branch_opcodes[f].op; f++) + { + if (CompareString(argv[0], branch_opcodes[f].op)) + { + int offset; + + CMD_ARGC_CHECK(2); + + CMD_EXPR(argv[1], offset); + + offset = offset - (PC() + 2); + + if (IsFinalPass() && (offset < -128 || offset > 127)) + { + snprintf(err, errsize, "%s: Branch offset (%d) too big", argv[1], offset); return CMD_FAILED; } @@ -1570,7 +2284,7 @@ CommandStatus Handler_6502(const char *label, int argc, char *argv[], } - /* Check for other opcodes + /* Check for legal opcodes */ for(f = 0; handler_table[f].op; f++) { @@ -1582,6 +2296,18 @@ CommandStatus Handler_6502(const char *label, int argc, char *argv[], } + /* Check for undocumented opcodes + */ + for(f = 0; undocumented_handler_table[f].op; f++) + { + if (CompareString(argv[0], undocumented_handler_table[f].op)) + { + return undocumented_handler_table[f].cmd(label, argc, argv, + quoted, err, errsize);; + } + } + + return CMD_NOT_KNOWN; } diff --git a/src/test/6502.1 b/src/test/6502.1 index f94bcc8..6f15101 100644 --- a/src/test/6502.1 +++ b/src/test/6502.1 @@ -5,6 +5,9 @@ option list-labels,all option list-macros,all + option output-file, "6502.bin" + option output-format, raw + ; ; Test basically created by pasting in opcodes from 6502.org ; @@ -45,6 +48,8 @@ addr_mode_tests: ; Uncomment to test ; adc ($44,y) ; Wrong indirect reg ; adc ($44),x ; Wrong indirect reg + option zero-page,auto + and_test and #$44 and $44 @@ -270,3 +275,72 @@ stack_test fwd_80: equ $80 fwd_101 equ $101 + +; Illegal opcodes + JAM + ALR #$44 + ANC #$44 + ANC2 #$44 + ANE #$44 + ARR #$44 + DCP $44 + DCP $44,X + DCP $4400 + DCP $4400,X + DCP $4400,Y + DCP ($44,X) + DCP ($44),Y + ISC $44 + ISC $44,X + ISC $4400 + ISC $4400,X + ISC $4400,Y + ISC ($44,X) + ISC ($44),Y + LAS $4400,Y + LAX $44 + LAX $44,Y + LAX $4400 + LAX $4400,Y + LAX ($44,X) + LAX ($44),Y + LXA #$44 + RLA $44 + RLA $44,X + RLA $4400 + RLA $4400,X + RLA $4400,Y + RLA ($44,X) + RLA ($44),Y + RRA $44 + RRA $44,X + RRA $4400 + RRA $4400,X + RRA $4400,Y + RRA ($44,X) + RRA ($44),Y + SAX $44 + SAX $44,Y + SAX $4400 + SAX ($44,X) + SBX #$44 + SHA $4400,Y + SHA ($44),Y + SHX $4400,Y + SHY $4400,X + SLO $44 + SLO $44,X + SLO $4400 + SLO $4400,X + SLO $4400,Y + SLO ($44,X) + SLO ($44),Y + SRE $44 + SRE $44,X + SRE $4400 + SRE $4400,X + SRE $4400,Y + SRE ($44,X) + SRE ($44),Y + TAS $4400,Y + USBC #$44 -- cgit v1.2.3