1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Eliminate branches from SBCD.

This commit is contained in:
Thomas Harte 2022-05-12 15:18:03 -04:00
parent c6d84e7e60
commit 79c5af755f

View File

@ -37,10 +37,11 @@ template <
// Pull out the two halves, for simplicity. // Pull out the two halves, for simplicity.
const uint8_t source = src.b; const uint8_t source = src.b;
const uint8_t destination = dest.b; const uint8_t destination = dest.b;
const int extend = (status.extend_flag ? 1 : 0);
// Perform the BCD add by evaluating the two nibbles separately. // Perform the BCD add by evaluating the two nibbles separately.
const int unadjusted_result = destination + source + (status.extend_flag ? 1 : 0); const int unadjusted_result = destination + source + extend;
int result = (destination & 0xf) + (source & 0xf) + (status.extend_flag ? 1 : 0); int result = (destination & 0xf) + (source & 0xf) + extend;
if(result > 0x09) result += 0x06; if(result > 0x09) result += 0x06;
result += (destination & 0xf0) + (source & 0xf0); result += (destination & 0xf0) + (source & 0xf0);
if(result > 0x9f) result += 0x60; if(result > 0x9f) result += 0x60;
@ -787,30 +788,26 @@ template <
status.overflow_flag = status.carry_flag = 0; status.overflow_flag = status.carry_flag = 0;
break; break;
#define sbcd(d) \ #define sbcd(d) \
/* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \ const int extend = (status.extend_flag ? 1 : 0); \
const int unadjusted_result = destination - source - (status.extend_flag ? 1 : 0); \ const int unadjusted_result = destination - source - extend; \
\ \
int top = (destination & 0xf0) - (source & 0xf0); \ const int top = (destination & 0xf0) - (source & 0xf0) - (0x60 & (unadjusted_result >> 4)); \
if(unadjusted_result & 0x100) top -= 0x60; \ \
\ int result = (destination & 0xf) - (source & 0xf) - extend; \
int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag ? 1 : 0); \ const int low_adjustment = 0x06 & (result >> 4); \
if(result & 0xf0) { \ status.extend_flag = status.carry_flag = Status::FlagT( \
result -= 0x06; \ (unadjusted_result - low_adjustment) & 0x300 \
status.extend_flag = status.carry_flag = Status::FlagT((unadjusted_result - 0x6) & 0x300); \ ); \
} else { \ result = result + top - low_adjustment; \
status.extend_flag = status.carry_flag = Status::FlagT(unadjusted_result & 0x300); \ \
} \ /* Store the result. */ \
\ d = uint8_t(result); \
result += top; \ \
\ /* Set all remaining flags essentially as if this were normal subtraction. */ \
/* Set all remaining flags essentially as if this were normal subtraction. */ \ status.zero_result |= d; \
status.zero_result |= result & 0xff; \ status.negative_flag = result & 0x80; \
status.negative_flag = result & 0x80; \ status.overflow_flag = unadjusted_result & ~result & 0x80; \
status.overflow_flag = unadjusted_result & ~result & 0x80; \
\
/* Store the result. */ \
d = uint8_t(result);
/* /*
SBCD subtracts the lowest byte of the source from that of the destination using SBCD subtracts the lowest byte of the source from that of the destination using