|
|
View previous topic :: View next topic |
Author |
Message |
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
Isn't it a bug ? CCS 3.202 version |
Posted: Wed Jun 02, 2004 1:38 am |
|
|
I'm not fluent in assembly langage but the last instruction in this for(;;) loop seems to take an absolute address instead of the relative jump specified for BRA instruction ?
In 3.191 version a goto instruction with an absolute jump was used and everything works perfectly well in my soft. With 3.202 everything is messed up.
Is it a bug in 3.202 version or am I missing something ?
Code: |
.................... for(i=0; i<(LONGUEUR_TRAME_EMISSION-1); i++) trame_emission[(LONGUEUR_TRAME_EMISSION-1)]^=trame_emission[i];
24D2: MOVLB 5
24D4: CLRF i
24D6: MOVF i,W
24D8: SUBLW 11
24DA: BNC 24F6
24DC: CLRF @03
24DE: MOVF i,W
24E0: ADDLW trame_emission
24E2: MOVWF FSR0L
24E4: MOVLW trame_emission+-118
24E6: ADDWFC @03,W
24E8: MOVWF FSR0H
24EA: MOVF INDF0,W
24EC: MOVLB 0
24EE: XORWF trame_emission+18,F
24F0: MOVLB 5
24F2: INCF i,F
24F4: BRA 24D6
|
|
|
|
C-H Wu Guest
|
false alarm ? |
Posted: Wed Jun 02, 2004 4:27 am |
|
|
'GOTO' takes 2 words while 'BRA' takes only 1. Using BRA for short jump is the new default optimization for 3.202 such that the code size can be reduced by 10 ~ 15%. If you don't like it, you can use #opt 5 or #opt 7 to go back to the old days.
Instead of using the symbolic listing, try Microchip format for the LST file by Option -> File format, then you can read the OP code to find out that 'BRA' is in fact short jump, the symbolic listing shows the absolute address just for easy reading.
By the way, did you test your code ? Anything wrong other than code size reduction ?
Best regards
C-H Wu |
|
|
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
False alarm |
Posted: Wed Jun 02, 2004 8:45 am |
|
|
Thank you for your help
Yes, I tested it. It doesn't work. I have a subroutine tha displays graphic icons on LCD. No icon displayed. This is probably the visible part of the iceberg, I didn't tracked down the problem any further to get back to work and came back to the 3.191 version. |
|
|
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
Additional information |
Posted: Wed Jun 02, 2004 8:52 am |
|
|
I've just tested version 3.202 with the #opt 5 you mentionned. And now icons are displayed perfectly well. I had a look at the lst file and find GOTO instructions instead of BRA at the end of for(;;) loops. |
|
|
C-H Wu Guest
|
Re: False alarm |
Posted: Wed Jun 02, 2004 10:10 am |
|
|
Schmobol wrote: | Thank you for your help
Yes, I tested it. It doesn't work. I have a subroutine tha displays graphic icons on LCD. No icon displayed. This is probably the visible part of the iceberg, I didn't tracked down the problem any further to get back to work and came back to the 3.191 version. |
Well, sounds like a real bug !
If you have time, please try to narrow in the problem and send a bug report to CCS, we will be grateful to your help.
Also, be careful with the delay_us() bug, it is still there in 3.191 although 3.201 fixed this bug.
Code: | // bug_3191_delay_us.c
#include <18F458.H>
#fuses HS, NOLVP, NOWDT, NODEBUG, PUT
#use delay(clock= 40000000)
#use RS232(baud = 115200, xmit= PIN_C6, rcv= PIN_C7)
void main()
{
int16 i; int8 k= 0;
while ( 1 )
{
for(i=0;i< 5000;i++) delay_us(200);
printf("%u ", ++k); // numbers should come out once every second,
// but ... it runs like crazy with 3.191 !
}
}
|
delay_us( n ) has bug if n > 153 in this case. The problem is, which version shall we call it 'stable' ? My feeling is 3.202 with #opt 5 might be better than 3.191.
Best regards
C-H Wu |
|
|
kory Guest
|
#opt 5 didn't help me |
Posted: Wed Jun 02, 2004 1:11 pm |
|
|
I'm having the same problem (absolute jumps to bad addresses) but adding the "#opt 5" didn't help at all. I even tried #opt 4 and 3.
Kory |
|
|
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
bug identified |
Posted: Thu Jun 03, 2004 3:25 am |
|
|
I think I finally found a problem. Hereafter is a Branch instruction at the end of a for(;;) loop
Address Opcode Disassembly
1B9E D277 BRA 0x208E
The code optimization replaces a GOTO instruction by the BRA instrution (that takes a relative jump between -1023 and 1024). The goal is to jump to absolute address 0x208E but the compiler doesn't seem to realise that 0x208E - 0x1B9E = 0x4f0 (1264 in decimal) is greater that the range of the BRA argument.
The opcode D277 makes a relative jump of 0x277 to 0x1B9E + 0x277 = 0x1E15, which is obviously erroneous.
It seems that the compiler doesn't verify the range of the jump before replacing a GOTO instruction (in previous compiler version) to BRA instruction for optimization. |
|
|
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
Bug identified |
Posted: Thu Jun 03, 2004 3:39 am |
|
|
Bug has been reported to CCS. For those of you who are experiencing the same problem, I solved this specific problem by adding #opt 5 while keeping 3.202 version.
Thanks to C-H Wu for this good advice. By the way, where is the "#opt x" command documented ? |
|
|
Schmobol
Joined: 01 Mar 2004 Posts: 22 Location: Nice, France
|
Not a bug |
Posted: Thu Jun 03, 2004 4:10 am |
|
|
I missed something int he calculation of the relative jump. As specified by the datasheet the relative jump is calculated by the following formula 2n+2. And the BRA instruction previoulsy mentionned is correct.
The problem is somewhere else ! |
|
|
Guest
|
Re: Bug identified |
Posted: Thu Jun 03, 2004 4:34 am |
|
|
Help -> index -> #opt
#OPT
Syntax:
#OPT n
Elements:
n is the optimization level 0-9
Purpose:
The optimization level is set with this directive. The directive applies to the entire program and may appear anywhere in the file. Optimization level 5 will set the level to be the same as the PCB,PCM,PCH stand-alone compilers. The PCW default is 9 for full optimization. This may be used to set a PCW compile to look exactly like a PCM compile for example. It may also be used if an optimization error is suspected to reduce optimization.
Examples:
#opt 5 |
|
|
C-H Wu Guest
|
Is it a bug, or some ANSI ? |
Posted: Sat Jun 05, 2004 10:59 am |
|
|
Hi, All:
I have a question for the following code for 18F458:
Code: | int8 x = 0x10;
int1 bit_a = 0;
bit_a = x & 0x30; printf(" %u ", bit_a);
|
PCWH 3.202 returns 0 for bit_a while 3.187 returns 1 !!!!!
There are no error or warning message.
What should be the result under ANSI ?
It took me a couple of hours to find out this _NEW_ feature.
Thanks for your comments and ...
Best wishes
C-H Wu |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: Is it a bug, or some ANSI ? |
Posted: Mon Jun 07, 2004 1:30 pm |
|
|
Quote: | I have a question for the following code for 18F458:
Code: | int8 x = 0x10;
int1 bit_a = 0;
bit_a = x & 0x30;
printf(" %u ", bit_a);
|
PCWH 3.202 returns 0 for bit_a while 3.187 returns 1
There are no error or warning message.
What should be the result under ANSI ?
It took me a couple of hours to find out this _NEW_ feature. |
I tested this problem with PCM vs. 3.188 and 3.202, and I saw
a similar result. I looked at the ASM code in the LST file.
In 3.188, the compiler acts as if int1 is an built-in Boolean data type.
It checks if the expression on the right is non-zero, and if so, it
sets the int1 variable = 1. In other words, it does a type conversion
on the result of the expression, and converts it to a boolean type.
In PCM vs. 3.202, it's done differently. The code just checks bit 0
of the expression result and sets the int1 variable equal to that value.
That's completely different ! The compiler is now acting as if an
int1 variable is a 1-bit wide integer. So if you assign an integer of
a larger width to an integer of a smaller size, the upper portion of
the integer is truncated. That's correct, in terms of doing a type
conversion.
But this is a huge change in philosophy on the treatment of int1
variables, and there is no notice given in the Readme file.
That being said, when I first saw your test program, my first thought
was "I would never write code like that". I would have written it like this:
Code: | if(x & 0x30)
bit_a = 1;
else
bit_a = 0; |
Or if I was feeling really strict with myself, I would do it like this:
Code: | if((x & 0x30) != 0)
bit_a = 1;
else
bit_a = 0; |
I can't really tell you why I write code like this. I just automatically
do it. Maybe I have been "trained" by CCS to do it this way.
But you can see the difference. Your method requires a basic trust
that a proper type conversion will be done. My method does not.
I have seen one method of converting an integer expression to a
boolean type. It uses the "logical negation operator".
bit_a = !!(x & 0x30);
This works because the first negation automatically turns the
expression result into a Boolean value. The 2nd negation then
turns that result into positive logic.
The only reason I would not use this method is because it's very easy
to type in only one exclamation point, by accident.
---------------
Since you discovered this problem, do you want to email CCS about it ? |
|
|
C-H Wu Guest
|
Is 'int1' boolean ? or integer ? |
Posted: Mon Jun 07, 2004 8:23 pm |
|
|
PCM programmer:
Thanks for your reply.
Regarding the _NEW_ feature of 3.202 in int1 variable operation :
Code: | int8 x = 0x10;
int1 bit_a = 0;
bit_a = x & 0x30; |
1. I wrote to CCS asking for a warning meesage, no response yet, well, its Monday, I will wait. BTW, they raise an error message to bit_a = 0x30; in 3.202 but not in 3.187, 188 or 3.191.
2. the 'stable' version 3.191, also return 1. The change seems to started from 3.200 (?).
3. I fully agree that I should _NEVER_ write code like that because of the _ambiguity_ behind the code. But, it just happened during the time I was trying, playing and learning bit operation with mask using CCS. And I told myself, gee, CCS is a _SPECIAL_ C-compiler that allow you to save some typing. It was 8 monthes ago when I left the code like that, which is part of a general purpose library for many ongoing projects not just my project, so, what will happen if I tell my people let's go for the new 3.202 ? (motto: _NEVER_ upgrade CCS unless you really need it.) Now I modified the code after this surprise with more considerations on reliability and future maintenance Code: | bit_a =(x & 0x30) > 0 ;
bit_a =(x & 0x30) > 0 ? 1 : 0;
bit_a = x & 0x30 ? 1 : 0;
| My personal choice is the second one with the '?' operator since it is just another expression of the if-else statement, less typing, ANSI standard, although it is a little bit less explicit than the if-else statement.
Is 'int1' boolean or integer ? What will be the result of bit_a = x & 0x30 according to the philosophy of ANSI ? I looked into K&R's 2nd ed.,section 6.9, Bit-fields, page 149, seems like that int1 should be treated as a _small_ integer instead of boolean.
I just hope no one else got this kind of bite like me.
Best wishes
C-H Wu
BTW, I will use my story as a 'lesson' for students. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Jun 08, 2004 1:37 am |
|
|
Quote: | Code: | bit_a =(x & 0x30) > 0 ;
bit_a =(x & 0x30) > 0 ? 1 : 0;
bit_a = x & 0x30 ? 1 : 0; |
|
In ANSI-C an expression is TRUE when the result is not equal to 0. Your code will work well most of the times because of an other curiosity of the CCS compiler, variables are standard unsigned instead of signed. Your code might fail in the case of signed integers therefor I suggest:
Code: | bit_a =(x & 0x30) != 0 ;
bit_a =(x & 0x30) != 0 ? 1 : 0;
bit_a = x & 0x30 ? 1 : 0; |
|
|
|
|
|
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
|