Question

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?

Was it helpful?

Solution

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top