Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/..

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/..

Post by Emu6502Writer »

I'm currently implementing the last few illegals in my emulator, already passing the functional 6502 suite and NESTest. But I'm having a problem with ANC ($0B/$02), ALR ($4B) and ARR ($6B).

ANC is described in multiple references (http://www.oxyron.de/html/opcodes02.html, http://www.ataripreservation.org/websit ... lopc31.txt) to set the SR based on (A & Immediate). In my tests with Visual 6502 I find it does not do that. It seems to completely ignore the immediate value and just set the flags based on A. Same for ALR - I perfectly match Visual 6502 as soon as I remove the & and just ignore the immediate operand. Exact same story for ARR.

Looking at other emulators (i.e. http://sourceforge.net/p/vice-emu/code/ ... re.c#l2075) it's pretty clear they actually do the and. I don't see how this could work, assuming Visual 6502 to be the ground truth here.

Now if we assume that ANC sets the SR flags based on (A & Immediate), shouldn't the following code produce

LDA #$FF
ANC #$00

a set zero flag, and no negative/carry? But it doesn't. It just sets the flags based on $FF, not doing the &. I have a dozen or so test cases for ANC, ALR and ARR, and they all show that in Visual 6502 the immediate value is completely ignored and no & is performed.

Another example:

SEC
LDA #$AA
ARR #$55

After the & we should have a value of 0, and the ROR with set carry should give $80. But it doesn't. There's no & being done, the Immediate operand completely ignored and ROR is done on $AA, giving $D5.

So what's the deal here? Is every emulator and opcode reference I looked at wrong, Visual 6502 not correct, or, more likely, I'm just completely missing something here?

Thanks!
tepples
Posts: 22426
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by tepples »

I imagine that the unofficial instructions with #imm addressing mode depend on analog effects that Visual 6502 doesn't emulate. Anything on the same row of the "CPU unoficial instructions" chart" as ADC, SBC, or possibly CMP is especially difficult because bits 0 and 4 in the adder are unaffected by decimal correction and thus run through a shorter data path than the other bits. Most of the decimal circuitry is still in the 2A03; the enable lines were just cut to work around the patent.

Try making some tests and running them on an NES. But even that might be difficult, as some of these instructions appear to depend on what's put on the data bus during the internal operation cycles, and the PowerPak's open bus behavior has been seen to differ from that of a donor as shown by Mindscape's controller reading subroutine.
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

Ok, fascinating! I'm trying to implement a full NMOS 6502 first and then later disable the BCD stuff when I start with the PPU.

Quoting http://www.viceteam.org/plain/64doc.txt:

"Many undocumented commands do not use AND between registers, the CPU
just throws the bytes to a bus simultaneously and lets the
open-collector drivers perform the AND. I.e. the command called 'SAX',
which is in the STORE section (opcodes $A0...$BF), stores the result
of (A & X) by this way."

I know very little about these sorts of analog effects, but since Visual 6502 seems to get the SAX right I expected it would get ANC/ALR/ARR right as well.

I unfortunately don't have access to a NES / PowerPak / composite input display / etc. Is there any other way I can test this and make sure I got these instructions right? I don't know of any comprehensive test for these instructions or anything that would have a reference trace available.
tepples
Posts: 22426
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by tepples »

There are other 6502 computers, especially if you're interested in emulating the entire MOS Technology part. Does anyone you know have a Commodore 64, Apple II/II+/IIe (not the IIGS, IIc, or platinum IIe), or Atari 800?
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

I'd expect some deficiencies only with the truly unstable XAA $8B / LAX $AB, but here they make it really sound like you'd get quite accurate emulation:

http://visual6502.org/wiki/index.php?ti ... 56_Opcodes
"The transistor-level emulation seems to be able to successfully emulate illegal opcodes as well,"

I was hoping I could avoid messing with the actual HW and Visual 6502 / 2A03 would be enough to settle everything that pops up. So I guess the behavior of ANC/ALR/ARR is not a well-known & settled issue? I must be like number 10000 writing an emulator for a 6502 based machine ;-)

Getting a C64 or an NES shouldn't be too expensive / difficult, but then I'd probably need to get some extra development hardware, serial cables, cartridges, whatever. What do you think is the easiest way to get a 6502 platform where I can do some testing? Any volunteers wanting to run some test code?
User avatar
miker00lz
Posts: 235
Joined: Thu Sep 23, 2010 7:28 pm

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by miker00lz »

Emu6502Writer wrote:I'd expect some deficiencies only with the truly unstable XAA $8B / LAX $AB, but here they make it really sound like you'd get quite accurate emulation:

http://visual6502.org/wiki/index.php?ti ... 56_Opcodes
"The transistor-level emulation seems to be able to successfully emulate illegal opcodes as well,"

I was hoping I could avoid messing with the actual HW and Visual 6502 / 2A03 would be enough to settle everything that pops up. So I guess the behavior of ANC/ALR/ARR is not a well-known & settled issue? I must be like number 10000 writing an emulator for a 6502 based machine ;-)

