6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 6:09 am

All times are UTC




Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Sep 09, 2019 9:40 am 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
Greetings all,

I've been building on a WDC 65C02 simulation in C/C++ for a little while now, and while it definitely needs more work, I think it's in good enough shape to make known. It's available here: https://github.com/TheTrueForce/simulieren-6502. Questions and comments are welcome.

This passes most of Klaus' NMOS 6502 test suite, with the exception of the decimal mode tests, and the BRK test.
I've determined that the BRK test fails because I've implemented the 'C02 version of BRK, which behaves slightly differently to the NMOS one.
Decimal mode failing is probably because it doesn't handle decimal mode in quite the same way as the actual hardware. Simulieren converts the addends to binary, adds, and then converts back to BCD. I gather that real hardware just adds and then does some sort of adjustment on the result. Decimal-mode SBC is completely out the window, because I've implemented SBC as ADC, but with an inverted input. This works for binary mode, but obviously does not for BCD.
It does not pass many of the 'C02 tests, however, and seems to hang before completing the whole battery, for some reason. Like I said, it needs more work.

My approach with this has been to make it simulate the 'C02 only, and not concern myself with cycle-accuracy. There are two routines that are not implemented in the simulation, and these are to read and write memory. There are calls available to whatever is hosting the sim, to reset the simulated MPU, have it execute the next instruction, and send interrupts. Because this is written in C, the registers can be accessed from other modules using an extern declaration. (Simulieren is written in C, but it's a .cpp file because the Arduino uses C++, and I didn't want to bother having to deal with interfacing C to C++).

