Simulieren-6502 - a WIP W65C02 simulation library

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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.
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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".
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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: Select all

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.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by BigEd »

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
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

I hadn't heard of that. I'll look into it. Thanks.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by BigEd »

Oh, I notice there's also errata in another appendix:
http://www.6502.org/tutorials/decimal_mode.html#D
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by Chromatix »

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: Select all

	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++;
		}
	}
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by barrym95838 »

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)
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by Druzyek »

Can you single step the test or somehow else figure out which two values it fails on?
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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.
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by Druzyek »

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.
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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.
Klaus2m5
Posts: 442
Joined: 28 Jul 2012
Location: Wiesbaden, Germany

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by Klaus2m5 »

Code: Select all

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
DerTrueForce
Posts: 483
Joined: 04 Jun 2016
Location: Australia

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by DerTrueForce »

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.
Klaus2m5
Posts: 442
Joined: 28 Jul 2012
Location: Wiesbaden, Germany

Re: Simulieren-6502 - a WIP W65C02 simulation library

Post by Klaus2m5 »

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
Post Reply