Getting a C64 or an NES shouldn't be too expensive / difficult, but then I'd probably need to get some extra development hardware, serial cables, cartridges, whatever. What do you think is the easiest way to get a 6502 platform where I can do some testing? Any volunteers wanting to run some test code?
I could poke some assembly code into my Apple //e. Just don't make it too long please! It's slow to input this stuff, but you can do it right from the built-in monitor ROM or BASIC by typing in the hex values and addresses, then jump to it. Speaking of the Apple, that might be the ideal machine to buy if you wanted to do a lot of 6502 testing yourself. They are dirt cheap. Hell, I got mine for free with two boxes of games and programs via freecycle.

EDIT: Nevermind, I just remembered the //e has a 65C02 instead of the 6502. I think there is a PHD where the original 6502 had ANC. You could still get a regular older Apple ][ if you wanted to test.
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by ulfalizer »

For what it's worth, I set the status flags based on the & result for those instructions and pass blargg's instr_test-v4. Haven't looked at how comprehensively it tests those instructions though, but it seems to be a more comprehensive test than nestest overall at least.
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

Yeah, the CMOS version should be very different from what's in the NES/C64 etc. regarding those opcodes. Before starting to implement the last few illegal opcodes I wrote a short series of tests. It assembles to around 200 bytes and pushes the results of each test on the stack. Not sure if it's a good test, it was based on my initial understanding of what these opcodes are supposed to do and tries out cases that are supposed to set a range of flags and test some edge cases. I'd love to know what a correct stack dump for that program looks like, or even just what the correct result for the 4 and 5 byte snippets from my original post is.

I'm really quite surprised by getting told that Visual 6502 is likely to not get ANC/ALR/ARR right. Could somebody that actually used these on real 6502 hardware chime in on the whole skipping/doing '& Immediate' thing?
User avatar
ulfalizer
Posts: 349
Joined: Fri Mar 08, 2013 9:55 pm
Location: Linköping, Sweden

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by ulfalizer »

Emu6502Writer wrote:I know very little about these sorts of analog effects, but since Visual 6502 seems to get the SAX right I expected it would get ANC/ALR/ARR right as well.
For a high-level overview, it has to do with a line being driven to 0 and 1 simultaneously (i.e., having power applied to it and also being sunk to ground). In NMOS, which is the transistor technology used for the 6502 (in classic systems at least), a 0 tends to "win" in such situations, which is why many of the unofficial instructions get AND behavior (since a 1 will only survive if the other input is also a 1).

I remember Visual 6502 getting some other unofficial instructions with bus conflicts right though, so not sure what's going on. Could be something NES-specific related to removal of decimal mode I guess.
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

Seems like you're in good company with the decision of including the &, the emus I checked out all do it like that...

Supposedly the SAX instruction gets its & behavior from the bus conflict you're describing, and Visual 6502 certainly does the & for that one.

I linked some source of VICE / Versatile Commodore Emulator in my original post, so it seems this is not 2A03 specific. That code seems to do the &s as described.

I wonder if this is worth asking somebody from the Visual 6502 project about? From everything I read on their wiki I'd expect perfect emulation of these opcodes with only XAA $8B / LAX $AB depending on analog behavior they do not capture in their simulation model. I'd first need to be really sure the actual hardware differs from what I get from Visual 6502 ;-)
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

