6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 9:03 pm

All times are UTC




Post new topic Reply to topic  [ 41 posts ]  Go to page Previous  1, 2, 3
Author Message
 Post subject:
PostPosted: Wed Jan 26, 2011 6:36 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Glad you fixed it - I was wondering if I'd try to run two simulators and compare traces. Bruce has written a good tutorial about the V flag.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jan 29, 2011 11:55 am 
Offline

Joined: Wed Oct 27, 2010 1:28 pm
Posts: 25
Location: Valladolid (Spain)
Sorry for the bad news, but the emulator is still buggy.
This time I tried the Apple 1 assembler from http://www.sbprojects.com/projects/apple1/a1asm.htm and it hangs after the "AUTO" command.

Because I wasn't sure if the assembler was OK I wrote another A1 emulator using the 6502 core of Marat Fayzullin (from "mame" code) and tested the assembler. It ran without problems. So, I guess there are still some bugs around in your emulator.

My emulator can be downloaded from here: http://www.ele.uva.es/~jesus/6502/a1.tgz

It is not very accurate regarding the Apple I, but the 6502 emulation code is well tested. You can merge this code with your CPU emulator and compare results in order to hunt for bugs...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 30, 2011 11:02 pm 
Offline

Joined: Wed Oct 27, 2010 1:28 pm
Posts: 25
Location: Valladolid (Spain)
I got the time to do the emulator comparison myself, but it was harder than I though. I found the error while executing a RTS instruction:
Code:
$9132 rts          A =  $8D  $00|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9133 lda  #$AE    X =  $04  $10|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9135 bne  $913D   Y =  $00  $20|00 00 00 00 00 90 00 90.00 90 00 00 00 00 00 00
$9137 lda  #$A0    S =$1.FB  $30|00 00 00 00 00 00 00 00.00 00 00 00 00 00 C1 D5
$9139 bne  $913D   PC=$9132  $40|D4 CF 8D 00 00 00 00 00.00 00 00 00 00 00 00 00
$913B lda  #$8D              $50|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$913D jmp  $FFEF   .V_...ZC  $60|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9140 pha                    $70|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9141 lda  #$A4    - stack-  $80|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9143 jsr  $FFEF   $00 $00   $90|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9146 pla          $00 $00   $A0|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$9147 jsr  $FFDC   $00 $00   $B0|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$914A tya          $00 $00   $C0|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$914B jmp  $FFDC   $00 $00   $D0|00 00 00 00 C1 00 00 00.00 00 00 00 00 00 00 00
$914E cld          $90 $80   $E0|00 00 00 00 00 00 00 00.00 00 00 00 00 00 00 00
$914F ldy  #$00    $94 $A6   $F0|E8 03 0A 00 00 00 92 91.00 00 00 00 00 06 00 10

Breakp: 9132    Clocks: 6280468

[Command,'?']-> e
Error
Before
    PC=9132 A=8D X=04 Y=00 S=FB P=63
Op-Code: 60
After: correct
    PC=94A7 A=8D X=04 Y=00 S=FD P=63
After: bad
    PC=A695 A=8D X=04 Y=00 S=FD P=63

The return address is bad, but this was the second time this RTS was executed, the first time it was OK. I'm just comparing the registers of the emulated CPUs and, therefore, errors related to stack can have passed unnoticed. I guess the problem is the way 16-bit addresses are pushed into/pulled from the stack. I think you are pushing the LSB first, and a real 6502 will push the MSB first. As long as the RTS returns from an address pushed by a JSR instruction the PC is OK, but the assembler could have pushed a return address using PHA instructions and then executed an RTS.

I hope this can help to solve the bugs of the emulator. I like it because of its compactness...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Jan 31, 2011 9:37 pm 
Offline

Joined: Wed Oct 27, 2010 1:28 pm
Posts: 25
Location: Valladolid (Spain)
jesari wrote:
... but the assembler could have pushed a return address using PHA instructions and then executed an RTS.


That's exactly what the assembler is doing:
Code:
        LDA     .JUMPS+1,Y
        PHA
        LDA     .JUMPS,Y
        PHA
        ...
        RTS
.JUMPS  .DA     DIR_AS-1
        .DA     DIR_AT-1
        ...

... And I found another bug. This time regarding the Carry flag and SBC.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 01, 2011 7:26 am 
Offline

Joined: Fri Dec 31, 2010 5:05 am
Posts: 9
I think I fixed JSR/RTS, and SBC is probably still broken but in a different way ;)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Feb 02, 2011 8:35 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
I collected some links to various 6502 test suites on the visual6502 wiki.

Cheers
Ed

Edit: oops, I see I already linked to that in this very thread. Sorry for the useless repetition!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Feb 02, 2011 11:10 pm 
Offline

