Pages: [1]   Go Down
Author Topic: Inline Assembler; "Impossible constraint" for byte value > 127  (Read 568 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
void setup() {}

void loop() {

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

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

}
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1837
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Shannon Member
****
Karma: 201
Posts: 11744
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?)
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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" smiley-wink
« Last Edit: October 12, 2012, 05:21:52 pm by paulo999 » Logged

Pages: [1]   Go Up
Jump to: