Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining carry and overflow flag in 6502 emulation in Java?

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?

like image 601
ZimZim Avatar asked May 30 '13 21:05

ZimZim


People also ask

What is the carry flag on 6502?

Addition on the 6502 The carry flag is used as the carry-in for the operation, and the resulting carry-out value is stored in the carry flag. The carry flag can be used to chain together multiple ADC operations to perform multi-byte addition.

How do you set an overflow flag?

The overflow flag is thus set when the most significant bit (here considered the sign bit) is changed by adding two numbers with the same sign (or subtracting two numbers with opposite signs).


1 Answers

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)

like image 147
Tommy Avatar answered Sep 18 '22 16:09

Tommy