# Can someone explain this algorithm used to compute the auxiliary carry flag?

I'm debugging my 8080 emulator and I've gone the route of comparing it to the output of another tested emulator to see where I went wrong. When calculating the auxiliary carry flag, I used this algorithm for subtraction:

``````// a and b are uint8_t, cf_.ac is the auxiliary flag
a &= 0x0F; // lower nibble
b &= 0x0F; // lower nibble
cf_.ac = (a < b); // there must be borrow if minuend is less than subtrahend
``````

On the other hand, the emulator I'm comparing with uses this algorithm:

``````// hf is the auxiliary flag, a and val are uint8_t
const uint16_t result = c->a - val;
c->hf = ~(c->a ^ result ^ val) & 0x10;
``````

Our emulators are mismatching after this instruction:

``````Instructions Ran: 32
Program Counter: 022A
Memory Immediate: 0xFE
Instruction: CPI D8 0
Registers (B/C/D/E/H/L/A): 00 00 00 00 00 00 F5
Flags (Z/S/P/C/AC): 0 1 1 1 1
Cycles: 305
``````

where my auxiliary flag is not set (`0xF5 - 0x00` shouldn't set the AF flag?) while theirs is set. I don't completely understand their algorithm so I am not able logically tell if it's wrong. Is my algorithm faulty or is theirs?

• I'm voting to close this question as off-topic because debugging new code for new products isn't exactly RC stuff. Please narrow it down to questions about classic hardware, not modern coding - until then you might as well want to give Ken Shirriff's great blog article about the 8085 flag handling a read. Jun 5 '19 at 22:43
• @Raffzahn Programming oldie things is about oldie things. This site is about oldie things. The rule you want to apply, does not exist. Jun 6 '19 at 1:22
• I agree with Raffzahn. The essence of this question is "debug my code". It would be fine to ask about how the 8080 auxiliary carry flag worked, but don't bring your own project into the question or it will be off-topic. Jun 6 '19 at 3:45
• This is about getting an emulator for an ancient CPU working. The question is about the correct behaviour of one of the status flags. It absolutely does belong on this site. Jun 6 '19 at 9:07
• In my mind this could be rephrased as an appropriate question, if it went along the lines of "a piece of documentation 1 says that Z80 command CPI does such and such flag this way, whereas a piece of documentation 2 says something contradictory. Please advise, which way is correct." As is, this is not an appropriate question (I do not understand how this works, I have two sets of code that seem to not do the same, tell me how to fix this) that I am voting to close as well. Jun 6 '19 at 9:26

The auxiliary carry, or in z80 terms the half carry, records whether there was carry (or borrow) between bit 3 and bit 4 in the preceding arithmetic operation.

`CPI` means compare immediate, so it uses the ALU to subtract the immediate value from the accumulator, then keeps the flags but throws away the result.

Probably the relevant clue compared to the choice you've posted: `CPI` doesn't pay any regard to the carry flag. It's like `SUI`, not `SBI`.

• Sorry my bad. I should note that the `dif_flags` function takes the `cy` argument as an optional one; the default value is `0`, which is what my `cpi` function uses.
– dav
Jun 5 '19 at 23:33
• Can somebody explain how this answers the question? Why is the half carry different between the two emulators when the code in each case gives the same value for the auxiliary carry flag? Jun 6 '19 at 9:27
• @JeremyP: your question seems to be much the same topic as you are debating with Raffzahn above — whether just discussing the retro aspect (i.e. the definition of auxiliary carry) is appropriate or whether dissection of the supplied code is appropriate. Although not exactly, as this answer covers something the posted code originally included: carry. Which was a reasonable guess as to the divergence. But I'll decline to extend the other discussion into a second comment area. Jun 6 '19 at 12:32

Is my algorithm faulty or is theirs?

What their algorithm does is check to see if there has been a carry from bit 3 to bit 4. If you add two bits (even subtraction is done by taking the twos complement and adding), the answers are as follows

``````0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 (+ carry)
``````

So bit 4 of the result should be the same as bit 4 of the accumulator exclusive or with bit 4 of the immediate operand i.e.

``````(c->a ^ val) & 0x10
``````

However, a carry from bit 3 would change that. So a carry will have occurred if

``````((c->a ^ val) & 0x10) != (result & 0x10)
``````

`!=` is the same as exclusive or for single bits (and booleans) so you can rewrite the above as

``````((c->a ^ val) & 0x10) ^ (result & 0x10)
``````

which is clearly the same as

``````(c->a ^ val ^ result) & 0x10)
``````

They then invert that to get the half carry flag, their reasoning being (I think) that they did a subtraction rather than a twos complement addition.

``````~(c->a ^ val ^ result) & 0x10)
``````

If you use that formula on the Intel example (documented here under the `SUI` description), which is 0 - 1, it gives the half carry flag as 0 which is correct according to Intel.

• So if the half carry flag shouldn't be set, does that make their algorithm wrong? As their half carry flag is set
– dav
Jun 6 '19 at 16:18
• @DavidTran No. The half carry should not be set when a borrow is required as in `00` - `01`. And it should therefore be set when a borrow is not required as in `F5` - `00`. Jun 6 '19 at 18:10
• Oh wow I had it backwards this whole time... so the flag is set when there is no borrow? That's weird. Is that the same case for the carry flag?
– dav
Jun 7 '19 at 3:29
• @DavidTran No. The documentation specifically states that the carry flag is the inverse of the carry out from the two's complement sum when you are doing a subtraction. I just think that the logic to invert the flag is missing for the half carry. Jun 7 '19 at 8:53

Ассоrding to this reverse-engineered verilog source of the KR580VM80A (an USSR clone of i8080), auxilliary carry is set as if it is always an addition:

``````psw_ac <= (c & ~id_xra & ~id_ora & ~id_rxc) | (id_ana & (x | r)); // line 922
``````

while the normal carry flag is set to either non-inverted or inverted carry from the carry chain:

``````           if (id_cmp | id_sbb | id_sub) // line 930
psw_c <= ~(t2133 | id_rxc & x);
``````     t2133    <= ~id_rxc & c; // line 888
The reason behind that is that auxilliary carry flag is used only in `DAA`, which in turn corrects only the result of addition, as it is stated in the instruction set manual.
• That's interesting because the Z80 diverges here; you can `DAA` after a `SUB` and expect to get the proper outcome — the subtract flag even exists specifically so that `DAA` knows what it is following. So, I guess, beware emulations and test suites for the 8080 that face relied too heavily on the much-more-available Z80 documentation. Jun 6 '19 at 14:36