BCD and flags

want to talk about MESS/model b/beebem/b-em/electrem/elkulator? do it here!
User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

BCD and flags

Post by Matt Godbolt » Fri Oct 10, 2014 3:06 am

Hey y'all

Tom Seddon pointed me at a suite of 6502 tests that I've gotten working in jsbeeb.

The first failure I've found is - surprise, surprise - in the handling of BCD flags. I'd borrowed quite heavily from the excellent b-em (v2.2) and I think I use the same logic, but that seems to give the wrong answers.

In this case, the test is for

Code: Select all

LDA #0
SED
ADC #11
and according to the test suite this should clear the zero flag. In my implementation I see zero set.

Code: Select all

before  11  00 b1 6c nv0bDiZc fd
after   11  11 b1 6c nv1BDiZc fd
right   11  11 b1 6c nv1BDizc fd
Using Visual 6502 seems to back up the clearing of the zero flag: http://www.visual6502.org/JSSim/expert. ... a&steps=16

b-em (and thus jsbeeb...) sets the zero flag IFF the binary result pre-BCD-fixup is zero. It never clears the zero flag; and I think that's where the mistake is. Certainly fixing this up gets me further (and into the world of the N flag being wrong, but that's another story).

Am I missing something? I'm wary of blindly following this test suite, but Visual 6502 and "reason" seem to back me up. I'm well aware that reason needs to be abandoned when doing BCD though :)

User avatar
richardtoohey
Posts: 3720
Joined: Thu Dec 29, 2011 5:13 am
Location: Tauranga, New Zealand
Contact:

Re: BCD and flags

Post by richardtoohey » Fri Oct 10, 2014 3:41 am

Hi, Matt.

Using a real Electron, Starmon debugger.

I clear the Status Register - so all flags zeroed.

A SR 0

Code: Select all

-V.BDIZC
00000000
LDA #&00 gives ZF set:

Code: Select all

-V.BDIZC
00110010
SED sets BCD flag:

Code: Select all

-V.BDIZC
00111010
ADC #11 - zero and carry clear:

Code: Select all

-V.BDIZC
00111000
- Sign flag, V oVerflow, . not used, B Break, D Decimal arithmetic, I Interrupt, Z Zero, C Carry

Very much worth someone else checking - I'm not a Starmon wizard, but think I've followed the steps correctly (and the flags seem to update correctly as I single-step.)
Last edited by richardtoohey on Fri Oct 10, 2014 3:45 am, edited 1 time in total.

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Fri Oct 10, 2014 3:45 am

Thanks! That backs up both v6502 and the test suite (as I'd hoped!). I've found some c64 docs that seem to tally with what I see in v6502 here, so hopefully with that I can get all the tests passing!

Cheers again! :)

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 10, 2014 6:38 am

I had some fun recently getting Klaus Dormann's 6502 test suite to work on a Rasperry Pi port of Atomulator.
http://www.stardot.org.uk/forums/viewto ... =44&t=8653

This uses an ARM assember version port of the 6502 emulation code from Tom Walker's B-Em. So, the same code base I think.

Two separate bugs were discovered, which had been present in Atomulator for years:
- opcode E1 - SBC (ZP,X) - was missing
- the overflow flag was not correctly implemented on all SBC operations

Your bug sounds different, but I'd recommend trying the Dormann tests as well:
https://github.com/Klaus2m5/6502_65C02_functional_tests

Dave

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 10, 2014 7:29 am

This is the code currently used in Optima/Atomulator:
https://github.com/hoglet67/Optima/blob ... src/6502.c

Code: Select all

int adc_bcd(M6502* cpu, uint8_t temp) {
    //rpclog("Doing ADC BCD! %d", temp);
    register int ah=0;
    register uint8_t tempb = cpu->a+temp+((cpu->p & FLAG_C)?1:0);
    if (!tempb)
       cpu->p |= FLAG_Z;
    register int al=(cpu->a&0xF)+(temp&0xF)+((cpu->p & FLAG_C)?1:0);
    if (al>9) {
        al-=10;
        al&=0xF;
        ah=1;
    }
    ah+=((cpu->a>>4)+(temp>>4));
    if (ah&8)
        cpu->p |= FLAG_N;
    SET_FLAG(FLAG_V, (((ah << 4) ^ cpu->a) & 128) && !((cpu->a ^ temp) & 128));
    cpu->p &= ~FLAG_C;
    if (ah>9) {
        cpu->p |= FLAG_C;
        ah-=10;
        ah&=0xF;
    }
    cpu->a=(al&0xF)|(ah<<4);
}
This seems to have the "set only" behaviour for both Z and N.

The intuitively seems wrong to me, and also is counter to this reference:
http://www.6502.org/tutorials/decimal_mode.html#3.2.2

Looking at the SBC code, that includes the following line at the start:

Code: Select all

	cpu->p &= ~(FLAG_Z | FLAG_N);
So I guess this got missed out of ADC.

I'm surprised the Dormann tests didn't pick this up. Maybe I'll try to get your test suite running on the Atom as well.

Dave

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 10, 2014 7:37 am

