Page 1 of 3
Debugging the cpu core
Posted: Sun Sep 08, 2013 7:30 pm
by Dartht33bagger
I thought I'd just make a new thread for this. I've been trying for weeks now to debug my cpu core and I just don't know where to go from here. My core passes some of blarg's tests. Here are what each of the tests do:
01-basics: passes
02-implied: passes
03-immediate: Doesn't pass. $6000 = $80 no matter how much time passes. Goes into an infinite BRK instruction after INC instruction is carried out at $03A1
04-zero_page: Doesn't pass. $6000 = $80 no matter how much time passes. Goes into infinite BRK after $03A1
05-zp_xy: Doesn't pass. $6000 = $80 no matter how much time passes.
06-absolute: Doesn't pass. $6000 = $80 no matter how much time passes.
07-abs_xy: Doesn't pass. $6000 = $80 no matter how much time passes.
08-ind_x: Fails but only illegal opcodes are output as being wrong (I'm only testing official opcodes)
09-ind_y: Same as ind_x
10-branches: passes
11-stack: passes
12-jmp_jsr: passes
13-rts: passes
14-rti:passes
15-brk: fails. $6000 = $80 no matter how much time passes.
16-special: fails. $6000 = $80 no matter how much time passes.
I have a debug function written that outputs all instructions like this, but the text file gets so big that I have no idea how it's helpful:
E883 78 SEI A:00 X:00 Y:00 P:30 SP:FD CYC: 0
E884 4C B3 EC JMP $ECB3 A:00 X:00 Y:00 P:34 SP:FD CYC: 6
ECB3 8D 24 02 STA $0224 = 00 A:00 X:00 Y:00 P:34 SP:FD CYC: 15
ECB6 A9 00 LDA #$00 A:00 X:00 Y:00 P:34 SP:FD CYC: 27
ECB8 8D 00 20 STA $2000 = 00 A:00 X:00 Y:00 P:36 SP:FD CYC: 33
ECBB 8D 01 20 STA $2001 = 00 A:00 X:00 Y:00 P:36 SP:FD CYC: 45
ECBE 4C 87 E8 JMP $E887 A:00 X:00 Y:00 P:36 SP:FD CYC: 57
So, what is the best way of going about debugging this CPU core? All of the tests that fail get off track some way or another and never actually print any output ($6000 is always $80, so it's still running) because it gets stuck in an infinite BRK. I have no idea what opcodes to even start looking at.
Re: Debugging the cpu core
Posted: Sun Sep 08, 2013 8:09 pm
by blargg
There's always
nestest with a log of correct execution to compare your CPU with. Pinpoints exactly where you go astray.
Re: Debugging the cpu core
Posted: Sun Sep 08, 2013 11:11 pm
by Dartht33bagger
I was using that test originally, but I switched over to yours because the nestest tests illegal opcodes. My cpu is correct up until the illegal opcodes start. Some of my illegal opcodes aren't right and I couldn't figure out the correct behavior for their flags, so I turned them off.
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 12:56 am
by blargg
My individual CPU tests also try unofficial opcodes, I'm pretty sure. Only the large multi-test ROMs have a version of only official opcodes. It's not too hard to have your core just skip unofficial instructions.
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 1:04 pm
by Dartht33bagger
I tried a variant of my cpu core once before that moved the PC counter accordingly for the unoffical opcodes but nothing more. This caused a lot of issues on the nestest, however, because the processor status flags weren't correct when branch instructions came up. Maybe it would have a different affect on your tests?
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 1:47 pm
by blargg
My instruction tests do each one individually, so that a failing one won't affect others (unless it's an instruction used by the tests, like say CMP # or something basic). It'd be interesting to make the CPU test immune to emulators that treat unofficial instructions as one-byte NOPs. Maybe it could try executing them with zero-byte operands and if a BRK occurs, skip that instruction.
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 2:20 pm
by Grapeshot
You can generate known good logs of the tests you're failing with Nintendulator's debugger and then diff them with yours (assuming the format is the same). A lot of programs have trouble with 300mb log files, but
Beyond Compare worked for that when I needed it.
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 11:35 pm
by Dartht33bagger
I took Grapeshot's suggestion and went with it. I'm running through 03-immediate right now.
Somehow my $2C BIT test isn't working right. Everything matches up for 9000+ lines until Nestendulator just randomly switches up how $2C works. I can't post the lines in question because the formatting gets messed up, but here is what happens the best I can explain it:
A long loop occurs where $2C bit and BMI/BNE are alternated between. Opcode $2C is reading address $2002 during the entire loop which is always set to $FF. This leaves the processor status flags as $26 whenever the $2C opcode is ran UNTIL the last one that throws off my emulator. The last $2C opcode that breaks out of the loop sets the negative flag (making the processor status $A6 so that the next BMI branches) even though it's still bit testing $FF. I cannot for the life of me figure out why.
Here is my code for $2C. Originally, my processor status flags were wrong when running $2C. The wiki said that V and N were set to bits 6 and 7 of the data read. That didn't work so I tried the not of the bits and it worked up until the last bit test I mentioned above. So theres that for you.
Code: Select all
case 0x2C: //Absolute bit test
temp = absolute(memory, ppu);
data = memory->readRAM(temp, ppu);
Z = !(A & data);
V = !(data & 0x40); //Gets the 6th bit only
N = !(data & 0x80); //Gets the 7th bit only
debugAbs(opcode, memory->readRAM(PC + 1, ppu), memory->readRAM(PC, ppu), data, "BIT");
cycles = 4;
PC += 2;
break;
Re: Debugging the cpu core
Posted: Mon Sep 09, 2013 11:51 pm
by lidnariq
$2002 should definitely not return $FF forever. At the very least, the MSB should be cleared after you read from it.
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 12:08 am
by blargg
You're setting N and V to the opposite of what they should be. Add a bang:
V = !!(data & 0x40); //Gets the 6th bit only
N = !!(data & 0x80); //Gets the 7th bit only
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 12:31 am
by Dartht33bagger
lidnariq wrote:$2002 should definitely not return $FF forever. At the very least, the MSB should be cleared after you read from it.
That's what my code originally did but it was wrong according to Nintendulator. Nintendulator kept $FF in $2002 and I had $7F in $2002, which vimdiff didn't like since the log files didn't match.
blargg wrote:You're setting N and V to the opposite of what they should be. Add a bang:
V = !!(data & 0x40); //Gets the 6th bit only
N = !!(data & 0x80); //Gets the 7th bit only
My original code looked like this, but my log file would have the wrong processor status after the first bit test occured.
Code: Select all
V = data & 0x40; //Gets the 6th bit only
N = data & 0x80; //Gets the 7th bit only
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 8:47 am
by blargg
Dartht33bagger wrote:My original code looked like this, but my log file would have the wrong processor status after the first bit test occured.
V = data & 0x40; //Gets the 6th bit only
N = data & 0x80; //Gets the 7th bit only
Maybe the data was wrong, rather than the instruction behavior?
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 1:57 pm
by Dartht33bagger
Alright, I'm just going to post the lines in question from the two logs files the best that I can. My log file will be using code that doesn't not the V and N bits and clears bit 7 of $2002 after read.
From Nintendulator's log:
E944 2C 02 20 BIT $2002 = FF A:00 X:01 Y:18 P:24 SP:FB CYC: 0 SL:171
E947 2C 02 20 BIT $2002 = FF A:00 X:01 Y:18 P:26 SP:FB CYC: 12 SL:171
E94A 30 06 BMI $E952 A:00 X:01 Y:18 P:26 SP:FB CYC: 24 SL:171
E94C CA DEX A:00 X:01 Y:18 P:26 SP:FB CYC: 30 SL:171
E94D D0 F8 BNE $E947 A:00 X:00 Y:18 P:26 SP:FB CYC: 36 SL:171
E94F 88 DEY A:00 X:00 Y:18 P:26 SP:FB CYC: 42 SL:171
E950 10 F5 BPL $E947 A:00 X:00 Y:17 P:24 SP:FB CYC: 48 SL:171
E947 2C 02 20 BIT $2002 = FF A:00 X:00 Y:17 P:24 SP:FB CYC: 57 SL:171
From my log on the same lines:
E944 2C 02 20 BIT $2002 = FF A:00 X:01 Y:18 P:24 SP:FB CYC: 0 SL:171
E947 2C 02 20 BIT $2002 = 7F A:00 X:01 Y:18 P:E6 SP:FB CYC: 12 SL:171
E94A 30 06 BMI $E952 A:00 X:01 Y:18 P:66 SP:FB CYC: 24 SL:171
E94C CA DEX A:00 X:01 Y:18 P:66 SP:FB CYC: 30 SL:171
E94D D0 F8 BNE $E947 A:00 X:00 Y:18 P:66 SP:FB CYC: 36 SL:171
E94F 88 DEY A:00 X:00 Y:18 P:66 SP:FB CYC: 42 SL:171
E950 10 F5 BPL $E947 A:00 X:00 Y:17 P:64 SP:FB CYC: 48 SL:171
E947 2C 02 20 BIT $2002 = 7F A:00 X:00 Y:17 P:64 SP:FB CYC: 57 SL:171
Nintendulators N and V flags are always opposite to mine. It also keeps reading $FF from $2002. I'm stumped.
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 2:31 pm
by blargg
Nintendulator's log doesn't even make sense, or it's lying about the value read from $2002.
Re: Debugging the cpu core
Posted: Tue Sep 10, 2013 2:38 pm
by Zepper
...