Imagecraft ICCAVR & ANSI Standards compliance

Hi everyone.

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.

As an example the following declaration:

long my_long_variable = (1

Reply to
Vincent
Loading thread data ...

That's what I'd expect. If you want to shift a 32 bit value, you can write

1L

I don't got IAR, but GCC 3.3.1 for the AVR produces the same result as ICC:

sts my_long_variable,__zero_reg__ sts (my_long_variable)+1,__zero_reg__ sts (my_long_variable)+2,__zero_reg__ sts (my_long_variable)+3,__zero_reg__

Please note, that x86 and ARM use 32-bit integers.

In my view ImageCraft is producing the correct result. The type of the lvalue should not initiate any kind of automatic conversion on the rvalue.

Regards, Harald

--
For spam do not replace spamtrap with my name
Reply to
Harald Kipp

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!!
Reply to
Grant Edwards

... snip ...

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!
Reply to
CBFalconer

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.

Doug

Reply to
Doug Dotson

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:

(long)65532 + 250 65532 + (long)250 65532L + 250 65532 + 250L

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];

printf("Enter Degrees Centigrade: "); fflush(stdout): fgets(input, sizeof input, stdin); cent = strtol(input, NULL, 0); fahr = cent * (5/9); printf("Fahrenheit Degrees = %f\n"); return 0; }

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
Reply to
Jack Klein

In addition to the excellent information above, the link below leads to still more info that you might find helpful.

--
Morris Dovey
West Des Moines, Iowa USA
C links at http://www.iedu.com/c
Read my lips: The apple doesn't fall far from the tree.
Reply to
Morris Dovey

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.

Reply to
David Brown
[...]

So 'C' is nonintuitive.

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.

Oliver

--
Oliver Betz, Muenchen
Reply to
Oliver Betz

Hello,

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.

------- Vincent

Reply to
Vincent

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).

Reply to
David Brown

David Brown wrote: [...]

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

Reply to
Hans-Bernhard Broeker

data

shifts,

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

Reply to
David Brown

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.