Release 0.95.4: Added the last remaining undocumented ("illegal") opcodes: LAS, TAS, SHA, SHX, SHY and ANE.

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@44 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2014-11-25 23:57:15 +00:00
parent ded7f1a065
commit e85f677cbd
6 changed files with 97 additions and 87 deletions

View File

@ -12,6 +12,14 @@ platform used. There should be another help file in this archive
outlining the platform specific changes.
----------------------------------------------------------------------
Section: New in release 0.95.4
----------------------------------------------------------------------
Added the last remaining undocumented ("illegal") opcodes: LAS, TAS,
SHA, SHX, SHY and ANE.
----------------------------------------------------------------------
Section: New in release 0.95.3
----------------------------------------------------------------------

View File

@ -13,32 +13,42 @@ In release 0.89, some more were added.
In release 0.94.8, another one was added (lxa).
In release 0.95.3, C64DTV2 support was added, which includes these
opcodes as well.
In release 0.95.4, the remaining seven were added.
Here are the mnemonics, addressing modes and generated opcodes:
Here are the new mnemonics, possible addressing modes and generated
opcodes (mnemonics in parentheses are used by other sources):
| addressing mode |
Mnemo | 8 8,x 8,y 16 16,x 16,y (8,x) (8),y | performs:
------+--------------------------------------------------+-----------
slo | 07 17 -- 0f 1f 1b 03 13 | asl + ora
rla | 27 37 -- 2f 3f 3b 23 33 | rol + and
sre | 47 57 -- 4f 5f 5b 43 53 | lsr + eor
rra | 67 77 -- 6f 7f 7b 63 73 | ror + adc
sax | 87 -- 97 8f -- -- 83 -- | stx + sta
lax | a7 -- b7 af -- bf a3 b3 | ldx + lda
dcp | c7 d7 -- cf df db c3 d3 | dec + cmp
isc | e7 f7 -- ef ff fb e3 f3 | inc + sbc
| addressing mode |
mnemonic | 8 8,x 8,y 16 16,x 16,y (8,x) (8),y | performs:
----------------+--------------------------------------+-----------
slo (aso) | 07 17 0f 1f 1b 03 13 | asl + ora
rla | 27 37 2f 3f 3b 23 33 | rol + and
sre (lse) | 47 57 4f 5f 5b 43 53 | lsr + eor
rra | 67 77 6f 7f 7b 63 73 | ror + adc
sax (axs, aax) | 87 97 8f 83 | stx + sta
lax | a7 b7 af bf a3 b3 | ldx + lda
dcp (dcm) | c7 d7 cf df db c3 d3 | dec + cmp
isc (isb, ins) | e7 f7 ef ff fb e3 f3 | inc + sbc
las (lar, lae) | bb | A,X,S = {addr} & S
These five are said to be unstable:
tas (shs, xas) | 9b | S = A & X {addr} = A&X& {H+1}
sha (axa, ahx) | 9f 93 | {addr} = A & X & {H+1}
shx (xas, sxa) | 9e | {addr} = X & {H+1}
shy (say, sya) | 9c | {addr} = Y & {H+1}
| addressing mode |
Mnemo | implied #8 8 8,x 16 16,x | performs:
------+-------------------------------------+------------------------
anc | -- 0b* -- -- -- -- | A = A & arg, then C=N
asr | -- 4b -- -- -- -- | A = A & arg, then lsr
arr | -- 6b -- -- -- -- | A = A & arg, then ror
sbx | -- cb -- -- -- -- | X = (A & X) - arg
dop | 80** 80 04 14 -- -- | skips next byte
top | 0c** -- -- -- 0c 1c | skips next two bytes
jam | 02 -- -- -- -- -- | crash (wait for reset)
lxa | -- ab*** -- -- -- -- | A/X = (A | ??) & arg
| addressing mode |
mnemonic | implied #8 8 8,x 16 16,x | performs:
----------------+---------------------------------+-----------------------
anc | 0b* | A = A & arg, then C=N
asr (alr) | 4b | A = A & arg, then lsr
arr | 6b | A = A & arg, then ror
sbx (axs, sax) | cb | X = (A & X) - arg
dop (nop, skb) | 80** 80 04 14 | skips next byte
top (nop, skw) | 0c** 0c 1c | skips next two bytes
jam (kil, hlt) | 02 | crash (wait for reset)
These two are somewhat unstable, because they involve an arbitrary value:
ane (xaa) | 8b*** | A = (A | ??) & X & arg
lxa (lax, atx) | ab*** | A,X = (A | ??) & arg
Example:
!cpu 6510 ; activate additional mnemonics...
@ -49,16 +59,19 @@ Example:
ACME version 0.95.2, anc#8 generates opcode 0x0b. Both opcodes work
the same way on a 6510. I am told 0x2b does not work on the C64DTV2.
**) Note that "dop" and "top" can be used with implied addressing, but
the generated opcodes are those for immediate and 16-bit absolute
addressing, respectively. Using dop/top with x-indexed addressing
might have its uses when timing is critical (crossing a page border
adds a penalty cycle).
**) Note that DOP ("double nop") and TOP ("triple nop") can be used
with implied addressing, but the generated opcodes are those for
immediate and 16-bit absolute addressing, respectively. Using dop/top
with x-indexed addressing might have its uses when timing is critical
(crossing a page border adds a penalty cycle).
***) This opcode is said to first perform an ORA with an arbitrary(!)
value, then do an AND with the given argument, then do a TAX.
This means it is unstable and therefore useless - unless the given
argument is zero, in which case it reliably clears both A and X.
***) ANE and LXA first perform an ORA with an arbitrary(!) value and
then perform an AND with the given argument. So they are unstable and
therefore useless - unless the given argument is zero:
ANE #0 reliably clears A - which is still useless; just use LDA #0.
LXA #0 reliably clears both A and X.
ACME will output a warning if these opcodes get assembled with a
nonzero argument.
There is no guarantee that these opcodes actually work on a given 6502
(or 6510, or 8500, or 8502) CPU. But as far as I know, nobody ever
@ -100,15 +113,8 @@ Opcode| Description C64DTV2
7c | same as 1c and others top 16,x
82 | same as c2/e2 dop #8, but said to CRASH sometimes
89 | same as 80 dop #8
8b | see notes below
92 | same as 02 and others jam CRASH
93 | see notes below
9b | see notes below
9c | see notes below
9e | see notes below
9f | see notes below
b2 | same as 02 and others jam CRASH
bb | see notes below
c2 | same as 82/e2 dop #8, but said to CRASH sometimes
d2 | same as 02 and others jam CRASH
d4 | same as 14 and others dop 8,x
@ -121,22 +127,9 @@ Opcode| Description C64DTV2
fa | same as (*legal*) ea nop
fc | same as 1c and others top 16,x
Concerning opcodes 8b, 93, 9b, 9c, 9e, 9f, bb:
These opcodes are said to be unstable. For more information about what
they do, see these documents:
For more information about what these opcodes do, see these documents:
John West, Marko Mäkelä. '64doc' file, 1994/06/03.
Extra Instructions Of The 65XX Series CPU, Adam Vardy, 27 Sept. 1996
6502 Undocumented Opcodes, by Freddy Offenga, 5/17/1997
AAY64 (All About Your 64)
I did not see much point in assigning mnemonics for these opcodes. The
reference documents above call them:
8b: ane, xaa
93: sha, axa, ahx
9b: shs, tas, xas
9c: shy, say, sya
9e: shx, xas, sxa
9f: sha, axa, ahx
bb: las, lar, lae
NMOS 6510 Unintended Opcodes

