From 294fe25c3664dd294ea6112fbb0dc27226957a3f Mon Sep 17 00:00:00 2001 From: marcobaye Date: Wed, 28 Dec 2016 20:32:00 +0000 Subject: [PATCH] ACME Release 0.96: Added experimental support for instruction sets of Rockwell 65C02, WDC 65C02(S), CSG 65CE02 and CSG 4502. Stack indexing can now be given either as ",s" or as ",sp" (only relevant for 65816 and 65CE02). git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@78 4df02467-bbd4-4a76-a152-e7ce94205b78 --- docs/AllPOs.txt | 18 +- docs/Changes.txt | 10 + docs/Errors.txt | 10 + docs/cputypes.txt | 129 +++++++ src/_amiga.h | 4 +- src/_dos.c | 4 +- src/_dos.h | 4 +- src/_riscos.c | 4 +- src/_riscos.h | 4 +- src/_std.c | 4 +- src/_std.h | 4 +- src/acme.c | 2 +- src/acme.h | 4 +- src/alu.c | 2 +- src/alu.h | 2 +- src/cliargs.c | 4 +- src/cliargs.h | 4 +- src/config.h | 2 +- src/cpu.c | 44 ++- src/cpu.h | 3 +- src/dynabuf.c | 4 +- src/dynabuf.h | 4 +- src/encoding.c | 4 +- src/encoding.h | 4 +- src/flow.c | 4 +- src/flow.h | 4 +- src/global.c | 2 +- src/global.h | 2 +- src/input.c | 2 +- src/input.h | 2 +- src/macro.c | 2 +- src/macro.h | 4 +- src/mnemo.c | 840 ++++++++++++++++++++++++++++---------------- src/mnemo.h | 40 ++- src/output.c | 2 +- src/output.h | 2 +- src/platform.c | 4 +- src/platform.h | 4 +- src/pseudoopcodes.c | 2 +- src/pseudoopcodes.h | 4 +- src/section.c | 2 +- src/section.h | 2 +- src/symbol.c | 2 +- src/symbol.h | 2 +- src/tree.c | 4 +- src/tree.h | 2 +- src/typesystem.c | 4 +- src/typesystem.h | 4 +- src/version.h | 6 +- 49 files changed, 810 insertions(+), 416 deletions(-) create mode 100644 docs/cputypes.txt diff --git a/docs/AllPOs.txt b/docs/AllPOs.txt index de4c33c..b9cd335 100644 --- a/docs/AllPOs.txt +++ b/docs/AllPOs.txt @@ -817,13 +817,17 @@ Purpose: Select the processor to produce code for. If this PO the previously chosen CPU value is restored afterwards. Parameters: KEYWORD: Currently valid keywords are: - 6502 mnemonics and addressing modes of 6502 cpu - 65c02 superset of 6502, adds 65c02 extensions - 65816 superset of 65c02, adds 65816 extensions - 6510 superset of 6502, adds mnemonics for - undocumented opcodes - c64dtv2 superset of 6510, adds mnemonics for DTV2 - extensions (BRA/SAC/SIR) + 6502 for the original MOS 6502 + 6510 6502 plus undocumented opcodes + 65c02 6502 plus BRA,PHX/Y,PLX/Y,STZ,TRB/TSB + r65c02 65c02 plus BBRx, BBSx, RMBx, SMBx + w65c02 r65c02 plus STP/WAI + 65816 65c02 plus 16/24-bit extensions + 65ce02 r65c02 plus Z reg, long branches, ... + 4502 65ce02 with MAP instead of AUG + c64dtv2 6502 plus BRA/SAC/SIR plus some of the + undocumented opcodes + See "docs/cputypes.txt" for more info. BLOCK: A block of assembler statements. Examples: !if cputype = $65c02 { !cpu 65c02 { ; temporarily allow 65c02 stuff diff --git a/docs/Changes.txt b/docs/Changes.txt index 20030a3..e03b0a4 100644 --- a/docs/Changes.txt +++ b/docs/Changes.txt @@ -12,6 +12,16 @@ platform used. There should be another help file in this archive outlining the platform specific changes. +---------------------------------------------------------------------- +Section: New in release 0.96 +---------------------------------------------------------------------- + +Added experimental support for instruction sets of Rockwell 65C02, + WDC 65C02(S), CSG 65CE02 and CSG 4502. +Stack indexing can now be given either as ",s" or as ",sp" (only + relevant for 65816 and 65CE02). + + ---------------------------------------------------------------------- Section: New in release 0.95.8 ---------------------------------------------------------------------- diff --git a/docs/Errors.txt b/docs/Errors.txt index 171d5d7..a0c54b4 100644 --- a/docs/Errors.txt +++ b/docs/Errors.txt @@ -71,6 +71,12 @@ Found new "!for" syntax. When using the "-Wno-old-for" switch to disable the warning about the older syntax, the new syntax will trigger this warning. +Found SED instruction for CPU with known decimal SBC bug. + This warning is only ever given for CPU types 65ce02 and 4502, + because they are known to be buggy in decimal mode. + Pavel Zima and Eric Smith found an example where $41 minus $08 + gave $39 instead of $33. + Label name not in leftmost column. A label definition has blanks before the label name. Imagine this source code: @@ -408,6 +414,10 @@ IllegalBlockTerminator IllegalOperatorHandle The expression parser found an operator that does not exist. +IllegalImmediateMode + The mnemonic tree contains invalid info about the size of immediate + arguments. + OperandStackNotEmpty The expression parser has finished though there are still operands left to parse. diff --git a/docs/cputypes.txt b/docs/cputypes.txt new file mode 100644 index 0000000..bdece96 --- /dev/null +++ b/docs/cputypes.txt @@ -0,0 +1,129 @@ + + + ACME + + ...the ACME Crossassembler for Multiple Environments + + --- cpu types --- + + +ACME supports the following cpu types: + + + + +*** 6502 + +This is the instruction set of the original NMOS 6502 designed by MOS +(later CSG). +There are 151 documented opcodes. + + + + +*** 6510 + +This is the 6502 variant used in the C64 computer. It uses the same +instruction set as the 6502, but in addition to that, ACME supports +most of the undocumented opcodes as well. +See docs/Illegals.txt for more info. + + + + +*** 65c02 + +This is the CMOS re-design of the 6502. It seems to have also been +available from Rockwell, GTE/CMD and others. Features: +- new instructions: + BRA (branch always) + PHX, PHY, PLX, PLY (push/pull X/Y register) + STZ (store zero, 4 addr modes) + TRB (test and reset bits, 2 addr modes) + TSB (test and set bits, 2 addr modes) +- new addressing modes for existing instructions: + BIT #$12 + BIT $12, x + BIT $1234, x + LDA/STA/ADC/SBC ($12) (zp indirect without index) + AND/ORA/EOR/CMP ($12) (zp indirect without index) + INC (increment accumulator) + DEC (decrement accumulator) + JMP ($1234,x) (jump indexed indirect) +- bugfix for flags in decimal mode +- bugfix for JMP($xxff) instruction +- undocumented opcodes are NOPs (although of different lengths) +There are 178 documented opcodes. + + + +*** r65c02 + +This is a superset of 65c02, probably originally from Rockwell. +- It adds bit manipulation instructions: + BBR0..BBR7 (branch on bit reset) + BBS0..BBS7 (branch on bit set) + RMB0..RMB7 (reset memory bit) + SMB0..SMB7 (set memory bit) +Chips with this instruction set seem to have been available from +Rockwell, GTE/CMD and others. +There are 210 documented opcodes. + + + +*** w65c02 + +This is a superset of r65c02, originating at WDC. +- It adds the STP and WAI instructions. +There are 212 documented opcodes. + + + +*** 65816 + +This is a superset of 65c02, originally designed by WDC (it seems to +have been available from GTE/CMD as well). Features: +- register sizes can be changed to 16-bit +- 24-bit address space +- several new addressing modes +- block transfers +There are 256 documented opcodes, but one of them ("WDM") is reserved +for future expansion. + + + +*** 65ce02 + +This is a superset of r65c02, originating at CSG. Features: +- Z register +- 16-bit stack pointer +- 16-bit branches +- a few 16-bit instructions +- new addressing modes +There is a known bug: SBC does not work corrently in decimal mode. +There are 256 documented opcodes, but one of them ("AUG") is reserved +for future expansion. + + + +*** 4502 + +This is basically the same as 65ce02, but +- MAP replaces AUG +- EOM is synonymous to NOP +This cpu core can be found in the CSG4510 chip in the C65. +There are 256 documented opcodes. + + + +*** c64dtv2 + +This is the cpu in version 2 of the C64DTV. It uses a superset of the +6502 instruction set. Features: +- new instructions: + BRA $1234 (branch always) + SAC #$12 (set accumulator mapping) + SIR #$12 (set index register mapping) +- support for some of the undocumented opcodes. + + diff --git a/src/_amiga.h b/src/_amiga.h index 5e398e6..315b601 100644 --- a/src/_amiga.h +++ b/src/_amiga.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for AmigaOS) diff --git a/src/_dos.c b/src/_dos.c index 3e83098..6ba973a 100644 --- a/src/_dos.c +++ b/src/_dos.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for DOS, OS/2 and Windows) diff --git a/src/_dos.h b/src/_dos.h index 0d5b099..4e3c288 100644 --- a/src/_dos.h +++ b/src/_dos.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for DOS, OS/2 and Windows) diff --git a/src/_riscos.c b/src/_riscos.c index 03dd3ff..ce28753 100644 --- a/src/_riscos.c +++ b/src/_riscos.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for RISC OS) diff --git a/src/_riscos.h b/src/_riscos.h index d3a6b62..bea08a6 100644 --- a/src/_riscos.h +++ b/src/_riscos.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for RISC OS) diff --git a/src/_std.c b/src/_std.c index 25f1509..9fac2df 100644 --- a/src/_std.c +++ b/src/_std.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for unknown OSes) diff --git a/src/_std.h b/src/_std.h index 23f30e8..ecddf64 100644 --- a/src/_std.h +++ b/src/_std.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff (in this case, for unknown OSes) diff --git a/src/acme.c b/src/acme.c index 8f91d88..b2e35fe 100644 --- a/src/acme.c +++ b/src/acme.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // // This program is free software; you can redistribute it and/or modify diff --git a/src/acme.h b/src/acme.h index 619ad25..3296501 100644 --- a/src/acme.h +++ b/src/acme.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Main definitions diff --git a/src/alu.c b/src/alu.c index 7a8716d..b259d40 100644 --- a/src/alu.c +++ b/src/alu.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/alu.h b/src/alu.h index cffb43b..1eef42b 100644 --- a/src/alu.h +++ b/src/alu.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/cliargs.c b/src/cliargs.c index 955d2c0..9ba7232 100644 --- a/src/cliargs.c +++ b/src/cliargs.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // CLI argument stuff diff --git a/src/cliargs.h b/src/cliargs.h index aa1efad..10a7ef2 100644 --- a/src/cliargs.h +++ b/src/cliargs.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // CLI argument stuff diff --git a/src/config.h b/src/config.h index 55c7cd4..535f15e 100644 --- a/src/config.h +++ b/src/config.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/cpu.c b/src/cpu.c index 222638b..41afad5 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // @@ -16,42 +16,50 @@ // constants static struct cpu_type cpu_type_6502 = { - keyword_is_6502mnemo, + keyword_is_6502_mnemo, CPUFLAG_INDIRECTJMPBUGGY, // JMP ($xxFF) is buggy 234 // !align fills with "NOP" }; static struct cpu_type cpu_type_6510 = { - keyword_is_6510mnemo, + keyword_is_6510_mnemo, CPUFLAG_INDIRECTJMPBUGGY | CPUFLAG_8B_AND_AB_NEED_0_ARG, // JMP ($xxFF) is buggy, ANE/LXA #$xx are unstable unless arg is $00 234 // !align fills with "NOP" }; static struct cpu_type cpu_type_c64dtv2 = { - keyword_is_c64dtv2mnemo, + keyword_is_c64dtv2_mnemo, CPUFLAG_INDIRECTJMPBUGGY | CPUFLAG_8B_AND_AB_NEED_0_ARG, // JMP ($xxFF) is buggy, ANE/LXA #$xx are unstable unless arg is $00 234 // !align fills with "NOP" }; static struct cpu_type cpu_type_65c02 = { - keyword_is_65c02mnemo, + keyword_is_65c02_mnemo, 0, // no flags 234 // !align fills with "NOP" }; -/* -static struct cpu_type cpu_type_Rockwell65c02 = { - keyword_is_Rockwell65c02mnemo, +static struct cpu_type cpu_type_r65c02 = { + keyword_is_r65c02_mnemo, 0, // no flags 234 // !align fills with "NOP" }; -static struct cpu_type cpu_type_WDC65c02 = { - keyword_is_WDC65c02mnemo, +static struct cpu_type cpu_type_w65c02 = { + keyword_is_w65c02_mnemo, 0, // no flags 234 // !align fills with "NOP" }; -*/ static struct cpu_type cpu_type_65816 = { - keyword_is_65816mnemo, + keyword_is_65816_mnemo, CPUFLAG_SUPPORTSLONGREGS, // allows A and XY to be 16bits wide 234 // !align fills with "NOP" }; +static struct cpu_type cpu_type_65ce02 = { + keyword_is_65ce02_mnemo, + CPUFLAG_DECIMALSUBTRACTBUGGY, // SBC does not work reliably in decimal mode + 234 // !align fills with "NOP" +}; +static struct cpu_type cpu_type_4502 = { + keyword_is_4502_mnemo, + CPUFLAG_DECIMALSUBTRACTBUGGY, // SBC does not work reliably in decimal mode + 234 // !align fills with "NOP" +}; // variables @@ -59,15 +67,17 @@ static struct cpu_type cpu_type_65816 = { // predefined stuff static struct ronode *cputype_tree = NULL; static struct ronode cputype_list[] = { -#define KNOWN_TYPES "'6502', '6510', 'c64dtv2', '65c02', '65816'" // shown in CLI error message for unknown types +#define KNOWN_TYPES "'6502', '6510', '65c02', 'r65c02', 'w65c02', '65816', '65ce02', '4502', 'c64dtv2'" // shown in CLI error message for unknown types // PREDEFNODE("z80", &cpu_type_Z80), PREDEFNODE("6502", &cpu_type_6502), PREDEFNODE("6510", &cpu_type_6510), - PREDEFNODE("c64dtv2", &cpu_type_c64dtv2), PREDEFNODE("65c02", &cpu_type_65c02), -// PREDEFNODE("Rockwell65c02", &cpu_type_Rockwell65c02), -// PREDEFNODE("WDC65c02", &cpu_type_WDC65c02), - PREDEFLAST("65816", &cpu_type_65816), + PREDEFNODE("r65c02", &cpu_type_r65c02), + PREDEFNODE("w65c02", &cpu_type_w65c02), + PREDEFNODE("65816", &cpu_type_65816), + PREDEFNODE("65ce02", &cpu_type_65ce02), + PREDEFNODE("4502", &cpu_type_4502), + PREDEFLAST("c64dtv2", &cpu_type_c64dtv2), // ^^^^ this marks the last element }; const char cputype_names[] = KNOWN_TYPES; // string to show if cputype_find() returns NULL diff --git a/src/cpu.h b/src/cpu.h index 394a053..cbfce00 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // @@ -22,6 +22,7 @@ struct cpu_type { #define CPUFLAG_SUPPORTSLONGREGS (1u << 1) // allow "!al" and "!rl" pseudo opcodes #define CPUFLAG_8B_AND_AB_NEED_0_ARG (1u << 2) // warn if "ane/lxa #$xx" uses non-zero arg #define CPUFLAG_ISBIGENDIAN (1u << 3) // for 16/24/32-bit values, output msb first +#define CPUFLAG_DECIMALSUBTRACTBUGGY (1u << 4) // warn if "sed" is assembled // if cpu type and value match, set register length variable to value. diff --git a/src/dynabuf.c b/src/dynabuf.c index 6d73e96..2e078a7 100644 --- a/src/dynabuf.c +++ b/src/dynabuf.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Dynamic buffer stuff diff --git a/src/dynabuf.h b/src/dynabuf.h index 0957f90..d143753 100644 --- a/src/dynabuf.h +++ b/src/dynabuf.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Dynamic buffer stuff diff --git a/src/encoding.c b/src/encoding.c index 9f65b6b..45d16b7 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Character encoding stuff diff --git a/src/encoding.h b/src/encoding.h index 1db0920..9fd0c92 100644 --- a/src/encoding.h +++ b/src/encoding.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Character encoding stuff diff --git a/src/flow.c b/src/flow.c index 63835ec..9ef0106 100644 --- a/src/flow.c +++ b/src/flow.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Flow control stuff (loops, conditional assembly etc.) diff --git a/src/flow.h b/src/flow.h index 74cf9e3..cf30b2e 100644 --- a/src/flow.h +++ b/src/flow.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2015 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // flow control stuff (loops, conditional assembly etc.) diff --git a/src/global.c b/src/global.c index 807b392..854d183 100644 --- a/src/global.c +++ b/src/global.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/global.h b/src/global.h index 20f1ded..b68129e 100644 --- a/src/global.h +++ b/src/global.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/input.c b/src/input.c index 1a0fe39..43f555e 100644 --- a/src/input.c +++ b/src/input.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/input.h b/src/input.h index 47e7d6d..1e20511 100644 --- a/src/input.h +++ b/src/input.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/macro.c b/src/macro.c index 867f7e1..c310dea 100644 --- a/src/macro.c +++ b/src/macro.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/macro.h b/src/macro.h index 74ee5b9..7d423bc 100644 --- a/src/macro.h +++ b/src/macro.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Macro stuff diff --git a/src/mnemo.c b/src/mnemo.c index f8b8e68..5f2fdd7 100644 --- a/src/mnemo.c +++ b/src/mnemo.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2015 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Mnemonics stuff @@ -19,42 +19,39 @@ #define s_ror (s_error + 2) // Yes, I know I'm sick #define MNEMO_DYNABUF_INITIALSIZE 8 // 4 + terminator should suffice -// These values are needed to recognize addressing modes. -// Bits: -// 7....... "Implied" no value given -// .6...... "Immediate" "#" at start -// ..5..... "IndirectLong" "[" at start and "]" after value -// ...4.... "Indirect" Value has at least one unnecessary pair of "()" -// ....32.. "Indexed-Int" Index given inside of "()" -// ......10 "Indexed-Ext" Index given outside of (or without any) "()" -// -// Index bits: -// 00 = no index -// 01 = ",s" (Stack-indexed) -// 10 = ",x" (X-indexed) -// 11 = ",y" (Y-indexed) +// These values are needed to recognize addressing modes: +// indexing: +#define INDEX_NONE 0 // no index +#define INDEX_S 1 // stack-indexed (",s" or ",sp"), for 65816 and 65ce02 +#define INDEX_X 2 // x-indexed (",x") +#define INDEX_Y 3 // y-indexed (",y") +#define INDEX_Z 4 // z-indexed (",z"), only for 65ce02 + // 5..7 are left for future expansion, 8 would need the AMB_INDEX macro below to be adjusted! +// adress mode bits: +#define AMB_IMPLIED (1u << 0) // no value given +#define AMB_IMMEDIATE (1u << 1) // '#' at start +#define AMB_INDIRECT (1u << 2) // value has at least one unnecessary pair of "()" +#define AMB_LONGINDIRECT (1u << 3) // value is given in [] +#define AMB_PREINDEX(idx) ((idx) << 4) // three bits for indexing inside () +#define AMB_INDEX(idx) ((idx) << 7) // three bits for external indexing -// Components (Values for indices) -#define HAM__ (0u << 0) // No index -#define HAM_S (1u << 0) // Stack-indexed -#define HAM_X (2u << 0) // X-indexed -#define HAM_Y (3u << 0) // Y-indexed - -// End values base value internal index external index -#define HAM_IMP (1u << 7) -#define HAM_IMM (1u << 6) -#define HAM_ABS 0 -#define HAM_ABSS (1u << 0) -#define HAM_ABSX (2u << 0) -#define HAM_ABSY (3u << 0) -#define HAM_IND (1u << 4) -#define HAM_XIND ((1u << 4) | (2u << 2)) -#define HAM_INDY ((1u << 4) | (3u << 0)) -#define HAM_SINDY ((1u << 4) | (1u << 2) | (3u << 0)) -#define HAM_LIND (1u << 5) -#define HAM_LINDY ((1u << 5) | (3u << 0)) -// Values of internal indices equal values of external indices, shifted left -// by two bits. The program relies on this ! +// end values (here, "absolute addressing" always includes zeropage addressing, because they look the same) +#define IMPLIED_ADDRESSING AMB_IMPLIED +#define IMMEDIATE_ADDRESSING AMB_IMMEDIATE +#define ABSOLUTE_ADDRESSING 0 +#define X_INDEXED_ADDRESSING AMB_INDEX(INDEX_X) +#define Y_INDEXED_ADDRESSING AMB_INDEX(INDEX_Y) +#define INDIRECT_ADDRESSING AMB_INDIRECT +#define X_INDEXED_INDIRECT_ADDRESSING (AMB_PREINDEX(INDEX_X) | AMB_INDIRECT) +#define INDIRECT_Y_INDEXED_ADDRESSING (AMB_INDIRECT | AMB_INDEX(INDEX_Y)) +// only for 65ce02: +#define INDIRECT_Z_INDEXED_ADDRESSING (AMB_INDIRECT | AMB_INDEX(INDEX_Z)) +// for 65816 and 65ce02: +#define STACK_INDEXED_INDIRECT_Y_INDEXED_ADDRESSING (AMB_PREINDEX(INDEX_S) | AMB_INDIRECT | AMB_INDEX(INDEX_Y)) +// only for 65816: +#define STACK_INDEXED_ADDRESSING AMB_INDEX(INDEX_S) +#define LONG_INDIRECT_ADDRESSING AMB_LONGINDIRECT +#define LONG_INDIRECT_Y_INDEXED_ADDRESSING (AMB_LONGINDIRECT | AMB_INDEX(INDEX_Y)) // Constant values, used to mark the possible parameter lengths of commands. // Not all of the eight values are actually used, however (because of the @@ -75,8 +72,11 @@ enum mnemogroup { GROUP_ALLJUMPS, // the jump instructions Byte value = table index GROUP_IMPLIEDONLY, // mnemonics using only implied addressing Byte value = opcode GROUP_RELATIVE8, // short branch instructions Byte value = opcode - GROUP_RELATIVE16, // mnemonics with 16bit relative addressing Byte value = opcode - GROUP_BOTHMOVES // the "move" commands MVP and MVN Byte value = opcode + GROUP_BITBRANCH, // bbr0..7 and bbs0..7 Byte value = opcode + GROUP_REL16_2, // 16bit relative to pc+2 Byte value = opcode + GROUP_REL16_3, // 16bit relative to pc+3 Byte value = opcode + GROUP_BOTHMOVES, // the "move" commands MVP and MVN Byte value = opcode + GROUP_MEMBIT // rmb0..7 and smb0..7 Byte value = opcode }; // save some space @@ -90,19 +90,20 @@ enum mnemogroup { // column to use here. The row depends on the used addressing mode. A zero // entry in these tables means that the combination of mnemonic and addressing // mode is illegal. -// | 6502 | 65c02 | 65816 | 6510 illegals | -enum { IDX_ORA,IDX_AND,IDX_EOR,IDX_ADC,IDX_STA,IDX_LDA,IDX_CMP,IDX_SBC,IDXcORA,IDXcAND,IDXcEOR,IDXcADC,IDXcSTA,IDXcLDA,IDXcCMP,IDXcSBC,IDX816ORA,IDX816AND,IDX816EOR,IDX816ADC,IDX816STA,IDX816LDA,IDX816CMP,IDX816SBC,IDX816PEI,IDX_SLO,IDX_RLA,IDX_SRE,IDX_RRA,IDX_SAX,IDX_LAX,IDX_DCP,IDX_ISC,IDX_SHA}; -SCL accu_abs[] = { 0x0d05, 0x2d25, 0x4d45, 0x6d65, 0x8d85, 0xada5, 0xcdc5, 0xede5, 0x0d05, 0x2d25, 0x4d45, 0x6d65, 0x8d85, 0xada5, 0xcdc5, 0xede5, 0x0f0d05, 0x2f2d25, 0x4f4d45, 0x6f6d65, 0x8f8d85, 0xafada5, 0xcfcdc5, 0xefede5, 0, 0x0f07, 0x2f27, 0x4f47, 0x6f67, 0x8f87, 0xafa7, 0xcfc7, 0xefe7, 0}; // $ff $ffff $ffffff -SCL accu_xabs[] = { 0x1d15, 0x3d35, 0x5d55, 0x7d75, 0x9d95, 0xbdb5, 0xddd5, 0xfdf5, 0x1d15, 0x3d35, 0x5d55, 0x7d75, 0x9d95, 0xbdb5, 0xddd5, 0xfdf5, 0x1f1d15, 0x3f3d35, 0x5f5d55, 0x7f7d75, 0x9f9d95, 0xbfbdb5, 0xdfddd5, 0xfffdf5, 0, 0x1f17, 0x3f37, 0x5f57, 0x7f77, 0, 0, 0xdfd7, 0xfff7, 0}; // $ff,x $ffff,x $ffffff,x -SCS accu_yabs[] = { 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0, 0x1b00, 0x3b00, 0x5b00, 0x7b00, 0x97, 0xbfb7, 0xdb00, 0xfb00, 0x9f00}; // $ff,y $ffff,y -SCB accu_xind8[] = { 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3, 0}; // ($ff,x) -SCB accu_indy8[] = { 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0, 0x13, 0x33, 0x53, 0x73, 0, 0xb3, 0xd3, 0xf3, 0x93}; // ($ff),y -SCB accu_imm[] = { 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // #$ff #$ffff -SCB accu_ind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ($ff) -SCB accu_sabs8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // $ff,s -SCB accu_sindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x13, 0x33, 0x53, 0x73, 0x93, 0xb3, 0xd3, 0xf3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ($ff,s),y -SCB accu_lind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07, 0x27, 0x47, 0x67, 0x87, 0xa7, 0xc7, 0xe7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [$ff] -SCB accu_lindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x17, 0x37, 0x57, 0x77, 0x97, 0xb7, 0xd7, 0xf7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [$ff],y +// | 6502 | 65c02 | 65ce02 | 65816 | 6510 illegals | +enum { IDX_ORA,IDX_AND,IDX_EOR,IDX_ADC,IDX_STA,IDX_LDA,IDX_CMP,IDX_SBC,IDXcORA,IDXcAND,IDXcEOR,IDXcADC,IDXcSTA,IDXcLDA,IDXcCMP,IDXcSBC,IDXeORA,IDXeAND,IDXeEOR,IDXeADC,IDXeSTA,IDXeLDA,IDXeCMP,IDXeSBC,IDX816ORA,IDX816AND,IDX816EOR,IDX816ADC,IDX816STA,IDX816LDA,IDX816CMP,IDX816SBC,IDX816PEI,IDX_SLO,IDX_RLA,IDX_SRE,IDX_RRA,IDX_SAX,IDX_LAX,IDX_DCP,IDX_ISC,IDX_SHA}; +SCB accu_imm[] = { 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0x09, 0x29, 0x49, 0x69, 0, 0xa9, 0xc9, 0xe9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // #$ff #$ffff +SCL accu_abs[] = { 0x0d05, 0x2d25, 0x4d45, 0x6d65, 0x8d85, 0xada5, 0xcdc5, 0xede5, 0x0d05, 0x2d25, 0x4d45, 0x6d65, 0x8d85, 0xada5, 0xcdc5, 0xede5, 0x0d05, 0x2d25, 0x4d45, 0x6d65, 0x8d85, 0xada5, 0xcdc5, 0xede5, 0x0f0d05, 0x2f2d25, 0x4f4d45, 0x6f6d65, 0x8f8d85, 0xafada5, 0xcfcdc5, 0xefede5, 0, 0x0f07, 0x2f27, 0x4f47, 0x6f67, 0x8f87, 0xafa7, 0xcfc7, 0xefe7, 0}; // $ff $ffff $ffffff +SCL accu_xabs[] = { 0x1d15, 0x3d35, 0x5d55, 0x7d75, 0x9d95, 0xbdb5, 0xddd5, 0xfdf5, 0x1d15, 0x3d35, 0x5d55, 0x7d75, 0x9d95, 0xbdb5, 0xddd5, 0xfdf5, 0x1d15, 0x3d35, 0x5d55, 0x7d75, 0x9d95, 0xbdb5, 0xddd5, 0xfdf5, 0x1f1d15, 0x3f3d35, 0x5f5d55, 0x7f7d75, 0x9f9d95, 0xbfbdb5, 0xdfddd5, 0xfffdf5, 0, 0x1f17, 0x3f37, 0x5f57, 0x7f77, 0, 0, 0xdfd7, 0xfff7, 0}; // $ff,x $ffff,x $ffffff,x +SCS accu_yabs[] = { 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0x1900, 0x3900, 0x5900, 0x7900, 0x9900, 0xb900, 0xd900, 0xf900, 0, 0x1b00, 0x3b00, 0x5b00, 0x7b00, 0x97, 0xbfb7, 0xdb00, 0xfb00, 0x9f00}; // $ff,y $ffff,y +SCB accu_xind8[] = { 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, 0x81, 0xa1, 0xc1, 0xe1, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3, 0}; // ($ff,x) +SCB accu_indy8[] = { 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0x11, 0x31, 0x51, 0x71, 0x91, 0xb1, 0xd1, 0xf1, 0, 0x13, 0x33, 0x53, 0x73, 0, 0xb3, 0xd3, 0xf3, 0x93}; // ($ff),y +SCB accu_ind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ($ff) +SCB accu_indz8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0x12, 0x32, 0x52, 0x72, 0x92, 0xb2, 0xd2, 0xf2, 0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ($ff) +SCB accu_sabs8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0x23, 0x43, 0x63, 0x83, 0xa3, 0xc3, 0xe3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // $ff,s +SCB accu_sindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x82, 0xe2, 0, 0, 0x13, 0x33, 0x53, 0x73, 0x93, 0xb3, 0xd3, 0xf3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // ($ff,s),y +SCB accu_lind8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x07, 0x27, 0x47, 0x67, 0x87, 0xa7, 0xc7, 0xe7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [$ff] +SCB accu_lindy8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x17, 0x37, 0x57, 0x77, 0x97, 0xb7, 0xd7, 0xf7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // [$ff],y // Code tables for group GROUP_MISC: // These tables are needed for finding out the correct code in cases when @@ -110,13 +111,13 @@ SCB accu_lindy8[] = { 0, 0, 0, 0, 0, 0, 0, // mnemotable), the assembler finds out the column to use here. The row // depends on the used addressing mode. A zero entry in these tables means // that the combination of mnemonic and addressing mode is illegal. -// | 6502 | 65c02 | 65816 | 6510 illegals | C64DTV2 | -enum { IDX_BIT,IDX_ASL,IDX_ROL,IDX_LSR,IDX_ROR,IDX_STY,IDX_STX,IDX_LDY,IDX_LDX,IDX_CPY,IDX_CPX,IDX_DEC,IDX_INC,IDXcTSB,IDXcTRB,IDXcBIT,IDXcDEC,IDXcINC,IDXcSTZ,IDX816COP,IDX816REP,IDX816SEP,IDX816PEA,IDX_ANC,IDX_ASR,IDX_ARR,IDX_SBX,IDX_DOP,IDX_TOP,IDX_JAM,IDX_LXA,IDX_ANE,IDX_LAS,IDX_TAS,IDX_SHX,IDX_SHY,IDX_SAC,IDX_SIR}; -SCS misc_abs[] = { 0x2c24, 0x0e06, 0x2e26, 0x4e46, 0x6e66, 0x8c84, 0x8e86, 0xaca4, 0xaea6, 0xccc4, 0xece4, 0xcec6, 0xeee6, 0x0c04, 0x1c14, 0x2c24, 0xcec6, 0xeee6, 0x9c64, 0x02, 0, 0, 0xf400, 0, 0, 0, 0, 0x04, 0x0c00, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // $ff $ffff -SCS misc_xabs[] = { 0, 0x1e16, 0x3e36, 0x5e56, 0x7e76, 0x94, 0, 0xbcb4, 0, 0, 0, 0xded6, 0xfef6, 0, 0, 0x3c34, 0xded6, 0xfef6, 0x9e74, 0, 0, 0, 0, 0, 0, 0, 0, 0x14, 0x1c00, 0, 0, 0, 0, 0, 0, 0x9c00, 0, 0}; // $ff,x $ffff,x -SCS misc_yabs[] = { 0, 0, 0, 0, 0, 0, 0x96, 0, 0xbeb6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbb00, 0x9b00, 0x9e00, 0, 0, 0}; // $ff,y $ffff,y -SCB misc_imm[] = { 0, 0, 0, 0, 0, 0, 0, 0xa0, 0xa2, 0xc0, 0xe0, 0, 0, 0, 0, 0x89, 0, 0, 0, 0, 0xc2, 0xe2, 0, 0x0b, 0x4b, 0x6b, 0xcb, 0x80, 0, 0, 0xab, 0x8b, 0, 0, 0, 0, 0x32, 0x42}; // #$ff -SCB misc_impl[] = { 0, 0x0a, 0x2a, 0x4a, 0x6a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3a, 0x1a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0c, 0x02, 0, 0, 0, 0, 0, 0, 0, 0}; // implied/accu +// | 6502 | 65c02 | 65ce02 | 65816 | 6510 illegals | C64DTV2 | +enum { IDX_BIT,IDX_ASL,IDX_ROL,IDX_LSR,IDX_ROR,IDX_STY,IDX_STX,IDX_LDY,IDX_LDX,IDX_CPY,IDX_CPX,IDX_DEC,IDX_INC,IDXcTSB,IDXcTRB,IDXcBIT,IDXcDEC,IDXcINC,IDXcSTZ,IDXeASR,IDXeASW,IDXeCPZ,IDXeDEW,IDXeINW,IDXeLDZ,IDXePHW,IDXeROW,IDXeRTN,IDXeSTX,IDXeSTY,IDX816COP,IDX816REP,IDX816SEP,IDX816PEA,IDX_ANC,IDX_ASR,IDX_ARR,IDX_SBX,IDX_DOP,IDX_TOP,IDX_JAM,IDX_LXA,IDX_ANE,IDX_LAS,IDX_TAS,IDX_SHX,IDX_SHY,IDX_SAC,IDX_SIR}; +SCB misc_impl[] = { 0, 0x0a, 0x2a, 0x4a, 0x6a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3a, 0x1a, 0, 0x43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x0c, 0x02, 0, 0, 0, 0, 0, 0, 0, 0}; // implied/accu +SCB misc_imm[] = { 0, 0, 0, 0, 0, 0, 0, 0xa0, 0xa2, 0xc0, 0xe0, 0, 0, 0, 0, 0x89, 0, 0, 0, 0, 0, 0xc2, 0, 0, 0xa3, 0xf4, 0, 0x62, 0, 0, 0, 0xc2, 0xe2, 0, 0x0b, 0x4b, 0x6b, 0xcb, 0x80, 0, 0, 0xab, 0x8b, 0, 0, 0, 0, 0x32, 0x42}; // #$ff #$ffff +SCS misc_abs[] = { 0x2c24, 0x0e06, 0x2e26, 0x4e46, 0x6e66, 0x8c84, 0x8e86, 0xaca4, 0xaea6, 0xccc4, 0xece4, 0xcec6, 0xeee6, 0x0c04, 0x1c14, 0x2c24, 0xcec6, 0xeee6, 0x9c64, 0x44, 0xcb00, 0xdcd4, 0xc3, 0xe3, 0xab00, 0xfc00, 0xeb00, 0, 0x8e86, 0x8c84, 0x02, 0, 0, 0xf400, 0, 0, 0, 0, 0x04, 0x0c00, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // $ff $ffff +SCS misc_xabs[] = { 0, 0x1e16, 0x3e36, 0x5e56, 0x7e76, 0x94, 0, 0xbcb4, 0, 0, 0, 0xded6, 0xfef6, 0, 0, 0x3c34, 0xded6, 0xfef6, 0x9e74, 0x54, 0, 0, 0, 0, 0xbb00, 0, 0, 0, 0, 0x8b94, 0, 0, 0, 0, 0, 0, 0, 0, 0x14, 0x1c00, 0, 0, 0, 0, 0, 0, 0x9c00, 0, 0}; // $ff,x $ffff,x +SCS misc_yabs[] = { 0, 0, 0, 0, 0, 0, 0x96, 0, 0xbeb6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x9b96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xbb00, 0x9b00, 0x9e00, 0, 0, 0}; // $ff,y $ffff,y // Code tables for group GROUP_ALLJUMPS: // These tables are needed for finding out the correct code when the mnemonic @@ -125,12 +126,12 @@ SCB misc_impl[] = { 0, 0x0a, 0x2a, 0x4a, 0x6a, 0, 0, // finds out the column to use here. The row depends on the used addressing // mode. A zero entry in these tables means that the combination of mnemonic // and addressing mode is illegal. -// | 6502 | 65c02 | 65816 | -enum { IDX_JMP,IDX_JSR,IDXcJMP,IDX816JMP,IDX816JML,IDX816JSR,IDX816JSL}; -SCL jump_abs[] = { 0x4c00, 0x2000, 0x4c00, 0x5c4c00, 0x5c0000, 0x222000, 0x220000}; // $ffff $ffffff -SCS jump_ind[] = { 0x6c00, 0, 0x6c00, 0x6c00, 0, 0, 0}; // ($ffff) -SCS jump_xind[] = { 0, 0, 0x7c00, 0x7c00, 0, 0xfc00, 0}; // ($ffff,x) -SCS jump_lind[] = { 0, 0, 0, 0xdc00, 0xdc00, 0, 0}; // [$ffff] +// | 6502 | 65c02 | 65ce02| 65816 | +enum { IDX_JMP,IDX_JSR,IDXcJMP,IDXeJSR,IDX816JMP,IDX816JML,IDX816JSR,IDX816JSL}; +SCL jump_abs[] = { 0x4c00, 0x2000, 0x4c00, 0x2000, 0x5c4c00, 0x5c0000, 0x222000, 0x220000}; // $ffff $ffffff +SCS jump_ind[] = { 0x6c00, 0, 0x6c00, 0x2200, 0x6c00, 0, 0, 0}; // ($ffff) +SCS jump_xind[] = { 0, 0, 0x7c00, 0x2300, 0x7c00, 0, 0xfc00, 0}; // ($ffff,x) +SCS jump_lind[] = { 0, 0, 0, 0, 0xdc00, 0xdc00, 0, 0}; // [$ffff] #undef SCB #undef SCS @@ -145,55 +146,62 @@ static const char exception_highbyte_zero[] = "Using oversized addressing mode." static struct dynabuf *mnemo_dyna_buf; // dynamic buffer for mnemonics // predefined stuff -static struct ronode *mnemo_6502_tree = NULL; // holds 6502 mnemonics -static struct ronode *mnemo_6502undoc1_tree = NULL; // holds 6502 undocumented ("illegal") opcodes supported by DTV2 -static struct ronode *mnemo_6502undoc2_tree = NULL; // holds remaining 6502 undocumented ("illegal") opcodes (currently ANC only, maybe more will get moved) -static struct ronode *mnemo_c64dtv2_tree = NULL; // holds C64DTV2 extensions (BRA/SAC/SIR) -static struct ronode *mnemo_65c02_tree = NULL; // holds 65c02 extensions -//static struct ronode *mnemo_Rockwell65c02_tree = NULL; // Rockwell -static struct ronode *mnemo_WDC65c02_tree = NULL; // WDC's "stp"/"wai" -static struct ronode *mnemo_65816_tree = NULL; // holds 65816 extensions +static struct ronode *mnemo_6502_tree = NULL; // 6502 mnemonics +static struct ronode *mnemo_6502undoc1_tree = NULL; // 6502 undocumented ("illegal") opcodes supported by DTV2 +static struct ronode *mnemo_6502undoc2_tree = NULL; // remaining 6502 undocumented ("illegal") opcodes (currently ANC only, maybe more will get moved) +static struct ronode *mnemo_c64dtv2_tree = NULL; // C64DTV2 extensions (BRA/SAC/SIR) +static struct ronode *mnemo_65c02_tree = NULL; // 65c02 extensions +static struct ronode *mnemo_bitmanips_tree = NULL; // Rockwell's bit manipulation extensions +static struct ronode *mnemo_stp_wai_tree = NULL; // WDC's "stp" and "wai" instructions +static struct ronode *mnemo_65816_tree = NULL; // WDC 65816 extensions +static struct ronode *mnemo_65ce02_tree = NULL; // CSG 65ce02/4502 extensions +static struct ronode *mnemo_aug_tree = NULL; // CSG 65ce02's "aug" instruction +static struct ronode *mnemo_map_eom_tree = NULL; // CSG 4502's "map" and "eom" instructions // Command's code and group values are stored together in a single integer. // To extract the code, use "& CODEMASK". -// To extract the group, use ">> GROUPSHIFT" -#define CODEMASK 0xff // opcode or table index -#define FLAGSMASK 0x300 // flags concerning immediate addressing: -#define IMM_ACCU 0x100 // ...depends on accumulator length -#define IMM_IDX 0x200 // ...depends on index register length -#define GROUPSHIFT 10 // shift right by this to extract group -#define MERGE(g, v) ((g << GROUPSHIFT) | v) +// To extract the immediate mode, use "& IMMASK". +// To extract the group, use GROUP() +#define CODEMASK 0x0ff // opcode or table index +// immediate mode: +#define IM_FORCE8 0x000 // immediate values are 8 bits (CAUTION - program relies on "no bits set" being the default!) +#define IM_FORCE16 0x100 // immediate value is 16 bits (for 65ce02's PHW#) +#define IM_ACCUMULATOR 0x200 // immediate value depends on accumulator length +#define IM_INDEXREGS 0x300 // immediate value depends on index register length +#define IMMASK 0x300 // mask for immediate modes +#define MERGE(g, v) (((g) << 10) | (v)) +#define GROUP(v) ((v) >> 10) static struct ronode mnemos_6502[] = { - PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX_ORA | IMM_ACCU)), - PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDX_AND | IMM_ACCU)), - PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDX_EOR | IMM_ACCU)), - PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX_ADC | IMM_ACCU)), + PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX_ORA)), + PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDX_AND)), + PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDX_EOR)), + PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX_ADC)), PREDEFNODE("sta", MERGE(GROUP_ACCU, IDX_STA)), - PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX_LDA | IMM_ACCU)), - PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX_CMP | IMM_ACCU)), - PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX_SBC | IMM_ACCU)), - PREDEFNODE("bit", MERGE(GROUP_MISC, IDX_BIT | IMM_ACCU)), + PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX_LDA)), + PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX_CMP)), + PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX_SBC)), + PREDEFNODE("bit", MERGE(GROUP_MISC, IDX_BIT)), PREDEFNODE(s_asl, MERGE(GROUP_MISC, IDX_ASL)), PREDEFNODE("rol", MERGE(GROUP_MISC, IDX_ROL)), PREDEFNODE(s_lsr, MERGE(GROUP_MISC, IDX_LSR)), PREDEFNODE(s_ror, MERGE(GROUP_MISC, IDX_ROR)), PREDEFNODE("sty", MERGE(GROUP_MISC, IDX_STY)), PREDEFNODE("stx", MERGE(GROUP_MISC, IDX_STX)), - PREDEFNODE("ldy", MERGE(GROUP_MISC, IDX_LDY | IMM_IDX)), - PREDEFNODE("ldx", MERGE(GROUP_MISC, IDX_LDX | IMM_IDX)), - PREDEFNODE("cpy", MERGE(GROUP_MISC, IDX_CPY | IMM_IDX)), - PREDEFNODE("cpx", MERGE(GROUP_MISC, IDX_CPX | IMM_IDX)), + PREDEFNODE("ldy", MERGE(GROUP_MISC, IDX_LDY)), + PREDEFNODE("ldx", MERGE(GROUP_MISC, IDX_LDX)), + PREDEFNODE("cpy", MERGE(GROUP_MISC, IDX_CPY)), + PREDEFNODE("cpx", MERGE(GROUP_MISC, IDX_CPX)), PREDEFNODE("dec", MERGE(GROUP_MISC, IDX_DEC)), PREDEFNODE("inc", MERGE(GROUP_MISC, IDX_INC)), - PREDEFNODE("bpl", MERGE(GROUP_RELATIVE8, 16)), - PREDEFNODE("bmi", MERGE(GROUP_RELATIVE8, 48)), - PREDEFNODE("bvc", MERGE(GROUP_RELATIVE8, 80)), - PREDEFNODE("bvs", MERGE(GROUP_RELATIVE8, 112)), - PREDEFNODE("bcc", MERGE(GROUP_RELATIVE8, 144)), - PREDEFNODE("bcs", MERGE(GROUP_RELATIVE8, 176)), - PREDEFNODE("bne", MERGE(GROUP_RELATIVE8, 208)), - PREDEFNODE("beq", MERGE(GROUP_RELATIVE8, 240)), + PREDEFNODE("bpl", MERGE(GROUP_RELATIVE8, 0x10)), + PREDEFNODE("bmi", MERGE(GROUP_RELATIVE8, 0x30)), + PREDEFNODE("bvc", MERGE(GROUP_RELATIVE8, 0x50)), + PREDEFNODE("bvs", MERGE(GROUP_RELATIVE8, 0x70)), + PREDEFNODE("bcc", MERGE(GROUP_RELATIVE8, 0x90)), + PREDEFNODE("bcs", MERGE(GROUP_RELATIVE8, 0xb0)), + PREDEFNODE("bne", MERGE(GROUP_RELATIVE8, 0xd0)), + PREDEFNODE("beq", MERGE(GROUP_RELATIVE8, 0xf0)), PREDEFNODE("jmp", MERGE(GROUP_ALLJUMPS, IDX_JMP)), PREDEFNODE("jsr", MERGE(GROUP_ALLJUMPS, IDX_JSR)), PREDEFNODE("brk", MERGE(GROUP_IMPLIEDONLY, 0)), @@ -224,6 +232,7 @@ static struct ronode mnemos_6502[] = { // ^^^^ this marks the last element }; +// undocumented opcodes of the NMOS 6502 that are also supported by c64dtv2: static struct ronode mnemos_6502undoc1[] = { PREDEFNODE("slo", MERGE(GROUP_ACCU, IDX_SLO)), // ASL + ORA (aka ASO) PREDEFNODE("rla", MERGE(GROUP_ACCU, IDX_RLA)), // ROL + AND @@ -249,32 +258,37 @@ static struct ronode mnemos_6502undoc1[] = { // ^^^^ this marks the last element }; +// undocumented opcodes of the NMOS 6502 that are _not_ supported by c64dtv2: static struct ronode mnemos_6502undoc2[] = { PREDEFLAST("anc", MERGE(GROUP_MISC, IDX_ANC)), // ROL + AND, ASL + ORA (aka AAC) // ^^^^ this marks the last element }; +// additional opcodes of c64dtv2: static struct ronode mnemos_c64dtv2[] = { - PREDEFNODE(s_bra, MERGE(GROUP_RELATIVE8, 0x12)), // branch always + PREDEFNODE(s_bra, MERGE(GROUP_RELATIVE8, 0x12)), // branch always PREDEFNODE("sac", MERGE(GROUP_MISC, IDX_SAC)), // set accumulator mapping PREDEFLAST("sir", MERGE(GROUP_MISC, IDX_SIR)), // set index register mapping // ^^^^ this marks the last element }; +// new stuff in CMOS re-design: static struct ronode mnemos_65c02[] = { - PREDEFNODE("ora", MERGE(GROUP_ACCU, IDXcORA | IMM_ACCU)), - PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDXcAND | IMM_ACCU)), - PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDXcEOR | IMM_ACCU)), - PREDEFNODE("adc", MERGE(GROUP_ACCU, IDXcADC | IMM_ACCU)), + // more addressing modes for some mnemonics: + PREDEFNODE("ora", MERGE(GROUP_ACCU, IDXcORA)), + PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDXcAND)), + PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDXcEOR)), + PREDEFNODE("adc", MERGE(GROUP_ACCU, IDXcADC)), PREDEFNODE("sta", MERGE(GROUP_ACCU, IDXcSTA)), - PREDEFNODE("lda", MERGE(GROUP_ACCU, IDXcLDA | IMM_ACCU)), - PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDXcCMP | IMM_ACCU)), - PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDXcSBC | IMM_ACCU)), + PREDEFNODE("lda", MERGE(GROUP_ACCU, IDXcLDA)), + PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDXcCMP)), + PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDXcSBC)), PREDEFNODE("jmp", MERGE(GROUP_ALLJUMPS, IDXcJMP)), - PREDEFNODE("bit", MERGE(GROUP_MISC, IDXcBIT | IMM_ACCU)), + PREDEFNODE("bit", MERGE(GROUP_MISC, IDXcBIT)), PREDEFNODE("dec", MERGE(GROUP_MISC, IDXcDEC)), PREDEFNODE("inc", MERGE(GROUP_MISC, IDXcINC)), - PREDEFNODE(s_bra, MERGE(GROUP_RELATIVE8, 128)), + // and eight new mnemonics: + PREDEFNODE(s_bra, MERGE(GROUP_RELATIVE8, 0x80)), PREDEFNODE("phy", MERGE(GROUP_IMPLIEDONLY, 90)), PREDEFNODE("ply", MERGE(GROUP_IMPLIEDONLY, 122)), PREDEFNODE("phx", MERGE(GROUP_IMPLIEDONLY, 218)), @@ -285,66 +299,77 @@ static struct ronode mnemos_65c02[] = { // ^^^^ this marks the last element }; -//static struct ronode mnemos_Rockwell65c02[] = { -// PREDEFNODE("rmb0", MERGE(G_ , 0x07)), -// PREDEFNODE("rmb1", MERGE(G_ , 0x17)), -// PREDEFNODE("rmb2", MERGE(G_ , 0x27)), -// PREDEFNODE("rmb3", MERGE(G_ , 0x37)), -// PREDEFNODE("rmb4", MERGE(G_ , 0x47)), -// PREDEFNODE("rmb5", MERGE(G_ , 0x57)), -// PREDEFNODE("rmb6", MERGE(G_ , 0x67)), -// PREDEFNODE("rmb7", MERGE(G_ , 0x77)), -// PREDEFNODE("smb0", MERGE(G_ , 0x87)), -// PREDEFNODE("smb1", MERGE(G_ , 0x97)), -// PREDEFNODE("smb2", MERGE(G_ , 0xa7)), -// PREDEFNODE("smb3", MERGE(G_ , 0xb7)), -// PREDEFNODE("smb4", MERGE(G_ , 0xc7)), -// PREDEFNODE("smb5", MERGE(G_ , 0xd7)), -// PREDEFNODE("smb6", MERGE(G_ , 0xe7)), -// PREDEFNODE("smb7", MERGE(G_ , 0xf7)), -// PREDEFNODE("bbr0", MERGE(G_ , 0x0f)), -// PREDEFNODE("bbr1", MERGE(G_ , 0x1f)), -// PREDEFNODE("bbr2", MERGE(G_ , 0x2f)), -// PREDEFNODE("bbr3", MERGE(G_ , 0x3f)), -// PREDEFNODE("bbr4", MERGE(G_ , 0x4f)), -// PREDEFNODE("bbr5", MERGE(G_ , 0x5f)), -// PREDEFNODE("bbr6", MERGE(G_ , 0x6f)), -// PREDEFNODE("bbr7", MERGE(G_ , 0x7f)), -// PREDEFNODE("bbs0", MERGE(G_ , 0x8f)), -// PREDEFNODE("bbs1", MERGE(G_ , 0x9f)), -// PREDEFNODE("bbs2", MERGE(G_ , 0xaf)), -// PREDEFNODE("bbs3", MERGE(G_ , 0xbf)), -// PREDEFNODE("bbs4", MERGE(G_ , 0xcf)), -// PREDEFNODE("bbs5", MERGE(G_ , 0xdf)), -// PREDEFNODE("bbs6", MERGE(G_ , 0xef)), -// PREDEFLAST("bbs7", MERGE(G_ , 0xff)), -// // ^^^^ this marks the last element -//}; +// bit-manipulation extensions (by Rockwell?) +static struct ronode mnemos_bitmanips[] = { + PREDEFNODE("rmb0", MERGE(GROUP_MEMBIT, 0x07)), + PREDEFNODE("rmb1", MERGE(GROUP_MEMBIT, 0x17)), + PREDEFNODE("rmb2", MERGE(GROUP_MEMBIT, 0x27)), + PREDEFNODE("rmb3", MERGE(GROUP_MEMBIT, 0x37)), + PREDEFNODE("rmb4", MERGE(GROUP_MEMBIT, 0x47)), + PREDEFNODE("rmb5", MERGE(GROUP_MEMBIT, 0x57)), + PREDEFNODE("rmb6", MERGE(GROUP_MEMBIT, 0x67)), + PREDEFNODE("rmb7", MERGE(GROUP_MEMBIT, 0x77)), + PREDEFNODE("smb0", MERGE(GROUP_MEMBIT, 0x87)), + PREDEFNODE("smb1", MERGE(GROUP_MEMBIT, 0x97)), + PREDEFNODE("smb2", MERGE(GROUP_MEMBIT, 0xa7)), + PREDEFNODE("smb3", MERGE(GROUP_MEMBIT, 0xb7)), + PREDEFNODE("smb4", MERGE(GROUP_MEMBIT, 0xc7)), + PREDEFNODE("smb5", MERGE(GROUP_MEMBIT, 0xd7)), + PREDEFNODE("smb6", MERGE(GROUP_MEMBIT, 0xe7)), + PREDEFNODE("smb7", MERGE(GROUP_MEMBIT, 0xf7)), + PREDEFNODE("bbr0", MERGE(GROUP_BITBRANCH, 0x0f)), + PREDEFNODE("bbr1", MERGE(GROUP_BITBRANCH, 0x1f)), + PREDEFNODE("bbr2", MERGE(GROUP_BITBRANCH, 0x2f)), + PREDEFNODE("bbr3", MERGE(GROUP_BITBRANCH, 0x3f)), + PREDEFNODE("bbr4", MERGE(GROUP_BITBRANCH, 0x4f)), + PREDEFNODE("bbr5", MERGE(GROUP_BITBRANCH, 0x5f)), + PREDEFNODE("bbr6", MERGE(GROUP_BITBRANCH, 0x6f)), + PREDEFNODE("bbr7", MERGE(GROUP_BITBRANCH, 0x7f)), + PREDEFNODE("bbs0", MERGE(GROUP_BITBRANCH, 0x8f)), + PREDEFNODE("bbs1", MERGE(GROUP_BITBRANCH, 0x9f)), + PREDEFNODE("bbs2", MERGE(GROUP_BITBRANCH, 0xaf)), + PREDEFNODE("bbs3", MERGE(GROUP_BITBRANCH, 0xbf)), + PREDEFNODE("bbs4", MERGE(GROUP_BITBRANCH, 0xcf)), + PREDEFNODE("bbs5", MERGE(GROUP_BITBRANCH, 0xdf)), + PREDEFNODE("bbs6", MERGE(GROUP_BITBRANCH, 0xef)), + PREDEFLAST("bbs7", MERGE(GROUP_BITBRANCH, 0xff)), + // ^^^^ this marks the last element +}; -static struct ronode mnemos_WDC65c02[] = { +// "stp" and "wai" extensions by WDC: +static struct ronode mnemos_stp_wai[] = { PREDEFNODE("stp", MERGE(GROUP_IMPLIEDONLY, 219)), PREDEFLAST("wai", MERGE(GROUP_IMPLIEDONLY, 203)), // ^^^^ this marks the last element }; +// most of the 65816 stuff static struct ronode mnemos_65816[] = { - PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX816ORA | IMM_ACCU)), - PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDX816AND | IMM_ACCU)), - PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDX816EOR | IMM_ACCU)), - PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX816ADC | IMM_ACCU)), + // CAUTION - these use 6502/65c02 indices, because the opcodes are the same - but I need flags for immediate mode! + PREDEFNODE("ldy", MERGE(GROUP_MISC, IDX_LDY | IM_INDEXREGS)), + PREDEFNODE("ldx", MERGE(GROUP_MISC, IDX_LDX | IM_INDEXREGS)), + PREDEFNODE("cpy", MERGE(GROUP_MISC, IDX_CPY | IM_INDEXREGS)), + PREDEFNODE("cpx", MERGE(GROUP_MISC, IDX_CPX | IM_INDEXREGS)), + PREDEFNODE("bit", MERGE(GROUP_MISC, IDXcBIT | IM_ACCUMULATOR)), + // more addressing modes for some mnemonics: + PREDEFNODE("ora", MERGE(GROUP_ACCU, IDX816ORA | IM_ACCUMULATOR)), + PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDX816AND | IM_ACCUMULATOR)), + PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDX816EOR | IM_ACCUMULATOR)), + PREDEFNODE("adc", MERGE(GROUP_ACCU, IDX816ADC | IM_ACCUMULATOR)), PREDEFNODE("sta", MERGE(GROUP_ACCU, IDX816STA)), - PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX816LDA | IMM_ACCU)), - PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX816CMP | IMM_ACCU)), - PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX816SBC | IMM_ACCU)), - PREDEFNODE("pei", MERGE(GROUP_ACCU, IDX816PEI)), + PREDEFNODE("lda", MERGE(GROUP_ACCU, IDX816LDA | IM_ACCUMULATOR)), + PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDX816CMP | IM_ACCUMULATOR)), + PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDX816SBC | IM_ACCUMULATOR)), PREDEFNODE("jmp", MERGE(GROUP_ALLJUMPS, IDX816JMP)), PREDEFNODE("jsr", MERGE(GROUP_ALLJUMPS, IDX816JSR)), + // + PREDEFNODE("pei", MERGE(GROUP_ACCU, IDX816PEI)), PREDEFNODE("jml", MERGE(GROUP_ALLJUMPS, IDX816JML)), PREDEFNODE("jsl", MERGE(GROUP_ALLJUMPS, IDX816JSL)), PREDEFNODE("mvp", MERGE(GROUP_BOTHMOVES, 0x44)), PREDEFNODE("mvn", MERGE(GROUP_BOTHMOVES, 0x54)), - PREDEFNODE("per", MERGE(GROUP_RELATIVE16, 98)), - PREDEFNODE(s_brl, MERGE(GROUP_RELATIVE16, 130)), + PREDEFNODE("per", MERGE(GROUP_REL16_3, 98)), + PREDEFNODE(s_brl, MERGE(GROUP_REL16_3, 130)), PREDEFNODE("cop", MERGE(GROUP_MISC, IDX816COP)), PREDEFNODE("rep", MERGE(GROUP_MISC, IDX816REP)), PREDEFNODE("sep", MERGE(GROUP_MISC, IDX816SEP)), @@ -367,6 +392,72 @@ static struct ronode mnemos_65816[] = { // ^^^^ this marks the last element }; +// 65ce02 has 46 new opcodes and a few changes: +static struct ronode mnemos_65ce02[] = { + // 65ce02 changes (zp) addressing of 65c02 to (zp),z addressing: + PREDEFNODE("ora", MERGE(GROUP_ACCU, IDXeORA)), + PREDEFNODE(s_and, MERGE(GROUP_ACCU, IDXeAND)), + PREDEFNODE(s_eor, MERGE(GROUP_ACCU, IDXeEOR)), + PREDEFNODE("adc", MERGE(GROUP_ACCU, IDXeADC)), + PREDEFNODE("sta", MERGE(GROUP_ACCU, IDXeSTA)), // +1 for (8,s),y + PREDEFNODE("lda", MERGE(GROUP_ACCU, IDXeLDA)), // +1 for (8,s),y + PREDEFNODE("cmp", MERGE(GROUP_ACCU, IDXeCMP)), + PREDEFNODE("sbc", MERGE(GROUP_ACCU, IDXeSBC)), + // more addressing modes: + PREDEFNODE("jsr", MERGE(GROUP_ALLJUMPS, IDXeJSR)), // +2 + PREDEFNODE("stx", MERGE(GROUP_MISC, IDXeSTX)), // +1 + PREDEFNODE("sty", MERGE(GROUP_MISC, IDXeSTY)), // +1 + // +10 long branches (8 normal, 1 unconditional, BSR uncond to subroutine)) + PREDEFNODE("lbpl", MERGE(GROUP_REL16_2, 0x13)), + PREDEFNODE("lbmi", MERGE(GROUP_REL16_2, 0x33)), + PREDEFNODE("lbvc", MERGE(GROUP_REL16_2, 0x53)), + PREDEFNODE("lbvs", MERGE(GROUP_REL16_2, 0x73)), + PREDEFNODE("lbcc", MERGE(GROUP_REL16_2, 0x93)), + PREDEFNODE("lbcs", MERGE(GROUP_REL16_2, 0xb3)), + PREDEFNODE("lbne", MERGE(GROUP_REL16_2, 0xd3)), + PREDEFNODE("lbeq", MERGE(GROUP_REL16_2, 0xf3)), + PREDEFNODE("bru", MERGE(GROUP_RELATIVE8, 0x80)), // alias for 65c02's "bra" + PREDEFNODE("bsr", MERGE(GROUP_REL16_2, 0x63)), + PREDEFNODE("lbru", MERGE(GROUP_REL16_2, 0x83)), + PREDEFNODE("lbra", MERGE(GROUP_REL16_2, 0x83)), // alias + // new mnemonics: + PREDEFNODE("asr", MERGE(GROUP_MISC, IDXeASR)), + PREDEFNODE("asw", MERGE(GROUP_MISC, IDXeASW)), + PREDEFNODE("cpz", MERGE(GROUP_MISC, IDXeCPZ)), + PREDEFNODE("dew", MERGE(GROUP_MISC, IDXeDEW)), + PREDEFNODE("inw", MERGE(GROUP_MISC, IDXeINW)), + PREDEFNODE("ldz", MERGE(GROUP_MISC, IDXeLDZ)), + PREDEFNODE("phw", MERGE(GROUP_MISC, IDXePHW | IM_FORCE16)), + PREDEFNODE("row", MERGE(GROUP_MISC, IDXeROW)), + PREDEFNODE("rtn", MERGE(GROUP_MISC, IDXeRTN)), + PREDEFNODE("cle", MERGE(GROUP_IMPLIEDONLY, 0x02)), + PREDEFNODE("see", MERGE(GROUP_IMPLIEDONLY, 0x03)), + PREDEFNODE("inz", MERGE(GROUP_IMPLIEDONLY, 0x1b)), + PREDEFNODE("dez", MERGE(GROUP_IMPLIEDONLY, 0x3b)), + PREDEFNODE("neg", MERGE(GROUP_IMPLIEDONLY, 0x42)), + PREDEFNODE("tsy", MERGE(GROUP_IMPLIEDONLY, 0x0b)), + PREDEFNODE("tys", MERGE(GROUP_IMPLIEDONLY, 0x2b)), + PREDEFNODE("taz", MERGE(GROUP_IMPLIEDONLY, 0x4b)), + PREDEFNODE("tab", MERGE(GROUP_IMPLIEDONLY, 0x5b)), + PREDEFNODE("tza", MERGE(GROUP_IMPLIEDONLY, 0x6b)), + PREDEFNODE("tba", MERGE(GROUP_IMPLIEDONLY, 0x7b)), + PREDEFNODE("phz", MERGE(GROUP_IMPLIEDONLY, 0xdb)), + PREDEFLAST("plz", MERGE(GROUP_IMPLIEDONLY, 0xfb)), + // ^^^^ this marks the last element +}; + +// 65ce02's "aug" opcode: +static struct ronode mnemos_aug[] = { + PREDEFLAST("aug", MERGE(GROUP_IMPLIEDONLY, 0x5c)), // actually a "4-byte NOP reserved for future expansion" + // ^^^^ this marks the last element +}; + +// 4502's "map" and "eom" opcodes: +static struct ronode mnemos_map_eom[] = { + PREDEFNODE("map", MERGE(GROUP_IMPLIEDONLY, 0x5c)), // change memory mapping + PREDEFLAST("eom", MERGE(GROUP_IMPLIEDONLY, 0xea)), // actually the NOP opcode + // ^^^^ this marks the last element +}; // Functions @@ -379,43 +470,53 @@ void Mnemo_init(void) Tree_add_table(&mnemo_6502undoc2_tree, mnemos_6502undoc2); Tree_add_table(&mnemo_c64dtv2_tree, mnemos_c64dtv2); Tree_add_table(&mnemo_65c02_tree, mnemos_65c02); -// Tree_add_table(&mnemo_Rockwell65c02_tree, mnemos_Rockwell65c02); - Tree_add_table(&mnemo_WDC65c02_tree, mnemos_WDC65c02); + Tree_add_table(&mnemo_bitmanips_tree, mnemos_bitmanips); + Tree_add_table(&mnemo_stp_wai_tree, mnemos_stp_wai); Tree_add_table(&mnemo_65816_tree, mnemos_65816); + Tree_add_table(&mnemo_65ce02_tree, mnemos_65ce02); + Tree_add_table(&mnemo_aug_tree, mnemos_aug); + Tree_add_table(&mnemo_map_eom_tree, mnemos_map_eom); } // Address mode parsing -// Utility function for parsing indices. +// utility function for parsing indices. result must be processed via AMB_PREINDEX() or AMB_INDEX() macro! static int get_index(int next) { - int addressing_mode = HAM__; - if (next) GetByte(); if (!Input_accept_comma()) - return addressing_mode; + return INDEX_NONE; + // there was a comma, so check next character (spaces will have been skipped): switch (GotByte) { case 's': case 'S': - addressing_mode = HAM_S; - break; + // if next character is 'p' or 'P', eat that as well, so ",sp" works just like ",s" + GetByte(); + if ((GotByte == 'p') || (GotByte == 'P')) + GetByte(); + SKIPSPACE(); + return INDEX_S; + case 'x': case 'X': - addressing_mode = HAM_X; - break; + NEXTANDSKIPSPACE(); + return INDEX_X; + case 'y': case 'Y': - addressing_mode = HAM_Y; - break; - default: - Throw_error(exception_syntax); - } - if (addressing_mode != HAM__) NEXTANDSKIPSPACE(); - return addressing_mode; + return INDEX_Y; + + case 'z': + case 'Z': + NEXTANDSKIPSPACE(); + return INDEX_Z; + } + Throw_error(exception_syntax); + return INDEX_NONE; } // This function stores the command's argument in the given result @@ -423,7 +524,7 @@ static int get_index(int next) static int get_argument(struct result *result) { int open_paren, - addressing_mode = HAM_ABS; + address_mode_bits = 0; SKIPSPACE(); switch (GotByte) { @@ -432,15 +533,15 @@ static int get_argument(struct result *result) ALU_int_result(result); typesystem_want_addr(result); if (GotByte == ']') - addressing_mode |= HAM_LIND | get_index(TRUE); + address_mode_bits |= AMB_LONGINDIRECT | AMB_INDEX(get_index(TRUE)); else Throw_error(exception_syntax); break; case '#': GetByte(); // proceed with next char - addressing_mode |= HAM_IMM; + address_mode_bits |= AMB_IMMEDIATE; ALU_int_result(result); - typesystem_want_imm(result); + typesystem_want_imm(result); // FIXME - this is wrong for 65ce02's PHW# break; default: // liberal, to allow for "(...," @@ -448,27 +549,27 @@ static int get_argument(struct result *result) typesystem_want_addr(result); // check for implied addressing if ((result->flags & MVALUE_EXISTS) == 0) - addressing_mode |= HAM_IMP; + address_mode_bits |= AMB_IMPLIED; // check for indirect addressing if (result->flags & MVALUE_INDIRECT) - addressing_mode |= HAM_IND; + address_mode_bits |= AMB_INDIRECT; // check for internal index (before closing parenthesis) if (open_paren) { // in case there are still open parentheses, // read internal index - addressing_mode |= (get_index(FALSE) << 2); + address_mode_bits |= AMB_PREINDEX(get_index(FALSE)); if (GotByte == ')') GetByte(); // go on with next char else Throw_error(exception_syntax); } // check for external index (after closing parenthesis) - addressing_mode |= get_index(FALSE); + address_mode_bits |= AMB_INDEX(get_index(FALSE)); } // ensure end of line Input_ensure_EOS(); //printf("AM: %x\n", addressing_mode); - return addressing_mode; + return address_mode_bits; } // Helper function for calc_arg_size() @@ -594,6 +695,9 @@ static int calc_arg_size(int force_bit, struct result *argument, int addressing_ // Mnemonics using only implied addressing. static void group_only_implied_addressing(int opcode) { + // for 65ce02 and 4502, warn about buggy decimal mode + if ((opcode == 248) && (CPU_state.type->flags & CPUFLAG_DECIMALSUBTRACTBUGGY)) + Throw_first_pass_warning("Found SED instruction for CPU with known decimal SBC bug."); Output_byte(opcode); Input_ensure_EOS(); } @@ -607,8 +711,8 @@ static void not_in_bank(intval_t target) Throw_error(buffer); } -// Mnemonics using only 8bit relative addressing (short branch instructions). -static void group_only_relative8_addressing(int opcode) +// helper function for branches with 8-bit offset (including bbr0..7/bbs0..7) +static void near_branch(int preoffset) { struct result target; intval_t offset = 0; // dummy value, to not throw more errors than necessary @@ -620,7 +724,7 @@ static void group_only_relative8_addressing(int opcode) if ((target.val.intval | 0xffff) != 0xffff) { not_in_bank(target.val.intval); } else { - offset = (target.val.intval - (CPU_state.pc.val.intval + 2)) & 0xffff; // clip to 16 bit offset + offset = (target.val.intval - (CPU_state.pc.val.intval + preoffset)) & 0xffff; // clip to 16 bit offset // fix sign if (offset & 0x8000) offset -= 0x10000; @@ -633,7 +737,6 @@ static void group_only_relative8_addressing(int opcode) } } } - Output_byte(opcode); // this fn has its own range check (see above). // No reason to irritate the user with another error message, // so use Output_byte() instead of output_8() @@ -642,8 +745,8 @@ static void group_only_relative8_addressing(int opcode) Input_ensure_EOS(); } -// Mnemonics using only 16bit relative addressing (BRL and PER). -static void group_only_relative16_addressing(int opcode) +// helper function for relative addressing with 16-bit offset +static void far_branch(int preoffset) { struct result target; intval_t offset = 0; // dummy value, to not throw more errors than necessary @@ -655,11 +758,10 @@ static void group_only_relative16_addressing(int opcode) if ((target.val.intval | 0xffff) != 0xffff) { not_in_bank(target.val.intval); } else { - offset = (target.val.intval - (CPU_state.pc.val.intval + 3)) & 0xffff; + offset = (target.val.intval - (CPU_state.pc.val.intval + preoffset)) & 0xffff; // no further checks necessary, 16-bit branches can access whole bank } } - Output_byte(opcode); output_le16(offset); Input_ensure_EOS(); } @@ -694,67 +796,83 @@ static void make_command(int force_bit, struct result *result, unsigned long opc // check whether 16bit immediate addressing is allowed. If not, return given // opcode. If it is allowed, set force bits according to CPU register length // and return given opcode for both 8- and 16-bit mode. -static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag) +static unsigned int imm_ops(int *force_bit, unsigned char opcode, int immediate_mode) { - // if the CPU does not allow 16bit immediate addressing (or if the - // opcode does not allow it), return immediately. - if (((CPU_state.type->flags & CPUFLAG_SUPPORTSLONGREGS) == 0) || (imm_flag == 0)) - return opcode; + int long_register = 0; - // check force bits (if no force bits given, use relevant flag) + switch (immediate_mode) { + case IM_FORCE8: + return opcode; // result in bits 0..7 forces single-byte argument + + case IM_FORCE16: // currently only for 65ce02's PHW# + return ((unsigned int) opcode) << 8; // opcode in bits8.15 forces two-byte argument + + case IM_ACCUMULATOR: // for 65816 + long_register = CPU_state.a_is_long; + break; + case IM_INDEXREGS: // for 65816 + long_register = CPU_state.xy_are_long; + break; + default: + Bug_found("IllegalImmediateMode", immediate_mode); + } + // if the CPU does not support long registers... + if ((CPU_state.type->flags & CPUFLAG_SUPPORTSLONGREGS) == 0) + return opcode; // result in bits 0..7 forces single-byte argument + + // check force bits - if no force bits given, use cpu state and convert to force bit if (*force_bit == 0) - *force_bit = ((imm_flag & IMM_ACCU) ? - CPU_state.a_is_long : - CPU_state.xy_are_long) ? - MVALUE_FORCE16 : - MVALUE_FORCE08; - // return identical opcodes for 8bit and 16bit args! + *force_bit = long_register ? MVALUE_FORCE16 : MVALUE_FORCE08; + // return identical opcodes for single-byte and two-byte arguments: return (((unsigned int) opcode) << 8) | opcode; } // The main accumulator stuff (ADC, AND, CMP, EOR, LDA, ORA, SBC, STA) // plus PEI. -static void group_main(int index, int imm_flag) +static void group_main(int index, int immediate_mode) { - unsigned long imm_opcodes; + unsigned long immediate_opcodes; struct result result; int force_bit = Input_get_force_bit(); // skips spaces after switch (get_argument(&result)) { - case HAM_IMM: // #$ff or #$ffff (depending on accu length) - imm_opcodes = imm_ops(&force_bit, accu_imm[index], imm_flag); + case IMMEDIATE_ADDRESSING: // #$ff or #$ffff (depending on accu length) + immediate_opcodes = imm_ops(&force_bit, accu_imm[index], immediate_mode); // CAUTION - do not incorporate the line above into the line // below - "force_bit" might be undefined (depends on compiler). - make_command(force_bit, &result, imm_opcodes); + make_command(force_bit, &result, immediate_opcodes); break; - case HAM_ABS: // $ff, $ffff, $ffffff + case ABSOLUTE_ADDRESSING: // $ff, $ffff, $ffffff make_command(force_bit, &result, accu_abs[index]); break; - case HAM_ABSX: // $ff,x, $ffff,x, $ffffff,x + case X_INDEXED_ADDRESSING: // $ff,x, $ffff,x, $ffffff,x make_command(force_bit, &result, accu_xabs[index]); break; - case HAM_ABSY: // $ffff,y (in theory, "$ff,y" as well) + case Y_INDEXED_ADDRESSING: // $ffff,y (in theory, "$ff,y" as well) make_command(force_bit, &result, accu_yabs[index]); break; - case HAM_ABSS: // $ff,s + case STACK_INDEXED_ADDRESSING: // $ff,s make_command(force_bit, &result, accu_sabs8[index]); break; - case HAM_XIND: // ($ff,x) + case X_INDEXED_INDIRECT_ADDRESSING: // ($ff,x) make_command(force_bit, &result, accu_xind8[index]); break; - case HAM_IND: // ($ff) + case INDIRECT_ADDRESSING: // ($ff) make_command(force_bit, &result, accu_ind8[index]); break; - case HAM_INDY: // ($ff),y + case INDIRECT_Y_INDEXED_ADDRESSING: // ($ff),y make_command(force_bit, &result, accu_indy8[index]); break; - case HAM_LIND: // [$ff] + case INDIRECT_Z_INDEXED_ADDRESSING: // ($ff),z + make_command(force_bit, &result, accu_indz8[index]); + break; + case LONG_INDIRECT_ADDRESSING: // [$ff] make_command(force_bit, &result, accu_lind8[index]); break; - case HAM_LINDY: // [$ff],y + case LONG_INDIRECT_Y_INDEXED_ADDRESSING: // [$ff],y make_command(force_bit, &result, accu_lindy8[index]); break; - case HAM_SINDY: // ($ff,s),y + case STACK_INDEXED_INDIRECT_Y_INDEXED_ADDRESSING: // ($ff,s),y make_command(force_bit, &result, accu_sindy8[index]); break; default: // other combinations are illegal @@ -763,41 +881,41 @@ static void group_main(int index, int imm_flag) } // Various mnemonics with different addressing modes. -static void group_misc(int index, int imm_flag) +static void group_misc(int index, int immediate_mode) { - unsigned long imm_opcodes; + unsigned long immediate_opcodes; struct result result; int force_bit = Input_get_force_bit(); // skips spaces after switch (get_argument(&result)) { - case HAM_IMP: // implied addressing + case IMPLIED_ADDRESSING: // implied addressing if (misc_impl[index]) Output_byte(misc_impl[index]); else Throw_error(exception_illegal_combination); break; - case HAM_IMM: // #$ff or #$ffff (depending on index register length) - imm_opcodes = imm_ops(&force_bit, misc_imm[index], imm_flag); + case IMMEDIATE_ADDRESSING: // #$ff or #$ffff (depending on index register length) + immediate_opcodes = imm_ops(&force_bit, misc_imm[index], immediate_mode); // CAUTION - do not incorporate the line above into the line // below - "force_bit" might be undefined (depends on compiler). - make_command(force_bit, &result, imm_opcodes); + make_command(force_bit, &result, immediate_opcodes); // check whether to warn about 6510's unstable ANE/LXA if ((CPU_state.type->flags & CPUFLAG_8B_AND_AB_NEED_0_ARG) && ((result.val.intval & 0xff) != 0x00) && (result.flags & MVALUE_DEFINED)) { - if (imm_opcodes == 0x8b) + if (immediate_opcodes == 0x8b) Throw_warning("Assembling unstable ANE #NONZERO instruction"); - else if (imm_opcodes == 0xab) + else if (immediate_opcodes == 0xab) Throw_warning("Assembling unstable LXA #NONZERO instruction"); } break; - case HAM_ABS: // $ff or $ffff + case ABSOLUTE_ADDRESSING: // $ff or $ffff make_command(force_bit, &result, misc_abs[index]); break; - case HAM_ABSX: // $ff,x or $ffff,x + case X_INDEXED_ADDRESSING: // $ff,x or $ffff,x make_command(force_bit, &result, misc_xabs[index]); break; - case HAM_ABSY: // $ff,y or $ffff,y + case Y_INDEXED_ADDRESSING: // $ff,y or $ffff,y make_command(force_bit, &result, misc_yabs[index]); break; default: // other combinations are illegal @@ -805,25 +923,70 @@ static void group_misc(int index, int imm_flag) } } -// Mnemonics using "8bit, 8bit" addressing. Only applies to "MVN" and "MVP". -static void group_move(int opcode) +// mnemonics using only 8bit relative addressing (short branch instructions). +static void group_std_branches(int opcode) { - intval_t source, + Output_byte(opcode); + near_branch(2); +} + +// "bbr0..7" and "bbs0..7" +static void group_bbr_bbs(int opcode) +{ + struct result zpmem; + + ALU_int_result(&zpmem); + typesystem_want_addr(&zpmem); + if (Input_accept_comma()) { + Output_byte(opcode); + Output_byte(zpmem.val.intval); + near_branch(3); + } else { + Throw_error(exception_syntax); + } +} + +// mnemonics using only 16bit relative addressing (BRL and PER of 65816, and the long branches of 65ce02) +static void group_relative16(int opcode, int preoffset) +{ + Output_byte(opcode); + far_branch(preoffset); +} + +// "mvn" and "mvp" +static void group_mvn_mvp(int opcode) +{ + struct result source, target; - // assembler syntax: "opcode source, target" - source = ALU_any_int(); + // assembler syntax: "mnemonic source, target" + ALU_int_result(&source); + typesystem_want_imm(&source); if (Input_accept_comma()) { - target = ALU_any_int(); // machine language: - Output_byte(opcode); // opcode - output_8(target); // target - output_8(source); // source + ALU_int_result(&target); + typesystem_want_imm(&target); + // machine language order: "opcode target source" + Output_byte(opcode); + output_8(target.val.intval); + output_8(source.val.intval); Input_ensure_EOS(); } else { Throw_error(exception_syntax); } } +// "rmb0..7" and "smb0..7" +static void group_rmb_smb(int opcode) +{ + struct result target; + + ALU_int_result(&target); + typesystem_want_addr(&target); + Output_byte(opcode); + output_8(target.val.intval); + Input_ensure_EOS(); +} + // The jump instructions. static void group_jump(int index) { @@ -831,10 +994,10 @@ static void group_jump(int index) int force_bit = Input_get_force_bit(); // skips spaces after switch (get_argument(&result)) { - case HAM_ABS: // absolute16 or absolute24 + case ABSOLUTE_ADDRESSING: // absolute16 or absolute24 make_command(force_bit, &result, jump_abs[index]); break; - case HAM_IND: // ($ffff) + case INDIRECT_ADDRESSING: // ($ffff) make_command(force_bit, &result, jump_ind[index]); // check whether to warn about 6502's JMP() bug if (((result.val.intval & 0xff) == 0xff) @@ -842,10 +1005,10 @@ static void group_jump(int index) && (CPU_state.type->flags & CPUFLAG_INDIRECTJMPBUGGY)) Throw_warning("Assembling buggy JMP($xxff) instruction"); break; - case HAM_XIND: // ($ffff,x) + case X_INDEXED_INDIRECT_ADDRESSING: // ($ffff,x) make_command(force_bit, &result, jump_xind[index]); break; - case HAM_LIND: // [$ffff] + case LONG_INDIRECT_ADDRESSING: // [$ffff] make_command(force_bit, &result, jump_lind[index]); break; default: // other combinations are illegal @@ -858,20 +1021,20 @@ static int check_mnemo_tree(struct ronode *tree, struct dynabuf *dyna_buf) { void *node_body; int code, - imm_flag; // flag for immediate addressing + immediate_mode; // size of immediate argument // search for tree item if (!Tree_easy_scan(tree, &node_body, dyna_buf)) return FALSE; code = ((int) node_body) & CODEMASK; // get opcode or table index - imm_flag = ((int) node_body) & FLAGSMASK; // get flag - switch (((long) node_body) >> GROUPSHIFT) { + immediate_mode = ((int) node_body) & IMMASK; // get immediate mode + switch (GROUP((long) node_body)) { case GROUP_ACCU: // main accumulator stuff - group_main(code, imm_flag); + group_main(code, immediate_mode); break; case GROUP_MISC: // misc - group_misc(code, imm_flag); + group_misc(code, immediate_mode); break; case GROUP_ALLJUMPS: // the jump instructions group_jump(code); @@ -880,13 +1043,22 @@ static int check_mnemo_tree(struct ronode *tree, struct dynabuf *dyna_buf) group_only_implied_addressing(code); break; case GROUP_RELATIVE8: // short relative - group_only_relative8_addressing(code); + group_std_branches(code); break; - case GROUP_RELATIVE16: // long relative - group_only_relative16_addressing(code); + case GROUP_BITBRANCH: // "bbr0..7" and "bbs0..7" + group_bbr_bbs(code); + break; + case GROUP_REL16_2: // long relative to pc+2 + group_relative16(code, 2); + break; + case GROUP_REL16_3: // long relative to pc+3 + group_relative16(code, 3); break; case GROUP_BOTHMOVES: // "mvp" and "mvn" - group_move(code); + group_mvn_mvp(code); + break; + case GROUP_MEMBIT: // "rmb0..7" and "smb0..7" + group_rmb_smb(code); break; default: // others indicate bugs Bug_found("IllegalGroupIndex", code); @@ -894,8 +1066,8 @@ static int check_mnemo_tree(struct ronode *tree, struct dynabuf *dyna_buf) return TRUE; } -// Check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. -int keyword_is_6502mnemo(int length) +// check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. +int keyword_is_6502_mnemo(int length) { if (length != 3) return FALSE; @@ -905,8 +1077,8 @@ int keyword_is_6502mnemo(int length) return check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf) ? TRUE : FALSE; } -// Check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. -int keyword_is_6510mnemo(int length) +// check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. +int keyword_is_6510_mnemo(int length) { if (length != 3) return FALSE; @@ -925,8 +1097,8 @@ int keyword_is_6510mnemo(int length) return check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf) ? TRUE : FALSE; } -// Check whether mnemonic in GlobalDynaBuf is supported by C64DTV2 cpu. -int keyword_is_c64dtv2mnemo(int length) +// check whether mnemonic in GlobalDynaBuf is supported by C64DTV2 cpu. +int keyword_is_c64dtv2_mnemo(int length) { if (length != 3) return FALSE; @@ -945,15 +1117,15 @@ int keyword_is_c64dtv2mnemo(int length) return check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf) ? TRUE : FALSE; } -// Check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. -int keyword_is_65c02mnemo(int length) +// check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. +int keyword_is_65c02_mnemo(int length) { if (length != 3) return FALSE; // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); - // first check extensions... + // first check extensions because some mnemonics gained new addressing modes... if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) return TRUE; @@ -961,63 +1133,119 @@ int keyword_is_65c02mnemo(int length) return check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf) ? TRUE : FALSE; } -//// Check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. -//int keyword_is_Rockwell65c02mnemo(int length) -//{ -// if ((length != 3) && (length != 4)) -// return FALSE; -// -// // make lower case version of mnemonic in local dynamic buffer -// DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); -// // first check 65c02 extensions... -// if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) -// return TRUE; -// -// // ...then check original opcodes... -// if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) -// return TRUE; -// -// // ...then check Rockwell/WDC extensions (rmb, smb, bbr, bbs) -// return check_mnemo_tree(mnemo_Rockwell65c02_tree, mnemo_dyna_buf) ? TRUE : FALSE; -//} +// check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. +int keyword_is_r65c02_mnemo(int length) +{ + if ((length != 3) && (length != 4)) + return FALSE; -//// Check whether mnemonic in GlobalDynaBuf is supported by WDC 65c02 cpu. -//int keyword_is_WDC65c02mnemo(int length) -//{ -// if ((length != 3) && (length != 4)) -// return FALSE; -// -// // make lower case version of mnemonic in local dynamic buffer -// DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); -// // first check 65c02 extensions... -// if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) -// return TRUE; -// -// // ...then check original opcodes... -// if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) -// return TRUE; -// -// // ...then check Rockwell/WDC extensions (rmb, smb, bbr, bbs)... -// if (check_mnemo_tree(mnemo_Rockwell65c02_tree, mnemo_dyna_buf)) -// return TRUE; -// -// // ...then check WDC extensions (only two mnemonics, so do last) -// return check_mnemo_tree(mnemo_WDC65c02_tree, mnemo_dyna_buf) ? TRUE : FALSE; -//} + // make lower case version of mnemonic in local dynamic buffer + DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); + // first check 65c02 extensions because some mnemonics gained new addressing modes... + if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) + return TRUE; -// Check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. -int keyword_is_65816mnemo(int length) + // ...then check original opcodes... + if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check Rockwell extensions (rmb, smb, bbr, bbs) + return check_mnemo_tree(mnemo_bitmanips_tree, mnemo_dyna_buf) ? TRUE : FALSE; +} + +// check whether mnemonic in GlobalDynaBuf is supported by WDC w65c02 cpu. +int keyword_is_w65c02_mnemo(int length) +{ + if ((length != 3) && (length != 4)) + return FALSE; + + // make lower case version of mnemonic in local dynamic buffer + DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); + // first check 65c02 extensions because some mnemonics gained new addressing modes... + if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check original opcodes... + if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check Rockwell extensions (rmb, smb, bbr, bbs)... + if (check_mnemo_tree(mnemo_bitmanips_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check WDC extensions "stp" and "wai" + return check_mnemo_tree(mnemo_stp_wai_tree, mnemo_dyna_buf) ? TRUE : FALSE; +} + +// check whether mnemonic in GlobalDynaBuf is supported by CSG 65CE02 cpu. +int keyword_is_65ce02_mnemo(int length) +{ + if ((length != 3) && (length != 4)) + return FALSE; + + // make lower case version of mnemonic in local dynamic buffer + DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); + // first check 65ce02 extensions because some mnemonics gained new addressing modes... + if (check_mnemo_tree(mnemo_65ce02_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check 65c02 extensions because of the same reason... + if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check original opcodes... + if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check Rockwell extensions (rmb, smb, bbr, bbs)... + if (check_mnemo_tree(mnemo_bitmanips_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check "aug" + return check_mnemo_tree(mnemo_aug_tree, mnemo_dyna_buf) ? TRUE : FALSE; +} + +// check whether mnemonic in GlobalDynaBuf is supported by CSG 4502 cpu. +int keyword_is_4502_mnemo(int length) +{ + if ((length != 3) && (length != 4)) + return FALSE; + + // make lower case version of mnemonic in local dynamic buffer + DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); + // first check 65ce02 extensions because some mnemonics gained new addressing modes... + if (check_mnemo_tree(mnemo_65ce02_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check 65c02 extensions because of the same reason... + if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check original opcodes... + if (check_mnemo_tree(mnemo_6502_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check Rockwell extensions (rmb, smb, bbr, bbs)... + if (check_mnemo_tree(mnemo_bitmanips_tree, mnemo_dyna_buf)) + return TRUE; + + // ...then check "map" and "eom" + return check_mnemo_tree(mnemo_map_eom_tree, mnemo_dyna_buf) ? TRUE : FALSE; +} + +// check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. +int keyword_is_65816_mnemo(int length) { if (length != 3) return FALSE; // make lower case version of mnemonic in local dynamic buffer DynaBuf_to_lower(mnemo_dyna_buf, GlobalDynaBuf); - // first check "new" extensions... + // first check 65816 extensions because some mnemonics gained new addressing modes... if (check_mnemo_tree(mnemo_65816_tree, mnemo_dyna_buf)) return TRUE; - // ...then "old" extensions... + // ...then check 65c02 extensions because of the same reason... if (check_mnemo_tree(mnemo_65c02_tree, mnemo_dyna_buf)) return TRUE; @@ -1026,5 +1254,5 @@ int keyword_is_65816mnemo(int length) return TRUE; // ...then check WDC extensions "stp" and "wai" - return check_mnemo_tree(mnemo_WDC65c02_tree, mnemo_dyna_buf) ? TRUE : FALSE; + return check_mnemo_tree(mnemo_stp_wai_tree, mnemo_dyna_buf) ? TRUE : FALSE; } diff --git a/src/mnemo.h b/src/mnemo.h index edf1af4..5abb7b1 100644 --- a/src/mnemo.h +++ b/src/mnemo.h @@ -1,30 +1,32 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // -// Mnemonic definitions +// mnemonic definitions #ifndef mnemo_H #define mnemo_H -// Prototypes - // create dynamic buffer, build keyword trees extern void Mnemo_init(void); -// Check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. -extern int keyword_is_6502mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. -extern int keyword_is_6510mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by C64DTV2 cpu. -extern int keyword_is_c64dtv2mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. -extern int keyword_is_65c02mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. -//extern int keyword_is_Rockwell65c02mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by WDC 65c02 cpu. -//extern int keyword_is_WDC65c02mnemo(int length); -// Check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. -extern int keyword_is_65816mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by 6502 cpu. +extern int keyword_is_6502_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by 6510 cpu. +extern int keyword_is_6510_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by C64DTV2 cpu. +extern int keyword_is_c64dtv2_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by 65c02 cpu. +extern int keyword_is_65c02_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by Rockwell 65c02 cpu. +extern int keyword_is_r65c02_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by WDC 65c02 cpu. +extern int keyword_is_w65c02_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by 65816 cpu. +extern int keyword_is_65816_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by CSG 65ce02 cpu. +extern int keyword_is_65ce02_mnemo(int length); +// check whether mnemonic in GlobalDynaBuf is supported by CSG 4502 cpu. +extern int keyword_is_4502_mnemo(int length); #endif diff --git a/src/output.c b/src/output.c index ed1ce0f..67c372e 100644 --- a/src/output.c +++ b/src/output.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/output.h b/src/output.h index f29a47c..965319b 100644 --- a/src/output.h +++ b/src/output.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/platform.c b/src/platform.c index 726447a..f9155a4 100644 --- a/src/platform.c +++ b/src/platform.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff diff --git a/src/platform.h b/src/platform.h index 760238a..063ee66 100644 --- a/src/platform.h +++ b/src/platform.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2009 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Platform specific stuff diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c index e213ea7..002fc91 100644 --- a/src/pseudoopcodes.c +++ b/src/pseudoopcodes.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/pseudoopcodes.h b/src/pseudoopcodes.h index b61a2b3..7b6047e 100644 --- a/src/pseudoopcodes.h +++ b/src/pseudoopcodes.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // pseudo opcode stuff diff --git a/src/section.c b/src/section.c index 6d71fd6..1e6df0f 100644 --- a/src/section.c +++ b/src/section.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/section.h b/src/section.h index 768e434..7bf3812 100644 --- a/src/section.h +++ b/src/section.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/symbol.c b/src/symbol.c index e542738..f85d69a 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/symbol.h b/src/symbol.h index 2cf1d8e..7e443e0 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/tree.c b/src/tree.c index d4be38e..adf65b9 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // tree stuff diff --git a/src/tree.h b/src/tree.h index e38622d..d4290da 100644 --- a/src/tree.h +++ b/src/tree.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // diff --git a/src/typesystem.c b/src/typesystem.c index 66913ce..8206d8e 100644 --- a/src/typesystem.c +++ b/src/typesystem.c @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // type system stuff diff --git a/src/typesystem.h b/src/typesystem.h index 590fd5a..bc46fd2 100644 --- a/src/typesystem.h +++ b/src/typesystem.h @@ -1,5 +1,5 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. -// Copyright (C) 1998-2014 Marco Baye +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. +// Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // // Type system stuff diff --git a/src/version.h b/src/version.h index e1595b6..69e2c0a 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -// ACME - a crossassembler for producing 6502/65c02/65816 code. +// ACME - a crossassembler for producing 6502/65c02/65816/65ce02 code. // Copyright (C) 1998-2016 Marco Baye // Have a look at "acme.c" for further info // @@ -7,9 +7,9 @@ #define version_H -#define RELEASE "0.95.8" // update before release (FIXME) +#define RELEASE "0.96" // update before release (FIXME) #define CODENAME "Fenchurch" // update before release -#define CHANGE_DATE "8 Oct" // update before release +#define CHANGE_DATE "28 Dec" // update before release #define CHANGE_YEAR "2016" // update before release //#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME