6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue May 07, 2024 12:53 am

All times are UTC




Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Wed Dec 10, 2014 3:09 am 
Offline

Joined: Sun Nov 30, 2014 5:15 am
Posts: 18
I'm running a 6502 expression in a simulator and it's reporting that the overflow flag is getting set, even though I don't expect it to be set. Consider the following:

Carry flag is on.
acc = 0x7f

So I run the expression:

SBC #$ff

And the overflow flag gets set, and acc is 0x80.

I thought the way to calculate the V flag is to use the formula from here (http://www.righto.com/2012/12/the-6502- ... ained.html):

(M^result)&(N^result)&0x80

If I take the information supplied above and use it;

((0xff^0x80)&(0x7f^0x80))&0x80

I get 0, which means that the overflow flag is off.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 3:22 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
I believe that you should consider the operation that you are requesting in a decimal representation:

$7F => 127 decimal
$FF => -1 decimal

the operation you are performing is 127 - (-1) = +128 which can not be represented in an 8-bit register. Hence the V flag should be set. Furthermore, the value of $80 you are reporting being returned in A is equal to -128 not +128.

If your intention was to decrement the $7F value while the Cy is set, you should do an SBC #$01 instruction instead.

The overflow flag is a signed arithmetic flag. The method that I use to set the overflow flag is based on the carries into and out of bit 7. When there's a carry from bit 6 into bit 7 and no carry out of from bit 7, an overflow has occurred.

The other method uses the sign of the operands of an "addition". Subtraction by 2's complement can be accomplished by taking the 2's complement of one number and then adding it to the other number. In this situation, the 2's complement of $FF is computed by taking its complement, i.e. $00, and adding 1, which is done in your situation because the carry is set. Thus, the two's complement of $FF is $01. In this case, the sign of the first number ($7F) is a 0, i.e. positive, and the sign of the second number ($01) is also 0. However, the sign of the result ($80) is a 1, i.e. negative. Thus, an overflow occurred.

Hope this helps.

_________________
Michael A.


Last edited by MichaelM on Wed Dec 10, 2014 3:46 am, edited 4 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 3:33 am 
Offline

Joined: Sun Nov 30, 2014 5:15 am
Posts: 18
MichaelM wrote:
I believe that you should consider the operation that you are requesting in a decimal representation:

$7F => 127 decimal
$FF => -1 decimal

the operation you are performing is 127 - (-1) = +128 which can not be represented in an 8-bit register. Hence the V flag should be set. Furthermore, the value of $80 you are reporting being returned in A is equal to -128 not +128.

If your intention was to decrement the $7F value while the Cy is set, you should do an SBC #$01 instruction instead.


I suppose my question was more about understanding why Ken Shirriff's formula does not work on that expression. It has worked on everything else I've tried, but for some reason, it fails to calculate the V flag when the condition I stated is present.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 3:49 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
Bob:

I edited my response to include some other material that should make clear the reason. Please refer to the second part of of my previous response.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 3:56 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1928
Location: Sacramento, CA, USA
I haven't studied the issue in depth, but could this comment from Ken Shirrif's blog be an important clue, in reference to the add ones-complement nature of SBC?
Quote:
Anonymous said...
Thank you for the very informative article. I referenced it trying to figure out a problem in my emulator. One note that might be helpful to others is that in the "Formulas for the overflow flag" section it wasn't completely clear to me that in the "(M^result) & (N^result) & 0x80" formula, the N is ones-complement of the target, not the target. It took several readings and much comprehension to give that a try.
May 23, 2013 at 7:45 PM


Mike


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 4:10 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
That's only partially true.

In terms of the actual implementation of the 6502 ALU, the SBC instruction only complements the operand.

If this was the only action taken, the resulting operation would be a 1's complement subtraction, with the programmer being required to add in any carries from the most significant bit of the result in order to get the correct result. Further, there would essentially be two values of 0. A positive 0 consisting of all 0s, and a negative 0 consisting of all 1s.

However, the programmer is required to set the carry flag before subtraction (or the first subtraction of a multi-precision subtraction). This requirement allows the 6502 to compute the desired 2's complement difference.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 4:32 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1928
Location: Sacramento, CA, USA
My point is that ADC is (or at least should be) the heavy lifter, and it is the only one that needs to update the accumulator and set the flags.
I am saying this because, if I'm not mistaken, SBC is implemented as a trivial operation: ones-complement the operand and pass everything else unchanged straight to ADC for all the rest of the work. This method should even work in decimal mode if the nines-complement (of the operand) is used instead, right?

Mike

[Edit: This technique can be utilized at the emulator code level or the hardware level with equal effectiveness. I don't see any reason for SBC to be any more complicated than, for example:
Code:
sbc() {
    operand = D_FLAG ? 0x99-operand : ~operand;
    adc();
}

Anything more is a waste of effort, IMO.]


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 5:17 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
Your suggestion is correct, but by setting the carry, the value passed to ADC is a 2's Complement value. It is the sign bits of the values passed to add ADC that should be used for determining overflow.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 10, 2014 7:12 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8432
Location: Southern California
This topic should clarify it:
viewtopic.php?f=1&t=62

_________________
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?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC


Who is online

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