Using constrains: GCC vs ICCAVR (was: Assembly delay function: GCC vs ICCAVR)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I think I now understand what exactly each command of the below inline
assembly code does (thanks to Tauno Voipio).
But again, if someone with real knowledge of Atmel AVR assembly code
finds a mistake, please correct my annotations.
Now I rewrote this function for the ICCAVR. But since I didn't find
out if and how this compiler uses constrains, I just omitted them. The
result is, that the generated assembler code uses r16 instead of r24
(upper register), which is used when compiled with gcc.
And the error output is: "Register 16 is not valid".
How can I force ICCAVR to use upper register (e.g. the "w" constrain
used with gcc)?

Thank you!


Following code works for gcc
/*************************************************************************
 delay loop for small accurate delays: 16-bit counter, 4 cycles/loop
*************************************************************************/
static inline void _delayFourCycles(unsigned int __count)
{
  if ( __count == 0 )                      //delay of 2 cycles  
    __asm__ __volatile__( "rjmp 1f\n 1:" );//relative jump to label 1
                                           //(forward decelerated)
                                           //\n(linefeed)separates
                                           //inline assembly commands
                                           //1: is label 1,with no
                                           //following code->2cycl.
  else                                     //__count is not equal 0
    __asm__ __volatile__ (                 //4 cycles/loop
      "1: sbiw %0,1" "\n\t"                //label 1: sbiw (subtract
                                           //immediate 1 from count)
            "brne 1b"                      //compare the result from sbiw
                                           //with 0 and brne(branch if
                                           //not equal) to label 1
                                           //(backward decelerated)
                                           //constrains for sbiw
            : "=w" (__count)               //"="-enables write-permission
                                           //for this register
                                           //"w"-use upper reg. pairs
                                           //(r24, r26, r28, r30)
            : "0" (__count)                //"0"-use the same reg. for
                                           //result as __count
    );
}

Following code does NOT work for ImageCrafts ICCAVR compiler
/*************************************************************************
 delay loop for small accurate delays: 16-bit counter, 4 cycles/loop
*************************************************************************/
static inline void _delayFourCycles(unsigned int __count)
{
    if ( %count == 0 )                     //2 cycles
       asm(
       "rjmp 1" "\n"
       "1:");
else                                       //4 cycles/loop
    asm(
    "1: sbiw %count,1" "\n"
    "brne 1");
}

Re: Using constrains: GCC vs ICCAVR

Quoted text here. Click to load it

You appear to have got it all right, except maybe the use of the term
"decelerated" in your description of the local labels.  You seem to
have got the idea right, but not the terminology.

Quoted text here. Click to load it

That will automatically make the resulting code a less useful than the
GCC version --- automatich register picking by GCC even for inline
assembler is a big potential win.  In particular, it means GCC can
plan ahead, knowing it'll need 'count' in a particular type of
register, and put it there a lot earlier, maybe even keep it there all
the time.  And if it doesn't, it'll know it has to move count into
such a register before expanding the actual inline assembly.

Quoted text here. Click to load it

Either you find out how to teach your assembler the same kind of
tricks as used by GCC's "extended inline asm", or you have to do that
manually.  I.e. you may have to move %count to r24 by hand, rather
than GCC doing that for you automagically.

I also strongly suspect your ICCAVR version of the forward
vs. backward jump direction won't work as coded.

Without the "extended" features of GCC inline asm, there may not even
be enough benefit left to warrant doing this in inline asm at all.
Writing a non-inlined subroutine in a separate asm source file may
thus very well end up being the best option.

--
Hans-Bernhard Broeker ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Site Timeline