Just found this in the comments of the Dormann tests:
Decimal ops will only be tested with valid BCD operands and ; N V Z flags will be ignored.
So that explains why his test suite didn't pick this up.

I wonder why he chose not to test this aspect, given the tests seem pretty comprehensive everywhere else.

Edit: Reading:
http://www.6502.org/tutorials/decimal_mode.html#4.1

It seems like different variants of the 6502 implement the N and Z flags differently.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Fri Oct 10, 2014 11:50 am

Interesting!

My understanding is that the differences in BCD flags between revisions were limited to the usual CMOS vs NMOS where CMOS has the behaviour as exhibited on Vis6502 and NMOS has mostly rational sensible behaviour.

If anyone can find any literature describing the sticky-flag-bit behaviour that b-em uses that would be ace.

Also; thanks for the link to the Dormann tests: I'll definitely take a look at those next.

Back to "fixing" undefined opcodes for me for now!

User avatar
SarahWalker
Posts: 1207
Joined: Fri Jan 14, 2005 3:56 pm
Contact:

Re: BCD and flags

Post by SarahWalker » Fri Oct 10, 2014 4:49 pm

Matt Godbolt wrote:If anyone can find any literature describing the sticky-flag-bit behaviour that b-em uses that would be ace.
There isn't any, it's a bug.

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Fri Oct 10, 2014 4:59 pm

Thanks Tom! It's so hard to be certain: BCD is so wacky I'd be prepared to believe anything!

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 10, 2014 5:45 pm

Matt,

If you compare the ADC and SBC #defines in 6502.c in the B-Em sources, you'll see that the SBC code includes the following line:

Code: Select all

    p.z = p.n = 0;
which is missing from the ADC code.

You just need to add it back in, and the sticky flags will be fixed.

I'll do the same for the Optima sources, and Kees (if you are listening) will need to do the same for the Atomulator sources.

Very interested what further errors (if any) you see from your test suite.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Fri Oct 10, 2014 6:16 pm

Thanks hoglet; I went with more of a rewrite in the end https://github.com/mattgodbolt/jsbeeb/c ... 1a8fc42cbf which simplified and fixed some more things for SBC too.

Cheers all, really appreciate the help here!

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Sat Oct 11, 2014 4:29 pm

I've been messing around with the BCD flags in Optima this afternoon.

I've been using Bruce Clark's BCD Test Suite from here:
http://www.6502.org/tutorials/decimal_mode.html#B

This is an exhaustive test, that tests all possible combinations of input to ADC and SBC in BCD mode, and checks the result, plus the C, Z, N and V flags.

I ported this to the Atom, then modified it a bit so that it prints lots of useful details about the failure.

I've eventually got this passing on both Optima and on Atomulator, but there were three separate bugs.

Matt, you should definitely use this test, if you want to confirm your JS 6502 is exactly the same as a real 6502.

Kees, we should figure out how to get these BCD fixes into the latest Atomulator code base....

Here's the final 6502.c file I ended up with:
6502.zip
(8.16 KiB) Downloaded 60 times
Here's the test program:
BCDTEST.zip
(589 Bytes) Downloaded 58 times
And here's what you should see with the fixes in place:
bcdtest.png
You should also confirm the DORMANN tests still work.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Sun Oct 12, 2014 11:34 pm

Sweet: thanks hoglet; I'll definitely add those tests too!

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Wed Oct 15, 2014 3:02 am

I've now got both the Dormann and the "test suite" tests all passing - yay. I'd like to get your tests in too hoglet, but two quick things:

1. How might I actually run the tests? I don't recognise the file format :) - where might I load it and what address to execute? (silly question I suppose)

2. Once I have it working, would you mind if I added the binary to my project (with appropriate license?) so I can make it part of the automated tests?

Thanks in advance! Matt :)

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Wed Oct 15, 2014 6:35 am

Matt Godbolt wrote:1. How might I actually run the tests? I don't recognise the file format :) - where might I load it and what address to execute? (silly question I suppose)
The file is an Acorn Atom ATM file, which has a 22 byte header on the front.
http://members.casema.nl/hhaydn/SD-file ... o_the_card
On the Atom BCDTEST loads and executes from #2900. But it uses several Atom OS routines, so will need porting to the Beeb.

Let me clean it up, so it only uses OSWRCH, and post a version of the BeebASM source that will build for either the Atom or the Beeb.

I've got a bit of spare time this evening to do this.
Matt Godbolt wrote:2. Once I have it working, would you mind if I added the binary to my project (with appropriate license?) so I can make it part of the automated tests?
This is fine by me.

Re: License, there was no license I could find with the original, so I assume it's in the public domain. All I did was make some minor changes to log the first failure. If you really need a license, you'll need to contact Bruce.

Dave

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Wed Oct 15, 2014 6:11 pm

Matt,

Here is a zip containing:
- BeebASM source code, that will build for the Atom or the Beeb
- BCDTEST_atom - an Atom ATM file
- BCDTEST_beeb - a Beeb raw file (no headers)
- BCDTEST.dsd - a Beeb disk image
clark_bcd.zip
(5.05 KiB) Downloaded 75 times
Happy to help if you hit any problems.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Thu Oct 16, 2014 2:38 am

