how to set properly the flags v and c

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
how to set properly the flags v and c
by on (#44514)
Flags: overflown and carry!
I still don't get it!
I always thought overflow is caused by ... for example: we have an register accumulator (8bits wide) and then one operation is add some number to acc and in the addition process the result number is bigger than 8bits (0x1F0) so here the overflown was to be setted...
And carry :roll: well I guess it should work like in the old math classes!
How can I take care of it?

Comparisons:
On this kind of operations the way to set V C flag is different? (and even the sign flag too?)

thanks in advance

by on (#44518)
for ADC:

Carry is set if the addition resulted in an unsigned overflow (sum > 255), and is cleared otherwise (<= 255).

Overflow is set if the addition resulted in a signed overflow (sum > 127, or < -128), and is cleared otherwise (sum >= -128 and sum <= 127).

In an emu you probably have all your numbers as unsigned, so checking for Carry is pretty simple:

Code:
C = (sum > 0xFF);
A = (sum & 0xFF);


Overflow is a bit weirder if you're dealing with unsigned logic. The common way to do it is check to see if:

Positive + Positive = Negative
or
Negative + Negative = Positive

If either of those are true, you set V, otherwise you clear it. In this case "negative" just means that the high bit is set. So:

Code:
V = ((sum ^ val) & (sum ^ A) & 0x80) != 0;
C = (sum > 0xFF);
A = (sum & 0xFF);


where 'val' is the value being added to A, 'A' is the accumulator before addition, and 'sum' is the resulting sum of A+val+C.

-------------------------------
for SBC:

SBC logic is just ADC inverted. You can implement SBC with the following, and it will work perfectly (provided your ADC is implemented correctly:

Code:
void DoSBC(u8 val)
{
  DoADC(val ^ 0xFF);
}


Or if you want to implement SBC on its own:

C is set if the unsigned result was >= 0, and is cleared if the unsigned result was < 0.

V is set under same conditions as for ADC (result caused signed overflow). Logic to implement this with unsigned types:

Positive - Negative = Negative
Negative - Positive = Positive

Ways to implement this:

Code:
C = (dif >= 0);   // note 'dif' would have to be a signed type
C = (dif > 0xFF); // otherwise you can do this if 'dif' is unsigned

V = ((A ^ dif) & (A ^ val) & 0x80) != 0;


-----------------------------------------
for CMP/CPX/CPY

Do not change V at all.

C is set the same as it is for SBC -- however note that while SBC will subtract an extra 1 if C is clear, CMP/CPX/CPY never subtract that extra 1.

------------------------------------------
for ASL/LSR/ROL/ROR

C is set or cleared as a result of the bit shifted out.
V is unchanged.

-----------------------------------------
the N flag (sign / negative flag)

is just set if the high bit (bit 7: 0x80) of the result is set, and is cleared otherwise:

Code:
N = (result & 0x80) != 0;

by on (#44519)
thanks so much! :wink:

by on (#44521)
Quote:
I always thought overflow is caused by ... for example: we have an register accumulator (8bits wide) and then one operation is add some number to acc and in the addition process the result number is bigger than 8bits (0x1F0) so here the overflown was to be setted...

And carry well I guess it should work like in the old math classes!

Do you see how carry works just like you thought overflow should, if the value exceeds the available space, you have a carry out? That is, carry is for unsigned overflow. Since signed values are represented as negative values basically being carry+00000...-magnitude, you can see how having a carry from a signed addition doesn't tell you much useful.

by on (#44527)
Here is WedNESday's (pre Binary Translation)

(Accumulator and Databus are both unsigned and 8-bit)

Code:
if (Accumulator + Databus > 0xFF)
   CF = 1; else CF = 0;

temp = (signed char)A8 + (signed char)Databus + CF;
   if (temp < -128 || temp > 127)
      Overflow = 1; else Overflow = 0;


Here is WedNESday's (post Binary Translation)

Code:
seto OF
setc CF

(Puts on his shades) 8)

by on (#44553)
Disch told you everything, but this post should help you too:

http://nesdev.com/bbs/viewtopic.php?t=637&highlight=flag