View previous topic :: View next topic |
Author |
Message |
CED123
Joined: 03 Aug 2006 Posts: 5
|
C compiler FOR loop |
Posted: Thu Aug 03, 2006 12:20 pm |
|
|
I can't find any reference to this problem in the archives.
A particular instance of a C FOR loop generates code that on termination branches to the correct instruction +1. In this case, it is a BCF 03.5 instruction to reset the memory bank that it fails to execute, causing a crash. The instruction is there in the code listing at 061A, but the FOR termination jumps to 061B instead. Inserting an explicit Bit_Clear(*3,5) in the C is a clumsy work-around.
Any comments on the problem (not about the functionality of the routine)?
Code: | #include <16f877a.h>
///////////////////////////////////////////////////////
// Send a long value in decimal down the serial line //
// This function avoids mult and div of longs //
///////////////////////////////////////////////////////
void send_value(long val)
{
long const dectab[5] = {10000,1000,100,10,1};
long v;
v = val;
if (v == 0) OutChar('0'); // spare us the print loop if zero
else
{
short lead = 0;
int i;
for (i = 0; i<5; ++i) // this branches to the wrong place on termination
{
int dig;
long div;
div = dectab[i];
for (dig=0; v>=div; ++dig) v-=div; // subtract until v too small
if (lead || dig) // print character unless leading zero
{
OutChar(dig + '0');
lead = 1; // flag to say we have a leading character
}
}
}
Bit_Clear(*3,5); // work around compiler bug
Eol();
}
void Eol(void)
{
putc('\r'); // Send Eol
}
void OutChar(char ch)
{
putc(ch); // Send the character
}
Generated code listing:
.................... int i;
.................... for (i = 0; i<5; ++i)
05E3: CLRF 50
05E4: MOVF 50,W
05E5: SUBLW 04
05E6: BTFSS 03.0
05E7: GOTO 61B
.
.
.
.................... }
0618: INCF 50,F
0619: GOTO 5E4
061A: BCF 03.5
.................... }
.................... Bit_Clear(*3,5);
061B: BCF 03.5
.................... Eol();
061C: CALL 4A3
061D: RETLW 00
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 03, 2006 12:26 pm |
|
|
What is your compiler version ? |
|
|
CED123
Joined: 03 Aug 2006 Posts: 5
|
|
Posted: Thu Aug 03, 2006 12:30 pm |
|
|
Quote: | What is your compiler version ? |
3.098 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 03, 2006 1:03 pm |
|
|
Before I research your problem, look at this section of the CCS versions
page. CCS added some "improvements" and then spent the next 30
days fixing them. I don't know if this will work, but try putting #opt 7
near the top of your program, right after the #include line. See if it affects the problem.
Quote: |
3.097 Optimization improvments
3.099 Fixed optimization problems (#opt 7 removes new opt, #opt 8 uses it)
3.100 Baseline version - passes all internal tests
3.101 More optimization improvments
3.103 Optimization bug fix
3.103 Some fuses that were not working are fixed
3.104 Another optimization bug fix |
|
|
|
Guest
|
|
Posted: Fri Aug 04, 2006 5:58 am |
|
|
Adding #opt 7 causes a small shift in the code addresses but does not fix the problem. |
|
|
CED123
Joined: 03 Aug 2006 Posts: 5
|
|
Posted: Fri Aug 04, 2006 6:00 am |
|
|
For some reason that last post named me as "Guest" even though I had logged in. I've logged in again now and am posting this as a test. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 04, 2006 10:02 am |
|
|
Report the bug to CCS support and show the C source and the ASM code.
Explain to them how this bank select bug makes your version unusable.
Give them your version of the compiler and your customer number,
and ask if they will give you an upgrade to a later, working version. |
|
|
CED123
Joined: 03 Aug 2006 Posts: 5
|
|
Posted: Fri Aug 04, 2006 10:21 am |
|
|
OK, I'll do that.
I've tried stripping code out of the loop, and the minimum it seems to need to produce the problem is:
(1) an IF statement with the true condition calling a function in a different bank
(2) a FOR loop in the ELSE clause
Example follows. Note that the BCF 03.5 at 0635 is unreachable, but is needed if the ELSE clause is executed.
Code: | void sv(long v)
{
if (v == 0) OutChar('0');
else
{
int i;
for (i = 0; i<5; ++i) {}
}
Eol();
}
.................... void sv(long v)
.................... {
.................... if (v == 0) OutChar('0');
*
0622: MOVF 54,F
0623: BTFSS 03.2
0624: GOTO 62E
0625: MOVF 55,F
0626: BTFSS 03.2
0627: GOTO 62E
0628: MOVLW 30
0629: MOVWF 57
062A: BCF 03.5
062B: CALL 46C
.................... else
062C: GOTO 636
062D: BSF 03.5
.................... {
.................... int i;
.................... for (i = 0; i<5; ++i) {}
062E: CLRF 56
062F: MOVF 56,W
0630: SUBLW 04
0631: BTFSS 03.0
0632: GOTO 636
0633: INCF 56,F
0634: GOTO 62F
0635: BCF 03.5
.................... }
.................... Eol();
0636: CALL 4A3
.................... }
|
|
|
|
CED123
Joined: 03 Aug 2006 Posts: 5
|
|
Posted: Mon Aug 07, 2006 3:36 am |
|
|
Thanks for your help on this one. CCS kindly sent me V3.125. This fixes the FOR loop bug at the expense of slower execution time and greater ROM usage. When waiting for character output, extra time is not a problem, of course, but there are time-critical loops in other parts of the code that I will have to check. |
|
|
|