I made this because I still haven't given up on trying to make a 65xxx-based handheld, but I've also gotten fed up with trying to design around certain properties of the hardware in question.
The '816s multiplexed data bus, the lack of interfaces of the '265, WinCUPL being ancient, broken and painful are the main ones. The fact that dedicated SPI hardware simply does not exist is also very irritating, because I plan to use that as my main internal and external expansion interface, and bit-banging something that central is just unacceptable to me.
I have an Arduino Due available, which has on it a SAM3X8E. This is an ARM-based microcontroller with 96KB of RAM, 512KB of Flash, and a large suite of very nice peripherals. If I could drop an '816 core into that in place of the ARM, I suspect it would be a very, very nice machine for my purpose. I can't replace the ARM core, but I can program it to simulate a 65C02(probably an '816 as well, but I haven't tried that yet.)
But regardless, I'm going to build Ittiara 4 around an Arduino Due, and this is the core of that but since it's likely to be useful for so much more than just that(especially when I've worked out the kinks), I've made it public so it can at least be inspected. I can't guarantee its usefulness, or that I'll work on it with any sort of regularity(Life takes precedence), but I've got it into a state that I think is somewhat acceptable.

This is my effort. I hope it's useful and acceptable, and I plan for it to become better.

EDIT to add the URL. Many thanks to BigEd for pointing out its absence.


Last edited by DerTrueForce on Mon Sep 09, 2019 10:34 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Mon Sep 09, 2019 12:30 pm 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
I just did a bit of poking around with 'C02 test $0B, and it turns out I was pushing PC and PS in the wrong order, and pulling it wrong in RTI as well, but consistently so, which masked the bug. This also had a side-effect of fixing the 6502 test $0B, which was the BRK test that I'd put down to "wrong processor".


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 08, 2019 7:16 am 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
I've come back to the project after a long stretch away from it, and I've been butting my head up against decimal mode for a couple days now, and SBC is proving incredibly painful. None of my implementations have passed test $2A, mostly because of incorrect flags coming out of the SBC.
I think I've got ADC down, but decimal-mode SBC has defeated me. I get the correct result, but sometimes the wrong carry is generated, and I can't figure out what is going on.

I'd had enough of trying to make this particular test happy on my own, so I went through the list of simulators , and found mos6502, which already passes Klaus' test suite. I wired in its SBC routine, and it also doesn't work for some reason, so I think I may well have discovered a bug in the test suite.
Looking at this output:
Code:
regs Y  X  A  PS PCLPCH
01F7 FF 0E 01 39 62 3F 7B 52 3E
000C 01 00 98 99 00 02 01
0200 2A 00 00 98 01 FF 00 01
press C to continue or S to skip current test
it seems that it's ANDing the status register with $01 and comparing it against $02(second last on the third line). This will never be true, so I suspect there's a logic error somewhere in test $2A.
I really don't know what to do about this except ignore the decimal mode tests and continue with the 'C02 tests(since $2A is the only one that's failing).

To be clear, I'm leaving the wired-in routine out of the git repo, because I want to keep that "all my own work" for now.


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 08, 2019 7:54 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
How very odd. Have you tried Bruce's decimal test? In the past, I've found that a more user-friendly way to understand any oddity. It is at least a second opinion.
http://www.6502.org/tutorials/decimal_mode.html#B


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 08, 2019 10:55 am 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
I hadn't heard of that. I'll look into it. Thanks.


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 08, 2019 11:21 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Oh, I notice there's also errata in another appendix:
http://www.6502.org/tutorials/decimal_mode.html#D


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 09, 2019 1:08 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
My approach to implementing decimal-mode SBC is to simply subtract the operand from 0x99, then continue as for decimal-mode ADC. It passes the test suite.
Code:
   void adc(uint16_t ea) {
      uint8_t B = read(ea);
      if(!D) {
         // binary add with carry
         uint16_t c = A+B+C;
         uint16_t v = (int8_t) A + (int8_t) B + C;
         A = (uint8_t) c;
         N = A >> 7;
         V = N ^ (v >> 15);
         Z = !A;
         C = c >> 8;
      } else {
         // decimal mode is fun
         uint8_t l = (A % 0x10) + (B % 0x10) + C;
         uint8_t h = (A / 0x10) + (B / 0x10);
         if(l >= 0x0A) { l = (l - 0x0A) & 0x0F; h++; }
         if(h >= 0x0A) { h -= 0x0A; C = 1; } else { C = 0; }
         uint8_t s = h * 0x10 + l;
         N = s >> 7;
         V = !(((A ^ B) >> 7) && ((A ^ s) >> 7));
         Z = !s;
         A = s;

         if(COUNT_CYCLES)
            cycles++;
      }
   }

   void sbc(uint16_t ea) {
      uint8_t B = read(ea);
      if(!D) {
         // binary subtract with borrow
         uint16_t c = A-B-!C;
         uint16_t v = (int8_t) A - (int8_t) B - !C;
         A = (uint8_t) c;
         N = A >> 7;
         V = N ^ (v >> 15);
         Z = !A;
         C = !(c >> 15);
      } else {
         // decimal mode is fun
         B = 0x99 - B;
         uint8_t l = (A % 0x10) + (B % 0x10) + C;
         uint8_t h = (A / 0x10) + (B / 0x10);
         if(l >= 0x0A) { l = (l - 0x0A) & 0x0F; h++; }
         if(h >= 0x0A) { h -= 0x0A; C = 1; } else { C = 0; }
         uint8_t s = h * 0x10 + l;
         N = s >> 7;
         V = !(((A ^ B) >> 7) && ((A ^ s) >> 7));
         Z = !s;
         A = s;

         if(COUNT_CYCLES)
            cycles++;
      }
   }


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 09, 2019 1:51 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1950
Location: Sacramento, CA, USA
I wrote an NMOS flavored BCD patch for Mike Chambers' code which I placed in the public domain. You are invited to fiddle with it at your leisure.

viewtopic.php?f=2&t=2052&p=37758&hilit=chambers#p37758

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 14, 2019 3:17 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Can you single step the test or somehow else figure out which two values it fails on?


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 15, 2019 6:49 am 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
Klaus' test suite produces output when a test fails, and that output contains most if not all of the information regarding the failure. However, it makes no attempt to make that easy to read. I have to refer to the assembler listing to make any sense out of it, which means that if a test does something wierd, I have a problem.

Speaking of which, in the 65C02 tests, the TRB zp/abs test seems to use the wrong locations for expected/actual results. I really don't know what to make of it. I see hard-coded offsets in the code, and there are (different) locations defined for those purposes, and they have symbols defined for them, so the fact that they're not being used strikes me as very strange.

I really don't want to have to debug the test suite that I'm using to debug my sim. That seems like it'd lead to second-guessing myself, and from there to insanity, since I have been unable to get the test suite to run on a real W65C02 at all, for some reason.


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 15, 2019 5:14 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Could you get your simulator to output all 256x256x2 combinations of SBC with all input values and carry inputs? It would be easy to generate the same file with a different simulator and compare. If you zip it, I could compare it to the output from my simulator which passes Klaus' test if that is useful.


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 15, 2019 9:08 pm 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
Now that's an idea I'd not thought of. Seems worth a shot. I can even test it against a real one. Good idea; I'll do that.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 16, 2019 8:10 am 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
Code:
regs Y  X  A  PS PCLPCH
01F7 FF 0E 01 39 62 3F 7B 52 3E
000C 01 00 98 99 00 02 01
0200 2A 00 00 98 01 FF 00 01
press C to continue or S to skip current test


The ADC/SBC decimal test is trying to add carry in=1, op1 (accu)=0, op2 (memory or #)=98 and expects accu=99 with carry out=0. Then it will subtract the decimal two's complement of op2=01 from op1=00 and carry in=1 and expects the same result (a=99, c=0). Remember that carry = not borrow in the 6502. So the expected SBC result is 99 with a borrow in this case.

To properly diagnose what went wrong one needs the listing to see what is happening just before the trap address. Assuming it was the SBC flags trap that failed the actual carry is in the stacked accu=01. So the carry is set, but it should be clear to indicate a borrow.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 16, 2019 9:49 am 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
That is the ADC test. I think it passed that at one point, and got into the SBC test, but I somehow managed to put it back to being broken. I gave up after that, as I spent a while battering away at it with no effect.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 16, 2019 12:21 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
Sorry to have confused you. The earlier version of my post contained the assumption, that it is failing in the ADC section of the test. That was wrong because the test is doing both with the same op1 and result. The only way to tell wether it is ADC or SBC is the trap address which I can't verify as I don't have the listing. The trap address really depends on your configuration of the test.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


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

All times are UTC


Who is online

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