View File

@ -15,9 +15,9 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define RELEASE "0.95.3" // update before release (FIXME)
#define RELEASE "0.95.4" // update before release (FIXME)
#define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "25 Nov" // update before release
#define CHANGE_DATE "26 Nov" // update before release
#define CHANGE_YEAR "2014" // 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

View File

@ -23,13 +23,13 @@ static struct cpu_type cpu_type_6502 = {
static struct cpu_type cpu_type_6510 = {
keyword_is_6510mnemo,
CPUFLAG_INDIRECTJMPBUGGY | // JMP ($xxFF) is buggy
CPUFLAG_AB_NEEDS_0_ARG, // LXA #$xx is unstable unless arg is $00
CPUFLAG_8B_AND_AB_NEED_0_ARG, // ANE/LXA #$xx are unstable unless arg is $00
234 // !align fills with "NOP"
};
static struct cpu_type cpu_type_c64dtv2 = {
keyword_is_c64dtv2mnemo,
CPUFLAG_INDIRECTJMPBUGGY | // JMP ($xxFF) is buggy
CPUFLAG_AB_NEEDS_0_ARG, // LXA #$xx is unstable unless arg is $00 (FIXME - correct?)
CPUFLAG_8B_AND_AB_NEED_0_ARG, // ANE/LXA #$xx are unstable unless arg is $00 (FIXME - correct?)
234 // !align fills with "NOP"
};
static struct cpu_type cpu_type_65c02 = {

View File

@ -20,7 +20,7 @@ struct cpu_type {
};
#define CPUFLAG_INDIRECTJMPBUGGY (1u << 0) // warn if "jmp ($xxff)" is assembled
#define CPUFLAG_SUPPORTSLONGREGS (1u << 1) // allow "!al" and "!rl" pseudo opcodes
#define CPUFLAG_AB_NEEDS_0_ARG (1u << 2) // warn if "lxa #$xx" uses non-zero arg
#define CPUFLAG_8B_AND_AB_NEED_0_ARG (1u << 2) // warn if "ane/lxa #$xx" uses non-zero arg
// create cpu type tree (is done early)
extern void CPUtype_init(void);

View File

@ -89,19 +89,19 @@ 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};
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}; // $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}; // $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}; // $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}; // ($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}; // ($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}; // #$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}; // ($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}; // $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}; // ($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}; // [$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}; // [$ff],y
// | 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
// Code tables for group GROUP_MISC:
// These tables are needed for finding out the correct code in cases when
@ -109,13 +109,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_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}; // $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}; // $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, 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, 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}; // implied/accu
// | 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
// Code tables for group GROUP_ALLJUMPS:
// These tables are needed for finding out the correct code when the mnemonic
@ -227,18 +227,24 @@ static struct ronode mnemos_6510[] = {
PREDEFNODE("rla", MERGE(GROUP_ACCU, IDX_RLA)), // ROL + AND
PREDEFNODE("sre", MERGE(GROUP_ACCU, IDX_SRE)), // LSR + EOR (aka LSE)
PREDEFNODE("rra", MERGE(GROUP_ACCU, IDX_RRA)), // ROR + ADC
PREDEFNODE("sax", MERGE(GROUP_ACCU, IDX_SAX)), // STX + STA (aka AAX aka AXS)
PREDEFNODE("sax", MERGE(GROUP_ACCU, IDX_SAX)), // STX + STA (aka AXS aka AAX)
PREDEFNODE("lax", MERGE(GROUP_ACCU, IDX_LAX)), // LDX + LDA
PREDEFNODE("dcp", MERGE(GROUP_ACCU, IDX_DCP)), // DEC + CMP (aka DCM)
PREDEFNODE("isc", MERGE(GROUP_ACCU, IDX_ISC)), // INC + SBC (aka ISB aka INS)
PREDEFNODE("las", MERGE(GROUP_MISC, IDX_LAS)), // A,X,S = {addr} & S (aka LAR aka LAE)
PREDEFNODE("tas", MERGE(GROUP_MISC, IDX_TAS)), // S = A & X {addr} = A&X& {H+1} (aka SHS aka XAS)
PREDEFNODE("sha", MERGE(GROUP_ACCU, IDX_SHA)), // {addr} = A & X & {H+1} (aka AXA aka AHX)
PREDEFNODE("shx", MERGE(GROUP_MISC, IDX_SHX)), // {addr} = X & {H+1} (aka XAS aka SXA)
PREDEFNODE("shy", MERGE(GROUP_MISC, IDX_SHY)), // {addr} = Y & {H+1} (aka SAY aka SYA)
PREDEFNODE("anc", MERGE(GROUP_MISC, IDX_ANC)), // ROL + AND, ASL + ORA (aka AAC)
PREDEFNODE(s_asr, MERGE(GROUP_MISC, IDX_ASR)), // LSR + EOR (aka ALR)
PREDEFNODE("arr", MERGE(GROUP_MISC, IDX_ARR)), // ROR + ADC
PREDEFNODE("sbx", MERGE(GROUP_MISC, IDX_SBX)), // DEX + CMP (aka AXS aka SAX)
PREDEFNODE("dop", MERGE(GROUP_MISC, IDX_DOP)), // skip next byte
PREDEFNODE("top", MERGE(GROUP_MISC, IDX_TOP)), // skip next two bytes
PREDEFNODE("top", MERGE(GROUP_MISC, IDX_TOP)), // skip next word
PREDEFNODE("jam", MERGE(GROUP_MISC, IDX_JAM)), // jam/crash/kill/halt-and-catch-fire
PREDEFLAST("lxa", MERGE(GROUP_MISC, IDX_LXA)), // ORA #?? + AND #arg + TAX (aka OAL aka ATX)
PREDEFNODE("ane", MERGE(GROUP_MISC, IDX_ANE)), // A = (A | ??) & X & arg (aka XAA)
PREDEFLAST("lxa", MERGE(GROUP_MISC, IDX_LXA)), // A,X = (A | ??) & arg (aka OAL aka ATX)
// ^^^^ this marks the last element
};
@ -768,12 +774,15 @@ static void group_misc(int index, int imm_flag)
// 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);
// check whether to warn about 6510's unstable LXA
if ((imm_opcodes == 0xab)
// 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)
&& (CPU_state.type->flags & CPUFLAG_AB_NEEDS_0_ARG))
Throw_warning("Assembling unstable LXA #NONZERO instruction");
&& (result.flags & MVALUE_DEFINED)) {
if (imm_opcodes == 0x8b)
Throw_warning("Assembling unstable ANE #NONZERO instruction");
else if (imm_opcodes == 0xab)
Throw_warning("Assembling unstable LXA #NONZERO instruction");
}
break;
case HAM_ABS: // $ff or $ffff
make_command(force_bit, &result, misc_abs[index]);