To be completely explicit:

This code

Code: Select all

SEC
LDA #$AA
ARR #$55
PHA
assembles into

Code: Select all

38 A9 AA 6B 55 48
loaded into Visual 6502

http://www.visual6502.org/JSSim/expert. ... a9aa6b5548

and we get a D5 on the stack. There's no & being done, the Immediate operand completely ignored and ROR is done on $AA, giving $D5. Trace:

Code: Select all

le	ab	db	rw	Fetch	pc	a	x	y	s	p
0	00f0	38	1	SEC	00f0	aa	00	00	fd	nv‑BdIZc
0	00f0	38	1	SEC	00f0	aa	00	00	fd	nv‑BdIZc
1	00f1	a9	1		00f1	aa	00	00	fd	nv‑BdIZc
1	00f1	a9	1		00f1	aa	00	00	fd	nv‑BdIZc
2	00f1	a9	1	LDA #	00f1	aa	00	00	fd	nv‑BdIZC
2	00f1	a9	1	LDA #	00f1	aa	00	00	fd	nv‑BdIZC
3	00f2	aa	1		00f2	aa	00	00	fd	nv‑BdIZC
3	00f2	aa	1		00f2	aa	00	00	fd	nv‑BdIZC
4	00f3	6b	1	unknown	00f3	aa	00	00	fd	Nv‑BdIzC
4	00f3	6b	1	unknown	00f3	aa	00	00	fd	Nv‑BdIzC
5	00f4	55	1		00f4	aa	00	00	fd	Nv‑BdIzC
5	00f4	55	1		00f4	aa	00	00	fd	Nv‑BdIzC
6	00f5	48	1	PHA	00f5	aa	00	00	fd	Nv‑BdIzc
6	00f5	48	1	PHA	00f5	aa	00	00	fd	Nv‑BdIzc
7	00f6	00	1		00f6	d5	00	00	fd	NV‑BdIzC
7	00f6	00	1		00f6	d5	00	00	fd	NV‑BdIzC
8	01fd	00	0		00f6	d5	00	00	fd	NV‑BdIzC
8	01fd	d5	0		00f6	d5	00	00	fd	NV‑BdIzC
9	00f6	00	1	BRK	00f6	d5	00	00	fc	NV‑BdIzC
ARR is widely described as 'Combined AND + ROR with different SR effects', so I'd expect that after the & we should have a value of 0, and the ROR with set carry should give $80. This does not happen here.

Looking at the code for VICE:

http://sourceforge.net/p/vice-emu/code/ ... ore.c#l622

The implementation clearly starts with doing the &:

Code: Select all

tmp = reg_a_read & (value);
Loading the small code snippet into vice and debugging with the monitor:

Code: Select all

fill $00f0 $00f5 38 A9 AA 6B 55 48

d 00f0 00f5
.C:00f0   38         SEC
.C:00f1   A9 AA      LDA #$AA
.C:00f3   6B 55      ARR #$55
.C:00f5   48         PHA
.C:00f6   00         BRK

r PC=00f0

r
  ADDR AC XR YR SP 00 01 NV-BDIZC LIN CYC
.;00f0 00 00 0a f3 2f 37 00100010 000 001

z

** Monitor 000 003
.C:00f0   38         SEC
z

** Monitor 000 005
.C:00f1   A9 AA      LDA #$AA
z

** Monitor 000 007
.C:00f3   6B 55      ARR #$55
z

** Monitor 000 009
.C:00f5   48         PHA
r
  ADDR AC XR YR SP 00 01 NV-BDIZC LIN CYC
.;00f5 80 00 0a f3 2f 37 10100000 000 009
We get a value of $80 in the accumulator, doing the &.

VICE is correct, Visual 6502 wrong? Or the other way around?
tepples
Posts: 22426
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by tepples »

This test case inserted into my test harness produces $80 in FCEUX and $80 on a PowerPak.

Code: Select all

  sec
  lda #$aa
  .byte $6B,$55
  sta debugHex1
Unfortunately, I haven't learned to rewire a Vice: Project Doom cart and test on that.
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

Thank you!

