Re: Telling inline asm that input register is clobbered?

Georg-Johann Lay <[email protected]>
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>
Paul Sokolovsky wrote:
> Hello,
> 
> Georg-Johann Lay wrote:
> 
>> Paul Sokolovsky wrote:
>>>
>>> I'd like to reimplement __builtin_avr_delay_cycles() function in
>>> inline assembly. The reason is that __builtin_avr_delay_cycles() has
>>> too-early operand checking, so for example
>>>
>>> static __attribute__((__always_inline__)) my_delay(int cycles)
>>> {
>>> 	__builtin_avr_delay_cycles(cycles);
>>> }
>> Would you supply a test case?
>>
>>> Will still complain that __builtin_avr_delay_cycles(cycles) is not
>>> constant even for cases like my_delay(10).
>> Also consider to make the function inline and to make 'cycles' const.
> 
> Thanks for good hinting!
> 
> Yes, first of all gcc can const-expr optimize following code if
> compiled with -O:
> 
> --------
> static void my_delay(int delay)
> { __builtin_avr_delay_cycles(delay); }
> int main()
> { my_delay(10); }
> --------
> 
> I guess, by marking that always_inline, compile without explicit -O
> would work too. What's crucial here is "static" however - without it,
> gcc tries to produce non-inlined version, and that's where it fails.

In order to make it work with C and without optimization, you will need a
properly prototyped my_delay:

static inline __attribute__((always_inline))
void my_delay (const unsigned long delay)
{
  __builtin_avr_delay_cycles (delay);
}

int main (void)
{
  my_delay (10);
}

Notice that the optimization with -O0 is very limited, thus if you ever need a
non-const delay, consider writing your own delay function.

Besides that, using design-pattern "delay" for anything else than short delays
to wait for, say, parasitical capacities / inductivities, can be considered as
a design flaw.  But that's a different story...

> However, my usecase is using that in C++ template lib, and I
> need that to be in a method of class, which can't be "static" in the
> same sense as static function in C.

Sorry, I cannot help you with dreaded [tm] languages like C++ ;-)

> But the case above reminded me - if you want to do this time of magic in
> gcc (essentially, compile-time evaluation), you need to use
> __builtin_constant_p() function. That's actually how I did it first for
> msp430, but then found out there it works even without
> __builtin_constant_p(), so I lazily commented it out (saves thinking
> what to do for !__builtin_constant_p() case) and then forgot about.

Maybe __builtin_avr_delay_cycles is too limited with the const delays.  Using
variable delays is possible if the requirement of cycle-exactness is dropped.

> So, I started another try on ldi-based approach, and just got lucky
> that my test code had "good" value of literal integer constant. Because
> it turned out that "M" asm constraint is very picky regarding value it
> gets. One would think that casting to uint8_t would be the best way to
> get a value suitable for it, but actually, that will throw "error:
> impossible constraint in ‘asm’" for any value >=0x80. Fortunately, I
> found that (& 0xff) does the trick, so mission accomplished.

The question is why you use "M" in the first place and not "n"?

> That "M" behavior still looks like bug, so hope a testcase below may be
> useful (not sure if attachments are allowed, so just pasting):
> 
> =========
> #include <stdint.h>
> 
> int delay1(int d)
> {
>     if (__builtin_constant_p(d)) {
>         asm(
>             "ldi    r24, %0 \n"
>             "1: \n"
>             "subi   r24, 1 \n" //1
>             "brne   1b \n"
>             : : "M" ((uint8_t)d) : "r24"
>         );
>     }
> }

You may want to consider code like the following:

static __inline__ __attribute__((always_inline))
void delay1 (const unsigned d)
{
    unsigned d2;
    __asm volatile ("1:"      "\n\t"
                    "dec  %0" "\n\t"
                    "brne 1b"
                    : "=r" (d2) : "0" (d));
}

Notice that inlining is indicated because otherwise, the call overhead will
garbage your delay time.  Similarly, the "const" is no sugar with -O0: it is
needed so minimize the overhead at -O0.  Try it out!

Moreover, without "volatile" the asm may be optimized away because it has no
side effects then.

Finally, notice that AVR Libc has similar stuff in util/delay.h


Johann


_______________________________________________
AVR-GCC-list mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.