Thanks Dave: I'm glad to say the tests passed first time - hooray!

Really appreciate you putting this together. I'll look at getting it to be part of the test process (in addition to the Dormann and the other test suite!)

I just got the 65c12 Dormann tests working too, so I'm now 99.9% sure I've got all the (functional) behaviour right. Timings are another thing, of course...

Cheers, Matt :)

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Thu Oct 16, 2014 7:09 am

Matt Godbolt wrote:Thanks Dave: I'm glad to say the tests passed first time - hooray!
I'm very impressed.

Is this the latest code?
https://github.com/mattgodbolt/jsbeeb/b ... er/6502.js
Matt Godbolt wrote: Really appreciate you putting this together. I'll look at getting it to be part of the test process (in addition to the Dormann and the other test suite!)
I just realized, this version only checks the original NMOS 6502.

Do you also need to check the 65C02/12 that is in the Master?

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Thu Oct 16, 2014 11:34 am

Yup that's the code.

I do also check the 65C12 using Dormann's tests but if you happen to have access to a real Master and can adapt your test I'd feel a lot more secure that things were just right if your tests worked for Master too!

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 17, 2014 6:25 pm

Matt,

I've updated the tests to auto-detect 6502 vs 65C02, and run the appropriate checks.

Latest code, and an .ssd file are here:
https://github.com/hoglet67/AtomSoftwar ... ests/clark

The autodetection is based on using the INC A operation ($1A) which is a NOP in the 6502, and is a valid operation in the 65C02 (which I'm sure you knew...)

I haven't run it on a real master yet....

Dave
Last edited by hoglet on Fri Oct 17, 2014 7:51 pm, edited 1 time in total.

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Fri Oct 17, 2014 7:14 pm

hoglet wrote: I haven't run it on a real master yet....
I have now, and it passes the tests.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Fri Oct 17, 2014 7:47 pm

Wow! Thanks so much Dave :)

I'll see if I can get this into the autotest suite for jsbeeb tonight! You're a star :)

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Sat Oct 18, 2014 10:17 pm

Well, it took a day longer than I thought (mainly due to accidentally ending up in the pub*), but it's running now...and finding issues with the ADC instruction! Yay :) Now to fix... first error is:

Code: Select all

TESTING ADC
V FAILED
EXPECTED: 40; ACTUAL: 00
INPUTS:
ACC = 79
OPERAND = 00
CARRY IN = 00
Will dig some more...the 65C02 Dormann tests pass, but they only test "valid" inputs and the 65C12 is a slightly different chip from the 65C02. I'm so glad you've tested this on a real Master too as it gives me confidence to match here and leave the Dormann tests should they differ.

Thanks! I'll keep you posted...

-matt

* or what passes for a pub in Chicago

User avatar
hoglet
Posts: 8679
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: BCD and flags

Post by hoglet » Sun Oct 19, 2014 6:48 am

Good stuff!

It's always nice when a test finds actual bugs.

As far as I understand from:
http://www.6502.org/tutorials/decimal_mode.html#A
the implementation of the V flag in BCD mode is identical between the 6502 and the 65C02.

Dave

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Mon Oct 20, 2014 7:03 pm

Right :) I've got ADC working now (yay) and I'm now working on SBC, which seems to do slightly unusual things (at least relative to the current implementation) with "invalid" BCD inputs.

User avatar
Rich Talbot-Watkins
Posts: 1556
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BCD and flags

Post by Rich Talbot-Watkins » Mon Oct 20, 2014 7:15 pm

SBC in BCD doesn't work exactly like ADC(val ^ 0xFF) in BCD too? (I have no idea, but I imagine if the binary version were wired like that, it ought to be using firing the same signals to the "random logic" part of the 6502 which performs the operation for either mode).

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Mon Oct 20, 2014 7:22 pm

Sadly not :(

First failure of that is:

Code: Select all

ACCUMULATOR FAILED
EXPECTED: 00, ACTUAL: 66
INPUTS:
ACC = 00
OPERAND = 00
CARRY IN = 00

User avatar
Rich Talbot-Watkins
Posts: 1556
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BCD and flags

Post by Rich Talbot-Watkins » Mon Oct 20, 2014 7:27 pm

Fairly early failure then :o

That's just madness. I don't think I'd like to even see how this is implemented at the silicon level...

User avatar
Rich Talbot-Watkins
Posts: 1556
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BCD and flags

Post by Rich Talbot-Watkins » Mon Oct 20, 2014 7:34 pm

Going back to my reasoning above though, the 6502 doesn't even have subtract as an operation in the ALU (it is synthesised entirely by a 1's compliment add), which means the BCD correction must have to deduce that the operand is actually "really" a subtract and do something different if so. I wonder if there's a more straightforward interpretation of all this?

User avatar
Matt Godbolt
Posts: 187
Joined: Mon Jul 31, 2006 10:02 am
Location: Chicago
Contact:

Re: BCD and flags

Post by Matt Godbolt » Mon Oct 20, 2014 7:36 pm

Seems like there should be. I'll have a play about...

Post Reply