Two solid emulators and the actual hardware suggesting there's an & being done, guess that settles it then? Will have to roll back some commits 'fixing' my emulator to match Visual 6502 ;-)

What's the significance of that game card? Is it especially suitable to be modified into a flashable card for homebrew NES development? Would using a commercial game card like that possibly change the result of illegal opcodes because of the change in data bus capacitance you mentioned earlier?
tepples
Posts: 22426
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by tepples »

Emu6502Writer wrote:What's the significance of that game card?
Name pun on "Loading the small code snippet into vice".
Would using a commercial game card like that possibly change the result of illegal opcodes because of the change in data bus capacitance you mentioned earlier?
It might, especially for the more "analog" ones like XAA.
Emu6502Writer
Posts: 13
Joined: Sun Aug 11, 2013 10:21 am

Re: Illegal Instructions doing (A & Immediate), ANC/ALR/ARR/

Post by Emu6502Writer »

Hehe, I thought so, just didn't want to laugh at it on the off chance this is actually some rare production cartridge with a JTAG header on it or whatever ;-)

For what it's worth, here is some test code for the more esoteric illegal opcodes and the result in VICE / Visual 6502:

Code: Select all

LDX #$FF
TXS

; ANC

LDA #$FF
;ANC($0B) #$00
 DCB $0B
 DCB $00
PHP ; $01FF

LDA #$81
;ANC($0B) #$01
 DCB $0B
 DCB $01
PHP ; $01FE

LDA #$AA
;ANC($0B) #$FF
 DCB $0B
 DCB $FF
PHP ; $01FD

LDA #$00
;ANC($2B) #$FF
 DCB $2B
 DCB $FF
PHP ; $01FC

LDA #$CD
;ANC($2B) #$FF
 DCB $2B
 DCB $FF
PHP ; $01FB

; ALR

LDA #$81
;ALR #$FF
 DCB $4B
 DCB $FF
PHA ; $01FA
PHP ; $01F9

LDA #$AB
;ALR #$55
 DCB $4B
 DCB $55
PHA ; $01F8
PHP ; $01F7

LDA #$FF
;ALR #$FF
 DCB $4B
 DCB $FF
PHA ; $01F6
PHP ; $01F5

; ARR

SEC
LDA #$AB
;ARR #$FF
 DCB $6B
 DCB $FF
PHA ; $01F4
PHP ; $01F3

CLC
LDA #$AB
;ARR #$FF
 DCB $6B
 DCB $FF
PHA ; $01F2
PHP ; $01F1

CLC
LDA #$FF
;ARR #$00
 DCB $6B
 DCB $00
PHA ; $01F0
PHP ; $01EF

SEC
LDA #$FF
;ARR #$FF
 DCB $6B
 DCB $FF
PHA ; $01EE
PHP ; $01ED

SEC
LDA #$AA
;ARR #$55
 DCB $6B
 DCB $55
PHA ; $01EC
PHP ; $01EB

; XAA

PHP

;XAA #$FF
 DCB $8B
 DCB $FF

; We'll only execute the instruction and test the time it takes before
; returning the registers to well defined states
PLP
LDA #$00

; AHX

LDA #$09
STA $10
LDA #$00
STA $11
LDA #$AA
LDX #$55
LDY #$01
;AHX ($10),Y
 DCB $93
 DCB $10
LDA $10
PHA ; $01EA

LDA #$BB
STA $10
LDA #$00
STA $11
LDA #$55
LDX #$FF
LDY #$01
;AHX ($10),Y
 DCB $93
 DCB $10
; Push the flags once for good measure, they shouldn't be affected
PHP ; $01E9
LDA $BC
PHA ; $01E8

LDA #$AA
LDX #$FF
LDY #$01
;AHX $C000,Y
 DCB $9F
 DCB $00
 DCB $C0
LDA $C001
PHA ; $01E7

; TAS

TSX     ; Save SP
STX $10

LDA #$55
LDX #$FF
LDY #$01

;TAS $0010,Y
 DCB $9B
 DCB $10
 DCB $00

TSX     ; Save SP in A through X - we want to push both SP and M on the stack
TXA

LDX $10 ; Restore SP
TXS

