It is currently Sat Nov 18, 2017 1:14 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Sat Sep 22, 2007 3:04 pm 
Offline

Joined: Sat Sep 22, 2007 8:32 am
Posts: 82
Location: Seattle, WA
Hello all,
I am trying to fix several CPU errors in my emulator but I am having trouble actually tracking them down. Using nestest I have found the errors, great, its opcode __, but what facet of opcode __? Are my flags wrong? Program counter error? Overlooked sign issues?
Does anyone have an idea as to where I might look to find more information for nestest errors?

For example:
I'm focusing on testing CMP absolute,X. I get 064h. I change some values around and get the flags seemingly right, I test again and now I get 061h. What happened? I see it testing the code, so I log it to get:
Code:
A : 40
M : 40
Flags: 0 1 1
A : 40
M : 3f
Flags: 0 1 0
A : 40
M : 41
Flags: 1 0 0
A : 80
M : 0
Flags: 0 1 0
A : 80
M : 80
Flags: 0 1 1
A : 80
M : 81
Flags: 1 0 0
A : 80
M : 7f
Flags: 0 1 0

based on http://homepage.ntlworld.com/cyborgsystems/CS_Main/6502/6502.htm#CMP it seem more correct, and Super Mario Bros still runs fine.
But I have other CPU issues I need to fix and i was hoping there would be a faster way with a more explained error code.


Top
 Profile  
 
PostPosted: Sat Sep 22, 2007 4:26 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
I'm assuming your flags are N, C, Z ? Would've been nice if you labelled them ;P I thought it was NZC at first

anyway I noticed this:

Code:
A : 80
M : 0
Flags: 0 1 0


should be : 1 1 0 (NCZ)

80 - 0 = 80 (negative)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 5:21 pm 
Offline

Joined: Sat Sep 22, 2007 8:32 am
Posts: 82
Location: Seattle, WA
Okay, I've been playing with nestest some more, and I've got more simple problems.

First, I pass absolute,X test, but only with the following code:
Code:
#define COMP_MEM_AIX(REG, CYCLES){                                       \
   addr = ((memory[program_counter+1] << 8) | memory[program_counter]) + x_reg;   \
   tmp2 = ((REG) - (addr));                                          \                     \
   tmp = memory_read(addr);                                          \
   carry_flag = (REG >= tmp) ? 1 : 0;                                    \
   sign_flag = ((REG < tmp) || (tmp == 0)) ? 1 : 0;                        \
   zero_flag = (REG == tmp) ? 1 : 0;                                    \
   printf("A   : %i \n", (signed char)REG);         \
   printf("M   : %i \n", (signed char)addr);         \
   printf("t   : %i \n", (signed char)tmp2);         \
   printf("Flag: %x : %x : %x\n", sign_flag, carry_flag, zero_flag);\
   program_counter += 2;                                             \
   cycle_count -= CYCLES;                                             \
   break;                                                         \
}

This code just doesn't look right with the '|| (tmp == 0)' portion, however the method used by the docs on the subject I've read (tmp & 0x80). This and every other of the CMP / CPY functions fail and I just keep going back to it so I can move on and fix some other issues.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 5:43 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
Your absolute,X code looks fine.

But I'm not sure about your N flag setting...

All the N flag means is set according to the high bit of the result (see below). That is... if the previous instruction resulted in $80 or higher (high bit set), N is also set. To make your life easier, just deal with everything as unsigned, since most all other behavior acts as if it were signed.

CMP is really a glorified subtraction instruction. The CPU subtracts the given value from a register and sets flags according to the result -- just as SBC does (although CMP doesn't change the register, or V, and it doesn't involve C in the subtraction)

So N would be set when (REG-tmp) & 0x80 is nonzero.

My CMP macro:

Code:
#define CMP(r)                           \
   tmp = r - val;                        \
   fC = !(tmp >> 8);                     \
   fN = fZ = (u8)tmp


'tmp' is a 16-bit temp value
'r' is register being used (A, X, or Y for CMP, CPX, CPY)
'fC' represents the C flag -- nonzero = set
'fZ' represents the Z flag -- zero = set
'fN' represents the N flag -- fN & 0x80 = set


EDIT --

If your x_reg is signed 8-bit... that's a big problem. Make sure it's unsigned.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 6:25 pm 
Offline

Joined: Fri Jul 29, 2005 3:40 pm
Posts: 345
Location: near chicago
i noticed that you are using macro's for some instructions. why? i tried that here once and my emulator went from slow to very slow. it makes the binary larger and causes more cache misses.

