Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6782943
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T16:48:17+00:00 2026-05-26T16:48:17+00:00

I have gotten round to implementing the ADD A,r set of opcodes on my

  • 0

I have gotten round to implementing the ADD A,r set of opcodes on my Z80 core. I had a bit of confusion about the carry and overflow flags which I think I’ve nailed, but I wanted to put it to the community to check that I’m right.

Basically, from what I can see, the ALU in the Z80 doesn’t care about signed/unsigned operations, it just adds bits. This means that if two 8-bit values are added together and cause a 9-bit value as a result of their addition, the carry flag will be set. This includes adding two negative two’s complement numbers, for example -20 (11101100) and -40 (11011000), as although the result is -60 (11000100), the result is actually a 9-bit value 1 1100 0100. This surely means if adding two negative two’s complement values, the carry flag will always be set, even when there is no overflow condition – am I right?

Secondly, I decided that to detect an overflow in this instruction, I would XOR bit 7 of both operands, and if the result was 10000000, then there is definitely no overflow – if the result of this is 00000000 then there could be an overflow as the signs are the same, and I would therefore XOR bit 7 of the result of the addition with bit 7 of either operand, and if the result of this is 10000000 then an overflow has occurred and I set the P/V overflow flag. Am I right here also?

Sorry for such a convoluted question, I’m pretty sure I’m right but I need to know before I carry on with countless more instructions based on this logic. Many thanks.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T16:48:17+00:00Added an answer on May 26, 2026 at 4:48 pm

    The bits of the result are obtained from the truncated sum of unsigned integers. The add instruction doesn’t care about the sign here nor does it care about your own interpretation of the integers as signed or unsigned. It just adds as if the numbers were unsigned.

    The carry flag (or borrow in case of subtraction) is that non-existent 9th bit from the addition of the 8-bit unsigned integers. Effectively, this flag signifies an overflow/underflow for add/sub of unsigned integers. Again, add doesn’t care about the signs here at all, it just adds as if the numbers were unsigned.

    Adding two negative 2’s complement numbers will result in setting of the carry flag to 1, correct.

    The overflow flag shows whether or not there’s been an overflow/underflow for add/sub of signed integers. To set the overflow flag the instruction treats the numbers as signed (just like it treats them as unsigned for the carry flag and the 8 bits of the result).

    The idea behind setting the overflow flag is simple. Suppose you sign-extend your 8-bit signed integers to 9 bits, that is, just copy the 7th bit to an extra, 8th bit. An overflow/underflow will occur if the 9-bit sum/difference of these 9-bit signed integers has different values in bits 7 and 8, meaning that the addition/subtraction has lost the result’s sign in the 7th bit and used it for the result’s magnitude, or, in other words, the 8 bits can’t accommodate the sign bit and such a large magnitude.

    Now, bit 7 of the result can differ from the imaginary sign bit 8 if and only if the carry into bit 7 and the carry into bit 8 (=carry out of bit 7) are different. That’s because we start with the addends having bit 7=bit 8 and only different carry-ins into them can affect them in the result in different ways.

    So overflow flag = carry-out flag XOR carry from bit 6 into bit 7.

    Both my and your ways of calculating the overflow flag are correct. In fact, both are described in the Z80 CPU User’s Manual in section “Z80 Status Indicator Flags”.

    Here’s how you can emulate most of the ADC instruction in C, where you don’t have direct access to the CPU’s flags and can’t take full advantage of the emulating CPU’s ADC instruction:

    #include <stdio.h>
    #include <limits.h>
    
    #if CHAR_BIT != 8
    #error char expected to have exactly 8 bits.
    #endif
    
    typedef unsigned char uint8;
    typedef signed char int8;
    
    #define FLAGS_CY_SHIFT 0
    #define FLAGS_OV_SHIFT 1
    #define FLAGS_CY_MASK  (1 << FLAGS_CY_SHIFT)
    #define FLAGS_OV_MASK  (1 << FLAGS_OV_SHIFT)
    
    void Adc(uint8* acc, uint8 b, uint8* flags)
    {
      uint8 a = *acc;
      uint8 carryIns;
      uint8 carryOut;
    
      // Calculate the carry-out depending on the carry-in and addends.
      //
      // carry-in = 0: carry-out = 1 IFF (a + b > 0xFF) or,
      //   equivalently, but avoiding overflow in C: (a > 0xFF - b).
      //
      // carry-in = 1: carry-out = 1 IFF (a + b + 1 > 0xFF) or,
      //   equivalently, (a + b >= 0xFF) or,
      //   equivalently, but avoiding overflow in C: (a >= 0xFF - b).
      //
      // Also calculate the sum bits.
      if (*flags & FLAGS_CY_MASK)
      {
        carryOut = (a >= 0xFF - b);
        *acc = a + b + 1;
      }
      else
      {
        carryOut = (a > 0xFF - b);
        *acc = a + b;
      }
    
    #if 0
      // Calculate the overflow by sign comparison.
      carryIns = ((a ^ b) ^ 0x80) & 0x80;
      if (carryIns) // if addend signs are the same
      {
        // overflow if the sum sign differs from the sign of either of addends
        carryIns = ((*acc ^ a) & 0x80) != 0;
      }
    #else
      // Calculate all carry-ins.
      // Remembering that each bit of the sum =
      //   addend a's bit XOR addend b's bit XOR carry-in,
      // we can work out all carry-ins from a, b and their sum.
      carryIns = *acc ^ a ^ b;
    
      // Calculate the overflow using the carry-out and
      // most significant carry-in.
      carryIns = (carryIns >> 7) ^ carryOut;
    #endif
    
      // Update flags.
      *flags &= ~(FLAGS_CY_MASK | FLAGS_OV_MASK);
      *flags |= (carryOut << FLAGS_CY_SHIFT) | (carryIns << FLAGS_OV_SHIFT);
    }
    
    void Sbb(uint8* acc, uint8 b, uint8* flags)
    {
      // a - b - c = a + ~b + 1 - c = a + ~b + !c
      *flags ^= FLAGS_CY_MASK;
      Adc(acc, ~b, flags);
      *flags ^= FLAGS_CY_MASK;
    }
    
    const uint8 testData[] =
    {
      0,
      1,
      0x7F,
      0x80,
      0x81,
      0xFF
    };
    
    int main(void)
    {
      unsigned aidx, bidx, c;
    
      printf("ADC:\n");
      for (c = 0; c <= 1; c++)
        for (aidx = 0; aidx < sizeof(testData)/sizeof(testData[0]); aidx++)
          for (bidx = 0; bidx < sizeof(testData)/sizeof(testData[0]); bidx++)
          {
            uint8 a = testData[aidx];
            uint8 b = testData[bidx];
            uint8 flags = c << FLAGS_CY_SHIFT;
            printf("%3d(%4d) + %3d(%4d) + %u = ",
                   a, (int8)a, b, (int8)b, c);
            Adc(&a, b, &flags);
            printf("%3d(%4d) CY=%d OV=%d\n",
                   a, (int8)a, (flags & FLAGS_CY_MASK) != 0, (flags & FLAGS_OV_MASK) != 0);
          }
    
      printf("SBB:\n");
      for (c = 0; c <= 1; c++)
        for (aidx = 0; aidx < sizeof(testData)/sizeof(testData[0]); aidx++)
          for (bidx = 0; bidx < sizeof(testData)/sizeof(testData[0]); bidx++)
          {
            uint8 a = testData[aidx];
            uint8 b = testData[bidx];
            uint8 flags = c << FLAGS_CY_SHIFT;
            printf("%3d(%4d) - %3d(%4d) - %u = ",
                   a, (int8)a, b, (int8)b, c);
            Sbb(&a, b, &flags);
            printf("%3d(%4d) CY=%d OV=%d\n",
                   a, (int8)a, (flags & FLAGS_CY_MASK) != 0, (flags & FLAGS_OV_MASK) != 0);
          }
    
      return 0;
    }
    

    Output:

    ADC:
      0(   0) +   0(   0) + 0 =   0(   0) CY=0 OV=0
      0(   0) +   1(   1) + 0 =   1(   1) CY=0 OV=0
      0(   0) + 127( 127) + 0 = 127( 127) CY=0 OV=0
      0(   0) + 128(-128) + 0 = 128(-128) CY=0 OV=0
      0(   0) + 129(-127) + 0 = 129(-127) CY=0 OV=0
      0(   0) + 255(  -1) + 0 = 255(  -1) CY=0 OV=0
      1(   1) +   0(   0) + 0 =   1(   1) CY=0 OV=0
      1(   1) +   1(   1) + 0 =   2(   2) CY=0 OV=0
      1(   1) + 127( 127) + 0 = 128(-128) CY=0 OV=1
      1(   1) + 128(-128) + 0 = 129(-127) CY=0 OV=0
      1(   1) + 129(-127) + 0 = 130(-126) CY=0 OV=0
      1(   1) + 255(  -1) + 0 =   0(   0) CY=1 OV=0
    127( 127) +   0(   0) + 0 = 127( 127) CY=0 OV=0
    127( 127) +   1(   1) + 0 = 128(-128) CY=0 OV=1
    127( 127) + 127( 127) + 0 = 254(  -2) CY=0 OV=1
    127( 127) + 128(-128) + 0 = 255(  -1) CY=0 OV=0
    127( 127) + 129(-127) + 0 =   0(   0) CY=1 OV=0
    127( 127) + 255(  -1) + 0 = 126( 126) CY=1 OV=0
    128(-128) +   0(   0) + 0 = 128(-128) CY=0 OV=0
    128(-128) +   1(   1) + 0 = 129(-127) CY=0 OV=0
    128(-128) + 127( 127) + 0 = 255(  -1) CY=0 OV=0
    128(-128) + 128(-128) + 0 =   0(   0) CY=1 OV=1
    128(-128) + 129(-127) + 0 =   1(   1) CY=1 OV=1
    128(-128) + 255(  -1) + 0 = 127( 127) CY=1 OV=1
    129(-127) +   0(   0) + 0 = 129(-127) CY=0 OV=0
    129(-127) +   1(   1) + 0 = 130(-126) CY=0 OV=0
    129(-127) + 127( 127) + 0 =   0(   0) CY=1 OV=0
    129(-127) + 128(-128) + 0 =   1(   1) CY=1 OV=1
    129(-127) + 129(-127) + 0 =   2(   2) CY=1 OV=1
    129(-127) + 255(  -1) + 0 = 128(-128) CY=1 OV=0
    255(  -1) +   0(   0) + 0 = 255(  -1) CY=0 OV=0
    255(  -1) +   1(   1) + 0 =   0(   0) CY=1 OV=0
    255(  -1) + 127( 127) + 0 = 126( 126) CY=1 OV=0
    255(  -1) + 128(-128) + 0 = 127( 127) CY=1 OV=1
    255(  -1) + 129(-127) + 0 = 128(-128) CY=1 OV=0
    255(  -1) + 255(  -1) + 0 = 254(  -2) CY=1 OV=0
      0(   0) +   0(   0) + 1 =   1(   1) CY=0 OV=0
      0(   0) +   1(   1) + 1 =   2(   2) CY=0 OV=0
      0(   0) + 127( 127) + 1 = 128(-128) CY=0 OV=1
      0(   0) + 128(-128) + 1 = 129(-127) CY=0 OV=0
      0(   0) + 129(-127) + 1 = 130(-126) CY=0 OV=0
      0(   0) + 255(  -1) + 1 =   0(   0) CY=1 OV=0
      1(   1) +   0(   0) + 1 =   2(   2) CY=0 OV=0
      1(   1) +   1(   1) + 1 =   3(   3) CY=0 OV=0
      1(   1) + 127( 127) + 1 = 129(-127) CY=0 OV=1
      1(   1) + 128(-128) + 1 = 130(-126) CY=0 OV=0
      1(   1) + 129(-127) + 1 = 131(-125) CY=0 OV=0
      1(   1) + 255(  -1) + 1 =   1(   1) CY=1 OV=0
    127( 127) +   0(   0) + 1 = 128(-128) CY=0 OV=1
    127( 127) +   1(   1) + 1 = 129(-127) CY=0 OV=1
    127( 127) + 127( 127) + 1 = 255(  -1) CY=0 OV=1
    127( 127) + 128(-128) + 1 =   0(   0) CY=1 OV=0
    127( 127) + 129(-127) + 1 =   1(   1) CY=1 OV=0
    127( 127) + 255(  -1) + 1 = 127( 127) CY=1 OV=0
    128(-128) +   0(   0) + 1 = 129(-127) CY=0 OV=0
    128(-128) +   1(   1) + 1 = 130(-126) CY=0 OV=0
    128(-128) + 127( 127) + 1 =   0(   0) CY=1 OV=0
    128(-128) + 128(-128) + 1 =   1(   1) CY=1 OV=1
    128(-128) + 129(-127) + 1 =   2(   2) CY=1 OV=1
    128(-128) + 255(  -1) + 1 = 128(-128) CY=1 OV=0
    129(-127) +   0(   0) + 1 = 130(-126) CY=0 OV=0
    129(-127) +   1(   1) + 1 = 131(-125) CY=0 OV=0
    129(-127) + 127( 127) + 1 =   1(   1) CY=1 OV=0
    129(-127) + 128(-128) + 1 =   2(   2) CY=1 OV=1
    129(-127) + 129(-127) + 1 =   3(   3) CY=1 OV=1
    129(-127) + 255(  -1) + 1 = 129(-127) CY=1 OV=0
    255(  -1) +   0(   0) + 1 =   0(   0) CY=1 OV=0
    255(  -1) +   1(   1) + 1 =   1(   1) CY=1 OV=0
    255(  -1) + 127( 127) + 1 = 127( 127) CY=1 OV=0
    255(  -1) + 128(-128) + 1 = 128(-128) CY=1 OV=0
    255(  -1) + 129(-127) + 1 = 129(-127) CY=1 OV=0
    255(  -1) + 255(  -1) + 1 = 255(  -1) CY=1 OV=0
    SBB:
      0(   0) -   0(   0) - 0 =   0(   0) CY=0 OV=0
      0(   0) -   1(   1) - 0 = 255(  -1) CY=1 OV=0
      0(   0) - 127( 127) - 0 = 129(-127) CY=1 OV=0
      0(   0) - 128(-128) - 0 = 128(-128) CY=1 OV=1
      0(   0) - 129(-127) - 0 = 127( 127) CY=1 OV=0
      0(   0) - 255(  -1) - 0 =   1(   1) CY=1 OV=0
      1(   1) -   0(   0) - 0 =   1(   1) CY=0 OV=0
      1(   1) -   1(   1) - 0 =   0(   0) CY=0 OV=0
      1(   1) - 127( 127) - 0 = 130(-126) CY=1 OV=0
      1(   1) - 128(-128) - 0 = 129(-127) CY=1 OV=1
      1(   1) - 129(-127) - 0 = 128(-128) CY=1 OV=1
      1(   1) - 255(  -1) - 0 =   2(   2) CY=1 OV=0
    127( 127) -   0(   0) - 0 = 127( 127) CY=0 OV=0
    127( 127) -   1(   1) - 0 = 126( 126) CY=0 OV=0
    127( 127) - 127( 127) - 0 =   0(   0) CY=0 OV=0
    127( 127) - 128(-128) - 0 = 255(  -1) CY=1 OV=1
    127( 127) - 129(-127) - 0 = 254(  -2) CY=1 OV=1
    127( 127) - 255(  -1) - 0 = 128(-128) CY=1 OV=1
    128(-128) -   0(   0) - 0 = 128(-128) CY=0 OV=0
    128(-128) -   1(   1) - 0 = 127( 127) CY=0 OV=1
    128(-128) - 127( 127) - 0 =   1(   1) CY=0 OV=1
    128(-128) - 128(-128) - 0 =   0(   0) CY=0 OV=0
    128(-128) - 129(-127) - 0 = 255(  -1) CY=1 OV=0
    128(-128) - 255(  -1) - 0 = 129(-127) CY=1 OV=0
    129(-127) -   0(   0) - 0 = 129(-127) CY=0 OV=0
    129(-127) -   1(   1) - 0 = 128(-128) CY=0 OV=0
    129(-127) - 127( 127) - 0 =   2(   2) CY=0 OV=1
    129(-127) - 128(-128) - 0 =   1(   1) CY=0 OV=0
    129(-127) - 129(-127) - 0 =   0(   0) CY=0 OV=0
    129(-127) - 255(  -1) - 0 = 130(-126) CY=1 OV=0
    255(  -1) -   0(   0) - 0 = 255(  -1) CY=0 OV=0
    255(  -1) -   1(   1) - 0 = 254(  -2) CY=0 OV=0
    255(  -1) - 127( 127) - 0 = 128(-128) CY=0 OV=0
    255(  -1) - 128(-128) - 0 = 127( 127) CY=0 OV=0
    255(  -1) - 129(-127) - 0 = 126( 126) CY=0 OV=0
    255(  -1) - 255(  -1) - 0 =   0(   0) CY=0 OV=0
      0(   0) -   0(   0) - 1 = 255(  -1) CY=1 OV=0
      0(   0) -   1(   1) - 1 = 254(  -2) CY=1 OV=0
      0(   0) - 127( 127) - 1 = 128(-128) CY=1 OV=0
      0(   0) - 128(-128) - 1 = 127( 127) CY=1 OV=0
      0(   0) - 129(-127) - 1 = 126( 126) CY=1 OV=0
      0(   0) - 255(  -1) - 1 =   0(   0) CY=1 OV=0
      1(   1) -   0(   0) - 1 =   0(   0) CY=0 OV=0
      1(   1) -   1(   1) - 1 = 255(  -1) CY=1 OV=0
      1(   1) - 127( 127) - 1 = 129(-127) CY=1 OV=0
      1(   1) - 128(-128) - 1 = 128(-128) CY=1 OV=1
      1(   1) - 129(-127) - 1 = 127( 127) CY=1 OV=0
      1(   1) - 255(  -1) - 1 =   1(   1) CY=1 OV=0
    127( 127) -   0(   0) - 1 = 126( 126) CY=0 OV=0
    127( 127) -   1(   1) - 1 = 125( 125) CY=0 OV=0
    127( 127) - 127( 127) - 1 = 255(  -1) CY=1 OV=0
    127( 127) - 128(-128) - 1 = 254(  -2) CY=1 OV=1
    127( 127) - 129(-127) - 1 = 253(  -3) CY=1 OV=1
    127( 127) - 255(  -1) - 1 = 127( 127) CY=1 OV=0
    128(-128) -   0(   0) - 1 = 127( 127) CY=0 OV=1
    128(-128) -   1(   1) - 1 = 126( 126) CY=0 OV=1
    128(-128) - 127( 127) - 1 =   0(   0) CY=0 OV=1
    128(-128) - 128(-128) - 1 = 255(  -1) CY=1 OV=0
    128(-128) - 129(-127) - 1 = 254(  -2) CY=1 OV=0
    128(-128) - 255(  -1) - 1 = 128(-128) CY=1 OV=0
    129(-127) -   0(   0) - 1 = 128(-128) CY=0 OV=0
    129(-127) -   1(   1) - 1 = 127( 127) CY=0 OV=1
    129(-127) - 127( 127) - 1 =   1(   1) CY=0 OV=1
    129(-127) - 128(-128) - 1 =   0(   0) CY=0 OV=0
    129(-127) - 129(-127) - 1 = 255(  -1) CY=1 OV=0
    129(-127) - 255(  -1) - 1 = 129(-127) CY=1 OV=0
    255(  -1) -   0(   0) - 1 = 254(  -2) CY=0 OV=0
    255(  -1) -   1(   1) - 1 = 253(  -3) CY=0 OV=0
    255(  -1) - 127( 127) - 1 = 127( 127) CY=0 OV=1
    255(  -1) - 128(-128) - 1 = 126( 126) CY=0 OV=0
    255(  -1) - 129(-127) - 1 = 125( 125) CY=0 OV=0
    255(  -1) - 255(  -1) - 1 = 255(  -1) CY=1 OV=0
    

    You can change #if 0 to #if 1 to use the sign-comparison-based method for overflow calculation. The result will be the same. At first glance it’s a bit surprising that the sign-based method takes care of the carry-in too.

    Please note that by using my method in which I calculate all carry-ins into bits 0 through 7, you also get for free the value of the half-carry flag (carry from bit 3 to bit 4) that’s needed for the DAA instruction.

    EDIT: I’ve added a function for subtraction with borrow (SBC/SBB instruction) and results for it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

i have gotten started with the code below. Perhaps I had false ideas about
I seem to have gotten a bit carried away with the number of libraries
I have gotten this to work a bit but can't seem to figure out
I have gotten a bit lazy(it's sometimes good) and started updating WinForms UI by
We have gotten several emails and phone calls about yellow text appearing on our
I am learning about backbone, and from the examples and tutorials I have gotten
I have gotten to the point of passing a value from set of Markers
I have gotten the following errors using ruby 1.9.2-p320 with Heroku's Taps-using 'db' commands
I have gotten myself into a catch 22 and cannot seem to find my
I have gotten a great deal of help from KandadaBoggu on my last question

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.