These are algorithms to compute the overflow, carry, and half-carry (Z80 family) flags for addition and subtraction operations, without the use of branches.
They are designed to not require extra bits in the result computation, so that they can be templated to larger-sized types, and be used even with the largest type a given machine is capable of using.
Of course, to template these, you will need a portable way to extract the highest bit of a given integer type for the overflow and carry masks, eg:
natural sign = (natural(0) - 1 >> 1) + 1;
In the below examples, natural can be any type from uint1 to uintmax. boolean has the same behavior as bool: output = input ? true : false — that is to say, value & bit will subtract a desired bit, rather than value >> bit – 1 & 1.
auto adc(natural target, natural source, boolean carry) -> uint8 {
natural result = target + source + carry;
natural carries = target ^ source ^ result;
natural overflow = (target ^ result) & (source ^ result);
flag.overflow = overflow & sign;
flag.carry = (carries ^ overflow) & sign;
flag.halfCarry = carries & 16; //Z80
return result;
}
Nearly all processors implementation subtraction via borrow. Certain CPU vendors have confused this, and named their implementations SBC (subtract with carry), even though that is a different operation. A notable example here is the Toshiba TLCS900H.
auto sbb(natural target, natural source, boolean carry) -> uint8 {
natural result = target - source - carry;
natural carries = target ^ source ^ result;
natural overflow = (target ^ result) & (source ^ target);
flag.overflow = overflow & sign;
flag.carry = (carries ^ overflow) & sign;
flag.halfCarry = carries & 16; //Z80
return result;
}
auto sbb(natural target, natural source, boolean carry) -> uint8 {
natural result = adc(target, ~source, !carry);
flag.carry = !flag.carry;
flag.halfCarry = !flag.halfCarry;
return result;
}
auto sbc(natural target, natural source, boolean carry) -> uint8 {
natural result = target - source - !carry;
natural carries = target ^ ~source ^ result;
natural overflow = (target ^ result) & (source ^ target);
flag.overflow = overflow & sign;
flag.carry = (carries ^ overflow) & sign;
flag.halfCarry = carries & 16; //Z80
return result;
}
auto sbc(natural target, natural source, boolean carry) -> uint8 {
return adc(target, ~source, carry);
}
BSNES is an open source SNES emulator (Super Nintendo Entertainment System) for Windows, Mac, Linux, Android and IOS devices that focuses on performance, accuracy, friendly UI and special features.
Experience all your favourite Super Nintendo Famicom games from the past with BSNES, the best and most popular SNES emulator available to date.