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.

CCS3.1.0,TMS320F2812,32-bit Signed and Unsigned Division

Hi,

   I have a problem with 32-bit signed division. Below is a portion of the code having problem. In the following functions disassembly lines follows the source line.


****************************
******* Case1: **************
****************************

//source view
void RECEIVER_Div(void)
{
   s_RxMaxPower = s_RxMaxPowerNr / s_RxMaxPowerDr;
}


//Mixed source/assembly view
void RECEIVER_Div(void)
{
line1:   s_RxMaxPower = s_RxMaxPowerNr / s_RxMaxPowerDr;
line2:   3F34D2 761F MOVW    DP,#0x0242
line3:   3F34D4 0610 MOVL    ACC,@16
line4:   3F34D5 1E42 MOVL    *-SP[2],ACC
line5:   3F34D6 060E MOVL    ACC,@14
line6:   3F34D7 00FF FFC     XAR7,UL$$DIV
line7:   3F34D9 1E08 MOVL    @8,ACC
}
line8:  3F34DA 0006 LRETR

****************************
********* Case2 *************
****************************

//source view
void RECEIVER_UDiv(void)
{
   s_uRxMaxPower = s_RxMaxPowerNr / s_RxMaxPowerDr;
}

//Mixed source/assembly view
void RECEIVER_UDiv(void)
{
line1:   s_uRxMaxPower = s_RxMaxPowerNr / s_RxMaxPowerDr;
line2:   3F34DB 761F MOVW    DP,#0x0242
line3:   3F34DD 0200 MOVB    ACC,#0
line4:   3F34DE A30E MOVL    P,@14
line5:   3F34DF F61F RPT     #31 ||
line6:   3F34E0 5617 SUBCUL  ACC,@16
line7:   3F34E2 A90A MOVL    @10,P
}
line8:   3F34E3 0006 LRETR

****************************
*** Known Conditions *****
****************************

IDE: CCS (Version : 3.1.0)

Build Options-
Opt level  : none
Program level opt: none

Stack Start : 0x0400
Stack Size  : 0x0400

Data types of variables-
s_RxMaxPower    32 bit signed int
s_uRxMaxPower   32 bit unsigned int
s_RxMaxPowerNr  32 bit unsigned int
s_RxMaxPowerDr  32 bit unsigned int
***********************************

My problem is with Case1. In Case1, at line1 StackPointer(SP) points to 0x408(this is very well within the safe range, because we start from 0x400 and has a size of 0x400). After executing line4 we loss the value of next-old RPC(Return Program Counter) because the dinominator is pushed into the stack where the next-old RPC value is saved. So reffering to the below given portion of main() code, after returning from RECEIVER_Div() it will execute Process2() and Process3(), but it will never reach Process4() and then to Process5(). Rather it will go to the location pointed to by the value of s_RxMaxPowerDr. Because in Case1, after line4 we loose the address of Process4() which was in the stack.

***********************************
main()
{
   Process1()
   {    
      RECEIVER_Div();
      Process2();
      Process3();
   }
   Process4();
   Process5();
}
***********************************

But in Case2 this not happens, because it is not using UL$$DIV and no need of the Denominator value to be pushed into the Stack.

We also noticed that if RECEIVER_Div() passes some prameters or if it has any local varible inside, this over-writting does not happen. Because a pair(32-bit) or more locations are initialized in the stack prior to entering in to RECEIVER_Div().

Q1. What is actually happening in Case1 as far as the Compiler is concerned?

Q2. Is it any problem with Compiler/Disassembler?

Q3. Is it due to we miss any math convention in coding?

Q4. How the compiler takes a 32-bit Division operation in which Numerator and Dinominator are Uint32 and the result has to be equated to an Int32 type varible?

-Any help is sincerely appriciated

