Failing CMP/CPY/CPX on blargg's cpu_test5

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190637)
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!
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190639)
Are you doing something like this:

Code:
  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;
  }
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190640)
zeroone wrote:
Are you doing something like this:

Code:
  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
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190641)
Does the test reveal which specific opcode is failing? There are many variations of those instructions.
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190642)
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.
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190644)
Those are zero page instructions. Did you inspect the logic that reads and writes to page 0?
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190645)
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.
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190647)
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:
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.
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190650)
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!
Re: Failing CMP/CPY/CPX on blargg's cpu_test5
by on (#190655)
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:
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:
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;
}