Functional Test for the NMOS 6502 - request for verification

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Functional Test for the NMOS 6502 - request for verifica

Post by BigEd »

Could you perhaps share your code? It seems that something is misbehaving, because Klaus' testsuite tells you so. If by reading the code we can see what's going wrong, it will then be easier to see why your subsequent tests are not failing as you expect.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Chromatix »

In case it helps, here's a trace of the first couple of dozen instructions from Klaus' test, from my sim with all the CPU state and memory activity exposed:

Code: Select all

0400: CLD             ; A=00 X=00 Y=00 S=00    I  ; 0 cyc       fetch 0400 -> D8
0401: LDX #$FF        ; A=00 X=00 Y=00 S=00    I  ; 2 cyc       fetch 0401 -> A2        fetch 0402 -> FF
0403: TXS             ; A=00 X=FF Y=00 S=00 N  I  ; 4 cyc       fetch 0403 -> 9A
0404: LDA #$00        ; A=00 X=FF Y=00 S=FF N  I  ; 6 cyc       fetch 0404 -> A9        fetch 0405 -> 00
0406: STA  $0200      ; A=00 X=FF Y=00 S=FF    IZ ; 8 cyc       fetch 0406 -> 8D        fetch 0407 -> 00        fetch 0408 -> 02        store 0200 <- 00
0409: LDX #$05        ; A=00 X=FF Y=00 S=FF    IZ ; 12 cyc      fetch 0409 -> A2        fetch 040A -> 05
040B: JMP  $0433      ; A=00 X=05 Y=00 S=FF    I  ; 14 cyc      fetch 040B -> 4C        fetch 040C -> 33        fetch 040D -> 04
0433: BNE *-10        ; A=00 X=05 Y=00 S=FF    I  ; 18 cyc      fetch 0433 -> D0        fetch 0434 -> F4
0429: DEX             ; A=00 X=05 Y=00 S=FF    I  ; 21 cyc      fetch 0429 -> CA
042A: DEX             ; A=00 X=04 Y=00 S=FF    I  ; 23 cyc      fetch 042A -> CA
042B: DEX             ; A=00 X=03 Y=00 S=FF    I  ; 25 cyc      fetch 042B -> CA
042C: DEX             ; A=00 X=02 Y=00 S=FF    I  ; 27 cyc      fetch 042C -> CA
042D: DEX             ; A=00 X=01 Y=00 S=FF    I  ; 29 cyc      fetch 042D -> CA
042E: BEQ *-32        ; A=00 X=00 Y=00 S=FF    IZ ; 31 cyc      fetch 042E -> F0        fetch 042F -> DE
040E: LDY #$05        ; A=00 X=00 Y=00 S=FF    IZ ; 34 cyc      fetch 040E -> A0        fetch 040F -> 05
0410: BNE *+10        ; A=00 X=00 Y=05 S=FF    I  ; 36 cyc      fetch 0410 -> D0        fetch 0411 -> 08
041A: DEY             ; A=00 X=00 Y=05 S=FF    I  ; 39 cyc      fetch 041A -> 88
041B: DEY             ; A=00 X=00 Y=04 S=FF    I  ; 41 cyc      fetch 041B -> 88
041C: DEY             ; A=00 X=00 Y=03 S=FF    I  ; 43 cyc      fetch 041C -> 88
041D: DEY             ; A=00 X=00 Y=02 S=FF    I  ; 45 cyc      fetch 041D -> 88
041E: DEY             ; A=00 X=00 Y=01 S=FF    I  ; 47 cyc      fetch 041E -> 88
041F: BEQ *+25        ; A=00 X=00 Y=00 S=FF    IZ ; 49 cyc      fetch 041F -> F0        fetch 0420 -> 17
0438: LDA  $0200      ; A=00 X=00 Y=00 S=FF    IZ ; 52 cyc      fetch 0438 -> AD        fetch 0439 -> 00        fetch 043A -> 02        fetch 0200 -> 00
043B: CMP #$00        ; A=00 X=00 Y=00 S=FF    IZ ; 56 cyc      fetch 043B -> C9        fetch 043C -> 00
043D: BNE *+0         ; A=00 X=00 Y=00 S=FF    IZC; 58 cyc      fetch 043D -> D0        fetch 043E -> FE
043F: LDA #$01        ; A=00 X=00 Y=00 S=FF    IZC; 60 cyc      fetch 043F -> A9        fetch 0440 -> 01
0441: STA  $0200      ; A=01 X=00 Y=00 S=FF    I C; 62 cyc      fetch 0441 -> 8D        fetch 0442 -> 00        fetch 0443 -> 02        store 0200 <- 01
This includes several taken branches both forward and backward; note the relationship between the target address, branch instruction address, and the actual encoding of the branch target opcode. Also beware: the branch offsets are in decimal in the listing, but everything else is in hex.
Klaus2m5
Posts: 442
Joined: 28 Jul 2012
Location: Wiesbaden, Germany

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Klaus2m5 »

