5

I'm making a 6502 emulator and I'm stuck (or I think I am at least) already at the beginning (implementing the ADC operation). The problem is that I have to determine if there's a carry or an overflow. The thing is, I can't really grasp the difference between them in my implementation. I know that a carry is when there's a 9th bit present after the operation, and I know that an overflow happens when the result is bigger than 255. Doesn't this make determining the carry AND the overflow flag the same thing?

if(result > 255) { 
    carry = 1;
    overflow = 1;
} else { 
    carry = 0; 
    overflow = 0;
}

Is this not correct? And if it isn't, what is correct and why?

ZimZim
  • 3,291
  • 10
  • 49
  • 67
  • http://www.righto.com/2012/12/the-6502-overflow-flag-explained.html – arcy May 30 '13 at 21:23
  • Thanks. I skimmed the thing as I have no time to read it in detail at the moment, and this is what I've understood. Basically, I was correct about the carry. If the result is above 255, there's a carry. When there's an addition and the number is negative, or there's a subtraction and the number is positive, there's an overflow (when using 8 bit signed bytes). Is that correct, or have I missed something? Anyway, thanks, I'll look more into it tomorrow. – ZimZim May 30 '13 at 21:49
  • 4
    IMO, if you don't have time to read it in detail, then you don't have time to program the emulator. An emulator is all about the detail, it's tedious and time-consuming, there isn't any big shortcut. – arcy May 30 '13 at 22:18
  • Don't worry. It was like midnight when I asked this question and got your reply, i.e. I just skimmed the article before I went to bed. I do have time, especially since summer holiday is coming, but yeah, I just mentioned that because I was about to get off the PC. – ZimZim May 31 '13 at 07:46
  • 1
    see also [The Overflow (V) Flag Explained](http://www.6502.org/tutorials/vflag.html) – Core Jun 01 '13 at 00:14
  • The overflow flag is set when an `adc` or `sbc` crosses the `7F-80` boundary. – puppydrum64 Dec 16 '22 at 12:52

1 Answers1

14

The overflow flag indicates when the sign of the number has changed improperly. So there is overflow if you add two positive numbers and get a negative result. There is also overflow if you add two negative numbers and get a positive result.

You can't get overflow when adding two numbers of different signs because the range doesn't allow it. The smallest positive plus the largest negative is 0 + (-128), which fits fine — 0 plus anything that fits in 8 bits will obviously fit in 8 bits. The smallest negative plus the largest positive is -1 + 127 = 126. Which fits.

(EDIT: and even with carry, 0 + -128 + 1 = -127, which fits, and -1 + 127 + 1 = 127, which fits)

So overflow is set if two inputs with the same sign produce a result with a different sign. Otherwise it is clear.

You can express that as a simple bitwise operation on the sign bits. Suppose you've got a + b = c.

a ^ b

will have a 1 in the sign bit if the signs were different. You want to know the opposite of that. So:

~(a ^ b)

gives a 1 in the sign bit if the signs were the same. That's the first part of the test covered. Supposing a and b had the same sign, you can test c against either of them. This time you do want to test for difference, so that's just:

a ^ c

You need the tested bit to be set in both parts of the test, so you can combine those with a binary and (leaving lots of brackets in to link to the verbal reasoning):

(~(a ^ b))&(a ^ c)

You only want the sign bit, so mask off that:

(~(a ^ b))&(a ^ c)&0x80

That'll evaluate to 0x00 if the overflow flag should be clear and 0x80 if it should be set. So just shift that into place.

(aside: though on a 6502 lots of instructions set flags and only one exposes the status register, so emulators often keep the flags separately in any convenient form and compose the status register on demand, in which case you wouldn't bother shifting and composing, you'd just store that result)

Tommy
  • 99,986
  • 12
  • 185
  • 204