Imagecraft ICCAVR & ANSI Standards compliance

V

Vincent

Guest
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<<17);

results in my_long_variable holding decimal 0 since the immediate value
of 1 is encoded as a 16-bit quantity, *then* shifted.

Note: That a long in this architecture[AVR] is 32-bits (signed) and
would have enough bits to hold decimal 131072.

As another example,

long second_long_variable = (65532+250);

results in second_long_variable holding decimal 246 instead of decimal
65782 at run-time.

The compiler does not evaluate the expression (65532+250) before an
assignment, but instead encodes 65532 as a 16-bit quantity, then adds
250, to a 16-bit quantity which results in a wrap-around to 246. Without
adding a cast operator in the declaration, the long variable is
initialized to an unexpected value (of 246).

If the compiler did look at the lvalue during the compile time and
realized it needed to store 65532 as a long, then the subsequent
addition operation would result in the variable holding the correct
value, even though it would involve an unnecessary add.

The only way I found to get the compiler to generate what I consider
"expected" behavior is to forcefully use the casting operator, as
follows:

long my_long_variable = ((long)1<<17);

or

long second_long_variable = ( (long)(65532+250) );

I was bitten by the encoding behavior not because I was declaring my
variables using the shift operator, but instead I had a code fragment as
follows:

/* Data typedefs */
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;

/* Macro to 'select' a bit */
#define BitPosition(bit) (1 << (bit))

void Send_IndividualBits_over_SPI(uint8 data_length, uint32 data_out)
{

uint8 index;

/* Send bits MSB first */
/* When index underflows to 255, all bits have been sent */
for(index=(data_length-1); index !=255; index--)
{
/* Grab each bit in data_word, MSB first and send it out */
if( data_out & ( BitPosition(index) ))
{
/* Code for sending when bit is high */
}
else
{
/* Code for sending when bit is low */

}
}

Due to the aforementioned encoding behavior, data_out would be ANDed
with (1<<index), except the immediate, 1 , would be represented by a 16-
bits, thus the shifted value would be 0 for data_lengths greater than
16-bits. The end result is that all the bits past the 16th would be sent
out as 0, regardless of their value.

My workaround was to declare a new BitPosition32 macro that included the
(uint32) casting operator in front of the '1' and then to have two
Send_SPI routines, one for 16-bit data and one for 32-bit data, each
using their own BitPosition macro.

I have verified the compiler operates in the manner I have mentioned by
not only studying the generated assembly, but also by testing with
working hardware (AT90S8515) and doing a final cross-check with the
Atmel AVR Studio 4.0 build 240(simulator).

I would like to state for the record that I am evaluating the compiler
and I that I am currently not a paying customer. I have e-mailed the
compiler author and while he was very prompt in responding (especially
given that I have not purchased it, thus I am technically not eligible
for support) he did not seem convinced this was a major issue or
something that should be fixed.

My code, including the examples of variable declarations( with (1<<17)
for instance), produces the "expected" results on all GCC/IAR platforms
I was able to test with (including x86, ARM & AVR). I tried on a few
other x86 only compilers too, including MSFT VisualC++ & Borland 5.02,
all of which behaved as "expected".

I feel that even if this behavior does not make ICCAVR non-ANSI
complaint, the manner in which it treats immediates is very confusing
and certainly nonintuitive/different than other "industry" compilers. I
have spent several days trackinn down this issue and had I been a paying
customer, I would be very displeased.

Finally, I would like to make it clear that I am not attempting to "air
dirty laundry", I simply would like to hear the opinions of other
qualified, working professionals in this field.

Thank you (and apologies for the length of the message!)
--------------------------------------------------------
Vincent.
 
I would like to apologize, this message was meant for comp.arch.embedded
and I accidentally posted it in here.

Sorry to everyone for the off-topic posting.

Vincent.
 

Welcome to EDABoard.com

Sponsor

Back
Top