Failing CMP/CPY/CPX on blargg's cpu_test5

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
pokane
Posts: 5
Joined: Tue Mar 07, 2017 12:05 pm

Failing CMP/CPY/CPX on blargg's cpu_test5

Post by pokane »

Hi,

First, thanks blargg for writing all of these useful tests, I appreciate it. I'm curiously failing all CMP/CPX/CPY tests for all addressing modes (NROM, multiple file versions) yet all other tests pass, except BRK. My cpu also passes all tests for nestest and all tests in nestress except BRK. Basic games like Donkey Kong are fully functional on my emulator.

Does anyone have any ideas why CMP/CPX/CPY would fail on blargg's test but not others? I've reviewed my logs and the zero, sign, and carry flags appear to be set correctly.

Thanks for your help!
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by zeroone »

Are you doing something like this:

Code: Select all

  private void CMP(int value) {
    C = A >= value ? 1 : 0;
    N = getBit(A - value, 7);
    Z = A == value ? 1 : 0;
  }

  private void CPX(int value) {
    C = X >= value ? 1 : 0;
    N = getBit(X - value, 7);
    Z = X == value ? 1 : 0;
  }

  private void CPY(int value) {
    C = Y >= value ? 1 : 0;
    N = getBit(Y - value, 7);
    Z = Y == value ? 1 : 0;
  }
pokane
Posts: 5
Joined: Tue Mar 07, 2017 12:05 pm

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by pokane »

zeroone wrote:Are you doing something like this:

Code: Select all

  private void CMP(int value) {
    C = A >= value ? 1 : 0;
    N = getBit(A - value, 7);
    Z = A == value ? 1 : 0;
  }

  private void CPX(int value) {
    C = X >= value ? 1 : 0;
    N = getBit(X - value, 7);
    Z = X == value ? 1 : 0;
  }

  private void CPY(int value) {
    C = Y >= value ? 1 : 0;
    N = getBit(Y - value, 7);
    Z = Y == value ? 1 : 0;
  }
Yea, that is my logic exactly. Here is a log of every CMP operation for the 04-zero_page.nes test. I don't see any incorrect results:
http://pastebin.com/JUBAiTdP
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by zeroone »

Does the test reveal which specific opcode is failing? There are many variations of those instructions.
pokane
Posts: 5
Joined: Tue Mar 07, 2017 12:05 pm

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by pokane »

zeroone wrote:Does the test reveal which specific opcode is failing? There are many variations of those instructions.
Yes, for the zero page test:

C5 CMP z
E4 CPX z
C4 CPY z

The log file I linked was my cpu status after every instance of C5 CMP z was run. Thanks for your help.
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by zeroone »

Those are zero page instructions. Did you inspect the logic that reads and writes to page 0?
pokane
Posts: 5
Joined: Tue Mar 07, 2017 12:05 pm

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by pokane »

zeroone wrote:Those are zero page instructions. Did you inspect the logic that reads and writes to page 0?
It's failing CMP/CPY/CPX for all addressing modes, not just zero. For example if I run the 03-immediate.nes test I get this:

C9 CMP #n
E0 CPX #n
C0 CPY #n

And similar results for the other files. I don't think I'm incorrectly reading the data for every addressing mode because the emulator passes all of nestest (logfile diff matched fceux), all of nestress, and all of the the other opcodes in blargg's cpu test. It also passes a good portion of blargg's ppu and timing tests.

Are there other possible reasons for the test not directly related to the CMP opcode you can think of? Perhaps something in the initialization steps is causing the tests to fail? This is the NROM version since I haven't implemented any other mappers yet.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by Zepper »

pokane wrote:Are there other possible reasons for the test not directly related to the CMP opcode you can think of? Perhaps something in the initialization steps is causing the tests to fail? This is the NROM version since I haven't implemented any other mappers yet.
This is my source code for CMP.

Code: Select all

CPUOP(CMP0)
  offset = cpu->A - value;
  if(offset < 0x100) {
     cpu->P |= C_BIT;
  } else {
     cpu->P &= ~C_BIT;
  }  
  SET_NZ_FLAGS(offset);
OPEND
Please, post yours.
fred
Posts: 67
Joined: Fri Dec 30, 2011 7:15 am
Location: Sweden

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by fred »

You could always try logging the instructions and see if there's something obviously wrong with the compares.
Alternatively (and likely easier), log and compare against another emulator that can generate logs and compare them.


Edit: I see you did log the results, oops!
pokane
Posts: 5
Joined: Tue Mar 07, 2017 12:05 pm

Re: Failing CMP/CPY/CPX on blargg's cpu_test5

Post by pokane »

Zepper wrote:
pokane wrote:Are there other possible reasons for the test not directly related to the CMP opcode you can think of? Perhaps something in the initialization steps is causing the tests to fail? This is the NROM version since I haven't implemented any other mappers yet.
This is my source code for CMP.

Code: Select all

CPUOP(CMP0)
  offset = cpu->A - value;
  if(offset < 0x100) {
     cpu->P |= C_BIT;
  } else {
     cpu->P &= ~C_BIT;
  }  
  SET_NZ_FLAGS(offset);
OPEND
Please, post yours.
It's Javascript so I had to use ArrayBuffers and typed arrays to get proper 8/16 bit integer types. cpu.u_int8[0] holds the 8 bit value fetched from memory, cpu.lastResult[0] is a 16 bit unsigned int, cpu.lastResultBytes[0] points to the lower 8 bits of lastResult (Array Buffers are little endian).

Code: Select all

function CMP (cpu) {
    cpu.lastResult[0] = cpu.A - cpu.u_int8[0];
    cpu.flagCarry = cpu.A >= cpu.u_int8[0]; 
}

function getFlagSign() { 
    return (this.lastResult[0] & 0x80) === 0x80;
}

function getFlagZero(){
    return this.lastResultBytes[0] === 0;
}
Post Reply