1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

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

Discussion in 'Embedded' started by FilterPunk, Jan 28, 2005.

  1. FilterPunk

    FilterPunk Guest

    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)
    //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
    "rjmp 1" "\n"
    else //4 cycles/loop
    "1: sbiw %count,1" "\n"
    "brne 1");
    FilterPunk, Jan 28, 2005
    1. Advertisements

  2. 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.
    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.
    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, Jan 28, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.