I have found what I consider to be a deficiency, if not a bug, in the ImageCraft ICCAVR C-compiler, ver 6.29. I would like to find out if what I consider to be a bug makes this compiler non-ANSI C complaint or not and what others here feel about my discovery.
I have e-mailed the author (please see my text at the end) but he does not feel this issue makes the compiler non-ANSI complaint and did not express an interest in changing the behavior.
The issue is that the compiler seems to always encode an immediate as an int data type (int on the AVR is 16-bits) and does not check the lvalue datatype (to see if it is something other than an int) during variable declarations or even usage in some cases.
That is correct behavior. If you want a "long" 1, you spell it
1L:
my_long_variable = 1L attempting to "air dirty laundry", I simply would like to hear
Opinions have nothing to do with it. The standard states that "1" is an "int". If you don't believe me, go ask in comp.lang.c, and somebody will quote the standard at you.
What makes you think the behavior you describe is incorrect (other than your wish that it be so)?
--
Grant Edwards grante Yow! VICARIOUSLY
at experience some reason
visi.com to LIVE!!
Your code is faulty. The digit 1 describes an int (which I assume is a 16 bit quantity on your system), and the shift of 17 causes overflow, and thus undefined behavior. You should start with a long, by using "1L" as the initial value.
Again, the same problem. The proper promotion of 65532 on a 16 bit system is to unsigned int, and in this case the action of adding 250 is properly described by the standard. Converting the result to long is giving the correct result.
The compiler appears to comply with the standards as it is.
--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
Available for consulting/temporary embedded and systems.
USE worldnet address!
Please cite the ANSI specification that has been violated by this behavior. All integer constants are by standard assumed to be int. Shifting by more bits than the size of the target is undefined and if I recall correctly is stated as such in the ANSI standard.
On Sun, 16 Nov 2003 02:44:34 -0600, Vincent wrote in comp.arch.embedded:
Others have pointed out that it is your understanding of the C language that is at fault, not the compiler.
[snip]
This would not work either. The addition would still produce the unsigned int value 246. The cast to long when assigning to long has absolutely no effect, the conversion is automatic with the assignment.
To get the result you want, you would minimally need to do something like this:
Really, you have been bitten by your misunderstanding of C.
I certainly hope so. The compiler would be seriously non-conforming it if did not act the way you observed.
Are you evaluating the compiler for personal use, or perhaps for use by your company? If the latter, you are frankly do not have enough knowledge of C to be qualified.
Almost all gcc ports other than ARV are for 32-bit targets, as are all current and recent Microsoft and Borland compilers. On a 32-bit architecture, int is 32 bits so your literals happen to be 32-bit even though they are int.
You sound a little like the newbies who post to alt.comp.lang.learn.c-c++ and comp.lang.c in puzzlement when one of their first assignments does not seem to work as expected. This one is a classic, the centigrade to fahrenheit conversion program:
#include #include
int main(void) { float cent, fahr; char input[100];
No matter what you enter at the prompt, the output is 0.000000. Why? Because the division 5/9 is a division of two integer values and produces an integer result, namely 0. In this case, it makes no difference whether int has 16 or 32 bits.
Not only is it not the compiler's job to notice that you are eventually using a floating point value, and so convert 5 and 9 to float for the division, it would violate the C standard if it did so.
There is an entry in the FAQ for comp.lang.c that exactly covers this situation:
formatting link
If you want become truly knowledgeable about C, start with the FAQ for comp.lang.c, length in my signature. For the true professional, the ANSI/ISO/IEC International Standard for C can be purchased and downloaded in PDF format for $18.00 from
formatting link
Just search for ISO number 9899.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Even once you have fixed your misunderstanding of how literals are treated in C, you might want to think a little about your code - it is a very inefficient way to solve your problem. When doing embedded programming, you should always be thinking about what the processor has to do, and if that is the best way to do it.
instead of _wasting_ (sic!) days, spend some money and buy a suitable static code checker.
Even if you _know_ some day what a C compiler has to do, you will still make errors by accident. Many of them can be detected by a static code checker. I suggest PC-Lint, but see the thread "Lint for microcontrollers" to learn that it's not only my opinion.
Lint early, lint often. Lint is your friend. Yes, I wasted also a lot of time before I bought it.
Nevertheless you should have some idea of 'C' to be able to use lint correctly.
First, my apologies for not following up the initial thread, my newsgroup server seems to have expired it, hence a new posting.
Secondly, I would like to thank everyone for pointing out MY mistakes and informing me of what the ANSI C standard states with respect to immediates (and thus showing that there was not a bug in ImageCraft ICCAVR).
I also realize in my post I should have simply asked what the ANSI standard states with respect to encoding immediates instead of implying that ICCAVR was treating them in a non-standards compliant manner.
There was also mention by David Brown that my code was inefficient; while I certainly do not expect other people to solve my problem, if anyone would like to offer suggestions on what might make the code smaller/faster, I would appreciate it. I suppose instead of shifting the data, I could use a is_bit_set type of macro which could make use of the AVR's bld/bst instructions or branch to a section of code if bit isn't set, etc.
Finally, I would like to apologize to Richard Man for implying that his product or his company were at fault(for anything). Even though there were no errors or mistakes on his part, Richard was still kind enough to provide a response, I can't say many companies would be willing to go out of their way as he did.
This post is such a rariety in usenet that it should be printed out and framed...
The key inefficiency was that you had a loop that was roughly:
uint32 data; uint8 i; for (i = len-1; i != 255; i--) { if (data & (1UL = 1; }
32 bits leads to 32 shifts. You could do even better by dealing with a single byte at a time, since that's what an AVR handles best, but the main point was to reduce the O(n^2) algorithm to O(n).
I don't think I can accept this way of counting shifts as a valid one, unless AVR had only a shift-by-one operator instead of one that takes the shift width as an operand. I'm not familiar with the AVR, but for an architecture that's often described here as C-friendly by design, that'd be a very silly state of affairs. I can see no acceptable reason a compiler should generate code of O(N) runtime to implement a shift-by-N.
I'd classify a compiler for any 8-bit architecture that uses all of 30 shift instructions to implement (1UL
I think you are gravely misunderstanding what is involved in 8-bit cpu design, what are sensible decisions in library code for such a micro, and what is expected of a good programmer for such a micro. I also think it is more than a little impolite to start referring to the ICCAVR author as "brain damaged" - even if you were correct in what you were saying.
First off, the AVR does not have a barrel shifter - even an 8-bit barrel shifter is expensive in real estate and power consumption for a cpu in which small size and power is critical, and the rarity of large shifts in real code means it is not worth having. It is a different matter for 32-bit cpus, where a barrel shifter can be made sensibly with a tree structure, and can save a lot of time for large shifts. The alternative to a barrel shifter would be microcoded shifters, which are a big no-no on a risc chip.
I don't see how "C-friendly" would imply a barrel shifter in any way - large shifts are not that common in most C code. And anyway, despite claims to the contrary, the AVR has a great deal of C-unfriendly architecture decisions, even though it is far more "C-friendly" than traditional accumulator-style 8-bit cpus.
And even if the chip had an 8-bit barrel shifter, it would be of limited use for 32-bit shifts - you would have to do so much masking and "cut and paste" of the bytes that it would hardly be worth it. It's like doing a 32-bit division on a cpu with a hardware 16-bit divider - it has to be done long-hand, without making use of the hardware divider.
So you are left with a using a library routine for the 32-bit shift (or indeed any other shifts). There are several ways to implement such a routine. The simplest would just loop through the shift-count, doing a single shift in each loop. A more complex routine would sort out groups of eight shifts, and handle these by byte movements, and then do individual shifts. A really advanced one would also use nibble swapping for shifts of
4, and consider left shifts of 7 as a right shift of 1 followed by byte movement, and so on. But is there any point in such optomisations? They would produce much bigger library code, for only a small gain, and almost never be used. The huge majority of shifts in real code are of 1 or 2 - large, variable shifts are very rare (the exception is for constants such as (1 shift instructions to implement (1UL brain-damaged. It should never take more than 6, and really only one
Ignoring the lack of a "shift by 6 instruction", what you have written here is code dedicated to the function (x O(D) on datatypes D times the machine's word size, right. But not
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.