SBC and carry flag

Let's talk about anything related to the 6502 microprocessor.
Post Reply
modem
Posts: 3
Joined: 22 Dec 2022

SBC and carry flag

Post by modem »

I'm playing with Klaus2m5's 6502 test suite and have run in to some behaviour in the SBC tests that has me pulling my hair out. I'm running the tests in a simulator I've built around Omar's modified version of the fake6502 library.

A lot of confusion around ADC/SBC seems to be around the overflow flag, however I've found the carry flag equally confusing for a particular case.

What should be the result of:

Code: Select all

clc
lda #0
sbc #$ff
?

At first glance I thought it would be A=0, C=1. Klaus' tests are looking for A=0, C=0. Surely the carry flag should be set because we have to borrow a bit to subtract $ff from it?

Then I thought about it as a signed number, where $ff has the value -1. 0 - (-1) = 1, so wouldn't the result be A=1, C=0?

I've run this through a few of the web based simulators and they all concur with A=0, C=0.

However, fake6502 (or at least the version I use) returns A=0, C=1.

I'm loathe to start fiddling with my simulator until I can understand what the behaviour should be - what am I missing?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: SBC and carry flag

Post by GARTHWILSON »

modem wrote:
At first glance I thought it would be A=0, C=1. Klaus' tests are looking for A=0, C=0.
0 & 0 is correct.
Quote:
Surely the carry flag should be set because we have to borrow a bit to subtract $ff from it?
In the case of subtraction, think of C as a borrow-not flag.  Normally a multi-byte subtraction will start with C set, meaning you have not borrowed yet.  What you did however was to start with it clear; so 0 minus $FF is 1 (because it will borrow from the next-most significant byte, assuming there will be one); and then with C clear, it subtracts another one, leaving you with 0.  It clears the C flag indicating that it had to borrow to subtract FF from 0 (ie, make it $100 minus $FF); but you already had it clear.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
MichaelM
Posts: 761
Joined: 23 Apr 2012
Location: Huntsville, AL

Re: SBC and carry flag

Post by MichaelM »

The operation of the carry flag in the 6502 architecture is like an active low borrow flag. In other words, when the carry is 0, a borrow has occurred.

The operation of the SBC instruction is: A = A + ~M + C. In other words, the contents of the accumulator are added to the 1's complement (bit wise complement) of the operand, M, and then the value of the C flag is added. If this operation generates a carry out of the msb of the sum, then the carry flag is set (1) after the instruction, otherwise the carry flag is cleared (0).

Your prescribed instruction sequence is equivalent to the following: 0 + ~FF + 0 = 0 + 0 + 0 = 0 with no carry from the msb of the sum. Therefore, following the instruction sequence given in your post: A = 0, and C = 0.

Edit: as usual Garth beat me to the answer while I was struggling to get the instruction sequence loaded into my py65 model. :D
Michael A.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: SBC and carry flag

Post by barrym95838 »

SBC used to be confusing for me too. But a couple of decades ago I encountered a trick that always works for me, at least for 6502 programming ... in binary mode, SBC #num executes exactly the same in every way as ADC #~num (one's complement). So, when I saw your example, I mentally converted the SBC #$FF to ADC #$00 and the correct accumulator and flag results became obvious. Decimal mode is a somewhat different beast, but that's a more complex adventure ...
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
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: SBC and carry flag

Post by Dr Jefyll »

barrym95838 wrote:
I mentally converted the SBC #$FF to ADC #$00
Yup. And that's even how the chip works internally. This is not an exaggeration or an analogy. ADC and SBC are the same in every way, except that for SBC the chip inverts all the bits of the memory operand before the ADC occurs.

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: SBC and carry flag

Post by BigEd »

(That's how I think of it too, much of the time. But note, as Mike does, that decimal mode applies a quite different correction for SBC. Decimal subtract bugs are probably the last ones to shake out of any given model!)

(Also worth noting, Klaus' tests will always be correct, because they are tested on real chips. One might wonder why the result is what it is, but it always will be the right result.)
modem
Posts: 3
Joined: 22 Dec 2022

Re: SBC and carry flag

Post by modem »

Many thanks to all, those explanations were very helpful.

The bug in my thinking was that I was using twos-complement and carry rather than ones-complement.

The bug in my simulator is that it was using subtraction rather than faithfully reproducing what the real chips do. The value was pulled from memory into a 16 bit variable which appears to cause unintended consequences. I need to dig deeper to find out why but for now masking out the high byte gets through test suite $29 which is what was failing.
BigEd wrote:
Also worth noting, Klaus' tests will always be correct
That is exactly what I needed to hear - and now I can approach the failing decimal ADC/SBC tests with this in mind.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: SBC and carry flag

Post by barrym95838 »

Don't peek unless you want to, but I offered something a few years back which seems to do the trick:

viewtopic.php?p=37758#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)
modem
Posts: 3
Joined: 22 Dec 2022

Re: SBC and carry flag

Post by modem »

barrym95838 wrote:
Don't peek unless you want to, but I offered something a few years back which seems to do the trick:

viewtopic.php?p=37758#p37758
Thanks Mike, that patch works beautifully in my fork of fake6502 and I'm happy to report that my simulator passes the test suite!
Post Reply