Go Down

Topic: Inline Assembler; "Impossible constraint" for byte value > 127 (Read 845 times) previous topic - next topic

paulo999

I'm trying to pass a byte to some inline assembly code.

0-127 works fine
>127 throws an 'impossible constraint' error.

I've read some gcc-avr documentation but am still stuck. Any help welcome!

Here's a sketch demonstrating my problem...

Code: [Select]

void setup() {}

void loop() {

  byte thebyte = 128;  //0-127 works, >127 causes "impossible constraint"
 
  asm volatile (
  "ldi r16,%[thebyte]"    "\n\t"

    ::
   
  [thebyte] "M" (thebyte)
    );

}


MichaelMeissner

Looking at the avg-gcc source, the "M" constraint that you are using only allows unsigned values (0..255).  There does not appear to be a constraint that would allow values in the signed range (-128..127).

MarkT

That suggests that instruction takes a _signed_ byte offset, so the value cannot be more than 127.  Replace "byte" by "char" and 128 by -128 (unless you want +128 in which case perhaps a different instruction sequence is needed?)
[ I won't respond to messages, use the forum please ]

paulo999

#3
Oct 13, 2012, 12:20 am Last Edit: Oct 13, 2012, 12:21 am by paulo999 Reason: 1
Ok, I've sorted it.

Mistake number 1:

ldi loads an immediate value, e.g. a constant. No good for passing in values which change.

Mistake number 2:

Specifying "M" in the input parameter binding, again, it's for use with constants.

What I should have been doing is using the mov instruction, and passing in using the "r" option, so that the value goes into a register.

So, the fixed code:

Code: [Select]

void setup() {}

void loop() {

 byte thebyte = 128;  //This works as intended, right up to 255
 
 asm volatile (
 "mov r16,%0"    "\n\t"

   ::"r" (thebyte)
   );

}


Oh and thanks Mark for having a go, and not saying "you shouldn't be using assembler" ;)

Go Up