Hi,my mcu is MC9S12X,ide is CodeWarrior V5.1.
Codes like:
float gf_e_a, gf_e_b, gf_e_c;
void test(void)
{
word va, vb, vc;
va = 3000;
vb = 89;
vc = 2000;
gf_e_a = 0;
gf_e_b = 0;
gf_e_c = 0;
while(1)
{
gf_e_a = va;
gf_e_b = vb;
gf_e_c = vc;
if(gf_e_c <= (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0))))
{
gf_e_c = gf_e_c - 0.01;
}
else
{
gf_e_c = (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0)));
}
}
}
I suppose it should goto 'else' and gf_e_c should be equal to (3000 * (1.0 - ((100 - 89)/20.0)) = 1350.
But the result is gf_e_c equal to 2006.
Then i check the assambly code:
330: float gf_e_a, gf_e_b, gf_e_c;
331: void test(void)
332: {
0000 1b98 [2] LEAS -8,SP
333: word va, vb, vc;
334: float res;
335:
336: va = 3000;
0002 cc0bb8 [2] LDD #3000
0005 6c86 [2] STD 6,SP
337: vb = 89;
0007 ce0059 [2] LDX #89
000a 6e84 [2] STX 4,SP
338: vc = 2000;
000c cd07d0 [2] LDY #2000
000f 6d82 [2] STY 2,SP
339:
340: gf_e_a = 0;
0011 c7 [1] CLRB
0012 87 [1] CLRA
0013 7c0000 [3] STD gf_e_a:2
341: gf_e_b = 0;
0016 7c0000 [3] STD gf_e_b:2
342: gf_e_c = 0;
0019 7c0000 [3] STD gf_e_c:2
343:
344: while(1)
345: {
346: gf_e_a = va;
001c ec86 [3] LDD 6,SP
001e 1887 [2] CLRX
0020 160000 [4] JSR _FUFLOAT
0023 7c0000 [3] STD gf_e_a:2
0026 7e0000 [3] STX gf_e_a
347: gf_e_b = vb;
0029 ec84 [3] LDD 4,SP
002b b705 [1] SEX A,X
002d 160000 [4] JSR _FUFLOAT
0030 7c0000 [3] STD gf_e_b:2
0033 7e0000 [3] STX gf_e_b
348: gf_e_c = vc;
0036 ec82 [3] LDD 2,SP
0038 1887 [2] CLRX
003a 160000 [4] JSR _FUFLOAT
003d 7c0000 [3] STD gf_e_c:2
0040 7e0000 [3] STX gf_e_c
349:
350: if(gf_e_c <= (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0))))
0043 fd0000 [3] LDY gf_e_b:2
0046 35 [2] PSHY
0047 fd0000 [3] LDY gf_e_b
004a 35 [2] PSHY
004b c7 [1] CLRB
004c 87 [1] CLRA
004d ce42c8 [2] LDX #17096
0050 160000 [4] JSR _FSUB
0053 18c7 [2] CLRY
0055 6da1 [2] STY 2,+SP
0057 6c82 [2] STD 2,SP
0059 cc41a0 [2] LDD #16800
005c 3b [2] PSHD
005d ec84 [3] LDD 4,SP
005f 160000 [4] JSR _FDIV
0062 6ca1 [2] STD 2,+SP
0064 34 [2] PSHX
0065 ce3f80 [2] LDX #16256
0068 b764 [1] TFR Y,D
006a 160000 [4] JSR _FSUB
006d fd0000 [3] LDY gf_e_a:2
0070 6da1 [2] STY 2,+SP
0072 fd0000 [3] LDY gf_e_a
0075 35 [2] PSHY
0076 160000 [4] JSR _FMUL
0079 6ca1 [2] STD 2,+SP
007b 34 [2] PSHX
007c b746 [1] TFR D,Y
007e fc0000 [3] LDD gf_e_c:2
0081 fe0000 [3] LDX gf_e_c
0084 160000 [4] JSR _FCMP
0087 1b84 [2] LEAS 4,SP
0089 2e16 [3/1] BGT *+24 ;abs = 00a1
351: {
352: gf_e_c = gf_e_c - 0.01;
008b ccd70a [2] LDD #55050
008e 3b [2] PSHD
008f cebc23 [2] LDX #48163
0092 34 [2] PSHX
0093 fc0000 [3] LDD gf_e_c:2
0096 fe0000 [3] LDX gf_e_c
0099 160000 [4] JSR _FADD
009c 1b84 [2] LEAS 4,SP
353: }
009e 060000 [3] JMP test:0x0019
354: else
355: {
356: gf_e_c = (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0)));
00a1 7d0000 [3] STY gf_e_c:2
00a4 060000 [3] JMP test:0x001c
357: }
358: }
359:
360: while(1);
361: }
There is something wrong in 'else'!
If i use key word 'volatile' to define the gf_e_xxx,it works.
But i want to know how to solve it officially.
Hi,
have you read my previous answer?
Is there still any issue with expected behavior or results based on code and optimization logic?
You are trying to fight against optimization process so it is necessary to safe all variables by modifiers static or volatile. If the optimizer sees that some process, variable,.... use useless to be processed then it is removed from process. Why to calculate or store anything what is not used anymore or does not influences next processes.
Best regards,
Ladislav
Hi,
the "issue" is your understanding of an optimization process and its implementation. Explained in the item 2 bellow.
The variable gf_e_c is not necessary to be calculated because it is not used anymore in the next process. The value is absolutely random value.
How to solve it? Two solutions.
1) make the variable as a volatile
2) move initialization of gf_e_c out of the while(1) cycle. If you use the initialization inside the cycle then the optimizer recognizes that the gf_e_c is not used in the loop as an input value for next cycle but it is initialized again (gf_e_c = vc;) so it is not necessary to be calculated and it is used somewhere else in some register or anywhere or nowhere.
Of course, there is one important question whether you want to use previous value gf_e_c in the loop for next comparison in the if(gf_e_c <= (... code line.
Your code
while(1)
{
gf_e_a = va;
gf_e_b = vb;
gf_e_c = vc;
if(gf_e_c <= (gf_e_c <= (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0))))
...
...
Suggested change; gf_e_c is used as an input parameter for a next comparison and not initialized in the while(1) loop:
gf_e_a = va;
gf_e_b = vb;
gf_e_c = vc;
while(1)
{
if(gf_e_c <= (gf_e_c <= (gf_e_a * (1.0 - ((100 - gf_e_b)/20.0))))
...
...
Best regards,
Ladislav
Thx very much for your help.
test() is an example to replay the issue.In my project code is:
if (Power.ReTime <= (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F))))
{
Power.ReTime = ((Power.ReTime) - 0.01);
}
else
{
Power.ReTime = (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F)));
}
The assembly code is:
221: if (Power.ReTime <= (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F))))
0320 f60000 [3] LDAB Power:1324
0323 87 [1] CLRA
0324 b705 [1] SEX A,X
0326 160000 [4] JSR _FUFLOAT
0329 3b [2] PSHD
032a 34 [2] PSHX
032b c7 [1] CLRB
032c 87 [1] CLRA
032d ce42c8 [2] LDX #17096
0330 160000 [4] JSR _FSUB
0333 18c7 [2] CLRY
0335 6da1 [2] STY 2,+SP
0337 6c84 [2] STD 4,SP
0339 cc41a0 [2] LDD #16800
033c 3b [2] PSHD
033d ec86 [3] LDD 6,SP
033f 160000 [4] JSR _FDIV
0342 6ca1 [2] STD 2,+SP
0344 34 [2] PSHX
0345 ce3f80 [2] LDX #16256
0348 b764 [1] TFR Y,D
034a 160000 [4] JSR _FSUB
034d 1b84 [2] LEAS 4,SP
034f 6c82 [2] STD 2,SP
0351 fc0000 [3] LDD Power:408
0354 6e80 [2] STX 0,SP
0356 b765 [1] TFR Y,X
0358 b746 [1] TFR D,Y
035a 160000 [4] JSR _FUFLOAT
035d 3b [2] PSHD
035e 34 [2] PSHX
035f ec86 [3] LDD 6,SP
0361 ee84 [3] LDX 4,SP
0363 160000 [4] JSR _FMUL
0366 6ca1 [2] STD 2,+SP
0368 34 [2] PSHX
0369 fc0000 [3] LDD Power:6
036c fe0000 [3] LDX Power:4
036f b746 [1] TFR D,Y
0371 6e88 [2] STX 8,SP
0373 160000 [4] JSR _FCMP
0376 1b84 [2] LEAS 4,SP
0378 2e11 [3/1] BGT *+19 ;abs = 038b
222: {
223: Power.ReTime = ((Power.ReTime) - 0.01);
037a ccd70a [2] LDD #55050
037d 3b [2] PSHD
037e cebc23 [2] LDX #48163
0381 34 [2] PSHX
0382 b764 [1] TFR Y,D
0384 ee88 [3] LDX 8,SP
0386 160000 [4] JSR _FADD
224: }
0389 2010 [3] BRA *+18 ;abs = 039b
225: else
226: {
227: Power.ReTime = (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F)));
038b b764 [1] TFR Y,D
038d 1887 [2] CLRX
038f 160000 [4] JSR _FUFLOAT
0392 3b [2] PSHD
0393 34 [2] PSHX
0394 ec86 [3] LDD 6,SP
0396 ee84 [3] LDX 4,SP
0398 160000 [4] JSR _FMUL
039b 1b84 [2] LEAS 4,SP
039d 7c0000 [3] STD Power:6
03a0 7e0000 [3] STX Power:4
228: }
At 038b the first code of 'else'(TFR Y,D) wnna put Power.Cyc_timeN into D,It means Y equal to Power.Cyc_timeN in previous code.But Y is set to Power:6 at address 036f(TFR D,Y).
Structure 'Power' is used everywhere,should not be optimized.
Hi,
Without getting entire project to see all dependencies it is not possible to say anything.
Or entire temporary (issue highlighting) project with comment at the line you see the issue.
Best regards,
Ladislav
I cann't provide the whole project for the sake of confidentiality.Please give me some advice based on these assembly codes.I make some comments:
221: if (Power.ReTime <= (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F))))
0320 f60000 [3] LDAB Power:1324 //load Power.group into X:D
0323 87 [1] CLRA
0324 b705 [1] SEX A,X
0326 160000 [4] JSR _FUFLOAT //change it to float & push into stack
0329 3b [2] PSHD
032a 34 [2] PSHX
032b c7 [1] CLRB //load 100.0f into X:D
032c 87 [1] CLRA
032d ce42c8 [2] LDX #17096
0330 160000 [4] JSR _FSUB //100.0f - (float)Power.group
0333 18c7 [2] CLRY //***Y==0
0335 6da1 [2] STY 2,+SP
0337 6c84 [2] STD 4,SP
0339 cc41a0 [2] LDD #16800 //load 20.0f & push into stack
033c 3b [2] PSHD
033d ec86 [3] LDD 6,SP
033f 160000 [4] JSR _FDIV //(100.0f-(float)Power.group)/20.0f
0342 6ca1 [2] STD 2,+SP
0344 34 [2] PSHX
0345 ce3f80 [2] LDX #16256 //load 1.0f
0348 b764 [1] TFR Y,D
034a 160000 [4] JSR _FSUB //1.0f - (100.0f-(float)Power.group)/20.0f & save the result
034d 1b84 [2] LEAS 4,SP
034f 6c82 [2] STD 2,SP
0351 fc0000 [3] LDD Power:408 //load (float)Power.Cyc_timeN
0354 6e80 [2] STX 0,SP
0356 b765 [1] TFR Y,X
0358 b746 [1] TFR D,Y //***Y==Power.Cyc_timeN
035a 160000 [4] JSR _FUFLOAT
035d 3b [2] PSHD
035e 34 [2] PSHX
035f ec86 [3] LDD 6,SP
0361 ee84 [3] LDX 4,SP
0363 160000 [4] JSR _FMUL //Power.Cyc_timeN * (1.0f - (100.0f-(float)Power.group)/20.0f)
0366 6ca1 [2] STD 2,+SP //save into stack
0368 34 [2] PSHX
0369 fc0000 [3] LDD Power:6 //load Power.ReTime,it's a float var
036c fe0000 [3] LDX Power:4
036f b746 [1] TFR D,Y //***Y=low half of Power.ReTime
0371 6e88 [2] STX 8,SP
0373 160000 [4] JSR _FCMP //CMP(Power.ReTime, Power.Cyc_timeN * (1.0f - (100.0f-(float)Power.group)/20.0f))
0376 1b84 [2] LEAS 4,SP
0378 2e11 [3/1] BGT *+19 ;abs = 038b
222: {
223: Power.ReTime = ((Power.ReTime) - 0.01);
037a ccd70a [2] LDD #55050
037d 3b [2] PSHD
037e cebc23 [2] LDX #48163
0381 34 [2] PSHX
0382 b764 [1] TFR Y,D
0384 ee88 [3] LDX 8,SP
0386 160000 [4] JSR _FADD
224: }
0389 2010 [3] BRA *+18 ;abs = 039b
225: else
226: {
227: Power.ReTime = (((real32_T)Power.Cyc_timeN) * (1.0F - ((100.0F - ((real32_T)Power.group)) / 20.0F)));
038b b764 [1] TFR Y,D //!!!!!!D should be Cyc_timeN,but at 036f,Y is set to low half of Power.ReTime
038d 1887 [2] CLRX
038f 160000 [4] JSR _FUFLOAT
0392 3b [2] PSHD
0393 34 [2] PSHX
0394 ec86 [3] LDD 6,SP
0396 ee84 [3] LDX 4,SP
0398 160000 [4] JSR _FMUL
039b 1b84 [2] LEAS 4,SP
039d 7c0000 [3] STD Power:6
03a0 7e0000 [3] STX Power:4
228: }
It's just like only store half of the result to gf_e_c.
Why?Compiler treat float as 4 bytes but 2 bytes at the end?