May I remind you of a little disclaimer that I have in the program's source code header:

Code: Select all

; Please note that in early tests some instructions will have to be used before
; they are actually tested!
So if you are absolutely sure that relative addressing works correctly in your emulator/simulator then you should consider skipping the test in question and run the remainder of the tests. Simply hack a JMP into the object code that skips the program between the two enclosing calls to the next_test macro.
6502 sources on GitHub: https://github.com/Klaus2m5
Jokse
Posts: 15
Joined: 29 Nov 2013
Location: Denmark

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Jokse »

I did manage to figure it out... I misread the listing and just ignored BPL, which was the culprit here... So I fixed that... More errors to fix, but that's for another day. Thanks Klaus for making a piece of very useful software :)
ashkalov
Posts: 4
Joined: 05 May 2020

Re: Functional Test for the NMOS 6502 - request for verifica

Post by ashkalov »

Hi.
Excuse me for my English.
This is a translation, since I am Russian.
I am currently performing a Dormann functional test. There is a problem with the JSR instruction. My emulator puts the address of the instruction that goes directly after JSR on the stack. Since JSR has absolute addressing, the argument also has a size of 2 bytes. So I get the address of the next instruction so [current address] + 1 byte JSR + 2 bytes argument.
I do not understand why the following happens in Easy6502 and in everyone who has passed the Dormann test:
the RTS statement extracts the address and adds 1 to it. Why add 1? shouldn't the stack have the correct address?
Here is a piece of code Easy6502:

Code: Select all

i60: function () {
 regPC = (stackPop () | (stackPop() << 8)) + 1;
 //RTS
}
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Dr Jefyll »

Welcome, ashkalov :)
ashkalov wrote:
Why add 1? shouldn't the stack have the correct address?
No. Strangely, that's the way 65xx JSR and RTS instructions work. When they were designing the chip back in the 1970's they found it was easier to do it this way.

(Easier for them. Harder for us! :lol: )

Cheers,
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
ashkalov
Posts: 4
Joined: 05 May 2020

Re: Functional Test for the NMOS 6502 - request for verifica

Post by ashkalov »

What was the difficulty in adding the correct address to the stack right away? Isn't adding 1 an additional operation?
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Functional Test for the NMOS 6502 - request for verifica

Post by BigEd »

If the 6502 had a temporary register like the 6800 did, it might have been able to stack the expected PC value. But note that the machine is entirely correct - the RTS compensates for the JSR. The problem with stacking the expected value is that the machine would need to hold both operand bytes somewhere while it did the stack manipulation, and it has nowhere to store two bytes. Instead, it stores the first operand byte in the stack pointer register, while the value from there is passing through the ALU to be decremented. At this time the second operand byte has not been read and the final PC increment has not occurred. When the stack business is done, the stack pointer goes back to S and the first operand byte comes out of S and passes through the ALU while the second operand byte is fetched. Finally, the machine has both bytes at the same instant, as it puts them onto the address bus to fetch the first instruction of the subroutine.

Edit: some previous posts on this oddity:
viewtopic.php?p=11932#p11932
viewtopic.php?p=66175#p66175
viewtopic.php?p=41557#p41557

Edit: the 6502 was made as small as it could be, so that temporary register might have been considered but the designers would have been very pleased to see a way to do without it.
ashkalov
Posts: 4
Joined: 05 May 2020

Re: Functional Test for the NMOS 6502 - request for verifica

Post by ashkalov »

Thanks, BigED! Everything fell into place!
ashkalov
Posts: 4
Joined: 05 May 2020

Re: Functional Test for the NMOS 6502 - request for verifica

Post by ashkalov »

Thank you very much, Klaus!
What would we do without You!
The test was completed successfully in 48 seconds.
nelbr
Posts: 15
Joined: 19 Apr 2005

Re: Functional Test for the NMOS 6502 - request for verifica

Post by nelbr »

Hello all,

I have written my own 6502 emulator from scratch in C (Linux gcc), with the sole objective of teaching me about 6502 working and also improve my programming skills. But let me warn you that my code is not clean, nor fast, nor efficient. I hope to improve as I learn more, and have spare time to dedicate to it. I am not a professional programmer, and I am doing this as a personal hobby, also as a way to develop my own Apple 2+ emulator using SDL 2.0.

Anyways, I am running Klaus Dormann's test suite, and yes, thank you so much Klaus for having created these. For now, I am running only the functional tests, and despite struggling a bit on how to interpret them, I have advanced significantly. From memory, I detected and fixed errors on BRK setting the B flag, setting of overflow flag and decimal mode calculation. This has been incredible useful, so thank you many times.

I have come to the point that I can use my 6502 to emulate an Apple 2 at native speed, so quite happy.