PHA ; $01E6
LDA $11
PHA ; $01E5

; SHX

LDY #$30
LDX #$AA
;SHX $C000,Y
 DCB $9E
 DCB $00
 DCB $C0
LDA $C030
PHA ; $01E4

LDY #$20
LDX #$FF
;SHX $0001,Y
 DCB $9E
 DCB $01
 DCB $00
LDA $0021
PHA ; $01E3

; SHY

LDX #$FF
;SHY $C800,X
 DCB $9C
 DCB $00
 DCB $C8
LDA $C8FF
PHA ; $01E2

LDX #$F0
;SHY $0000,X
 DCB $9C
 DCB $00
 DCB $00
LDA $F0
PHA ; $01E1

; LAS

TSX     ; Save SP
STX $10

LDA #$AA
STA $05
LDY #$04
;LAS $0001,Y
 DCB $BB
 DCB $01
 DCB $00

STX $11 ; Move X and SP from after LAS out of the way
TSX
STX $12

LDX $10 ; Restore SP
TXS

PHA ; $01E0
LDA $11
PHA ; $01DF
LDA $12
PHA ; $01DE

; AXS

LDA #$FF
LDX #$55
;AXS #$09
 DCB $CB
 DCB $09
PHP ; $01DD
TXA
PHA ; $01DC

LDA #$55
LDX #$00
;AXS #$01
 DCB $CB
 DCB $01
PHP ; $01DB
TXA
PHA ; $01DA
Assembling into:

Code: Select all

0000000 a2 ff 9a a9 ff 0b 00 08 a9 81 0b 01 08 a9 aa 0b
0000010 ff 08 a9 00 2b ff 08 a9 cd 2b ff 08 a9 81 4b ff
0000020 48 08 a9 ab 4b 55 48 08 a9 ff 4b ff 48 08 38 a9
0000030 ab 6b ff 48 08 18 a9 ab 6b ff 48 08 18 a9 ff 6b
0000040 00 48 08 38 a9 ff 6b ff 48 08 38 a9 aa 6b 55 48
0000050 08 08 8b ff 28 a9 00 a9 09 85 10 a9 00 85 11 a9
0000060 aa a2 55 a0 01 93 10 a5 10 48 a9 bb 85 10 a9 00
0000070 85 11 a9 55 a2 ff a0 01 93 10 08 a5 bc 48 a9 aa
0000080 a2 ff a0 01 9f 00 c0 ad 01 c0 48 ba 86 10 a9 55
0000090 a2 ff a0 01 9b 10 00 ba 8a a6 10 9a 48 a5 11 48
00000a0 a0 30 a2 aa 9e 00 c0 ad 30 c0 48 a0 20 a2 ff 9e
00000b0 01 00 a5 21 48 a2 ff 9c 00 c8 ad ff c8 48 a2 f0
00000c0 9c 00 00 a5 f0 48 ba 86 10 a9 aa 85 05 a0 04 bb
00000d0 01 00 86 11 ba 86 12 a6 10 9a 48 a5 11 48 a5 12
00000e0 48 a9 ff a2 55 cb 09 08 8a 48 a9 55 a2 00 cb 01
00000f0 08 8a 48 
This is how the stack in VICE looks like after the test:

Code: Select all

     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
01D0 00 00 00 00 00 00 00 00 00 00 FF B4 4C 35 A0 A0
01E0 A0 00 00 01 80 01 55 80 01 34 09 B4 80 B5 FF 36
01F0 00 75 55 F5 D5 35 7F 37 00 35 40 B5 36 B5 34 36
and Visual 6502:

Code: Select all

     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
01D0 00 00 00 00 00 00 00 00 00 00 FF F4 4C 75 E0 E0
01E0 A0 00 00 01 80 01 55 80 01 75 09 F5 D5 B5 FF 35
01F0 7F 75 55 F5 D5 35 7F 35 55 35 40 B5 36 B5 B5 B5
Rather different (all failures seem to be the result of missing &s). Note that in the stack a lot of the SR values are simply wrong because V gets set erroneously early on and never cleared.

If anybody wants runs this their own emulator / hardware, please share the results! ;-)
Post Reply