Forums

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

Started by sino...@nestgroup.net June 23, 2009
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)
{
line1: 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 *******
****************************

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 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 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.

I might expect some other group members to look into this in more detail, but first a
couple of quick questions:

1) Can you try with CCS v3.3? For C6x and C5x DSP devices, v3.1 is considered
buggy. I'm not sure about that for F28xx.

2) I notice the reference to DP (data pointer) in your disassembly. What memory
model are you using, and did you try different mem models? I ask because on C5x one
option is to use DP to point to kind of a "local stack" (that is not actually the
main stack) for storing local vars inside functions. I don't know if F28xx has
something similar or not.

-Jeff

> ****************************
> ******* 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)
> {
> line1: 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 *******
> ****************************
>
> 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 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

_____________________________________
Hi Jeff,

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

_____________________________________
Sinoj-

> The problem got solved.
>
> CCS Version: 3.3.38.2(120-days evaluation)
> Code Generation Tools: V4.1.3

Ok now you believe me when I say that CCS v3.1 is buggy :-)

> 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);

Probably there would have been a work-around, but too much trouble. My guess is that if you asked TI guys, they would
have said "first upgrade to 3.3 and see if the problem is still there".

Good luck with your project.

-Jeff

> > I might expect some other group members to look into this in more detail, but first a
> > couple of quick questions:
> >
> > 1) Can you try with CCS v3.3? For C6x and C5x DSP devices, v3.1 is considered
> > buggy. I'm not sure about that for F28xx.
> >
> > 2) I notice the reference to DP (data pointer) in your disassembly. What memory
> > model are you using, and did you try different mem models? I ask because on C5x one
> > option is to use DP to point to kind of a "local stack" (that is not actually the
> > main stack) for storing local vars inside functions. I don't know if F28xx has
> > something similar or not.
> >
> > -Jeff

> 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

_____________________________________