However, I am still struggling to finalize the functional test suite, so probably I still have some issues. My test runs for about 1m30s , and then it falls into an infinite loop. I output the current test number, as well as the contents of memory 0x200, 0x203 and 0x204 using printf() and here is what I get:

Teste numero F0 0 99
Teste numero F0 0 99
Teste numero F0 0 99
Teste numero F0 0 99
Teste numero F0 0 99
...

This repeats forever or for how long I managed to wait :-)

Would anyone be able to help me understand where to look to fix this ? Not sure what test F0 does (and I tried to check on the assembly code but really didn grasp it). I know I am close to the end of the testing, but thought that it would restart if finished, so I am guessing I am not quite there yet.

My code is here in case any of you are curious or would like to check and help me?

https://github.com/nelbr/6502

Thank you all,
Nelbr
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Chromatix »

A test code of $F0 indicates that all the tests ran to completion successfully. The test suite is designed to run on bare hardware with no OS or monitor or I/O, so the only thing it can do is go into an infinite loop.

Code: Select all

        lda #$f0        ;mark opcode testing complete
        sta test_case
nelbr
Posts: 15
Joined: 19 Apr 2005

Re: Functional Test for the NMOS 6502 - request for verifica

Post by nelbr »

Chromatix wrote:
A test code of $F0 indicates that all the tests ran to completion successfully. The test suite is designed to run on bare hardware with no OS or monitor or I/O, so the only thing it can do is go into an infinite
I see.

Thanks so much for your answer, this is good news then. I guess I was confused by this line below in the code which made me think a successful test would restart from the beginning.

Code: Select all

; S U C C E S S ************************************************
        jmp start       ;run again      
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Functional Test for the NMOS 6502 - request for verifica

Post by Chromatix »

It is entirely possible that the source code doesn't precisely match the supplied binary image. In my copy of the latter, there is a tight loop which my simulator's test harness interprets as a cue to exit - the "JMP start" is replaced with "JMP *":

Code: Select all

[...]
3452: BNE *+0         ; A=10 X=0E Y=FF S=FC  VD ZC; 96571846 cyc	fetch 3452 -> D0	fetch 3453 -> FE
3454: RTI             ; A=10 X=0E Y=FF S=FC  VD ZC; 96571848 cyc	fetch 3454 -> 40	fetch 01FD -> 70	fetch 01FE -> 55	fetch 01FF -> 34
3455: LDA #$55        ; A=10 X=0E Y=FF S=FF  V    ; 96571854 cyc	fetch 3455 -> A9	fetch 3456 -> 55
3457: ADC #$55        ; A=55 X=0E Y=FF S=FF  V    ; 96571856 cyc	fetch 3457 -> 69	fetch 3458 -> 55
3459: CMP #$AA        ; A=AA X=0E Y=FF S=FF NV    ; 96571858 cyc	fetch 3459 -> C9	fetch 345A -> AA
345B: BNE *+0         ; A=AA X=0E Y=FF S=FF  V  ZC; 96571860 cyc	fetch 345B -> D0	fetch 345C -> FE
345D: LDA  $0200      ; A=AA X=0E Y=FF S=FF  V  ZC; 96571862 cyc	fetch 345D -> AD	fetch 345E -> 00	fetch 345F -> 02	fetch 0200 -> 2B
3460: CMP #$2B        ; A=2B X=0E Y=FF S=FF  V   C; 96571866 cyc	fetch 3460 -> C9	fetch 3461 -> 2B
3462: BNE *+0         ; A=2B X=0E Y=FF S=FF  V  ZC; 96571868 cyc	fetch 3462 -> D0	fetch 3463 -> FE
3464: LDA #$F0        ; A=2B X=0E Y=FF S=FF  V  ZC; 96571870 cyc	fetch 3464 -> A9	fetch 3465 -> F0
3466: STA  $0200      ; A=F0 X=0E Y=FF S=FF NV   C; 96571872 cyc	fetch 3466 -> 8D	fetch 3467 -> 00	fetch 3468 -> 02	store 0200 <- F0
3469: JMP  $3469      ; A=F0 X=0E Y=FF S=FF NV   C; 96571876 cyc	fetch 3469 -> 4C	fetch 346A -> 69	fetch 346B -> 34
3469: A=F0 X=0E Y=FF S=FF NV   C
nelbr
Posts: 15
Joined: 19 Apr 2005

Re: Functional Test for the NMOS 6502 - request for verifica

Post by nelbr »

Actually, just wanted to add that now that I know "F0" is successful completion, I added a check on my test program so it will exit once it sees 0xF0 in memory address 0x200 and I removed the printf command that displayed which test was being run, which reduced execution time on my emulator to 1s (from the 90s I posted above).

So, seems my library is actually performing pretty fast :-)
Post Reply