This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TMS320F28379D: OVC flag not set, while performing 32bit addition

Part Number: TMS320F28379D


Tool/software: TI C/C++ Compiler

Hi,

I am trying to simulate the overflow condition in the controller by performing the 32-bit addition.

As per the documentation, the OVC flag will be set only when the operation is performed in the accumulator.

unsigned int32 var1 = 0xFFFFFFFF

unsigned int32 va2 = var1 + var1;

I am seeing the overflowed result in the var3, but the OVC flag is not set. instead, a Negative flag is set.

This confused me, could you please explain more on when the OVC will be set.

  • Mohan,

    Can you view the generated assembly instructions for this code and send it to me? Also please indicate what optimization level you are using. 

    Thanks,

    Sira

  • Hi Sira

    please see the below, optimization is OFF

    089db3:   FE16        ADDB         SP, #22
     42         UINT32 u16Var1 = 0xFFFFFFFF;
    089db4:   0200        MOVB         ACC, #0
    089db5:   1901        SUBB         ACC, #1
    089db6:   1E54        MOVL         *-SP[20], ACC
     44         UINT32 u16Var3 = 0;
    089db7:   0200        MOVB         ACC, #0
    089db8:   1E56        MOVL         *-SP[22], ACC
     46         u16Var3 = u16Var1 + u16Var1;
    089db9:   0654        MOVL         ACC, *-SP[20]
    089dba:   0754        ADDL         ACC, *-SP[20]
    089dbb:   1E56        MOVL         *-SP[22], ACC

  • I Observed one more detail here, 

    I have used Unsigned long variable, but the generated assembly code considering it as a Signed long variable, because of which  it  is generating an ADDL instruction instead of ADDUL

  • Mohan,

    That is odd. What version of the compiler are you using? I've asked for the Compiler team to provide inputs.

    Thanks,

    Sira

  • Mohan BM said:
    I have used Unsigned long variable, but the generated assembly code considering it as a Signed long variable, because of which  it  is generating an ADDL instruction instead of ADDUL

    Outside of a few intrinsics, the compiler ignores the OVC.  Thus, an ADDL instruction is an acceptable way to implement a 32-bit unsigned add.

    Note the OVC is not a flag, but a 6-bit wide counter.  It is in the most significant bits of the status register ST0.  The sequence of assembly instructions shown above should increment OVC by 1.  Do you see different behavior?

    Thanks and regards,

    -George

  • I am using 20.2.1

  • Yes, I do see different behavior. 

    OVC is not incremented when the above code is executed.

  • Hi

    did you had a chance to look at the behavior of the compiler

  • Mohan,

    I was able to reproduce the behavior. So for some reason, the compiler generates ADDL despite the declaration of unsigned variables and the Carry flag is set (as I would expect since the result is 0xFFFF FFFE with a carry generated) but the OVC is not incremented. The instruction set guide doesn't document this in the clearest way either. I've asked a CPU architect for his feedback.

    Thanks,

    Sira

  • Mohan,

    I spent some time thinking about this, and I now understand the behavior.

    The compiler is generating a signed instruction, and therefore signed-arithmetic rules regarding overflow apply. These rules are:

    Rules for an overflow during ADDL ACC, loc32.

    Sign-bit of ACC = 0 and Sign-bit of loc32 = 0  and sign-bit of result = 1 (positive overflow)

    Sign-bit of ACC = 1 and Sign-bit of loc32 = 1  and sign-bit of result = 0 (negative overflow)

    In our case, the numbers are 0xFFFFFFFF, 0xFFFFFFFF, and the result is 0xFFFFFFFE. Since there is no change of sign, it figures that no overflow occurred. And that’s because 0xffffffff in (2s complement) signed representation -1, so -1 + -1 = -2, so no overflow. So in this case, the user needs to pay attention to the carry bit to determine if there’s an overflow, since that is the sign of overflow for unsigned numbers.And you will notice that a Carry does occur in this case.

    Thanks,

    Sira

  • You haven't mentioned the value of OVM; based on the described behavior, I'll assume OVM=0.

    Briefly, for signed operations, OVC increments or decrements when the V (overflow) flag is set by a 32-bit operation.

    However, for unsigned operations, OVC increments or decrements when the C (carry) flag is set by a 32-bit operation.

    The OVC behavior is documented in the "TMS320C28x CPU and Instruction Set Reference Guide" SPRU430

    In SPRU430 revision F (2015), section 2.3 "Status Register ST0", it says:

    The overflow counter behaves differently for signed and unsigned operations.

    For signed operations, the overflow counter is a 6-bit signed counter with a range of -32 to 31.

    When overflow mode is off (OVM = 0), ACC overflows normally, and OVC keeps track of overflows.

    When overflow mode is on (OVM = 1) and an overflow occurs in ACC, the OVC is not affected. Instead, the CPU automatically fills ACC with a positive or negative saturation value (see the description for OVM).

    When ACC overflows in the positive direction (from 7FFFFFFF to 80000000), the OVC is incremented by 1. When ACC overflows in the negative direction (from 80000000 to 7FFFFFFF) the OVC is decremented by 1. The increment or decrement is performed as the overflow affects the V flag.

    For unsigned operations (OVCU), the counter increments for ADD when a Carry is generated and decrements for a SUB when a Borrow is generated (similar to a carry counter).

    The conditions under which the V bit are set are described later in the same section:

    An overflow occurs in ACC (and V is set) if the result of an addition or subtraction does not fit within the signed numerical range -2**31 to (+2**31 - 1), or 80000000 to 7FFFFFFF.

  • Thank you sira fo the analysis.

    I am okay with the signed logics. 

    My concern is, the compiler generated a signed instruction fo an unsigned arithmetic operation. 

    I will be using this for Level A aerospace program, where the program will be tested at the assembly level, this would lead to a discrepancy.

    please let us know if you could fix it.

  • Mohan,

    I would need to let the compiler team comment on that. Let me re-assign this to them.

    Thanks,

    Sira

  • Mohan,

    The C language does not have any mechanism that the compiler can use to handle overflow.

    As George mentioned earlier, the compiler ignores OVC in which case the ADDL instruction is a smaller (and therefore faster) way to accomplish the same thing (while ignoring OVC counter). All that matters is the computation result which is entirely in ACC.

    If you need an algorithm that accounts for the OVC counter then you will need to use assembly.

    Thanks
    Greg

  • Thank you Greg for your reply.

    I have considered the option of having the application level monitoring.

    My current concern is that the compiler generated a Signed instruction for an unsigned operation, which I couldn't understand.

  • Mohan BM said:
    My current concern is that the compiler generated a Signed instruction for an unsigned operation, which I couldn't understand.

    It is valid for the compiler to use the ADDL instruction to compute 32-bit wide unsigned addition.  The compiler only has to compute what is required by the ANSI standard for C.  In this case, the only concern is the result of the 32-bit unsigned addition.  The effect on any status bits which the compiler ignores, including OVC, is not of concern.  The ADDL instruction is a bit smaller and faster than ADDUL, so it is used.  

    Another way to think about it ... This compiler has been used in the field for more than 15 years.  If ADDL is the wrong instruction for 32-bit unsigned addition, that would have been discovered long before now.

    Thanks and regards,

    -George