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.

Unexpected sign extension plus destroying good 32bit value in ACC by copying AL onto ACC

Hello, I have a problem with CCS v3.3 where I have a function that returns an unsigned 32bit value which is to be stored in an unsigned 32bit local variable and immediately upon return the value is correct as expected in the accumulator but the next instruction is a SETC SXM followed by a MOV ACC, @AL... what this does is copies the low word of the accumulator onto the full accumulator with sign extension.

This behavior makes no sense, the function I am calling returns a 32bit in ACC... why would CCS generate assembly code that then immediately destroys the high word of that register? Furthermore, the return of this function and the variable that the return is being assigned to are unsigned, why is CCS setting sign extension?

C:

u32_Result = calc32(u32_Param);

ASM:

LCR calc32

SETC SXM

MOV ACC, @AL

If I go into mixed mode and break on the SXM instruction the value in the accumulator is correct, it is what I expected the function to return... then it is destroyed by the next line...

I realize CCS 3.3 is not the most recent version, but if someone could provide at least a workaround for this problem I would appreciate it.

  • Can you post your function and variable declarations?

    The ASM code leads me to believe that your compiler thinks it is a signed variable, as it is enabling the sign extension mode.

  • Sure:

    void SendUpdateToPhone()

    {

       Uint32 rightDist, rightIdx;

       ....

       rightDist = calc_Dist(rightIdx); //Get distance of screen right edge from its index

       ....

       //Send distance at right screen edge
       while(!ScibRegs.SCICTL2.bit.TXRDY);
       ScibRegs.SCITXBUF = rightDist >> 24;
       while(!ScibRegs.SCICTL2.bit.TXRDY);
       ScibRegs.SCITXBUF = rightDist >> 16;
       while(!ScibRegs.SCICTL2.bit.TXRDY);
       ScibRegs.SCITXBUF = rightDist >> 8;
       while(!ScibRegs.SCICTL2.bit.TXRDY);
       ScibRegs.SCITXBUF = rightDist;

    }

    Uint32 calc_Dist(Uint32 index)

    {

       Uint32 distance;

       distance= index - ZERO_OFFSET * 10000; //Subtract zero offset and scale up for precision

       distance /= 4064; //Scale to number of data points (truncation OK)

       distance *= CURRENT_RANGE; //Scale for current range

       distance *= IOR_SCALE; //Adjust distance for index of refraction (truncation OK)

       return distance;

    }

    Uint32 is defined as an unsigned long, ZERO_OFFSET and CURRENT_RANGE are both macros that give an unsigned int result, and IOR_SCALE is a macro that gives a float result.

    The calc_Dist() function works correct, and if I break on the return the value is as expected. Also, if I go into mixed mode, the final asm instruction in the function (other than restoring the stack) is to move the result from the stack to ACC for return. As I said before, as soon as the function returns CCS sets sign extend and then copies AL over ACC...

    Could the problem be the multiplication by the float at the end of the function? It produces the correct value every time, but is it confusing the compiler?

  • FWIW, I was able to work around the problem by inlining the function (not by specifying it as inline, but by copying it and pasting it in place of the call...). Unfortunately the function is used in many places in the project...

  • I would like to re-open this problem since I just ran into it again, same circumstances. I have a function that returns a 32bit unsigned value and I am calling it as the rvalue of an assignment to a 32bit unsigned local variable. At the very end of the function, with a breakpoint on the LRETR instruction, the correct return value is in ACC to be returned. Immediately after the return to the calling function an SXM is performed for no apparent reason and then the low word of the accumulator is copied onto the accumulator, destroying the high word of the value I am returning (MOV ACC,@AL).

    This has wasted HOURS of my time, because before I find out that the problem is due to a compiler fault I search for other possible problems. Last time this occurred I worked around it by inlining the function that I was calling, this time that is not an option, the function I am calling is too large and used in too many different places.

    The last time I brought this up a TI employee asked me for more information, which I provided, and then I never heard from anyone again... This time I would like an answer even if it is an admission of a bug in the compiler (for what it's worth I consider it more likely that I am at fault, but I cannot see my fault and neither can my coworkers or superiors).

  • Chris, Try this workaround while you wait for support from TI: 

    Pass in a reference to a Uint32 to store the return value - void calc_Dist (Uint32, Uint32 *);

    void calc_Dist(Uint32 index, Uin32* a_rDistance)

    {

       Uint32 distance;

       distance= ...;

      *a_rDistance  = distance;

    }

  • J Joson said:
    Chris, Try this workaround while you wait for support from TI:

    That worked and I can't believe I didn't think of it. Thank you very much!