|
|
View previous topic :: View next topic |
Author |
Message |
akohlsmith
Joined: 25 Apr 2012 Posts: 26
|
[solved] code gen bug - uses local var for function param? |
Posted: Wed Sep 11, 2013 8:12 am |
|
|
I've got an odd little code generation bug. I have allocated 10 bytes for local storage. I use that local storage and call a function with a single parameter. The last local storage byte gets overwritten with the parameter I pass to the function.
Please refer to the following listing:
Code: |
.................... void tx_status(void)
.................... {
*
09DA: MOV W5,[W15++]
.................... int8 i, resp[9];
....................
/*** snipped, just filling out resp[0] to resp[7] ***/
.................... resp[8] = (advance_paused) ? 1 : 0;
0A34: BTSS.B 9FE.2
0A36: BRA A3C
0A38: MOV.B #1,W0L
0A3A: BRA A3E
0A3C: CLR.B W0
0A3E: MOV.B W0L,A2C
....................
.................... blank_display(TRUE);
0A40: MOV.B #1,W0L
0A42: MOV.B W0L,A2C
0A44: CALL 348
.................... for (i = 0; i < sizeof(resp); i++) {
0A48: CLR.B A22
0A4A: MOV A22,W4
0A4C: CP.B W4L,#9
0A4E: BRA GE,A68
.................... fputc(resp[i], RADIO);
0A50: MOV.B A22,W0L
0A52: SE W0,W0
0A54: MOV #A24,W4
0A56: ADD W0,W4,W0
0A58: MOV.B [W0],W5L
0A5A: MOV.B W5L,W0L
0A5C: BTSS.B 223.0
0A5E: BRA A5C
0A60: MOV.B W0L,224
0A62: CLR.B 225
.................... }
0A64: INC.B 0A22
0A66: BRA A4A
.................... }
0A68: MOV [--W15],W5
0A6A: RETURN
|
The problem occurs between 0xa3c and 0xa42.
As you can see, resp[8] has memory location 0xa2c. The code correctly sets or clears the byte based on whether the advance_paused boolean variable is true or not. In my particular bug, advance_paused is FALSE, which causes the branch at 0xa34 to NOT be taken, so the branch to 0xa3c is taken and 0xa2c is written with value 0. I have verified that this code operates correctly, and with a breakpoint at 0xa40 the memory location 0xa2c correctly stores 0x00.
However the very next line which calls blank_display(TRUE) sets 0xa2c with a value of 1 (the value of TRUE). I believe this is erroneous, as I have allocated 9 bytes for int8 resp[9].
I'm using CCS 4.135 and my compiler options are "+DF +LS +T +A +M -Z +Y=0 +EA". This code generation bug occurs with optimization turned off, as shown in the compiler options. The target processor is a PIC24F32KA304.
I'm a little surprised to see that function parameters are implemented with fixed memory locations and not by passing values in the working register set. Perhaps that is an optimization which I've got turned off.
Last edited by akohlsmith on Wed Sep 11, 2013 8:46 am; edited 1 time in total |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Wed Sep 11, 2013 8:28 am |
|
|
Looking at yout listing it seems that you declared the array mid code. Change it to beginning of function and check lst file. It has been mentioned here on the forum that sometimes this mid code declaration does give problems.
Regards |
|
|
akohlsmith
Joined: 25 Apr 2012 Posts: 26
|
|
Posted: Wed Sep 11, 2013 8:46 am |
|
|
alan wrote: | Looking at yout listing it seems that you declared the array mid code. Change it to beginning of function and check lst file. It has been mentioned here on the forum that sometimes this mid code declaration does give problems. |
My C code actually declares it at the top of the function:
Code: | void tx_status(void)
{
int8 i, resp[9];
resp[0] = radio_address | 0x80;
resp[1] = eedata.upper_limit_temp;
resp[2] = eedata.adv_rate + 1; /* status version of this is 1-8, not 0-7 */
resp[3] = eedata.set_temp;
resp[4] = eedata.adv_stop_temp;
resp[5] = drybulb_temp / 10;
resp[6] = wetbulb_temp / 10;
resp[7] = 0;
if (burner_feedback) resp[7] |= (1 << 0);
if (wetbulb_bad) resp[7] |= (1 << 4);
if (drybulb_bad) resp[7] |= (1 << 5);
resp[8] = (advance_paused) ? 1 : 0;
blank_display(TRUE);
for (i = 0; i < sizeof(resp); i++) {
fputc(resp[i], RADIO);
}
} |
Now taking what you said in mind, I changed the first line to
and rebuilt, and the bug is gone. Interestingly enough, it's not gone because variable "i" is now being overwritten, it is gone because the compiler is correctly using an unused RAM location to store the TRUE value it passes to blank_display().
I was creating a tiny program to recreate the issue for a bug report, but I could not get the same code generation bug to occur, even with all the global vars copied directly from the large application source and copying tx_status() and blank_display() verbatim. It looks like this is definitely a corner case issue.
Thank you so much for posting your hunch! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Thu Sep 12, 2013 11:09 am |
|
|
Word alignment....
Is a compiler problem. Has been mentioned in some other threads to do with structures (but never something as simple as an array...).
Problem is that things really have to start on 16bit boundaries. Looks as if when the array is declared immediately after the int, it 'rounds down' the start address. Generically you can't really have a 9 byte array and a 1 byte variable 'comfortably' declared' one after the other on a PIC24. Some bugs on alignment, were fixed in later V4 releases.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|