testing my 6502 cpu emulator

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
Post Reply
bruce_lee
Posts: 8
Joined: 18 Jul 2008

testing my 6502 cpu emulator

Post by bruce_lee »

hi there!
i have written a emulator for the 6502 processor, ie all the opcodes and the addressing modes, trouble is i need to test to see if the results i am getting from the functions are all correct (the processor status, flags, x, y reg, program counter etc ). Does anyone have any test cases i can put against my work?
if nobody has such test cases, anything which will let me know where my code is going right and wrong? eg another simulator allowing me to set values, call functions and then see the results, which i can then compare to mine?

any help you guys can give would greatly be appreciated
thanks
Lost
Posts: 20
Joined: 07 Oct 2007
Location: Toronto, Canada
Contact:

6502 emulators

Post by Lost »

8-Bit (one of the more active posters here) built an emulator for one of his SBC projects. I don't have the link handy but I found it through his writeup on the 6502.org site.

Right now, I'm using a windows program called "6502 Macroassembler & Simulator written by Michal Kowalski, his web page is http://www.pacbell.net/michal_k

Also, a search for Apple II emulators will turn up quite a few 6502 emulators.
Thowllly
Posts: 51
Joined: 22 Oct 2003
Location: Norway

Post by Thowllly »

I remember running a c64 program that would test all opcodes for correct behavior, but I don't remember what it was called or anything. Searching for 'c64 emulator test suite' returns some results, like http://www.zimmers.net/anonftp/pub/cbm/ ... tors/pc64/ (near bottom). I don't know if it's any useful, I haven't tested it, but maybe you can adapt it, or something like it, to run on your emulator.
bruce_lee
Posts: 8
Joined: 18 Jul 2008

Post by bruce_lee »

hi guys, thanks for your replies,

i have done a few test and compared results with the simulator you guys mentioned, the good news is that all my opcodes return the same results as the simulator (for the moment yes but i still have to test with all addressing modes) with the exception of one - SBC, i get the correct value returned in the accumulator but not in the processor status, the algorithm i am using is as follows:

IF (P.D) //decimal mode
t = bcd(A) - bcd(M) - ~P.C
P.V = (t>99 OR t<0) ? 1:0
ELSE
t = A - M - ~P.C
P.V = (t>127 OR t<-128) ? 1:0 // i get an overflow but simulator does not
P.C = (t>=0) ? 1:0 // i get a carry simulator does not
P.N = t.7 // this is fine
P.Z = (t==0) ? 1:0 // this is fine
A = t & 0xFF //this is fine

the values i plug in are as follows:

accumulator = 16;
processor_stat = 32;

the results i get :

accumulator = 225; //overflow was set and carry
processor_stat = 241;

result from simulator:

accumulator = 160; //negative flag was set
processor_stat = 241

if any of you guys can shed some light as to why its going wrong (i spent hours on it couldnt understand why) i would really appreciate it, i have come too far to give up on my work!
User avatar
dclxvi
Posts: 362
Joined: 11 Mar 2004

Post by dclxvi »

bruce_lee wrote:
the results i get :

accumulator = 225; //overflow was set and carry
processor_stat = 241;

result from simulator:

accumulator = 160; //negative flag was set
processor_stat = 241
It looks like you've swapped the values of the accumulator and processor_stat in this part of your post. If so, it would appear that the value of M you used was 225 (you didn't mention what value you plugged in there). In that case, the "simulator" results are correct, i.e. entering with:

A register = 16, M variable = 225, d flag = 0, c flag = 0

the result should be:

A register = 241, n flag = 1, v flag = 0, z flag = 0, c flag = 0

The logic of what you are doing appears to be correct, but you have to pay careful attention to the width of t, the width of the subtraction operation, whether A and M are being sign extended, and whether the comparisons are signed or unsigned.

One thing that would give the behavior that you see is if t were declared as an unsigned variable. All unsigned values are greater than 0 so the t>=0 comparison would always be true. The t>127 OR t<-128 comparsions, for a 16-bit variable (e.g.) would be equivalent to the comparison unsigned comparsion (t > 127 AND t <= 65535) OR (t >= 0 AND t < 65536-128), which is always true.

Remember, the C flag is based on unsigned subtraction, and the V flag is based on signed subtraction. Here's one (untested) way of doing it (for the d flag = 0 case):

Code: Select all

// Inputs:
//
//   A: 8-bit integer
//   C: 0 or 1
//   M: 8-bit integer
//
// Outputs:
//
//   A: 8-bit integer
//   C: 0 or 1
//   N: 0 or 1
//   V: 0 or 1
//   Z: 0 or 1
//
// Local variables:
//
//   a16: signed 16-bit integer
//   m16: signed 16-bit integer
//     t: signed 16-bit integer

// when d flag is zero

// signed subtraction

a16 = A
m16 = M
a16 = (a16 & 0x7F) // ensure that 0 <= a16 <= 127
m16 = (m16 & 0x7F) // ensure that 0 <= m16 <= 127
a16 = a16 - (((A & 0x80) == 0) ? 0 : 128) // ensure that -128 <= a16 <= 127
m16 = m16 - (((M & 0x80) == 0) ? 0 : 128) // ensure that -128 <= m16 <= 127

t = a16 - m16 - C

V = (t >= -128 AND t <= 127) ? 0 : 1

// unsigned subtraction

a16 = A
m16 = M
a16 = (a16 & 0x00FF) // ensure that 0 <= a16 <= 255
m16 = (m16 & 0x00FF) // ensure that 0 <= a16 <= 255

t = a16 - m16 - C

A = (t & 0x00FF)
C = (t < 0) ? 0 : 1
N = ((t & 0x0080) == 0) ? 0 : 1
Z = ((t & 0x00FF) == 0) ? 0 : 1
Another option for the d flag = 0 case is to reuse your ADC code. Just call the ADC code with M XOR 0xFF (for 8-bit values, this is equal to 255-M). In other words:

SBC #NUMBER

gives exactly the same results (A register, and N, V, Z, and C flags) as:

ADC #255-NUMBER

assuming that, upon entry, the D flag was 0, and the same value of the A register and C flag were used in each case.
bruce_lee
Posts: 8
Joined: 18 Jul 2008

Post by bruce_lee »

cheers guys appreciate the help :)
Post Reply