Page 1 of 3

CPU Testing, Any Good Tips?

Posted: Sun Jan 11, 2009 8:15 pm
by MottZilla
As I mentioned in other threads, I'm working on a Gameboy (and later Gameboy Color) emulator. I've got a good bunch of games running but there are still problems that I think could be CPU related and not Gameboy emulation related. On the NES I was able to take advantage of Blargg's CPU Test. I've seen no such thing for Gameboy so I'm wondering if anyone has any good ideas for debugging? I know I can always go through each opcode one by one trying to spot errors but this will take awhile so I was just wondering if anyone had any tips.

Also if you have any ideas of something I could have been confused about and done wrong that I should check for, please let me know.

Posted: Mon Jan 12, 2009 4:31 am
by blargg
This tests a good number of instructions (wla-dx source included): gb_cpu_test.zip

Posted: Mon Jan 12, 2009 5:04 pm
by tomaitheous
I'm interested to know if the CPU really does have 4 T states to a single cpu cycle or if that was just assumed from some docs. Similar to docs for the z80 that are incorrect and/or don't give the T state counts or reduced/extended T states for some situations.

Posted: Mon Jan 12, 2009 9:38 pm
by MottZilla
I'm not sure exactly what you mean, but the Gameboy documents are pretty strange with Cycle counts. Sometimes people say something takes 1 cycle, others say that same opcode takes 4 cycles. Not what you want to get mixed up when you are trying to sync the PPU and CPU. Originally I did this with a 4x gap, so the PPU ran 4 times faster than it should, or you could say the Cpu ran 1/4th the speed it should.

Posted: Mon Jan 12, 2009 10:11 pm
by Celius
Yeah, I didn't have much luck either trying to find GB/GBC cycle counts. It'd be nice if there was some straight forward documentation about such things.

Posted: Mon Jan 12, 2009 10:33 pm
by tomaitheous
Well, on the Z80 you have the instructions listed in M cycles. Most docs list M cycle as 3 (or 4 depending on the doc) external clock source cycles, but really M cycles don't show the whole picture. An M cycle is made up of a variable accumulation of T states depending on the operation and also depending on the previous instruction from what I've read.

On the GB docs, they list an M cycle as 4 external clock cycles and instruction timings are given in M cycles. Since the GB cpu is a variant of the z80, who's to say that the same misunderstanding isn't applied to it was well. There are many processor documents with incorrect instruction timing information out there, so this would be the first if it were true.

Posted: Wed Jan 14, 2009 3:44 am
by mic_
Is there a list of what the expected values for A and F are for each iteration of the DAA test?

Posted: Wed Jan 14, 2009 6:18 am
by blargg
This code matches execution on a DMG/CGB. Flag bit masks below are named by flag name and hex value, for clarity.

Code: Select all

if ( !(flags & N40) )
{
    if ( (flags & H20) || (a & 0x0F) > 9 )
        a += 6;

    if ( (flags & C10) || a > 0x9F )
        a += 0x60;
}
else
{
    if ( flags & H20 )
        a = (a - 6) & 0xFF;

    if ( flags & C10 )
        a -= 0x60;
}

flags &= ~(H20 | Z80);
if ( a & 0x100 )
    flags |= C10;

a &= 0xFF;
if ( !a )
    flags |= Z80;

Posted: Wed Jan 14, 2009 7:39 am
by mic_
Ah, cool. Now I get "01-- 02". So I take it everything passed, but what does the 02 mean in that case?

Posted: Wed Jan 14, 2009 8:26 am
by blargg
This is the correct result:

Code: Select all

01-- 02-- 03-- 04--
05-- 06-- 07-- 08--
09-- 10--
Passed all tests
The -- are where an error code would be printed if that test failed. The test numbers correspond to the files in source/, for example test 02 is instruction timing. It takes a while to run all the tests.

Posted: Thu Jan 15, 2009 2:57 am
by mic_

Code: Select all

-    nop       ; 12
     nop
     nop
     wreg IF,0 ; 20
     lda  IF   ; 12
     bit  2,a  ; 8
     push af   ; 28
     pop  af
     jr   z,-  ; 12
I thought writing 0 to IF would reset all bits in IF. In that case, how is this loop ever supposed to finish? Is it waiting until a timer overflow occurs right after "wreg IF,0"? Because that seems like it could take a while, if it ever happens.

Posted: Thu Jan 15, 2009 6:36 am
by blargg
It's just my standard exact-synchronization loop. In timing.a, timing_init sets the timer to run every 96 clocks. The loop takes 92 clocks per iteration, so at most it could take 24 iterations before the timer expires within that critical window. By adjusting the delay after the coarse synchronization loop, worst-case is reduced.

Posted: Thu Jan 15, 2009 6:37 am
by mic_
Nevermind, I fixed that.

Posted: Thu Jan 15, 2009 8:03 am
by mic_
How do you find out which subtest is failing in those tests that doesn't use set_result? E.g. if subtest 02 of test 07 fails, which instruction is that?

Posted: Thu Jan 15, 2009 8:26 am
by blargg
Argh, I just noticed I already built each one individually, in the individual/ directory. If a main test fails, run that one individually to get the full output.