matt


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 8:19 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Quote:
i tried that here once and my emulator went from slow to very slow. it makes the binary larger and causes more cache misses.

The effect depends on how the emulator is written. If some other author finds that macros speed it up, then so be it.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 9:28 pm 
Offline

Joined: Fri Jul 29, 2005 3:40 pm
Posts: 345
Location: near chicago
i agree with that. seems that alot of people use that and when i tested it, it was slower. sorry for the off topic commment.

matt


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 10:10 pm 
Offline

Joined: Sat Sep 22, 2007 8:32 am
Posts: 82
Location: Seattle, WA
mattmatteh wrote:
i noticed that you are using macro's for some instructions. why? i tried that here once and my emulator went from slow to very slow. it makes the binary larger and causes more cache misses.

I'll give that a test and see if it actually does cause a slowdown (I'm on OSX v10.4.10), it's not slow as is though so I have nothing to lose.
After reading through the forms and links I found, I also pass NOP, SBX and SLO of the undocumented OP codes.
I can't thank you all enough for your help, as it stands I pass everything except:
(indirect,X) test: 59 STA didn't store the data where it was supposed to
(indirect,Y) test: EC should've wrapped zeropage address

And again I'm not sure what the result location I am looking for from the STA write is; nor do I know where it is refering to for the zeropage address.

The code:
Code:
#define STORE_IDI(REG, CYCLES){                           \
   addr = memory[program_counter];                        \
   tmp = ((memory[addr + 1] << 8) | memory[addr]) + x_reg;      \
   printf("Address: %x\n", addr);                        \
   printf("Memory : %x\n", tmp);                        \
   write_memory(tmp, REG);                              \
   program_counter++;                                 \
   cycle_count -= CYCLES;                              \
   break;                                          \
}
What I get is
Code:
Address: 80
Memory : 200
Address: 80
Memory : 202
Address: 80
Memory : 203
Address: ff
Memory : 0


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 24, 2007 10:47 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
MatthewCallis wrote:
(indirect,X) test: 59 STA didn't store the data where it was supposed to


(Indirect,X) is not (Indirect),X. The comma inside the parenthesis indicates the addition is performed before the indirection.

Inefficient but verbose pseudocode:

Code:
  temp = Read( PC );  // get pointer address
  temp += X;  // add X to it
  temp &= 0xFF;  // keep it on zero page
  addr = Read( temp ); // get low byte of pointer
  temp += 1;
  temp &= 0xFF;  // again, keep it on zero page
  addr |= Read( temp ) << 8;

  // do your STA or whatever to addr


Quote:
(indirect,Y) test: EC should've wrapped zeropage address


Same situation as above. The pointer is always read from zero page. So LDA ($FF),Y would get the low byte of the pointer from $00FF and the high byte from $0000 -- NOT $0100. But note (Indirect),Y has the comma outside the parenthesis -- indicating you add Y after the indirection.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 25, 2007 7:29 am 
Offline

Joined: Thu Jul 13, 2006 3:15 pm
Posts: 177
Is nestest hosted anywhere else? The link on the wiki doesnt work for me. Sorry for hijacking the thread.

Al


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 25, 2007 9:05 am 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
http://dischmeister.googlepages.com/nestest.zip


I don't have any readmes or anything. The "automated" ROM is the one that runs through the tests without any display or input (for bare-bones CPU emus to be able to test themselves). IIRC, it puts the error code or success code in zero page somewhere, but I can't remember.


[EDIT: Google Pages is dead. I have uploaded a copy of nestest and its readme. --tepples]


Attachments:
nestest not original zip.zip [12.47 KiB]
Downloaded 45 times
Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 25, 2007 11:03 am 
Offline

Joined: Thu Jul 13, 2006 3:15 pm
Posts: 177
Thanks. I havent written an emulator, but I did write a 6502 core as part of a "not very good disassembler", so this'll be useful for me.


Edit - I still have a lot of work to do before I can truly use it.

Al


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 25, 2007 2:50 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3075
Location: Brazil
Notice that if a particular instruction has failed in the test, it does NOT imply the error relies on THAT instruction. ^_^;;

_________________
Zepper
RockNES developer


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 25, 2007 7:47 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Quote:
Notice that if a particular instruction has failed in the test, it does NOT imply the error relies on THAT instruction.

You mean the way another failing instruction could cause an "innocent" instruction to get flagged, due to the inherent paradox of testing the CPU with the very instructions that are being tested?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google Adsense [Bot] and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group