Joined: Wed Oct 27, 2010 1:28 pm
Posts: 25
Location: Valladolid (Spain)
After trying to understand how the BCD really works on the 6502 I decided to make truth tables for the ADC and SBC instructions using a real 6502 (NMOS version). The tables can be downloaded from here:
http://www.ele.uva.es/~jesus/6502/bcd.zip
These tables include all the possible input values (2^17 cases, not only the valid BCD ones) and the resulting N,V,Z and C flags. This information can be useful for accurate emulator development.
On a NMOS 6502 the N,V and Z flags doesn't make much sense in BCD mode, but they behave in a deterministic way. Things can be different on a 65C02 or 65816, but, unfortunately I only got NMOS chips. The source code of the tests is included in the ZIP file.
The only emulator I tested versus the real chip was that of Marat Fayzullin. The resulting value in accumulator for ADC was OK, but only the C flag was changed.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Feb 03, 2011 8:33 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Thanks for the zip file.

Mike's py65 has 100% accurate BCD emulation (of the NMOS 6502), and Bruce's documents are 100% accurate too.

I think few emulators are completely accurate in this respect - and if they wish to be, they need to be decisive and explicit as to chip they accurately emulate! They might choose to be accurate only with respect to the manufacturer spec, in which case they may not get all flags right in all cases. As you say, these things are deterministic, for each chip design.


Last edited by BigEd on Fri Feb 04, 2011 1:21 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Feb 03, 2011 10:31 pm 
Offline

Joined: Wed Oct 27, 2010 1:28 pm
Posts: 25
Location: Valladolid (Spain)
Hi, Happycube.
I fixed the ADC/SBC routines. See the code attached. I tested them against the values of a real 6502 and they are OK. I don't like the use of 16-bit arithmetic but that was the only way I found to get the carry flag correct. In decimal mode only the carry was tested OK (N,V and Z doesn't match the real ones, but they are junk anyway) and the accumulator does not match the real 6502 for non BCD values. Even with these flaws I think the routines are good enough for the emulation of all practical codes.

Code:
inline u8 do_adc(u8 reg, int n)
{
   if (flags & F_BCD) {
      u8 p1 = ((flags & F_CARRY) != 0) + (reg & 0x0f) + (n & 0x0f);
      u8 p2 = (p1 >= 10) + (reg >> 4) + (n >> 4);

      flags &= ~(F_CARRY);
      if (p1 >= 10) p1 -= 10;
      if (p2 >= 10) {flags |= F_CARRY; p2 -= 10;}
   
      return (p2 << 4) + p1;
   } else {
      u16 tmp=reg+n;
      if (flags & F_CARRY) tmp++;

      if (tmp&0x100) flags |= F_CARRY; else flags &= ~F_CARRY;
      tmp&=0xff;
      if ( !((reg^n)&0x80) && ((reg^tmp)&0x80) )
         flags |= F_OVF; else flags &= ~(F_OVF);
         
      return tmp;
      
   }
}

inline u8 do_sbc(u8 reg, int n)
{
   if (flags & F_BCD) {
      int nd = ((n >> 4) * 10) + (n & 0x0f);
      if (!(flags & F_CARRY)) nd++;
      int val = ((reg >> 4) * 10) + (reg & 0x0f) - nd;

      flags |= F_CARRY;
      if (val < 0) {flags &= ~F_CARRY; val += 100;}

      return ((val / 10) << 4) + (val % 10);
   } else {
      u16 tmp=reg+(n^0xff);
      if (flags & F_CARRY) tmp++;

      if (tmp&0x100) flags |= F_CARRY; else flags &= ~F_CARRY;
      tmp&=0xff;
      if ( ((reg^n)&0x80) && ((reg^tmp)&0x80) )
         flags |= F_OVF; else flags &= ~(F_OVF);
         
      return tmp;
   }
}


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Feb 04, 2011 1:38 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Hi Jesari
I've linkified my previous post: py65's code is BSD-licensed so you're relatively free to take from that. All the other emulators which get BCD mode right are GPL licensed, so you can only take their code into a GPL project.

I liked the ascii screenshot you gave in your emulator comparison post - so I looked a bit deeper, and I see it's from Marat Fayzullin's M6502 emulator library - looks like a great resource which has been mentioned a couple of times on this forum but isn't in the list of emulators on this site. I see that usotsuki announced a 65c02 version - all the above carrying a non-commercial-use license and therefore not suitable for GPL projects.

Cheers
Ed


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Feb 05, 2011 8:27 pm 
Offline

Joined: Fri Dec 31, 2010 5:05 am
Posts: 9
Jesari - thanks! I checked it in with attribution.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 41 posts ]  Go to page Previous  1, 2, 3

All times are UTC


Who is online

Users browsing this forum: No registered users and 19 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: