illegal / undocumented opcode handling in emulators

discuss bbc micro and electron emulators (including mame) here!
Post Reply
User avatar
tricky
Posts: 6494
Joined: Tue Jun 21, 2011 9:25 am
Contact:

illegal / undocumented opcode handling in emulators

Post by tricky »

I've been working with some code that uses a lot of "undocumented / illegal" opcodes and been having issues with beebem and b-em!

beebjit seems to handle everything correctly as I would have expected :)

b-em, which I would also have expected to get it all correct has one "typo":

case 0xD3: /*Undocumented - DCP (),y */
forgets to add Y to the address retrieved from zp

beebem does quite well, but has a few issues:

case 0xcb: // SBX #n
forgets to do the AND of A and X before doing the subtract

case 0x2b: /* AND-MVC #n,b7 */
seems to OR the carry flag, rather than setting it, but I might have missed something

It also assumes that all illegal instructions are coming from RAM, so when reading addresses and immediate values it uses the optimised path of WholeRam[addr] rather than ReadPaged(addr) which in nearly every case should be fine as I don't know of any ROMs that use illegal opcodes!

With these changes in, I can now run the game that I am working on converting on all three emulators, allowing me to debug in my favourite beebem version ;)
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

On this note, I'm in the process of putting together a BBC-friendly version of the Lorenz test suite, something I've long used for checking b2's 6502 emulation. It's somewhat C64-centric, meaning I've never actually run it on real hardware, though its assumptions are easy enough to hack around when running under emulation. I've been assuming that this is no problem, but that's so far only been a theory :lol: - hence this mini project.

So far, I've found some opcodes that behave differently on my BBC B, but it's not quite obvious what the actual behaviour is - so my current plan is to produce two versions of the tests, one that runs to completion on my BBC B with no failures (with some tests skipped or modified), and one that runs every test, even the ones that fail. Then people can try both and see how they get on.

--Tom
User avatar
Diminished
Posts: 877
Joined: Fri Dec 08, 2017 9:47 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Diminished »

tom_seddon wrote:
Sat Jun 04, 2022 12:36 am
On this note, I'm in the process of putting together a BBC-friendly version of the Lorenz test suite, something I've long used for checking b2's 6502 emulation. It's somewhat C64-centric, meaning I've never actually run it on real hardware, though its assumptions are easy enough to hack around when running under emulation. I've been assuming that this is no problem, but that's so far only been a theory :lol: - hence this mini project.

So far, I've found some opcodes that behave differently on my BBC B, but it's not quite obvious what the actual behaviour is - so my current plan is to produce two versions of the tests, one that runs to completion on my BBC B with no failures (with some tests skipped or modified), and one that runs every test, even the ones that fail. Then people can try both and see how they get on.

--Tom
I was just about to ask whether there was anything like this for 6502. When I wrote a Game Boy emulator a few years ago, I discovered a set of test ROMs somewhere which would check for correct functioning of every single opcode in the CPU, which was incredibly useful for getting the DMG CPU core right.
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

tom_seddon wrote:
Sat Jun 04, 2022 12:36 am
On this note, I'm in the process of putting together a BBC-friendly version of the Lorenz test suite, something I've long used for checking b2's 6502 emulation. It's somewhat C64-centric, meaning I've never actually run it on real hardware, though its assumptions are easy enough to hack around when running under emulation. I've been assuming that this is no problem, but that's so far only been a theory :lol: - hence this mini project.
How does that compare with the Dormann test suite? That may also have been written for something else originally but there is definitely a BBC micro version. I have a disc from Hoglet with some tests to run from the command line and there is also a menu-driven version that detects what CPU you have an offers to run the most appropriate tests. There is a set of BCD tests too which are also accessible from the menu.
tom_seddon wrote:
Sat Jun 04, 2022 12:36 am
So far, I've found some opcodes that behave differently on my BBC B, but it's not quite obvious what the actual behaviour is - so my current plan is to produce two versions of the tests, one that runs to completion on my BBC B with no failures (with some tests skipped or modified), and one that runs every test, even the ones that fail. Then people can try both and see how they get on.
My suspicion is that behaviour of undocumented opcodes will be split between those where something logical and entirely predictable happens, just not something the designers thought about and which may or not be useful, and outcomes that depend on how internal bus contention is resolved which may depend on the particular CPU. In this respect it would be good to get an idea of whether there is variation between different people's actual BBC micro, i.e. I think we should not simply run this on one example of real hardware and declare that to be definitive.
User avatar
tricky
Posts: 6494
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tricky »