--------
-Regards
-Sinoj

  • Sinoj,

    I could not reproduce your error. I am using CCS3.3.82.13 and Compiler 5.2.1, No Optimization

    Here's my test C-Code:

    #include "DSP2833x_Device.h"

    long RxMaxPower, RxMaxPowerNr = 6, RxMaxPowerDr = 2;

    void Receiver_Div(void);

    void Process2(void);

    int main(void)

    {

                    Receiver_Div();

                    Process2();

    }

     

    void Receiver_Div(void)

    {

                    RxMaxPower = RxMaxPowerNr / RxMaxPowerDr;

    }

     

    void Process2()

    {

                    while(1);

    }

     This is the generated Assembly code:

     _Receiver_Div:

                     ADDB      SP,#2

                     MOVW      DP,#_RxMaxPowerDr

                    MOVL      ACC,@_RxMaxPowerDr    ; |15|

                    MOVL      *-SP[2],ACC           ; |15|

                     MOVL      ACC,@_RxMaxPowerNr    ; |15|

                    FFC       XAR7,#L$$DIV          ; |15|

                    MOVL      @_RxMaxPower,ACC      ; |15|

                     SUBB      SP,#2

                     LRETR

    It adds a space of 2 to the SP, before its used to pass RxMaxPowerDr into the stack.

    Could it be that the structure of your main - code causes your error? 

    What is the purpose of the bracket in the line after the call of  Process1() ?

    Process1()
       {   ?????

      }

    Hope this helps

     

     

     

  • Hello Frank,

    Thanks for the reply.

    Actually it was supposed to be

    ***********************************

    //main()


    main()
    {
       Process1();
       Process4();
       Process5();
    }
    ***********************************

    //Functions

       Process1()
       {    
          RECEIVER_Div();
          Process2();
          Process3();
       }

    ***********************************

    Sorry for the confusion caused .

    Now let me say...

    Comparing to the dis-assemby of yours, I miss (ADDB      SP,#2) and (SUBB      SP,#2) prior to pushing the denominator to the stack.

    Is it because my Compiler Ver. is different?. I'm using:

    Code Composer Version: 3.1.0
    Integrated Development: 5.90.0.227 Texas Instruments
    Code Generation Tools: v4.1.0

    Code Composer Studio Component Manager displays -> Code Compose Studio v3.1.3.1.19.0.

    Why you mention two versions, one for CCS and one for Compiler( CCS3.3.82.13 and Compiler 5.2.1)? I could not find a seperate ver. for the Compiler.

    - - - - - - - -

    -Regards

    -Sinoj

  • Sinoj,

    By Compiler - Version I meant "Code Generation Tools"  (Help ==> About ==> Component Manager).

    I just switched back to Code Generation Tools V4.1.3 (The oldest toolset  I have here) , result is the same, my code still includes  the ADD SP,#2 and SUBB SP,#2 instructions.

    Regards

     

  • Frank,

    Can you try this:

    signed long RxMaxPower

    unsigned long RxMaxPowerNr,  RxMaxPowerDr

    - - - - - - - -

    - Regards

    - Sinoj

  • Can you try this:

    signed long RxMaxPower

    unsigned long RxMaxPowerNr,  RxMaxPowerDr

    Sinoj;

    Result as expected, the compiler uses the RPT #31  || SUBCUL ACC,@4 instructions to divide. (SUBCUL = "Subtract Conditional Unsigned Long"). No stack access in function body.

    Regards

     

  • Frank,

    I'm afraid...

    I'm having trouble with the following operation:

    (signed long) = (unsigned long) / (unsigned long); ------------------ (Operation1)

    I would like you to make sure that, was it exactly the above operation(Operation1) you tested? Your result corresponds to the following operaion of my side:

     

    (unsigned long) = (unsigned long) / (unsigned long); ------------------ (Operation2)

     

    ... and (Operation2) is working fine for me.

    - - - - - - -

    -Rerards

    -Sinoj

  • Frank,

    In your diassembly it is L$$DIV. But in my case it is UL$$DIV .

    -R'gds, Sinoj

  • Sinoj,

    Compiler v4.1.0 is fairly old.  I would suggest moving to a newer compiler.  If you have the full version of Code Composer V3.3. then use the Code Composer Studio update advisor.  (Help->update advisor).

    If you have the 32k limited evaluation tools then you can download a newer compiler here:

    https://www-a.ti.com/downloads/sds_support/TICodegenerationTools/

    Remember in CCS 3.3 to select the new compiler in the component manager after installing (help->about->component manager-> build tools)

    If you still have an issue after moving to a newer compiler then please send a small testcase to support@ti.com.

    -Lori

     

  • Lori and Frank ... thanks for the support.

    The problem got solved.

    CCS Version: 3.3.38.2(120-days evaluation)
    Code Generation Tools: V4.1.3
     
    Now the compiler generated assembly-code does not contain 'UL$$DIV' routine-call, prior to which the denominator value was pushed into the Stack, which caused all the troubles. As far as the old-version-compiler is concerned the problem was with the below type math operation-
     
    (signed long) = (unsigned long) / (unsigned long);
     
    Below portion of example code shows an impact of the problem.
     
    *******************************
    //main()
    main()
       signed long y;
       unsigned long a,b;
     
       Process1();
       Process2();
       Process3();
     
       while(1);
    }
     
    //Functions
    Process1()
    {
       Process1A();
       Process1B();
       Process1C();
    }
     
    Process1A()
    {
      y = a / b;
    }
    *******************************
     
    Process1A(), Process1B() and Process1C() will get executed. But execution of Process2() and Process3() is not guranteed.
     
    --------
    -Regards
    -Sinoj