ImageCraft problem with locals

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have encountered a problem where it appears that a parameter to a function and a local variable in that function are being stored in the same pair of registers. Both are of type 'unsigned int'. This is using ICCAVR7.

I see the problem using the following code and stepping through the code in AVR Studio 4.

void bar(unsigned int param)
{
 unsigned int local;
 
 local = 2000*param;
 
 return;
}

void foo(void)
{
 bar(1000);
} 

void main(void)
{
	 while(1)
	 {
	 	foo();
   }
}

In this example, in the function foo(), when the value of local is changed, so does the value of param. The is a problem with 16 bit values as the operation is not atomic, thus the result will be wrong for values larger than 8 bits.

Am I missing something?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you observing this in the simulator/debugger of AVR Studio? Specifically in the "watch window" - If so then all bets are off.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Atomicity should not play a factor here, as the calculation is not getting interrupted.

Param is also a local to the function, and is free to change value as long as it is never used again. The watch window has no idea when the lifetime of a variable ends, so it amy appear that the variable is being altered, but when in fact it is dead, and has simply been replaced by a new variable in the same location. Return values are also placed in the same registers as parameters when the function is called, so it's no surprise to see the result of the calculation over-writing the calling parameter. (I'm amazed the compiler didn't throw the code away altogether, since the result is never used, [unless you have turned optimizations off])

Just as an FYI: your parameter size is "int" which is 16 bits... your calculation of 1000 * 2000 results in a value that is too large for an into to store. (hint: unsigned 16bit variable can hold a maximum value of 65535)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I bet you are looking at the .lst generated by the compiler, and you see that the register allocator has decided that the param used R16, but right after the param gets used, R16 is avail, and gets used?
Using version 7.20 or 7.20a? (latest versions)

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is that "local" was relative to the stack pointer and then "changed" when the stack pointer changed. (I'd kind of expect an "out of scope" but if register based it may not be detected/generated.)

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the input from everyone. Turns out my problem was actually due to (surprise, surprise) a coding error on my part and was not due to the register reuse. I was bitten by mathematical precidence and implicit type conversion.
My example was simplified from my actual code which had a calculation of the form:

#define BIGVAL 1000000

unsigned int ui1;
unsigned int ui2;

ui1 = BIGVAL/(100*ui2);

The product of 100*ui2 is implicited converted to an unsigned int. (listing shows xcall of 16 bit empy16s) Therefore if it is greater than that storable in a unsigned int (65536) it will be truncated. (ouch)
Rewriting the formula as:

ui1 = BIGVAL/100/ui2;

Since the '/' operator has left to right associativity, the compiler will do the math at compile time and load the result into 4 registers (32 bits) and use the 32bit division xcall div32s. The result will be implicitly converted to a unsigned int by only assigning the lower 16 bits.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggest you add the L or UL suffix to your BIGVAL constant, since numeric literals are taken to be of type signed int by default.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.