I guess that these tests are for all opcodes, except the ones that lock the chip, but these are the ones in the code that I am currently looking at:

Code: Select all

	; lxa #n ; A = X = n ; (A OR CONST) AND oper -> A -> X ; use either 0 as the operand or a value of $FF in the accumulator.
	illegal_opcode_LXA_IM = &AB : MACRO LXA_00 { EQUB illegal_opcode_LXA_IM, 0 } ENDMACRO ; replace once behavior matches ; lda #0   : tax

	; LAX ; LDA oper + LDX oper ; M -> A -> X ; A,X:={adr}
	illegal_opcode_LAX_ZP    = &A7 : MACRO LAX_ZP    zp  { EQUB illegal_opcode_LAX_ZP   , zp        } ENDMACRO ; 2 3
	illegal_opcode_LAX_ABS   = &AF : MACRO LAX_ABS   abs { EQUB illegal_opcode_LAX_ABS   : EQUW abs } ENDMACRO ; 3 4
	illegal_opcode_LAX_ABS_Y = &BF : MACRO LAX_ABS_Y abs { EQUB illegal_opcode_LAX_ABS_Y : EQUW abs } ENDMACRO ; 3 4*
	illegal_opcode_LAX_IND_Y = &B3 : MACRO LAX_IND_Y zp  { EQUB illegal_opcode_LAX_IND_Y, zp        } ENDMACRO ; 2 5*

	; DCP (DCM) ; DEC oper + CMP oper ; Bytes Cycles ; M - 1 -> M, A - M ; {adr}:={adr}-1 A-{adr}
	illegal_opcode_DCP_ABS_X = &DF : MACRO DCP_ABS_X abs { EQUB illegal_opcode_DCP_ABS_X : EQUW abs } ENDMACRO ; 3 7
	illegal_opcode_DCP_ABS_Y = &DB : MACRO DCP_ABS_Y abs { EQUB illegal_opcode_DCP_ABS_Y : EQUW abs } ENDMACRO ; 3 7
	illegal_opcode_DCP_IND_Y = &D3 : MACRO DCP_IND_Y zp  { EQUB illegal_opcode_DCP_IND_Y, zp        } ENDMACRO ; 2 8

	; ANC ; AND oper + set C as ASL ; A AND oper, bit(7) -> C ; A:=A&#{imm}
	illegal_opcode_ANC_IM    = &0B : MACRO ANC_IM    im  { EQUB illegal_opcode_ANC_IM   , im        } ENDMACRO ; 2 3

	; SBX (AXS, SAX) ; CMP and DEX at once, sets flags like CMP ; (A AND X) - oper -> X ; X:=A&X-#{imm}
	illegal_opcode_SBX_IM    = &CB : MACRO SBX_IM    im  { EQUB illegal_opcode_SBX_IM   , im        } ENDMACRO ; 2 2

	; ISC (ISB, INS) ; INC oper + SBC oper ; M + 1 -> M, A - M - C -> A ; {adr}:={adr}+1 A:=A-{adr}
	illegal_opcode_ISC_ABS   = &EF : MACRO ISC_ABS   abs { EQUB illegal_opcode_ISC_ABS   : EQUW abs } ENDMACRO ; 3 6
	illegal_opcode_ISC_ABS_X = &FF : MACRO ISC_ABS_X abs { EQUB illegal_opcode_ISC_ABS_X : EQUW abs } ENDMACRO ; 3 7
	illegal_opcode_ISC_IND_Y = &F3 : MACRO ISC_IND_Y zp  { EQUB illegal_opcode_ISC_IND_Y, zp        } ENDMACRO ; 2 8

	; ALR (ASR) ; AND oper + LSR ; A AND oper, 0 -> [76543210] -> C ; A:=(A&#{imm})/2
	illegal_opcode_ALR_IM    = &4B : MACRO ALR_IM    im  { EQUB illegal_opcode_ALR_IM   , im        } ENDMACRO ; 2 2
I think that LXA is the only unreliable one and is only used with #0 as a way to save a byte and a couple of cycles when setting A and X to 0.
SBX seems quite useful as a way of subtracting a constant from X (or adding if you like):
lda #&FF : sbx #8 ;; 4 bytes, 4 cycles
Or DCP for a dec abs,y which is usually only available as dec abs,x.

Anyway, I won't be using them for my own code as I like to make it master compatible even though it does cost performance on a B/B+.
vs
txa : sec : sbc #8 : tax ;; 5 bytes, 8 cycles
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

Coeus wrote:
Sat Jun 04, 2022 2:06 pm
How does that compare with the Dormann test suite? That may also have been written for something else originally but there is definitely a BBC micro version. I have a disc from Hoglet with some tests to run from the command line and there is also a menu-driven version that detects what CPU you have an offers to run the most appropriate tests. There is a set of BCD tests too which are also accessible from the menu.
actual BBC micro, i.e. I think we should not simply run this on one example of real hardware and declare that to be definitive.
There's a Beeb-friendly version of the Dormann test suite on GitHub here: https://github.com/mungre/beeb6502test - compared to that, the Lorenz test suite checks the illegal opcodes. Some info about it here: https://github.com/tom-seddon/b2/blob/m ... 202.15.txt (this is the unmodified, version for the C64. My emulator has a special mode to run it. See http://www.softwolves.com/arkiv/cbm-hackers/7/7114.html)

Regarding the illegal opcode behaviour, i've been assuming that the ones known to be consistent on the C64 will also be consistent on the Beeb (and behave the same way). But we'll find out!

--Tom
User avatar
1024MAK
Posts: 11563
Joined: Mon Apr 18, 2011 5:46 pm
Location: Looking forward to summer in Somerset, UK...
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by 1024MAK »

6502.org has plenty of information on the 6502.

It’s generally considered that all NMOS 65XX processors have the same core, so should execute the undocumented op codes the same. This includes the 6502 and the 6510.

Here’s a link to the subject of undocumented op codes on the 6502 forum.

This may also be interesting: How MOS 6502 Illegal Opcodes really work.

Mark
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

tom_seddon wrote:
Sat Jun 04, 2022 8:10 pm
There's a Beeb-friendly version of the Dormann test suite on GitHub here: https://github.com/mungre/beeb6502test
Thanks, that is the menu-driven one I remember, though I think I only had the SSD, not the URL for the GitHub repository.
tom_seddon wrote:
Sat Jun 04, 2022 8:10 pm
…compared to that, the Lorenz test suite checks the illegal opcodes. Some info about it here: https://github.com/tom-seddon/b2/blob/m ... 202.15.txt (this is the unmodified, version for the C64. My emulator has a special mode to run it. See http://www.softwolves.com/arkiv/cbm-hackers/7/7114.html)
Thanks for working on this, it will be a great asset when finished. I take it the approach of having individual assembler files or testing each instruction is something you inherited. It looks like a lot of the code in each is the same. It would have made porting this easier if the code in the template and the specifics for each test were combined with some scripting so an update to the template to assemble from a higher address and use BBC OS calls rather than C64 calls would have got many of the tests working on a BBC micro.
User avatar
Rich Talbot-Watkins
Posts: 1879
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Rich Talbot-Watkins »

Here's a detailed dissection of the XAA illegal opcode from the Visual6502 wiki (which is currently down for some reason - thanks Wayback Machine!)

https://web.archive.org/web/20170804185 ... AA,_ANE%29
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

1024MAK wrote:
Sat Jun 04, 2022 9:42 pm
Here’s a link to the subject of undocumented op codes on the 6502 forum.
Following one of the links there: https://www.nesdev.com/6502_cpu.txt gives a very interesting document - a cycle by cycle description of the various types of instructions. I had wondered if this existed before, i.e. something between the info in the data sheet and a full netlist simulation.
tom_seddon wrote:
Sat Jun 04, 2022 8:10 pm
Regarding the illegal opcode behaviour, i've been assuming that the ones known to be consistent on the C64 will also be consistent on the Beeb (and behave the same way). But we'll find out!
I had supposed that where the different PLA output lines caused more than one thing to drive an internal bus, for example the store equivalent of LAX (load A and X) where presumably the A and X register both drive an internal bus at the same time, the result would be somewhat random but looking at the descriptions of the undocumented instructions and the number of times things are being ANDed together it seems that, probably because of the way NMOS works with only the lower transistor actively driven and the upper one with fixed bias (so it behaves like a resistor) a zero will usually win over a one.
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

tricky wrote:
Fri Jun 03, 2022 10:59 am
b-em, which I would also have expected to get it all correct has one "typo":

case 0xD3: /*Undocumented - DCP (),y */
forgets to add Y to the address retrieved from zp
I have commited a change to the latest master which, I believe, fixes this. I have a party to go to but later, I will try to get the Lorenz test for this instruction working to double check this.
gfoot
Posts: 473
Joined: Tue Apr 14, 2020 9:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by gfoot »

Coeus wrote:
Sun Jun 05, 2022 1:12 pm
I had supposed that where the different PLA output lines caused more than one thing to drive an internal bus, for example the store equivalent of LAX (load A and X) where presumably the A and X register both drive an internal bus at the same time,
I think in that case they'd both be driven by the same bus rather than both driving it?
Coeus wrote:
Sun Jun 05, 2022 1:12 pm
the result would be somewhat random but looking at the descriptions of the undocumented instructions and the number of times things are being ANDed together it seems that, probably because of the way NMOS works with only the lower transistor actively driven and the upper one with fixed bias (so it behaves like a resistor) a zero will usually win over a one.
It makes sense - my understanding was that the internal buses are precharged to high before the cycle starts, then get pulled down from there, rather than having passive pull-ups. It's one reason the NMOS 6502s require at least a certain clock speed, so that this precharge does't dissipate too early.
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

gfoot wrote:
Sun Jun 05, 2022 1:37 pm
Coeus wrote:
Sun Jun 05, 2022 1:12 pm
I had supposed that where the different PLA output lines caused more than one thing to drive an internal bus, for example the store equivalent of LAX (load A and X) where presumably the A and X register both drive an internal bus at the same time,
I think in that case they'd both be driven by the same bus rather than both driving it?
I was thinking about the store version, not the load version, even though I talked about the load version. This is because, in the description I had been referring to, the store version was named after the AND feature rather than the store feature making it non-obvious but one example instruction would be opcode $83, described (in a different document) as SAX. Here both A and X get to drive something that ultimately ends up driving the external data pins to get a value stored in memory.
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

Coeus wrote:
Sun Jun 05, 2022 10:39 am
Thanks for working on this, it will be a great asset when finished. I take it the approach of having individual assembler files or testing each instruction is something you inherited. It looks like a lot of the code in each is the same. It would have made porting this easier if the code in the template and the specifics for each test were combined with some scripting so an update to the template to assemble from a higher address and use BBC OS calls rather than C64 calls would have got many of the tests working on a BBC micro.
Yes, what's at that link is the unmodified original. I'm currently pulling out the shared parts and reducing the duplication, then I'll centralize the system specifics and add symbols for the various memory locations it uses. (For example, it currently uses $1100 as a buffer in some tests - no good if you were hoping to *SPOOL the output.) I don't intend to keep C64 compatibility, but I'm expecting it'd be possible to port it back straightforwardly enough.

One slight issue as well is that there's over 200 tests, so fitting it all onto a DFS disk is going to be a challenge just due to the sheel number of files. So it'll be possible to build it with several tests packed into one file as well.

I also don't like the way each test chains the next one; hopefully I can get rid of that, and allow the tests (or groups thereof) to be run as one-offs, or in any order, possibly from a BASIC driver program.

--Tom
Last edited by tom_seddon on Sun Jun 05, 2022 2:09 pm, edited 1 time in total.
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

Coeus wrote:
Sun Jun 05, 2022 1:12 pm
Following one of the links there: https://www.nesdev.com/6502_cpu.txt gives a very interesting document - a cycle by cycle description of the various types of instructions. I had wondered if this existed before, i.e. something between the info in the data sheet and a full netlist simulation.
These tables are in the back of the Synertek 6502 hardware manual: https://github.com/bitshifters/bbc-docu ... manual.pdf (possibly amongst other places)

--Tom
Coeus
Posts: 2797
Joined: Mon Jul 25, 2016 12:05 pm
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Coeus »

Coeus wrote:
Sun Jun 05, 2022 1:24 pm
I have commited a change to the latest master which, I believe, fixes this. I have a party to go to but later, I will try to get the Lorenz test for this instruction working to double check this.
I ported the DCMIY Lorenz test and the updated B-Em now passes. Here's the ported test for reference - this is ADE/Lancaster syntax.

Code: Select all

null     macro
         asc    @1
         db     0
         endm

osasci   equ    &ffe3
osnewl   equ    &ffe7
oswrch   equ    &ffee
osbyte   equ    &fff4
uzp      equ    &70
         org    $1900

exec     jsr print
         db  13
         asc "(up)dcmiy"
         db  0

         lda #%00011011
         sta db
         lda #%11000110
         sta ab
         lda #%10110001
         sta xb
         lda #%01101100
         sta yb
         lda #0
         sta pb
         tsx
         stx sb

         lda #0
         sta db
         sta yb
         lda #>da
         sta uzp
         lda #<da
         sta uzp+1

next
         lda db
         sta da
         sta dr
         dec dr

         lda pb
         pha
         plp
         lda ab
         cmp dr
         sta ar

         php
         pla
         sta pr

         lda xb
         sta xr

         lda yb
         sta yr

         lda sb
         sta sr

         ldx sb
         txs
         lda pb
         pha
         lda ab
         ldx xb
         ldy yb
         plp

cmd      db  $d3
         db  uzp

         php
         cld
         sta aa
         stx xa
         sty ya
         pla
         sta pa
         tsx
         stx sa
         jsr check

         inc uzp
         bne noinc
         inc uzp+1
noinc    lda yb
         bne nodec
         dec uzp+1
nodec    dec yb

         inc db
         bne jmpnext
         inc pb
         beq nonext
jmpnext  jmp next
nonext

         jsr print
         asc " - ok"
         db  13,0
         lda #&fc
         ldx #&00
         ldy #&ff
         jsr osbyte
         lda #&8e
         jmp osbyte

db       db  0
ab       db  0
xb       db  0
yb       db  0
pb       db  0
sb       db  0
da       db  0
aa       db  0
xa       db  0
ya       db  0
pa       db  0
sa       db  0
dr       db  0
ar       db  0
xr       db  0
yr       db  0
pr       db  0
sr       db  0

check
         block
         lda da
         cmp dr
         bne error
         lda aa
         cmp ar
         bne error
         lda xa
         cmp xr
         bne error
         lda ya
         cmp yr
         bne error
         lda pa
         cmp pr
         bne error
         lda sa
         cmp sr
         bne error
         rts

error    jsr print
         db  13
         null "before  "
         ldx #<db
         ldy #>db
         jsr showregs
         jsr print
         db  13
         null "after   "
         ldx #<da
         ldy #>da
         jsr showregs
         jsr print
         db  13
         null "right   "
         ldx #<dr
         ldy #>dr
         jsr showregs
         jsr osnewl
wait2    jsr $ffe4
         beq wait2
         cmp #3
         beq stop
         rts
stop     lda 2
         beq basic
         jmp $8000
basic    jmp ($a002)

showregs stx uzp
         sty uzp+1
         ldy #0
         lda (uzp),y
         jsr hexb
         lda #32
         jsr oswrch
         lda #32
         jsr oswrch
         iny
         lda (uzp),y
         jsr hexb
         lda #32
         jsr oswrch
         iny
         lda (uzp),y
         jsr hexb
         lda #32
         jsr oswrch
         iny
         lda (uzp),y
         jsr hexb
         lda #32
         jsr oswrch
         iny
         lda (uzp),y
         ldx #"n"
         asl a
         bcc ok7
         ldx #"N"
ok7      pha
         txa
         jsr osasci
         pla
         ldx #"v"
         asl a
         bcc ok6
         ldx #"V"
ok6      pha
         txa
         jsr osasci
         pla
         ldx #"0"
         asl a
         bcc ok5
         ldx #"1"
ok5      pha
         txa
         jsr osasci
         pla
         ldx #"b"
         asl a
         bcc ok4
         ldx #"B"
ok4      pha
         txa
         jsr osasci
         pla
         ldx #"d"
         asl a
         bcc ok3
         ldx #"D"
ok3      pha
         txa
         jsr osasci
         pla
         ldx #"i"
         asl a
         bcc ok2
         ldx #"I"
ok2      pha
         txa
         jsr osasci
         pla
         ldx #"z"
         asl a
         bcc ok1
         ldx #"Z"
ok1      pha
         txa
         jsr osasci
         pla
         ldx #"c"
         asl a
         bcc ok0
         ldx #"C"
ok0      pha
         txa
         jsr osasci
         pla
         lda #32
         jsr oswrch
         iny
         lda (uzp),y
hexb     pha
         lsr a
         lsr a
         lsr a
         lsr a
         jsr hexn
         pla
         and #$0f
hexn     ora #$30
         cmp #$3a
         bcc hexn0
         adc #6
hexn0    jmp oswrch

print    pla
         block
         sta print0+1
         pla
         sta print0+2
         ldx #1
print0   lda *,x
         beq print1
         jsr osasci
         inx
         bne print0
print1   sec
         txa
         adc print0+1
         sta print2+1
         lda #0
         adc print0+2
         sta print2+2
print2   jmp *
EDIT: I have just noticed I have failed to port a call to a C64 routine to wait for something, a keystroke probably, but this is only invoked on failure. I'll not do any more on this as Tom is already working on this suite but I am keen to run the whole suite once that is finished.
User avatar
scarybeasts
Posts: 971
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by scarybeasts »

Coeus wrote:
Sun Jun 05, 2022 1:53 pm
I was thinking about the store version, not the load version, even though I talked about the load version. This is because, in the description I had been referring to, the store version was named after the AND feature rather than the store feature making it non-obvious but one example instruction would be opcode $83, described (in a different document) as SAX. Here both A and X get to drive something that ultimately ends up driving the external data pins to get a value stored in memory.
Somewhat famously (infamously?), Zalaga uses SAX and other undocumented opcodes in its sprite route.

(6502db) d 1174
[1172] 1174: SAX $80
[1172] 1176: ALR #$AA
[1172] 1178: SLO $80
[1172] 117A: EOR ($0C),Y
[1172] 117C: STA ($0C),Y


Cheers
Chris
User avatar
scarybeasts
Posts: 971
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by scarybeasts »

Rich Talbot-Watkins wrote:
Sun Jun 05, 2022 10:46 am
Here's a detailed dissection of the XAA illegal opcode from the Visual6502 wiki (which is currently down for some reason - thanks Wayback Machine!)

https://web.archive.org/web/20170804185 ... AA,_ANE%29
I found a beeb title that actually _used_ XAA -- Battle Tank. Unclear if it's an off-by-one accident, or some obfuscation to confuse back-in-the-day disassemblers that's part of the protection.

Code: Select all

[ITRP] 3530: RTS            [A=F3 X=00 Y=FF S=FB F=     1 N] 
DEBUG: undocumented opcode $8B at $34DE
breakpoint 0 hit 1 times
[ITRP] 34DE: XAA #$36       [A=F3 X=00 Y=FF S=FD F=     1 N] 
(6502db) d
[ITRP] 34DE: XAA #$36
[ITRP] 34E0: STA $01C6,Y
[ITRP] 34E3: DEY
[ITRP] 34E4: BPL $34DD
I tried XAA on a real model B issue 3 and did find the opcode to give unstable results. Here's the comment I added to beebjit describing what I observed:

Code: Select all

        /* EMU NOTE: Using 0xEE for the magic constant as per jsbeeb and b-em,
         * but on a Model B issue 3, I'm seeing the instability; magic constant
         * is usually 0xE8 but sometimes 0x68.
         * See: http://visual6502.org/wiki/index.php?title=6502_Opcode_8B_%28XAA,_ANE%29
         */
...
        v = p_mem_read[pc + 1];
        a = ((a | 0xEE) & x & v);

Cheers
Chris
User avatar
Rich Talbot-Watkins
Posts: 1879
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by Rich Talbot-Watkins »

Battle Tank was an eternal mystery to me, for a different reason. It didn't run on my Master (just used to hang when starting the game) and I never figured out why.
User avatar
BigEd
Posts: 5078
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by BigEd »

It's great to see the prospect of the Lorenz test suite running on the Beeb (and its emulators.)

Am I right in thinking that some Beebs come with Rockwell and some with Syntertek 6502s? Although they derive from the MOS original perhaps even to the degree of using the same mask patterns, the process might differ enough to skew some of these undocumented opcodes.

(As the visual6502 wiki is presently offline, please see the cached pages at archive.org for now)
User avatar
hoglet
Posts: 11435
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by hoglet »

Coeus wrote:
Sun Jun 05, 2022 11:27 pm
EDIT: I have just noticed I have failed to port a call to a C64 routine to wait for something, a keystroke probably, but this is only invoked on failure. I'll not do any more on this as Tom is already working on this suite but I am keen to run the whole suite once that is finished.
Tom Seddon?

I'm also very keen to be able to run the whole Lorenz test suite on the T65 core in BeebFpga.

Dave
User avatar
BigEd
Posts: 5078
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by BigEd »

From up-thread:
tom_seddon wrote:
Sat Jun 04, 2022 12:36 am
On this note, I'm in the process of putting together a BBC-friendly version of the Lorenz test suite, something I've long used for checking b2's 6502 emulation.
chrisn
Posts: 861
Joined: Sat Apr 19, 2014 12:31 pm
Location: UK
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by chrisn »

tricky wrote:
Fri Jun 03, 2022 10:59 am
beebem does quite well, but has a few issues:

case 0xcb: // SBX #n
forgets to do the AND of A and X before doing the subtract

case 0x2b: /* AND-MVC #n,b7 */
seems to OR the carry flag, rather than setting it, but I might have missed something

It also assumes that all illegal instructions are coming from RAM, so when reading addresses and immediate values it uses the optimised path of WholeRam[addr] rather than ReadPaged(addr) which in nearly every case should be fine as I don't know of any ROMs that use illegal opcodes!
I have fixed these instructions and the memory reads in BeebEm, so those changes will be in the next version. I think you're right about instruction 0x2b, all the other emulators set the carry flag the same as the N flag, so BeebEm now does the same.
Atom / BBC B with Music 5000/4000/2000 / Electron / A3000 / Master 128
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

tom_seddon wrote:
Sat Jun 04, 2022 12:36 am
On this note, I'm in the process of putting together a BBC-friendly version of the Lorenz test suite, something I've long used for checking b2's 6502 emulation.
After nearly 2 months of avoiding doing any more on it, I've decided to admit defeat on this, sorry about that - trying to pick apart the head-spinning amount of repeated code was starting to feel far too much like work. I've just archived as far as I got here: https://github.com/tom-seddon/lorenz-testsuite-beeb/ - further progress is rather unlikely!

I can't remember what state it's in exactly, but it isn't at all productized, so some self-assembly will be required.

--Tom

P.S. there's a copy in the b2 repo too: https://github.com/tom-seddon/b2/tree/m ... suite-2.15 - I think this is the unmodified original code, plus a Makefile I added that lets you build it on a modern system using 64tass.
User avatar
BigEd
Posts: 5078
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by BigEd »

That's a shame, but you had a go! And just maybe you've shown the way and someone else will manage to do it one day...
tom_seddon
Posts: 541
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by tom_seddon »

I'm still not going to do anything further with the Lorenz tests - but I wasn't happy about not having fulfilled my goal of having some kind of illegal opcode test suite that actually runs on the Beeb. So I thought I'd start on writing one, and it ended up actually taking a lot less time than I thought: https://github.com/tom-seddon/6502-tests

The goal here is to be useful for testing BBC emulators, so it tries not to duplicate what's already in the Dormann test suite, which is something you can run on a Beeb already and covers the documented aspects. My tests comprehensively test the BCD behaviour, and the illegal opcodes that are known to behave consistently on the C64, and it runs to completion on my BBC B and on b2. I'm now officially a bit more confident than I was before that b2's 6502 emulator reflects the BBC B's behaviour, when all I had was a (admittedly suggestive) successful Lorenz test suite run and no obvious issues.

(Also includes some tests for the BCD ADC/SBC behaviour on CMOS chips, but while putting the readme together I discovered that the Dormann suite can actually apparently test that too! - something I'd somehow previously missed. That part of these tests is actually redundant :oops:)

Plans for this in the longer term:

* more automation-friendly behaviour, so I can run it as part of the CI process for b2. At the moment, the only real way to tell if things succeeded or failed is to have an actual person look at it running using their eyes
* add test for SBX, which is reportedly consistent on C64, but has a time-consuming 24 bits of input
* add tests for the inconsistent C64 opcodes. Some of the inconsistent C64 opcodes are inconsistent on my Beeb too - but is that true for all of them?
* maybe add some portability stuff. The code is Beeb-specific at the moment, but in principle all it needs is 4 KB RAM and ideally some way of producing output

--Tom
User avatar
BigEd
Posts: 5078
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: illegal / undocumented opcode handling in emulators

Post by BigEd »

Well done! Victory, jaws of defeat, &co.
Post Reply

Return to “8-bit acorn emulators”