avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] How to reserve registers


From: Omar Choudary
Subject: Re: [avr-gcc-list] How to reserve registers
Date: Tue, 3 Jan 2012 14:43:56 +0000

Thanks for the tip, indeed the AVR I'm using (at90usb) has 3 GPIO registers.
Didn't know about this trick. However, I am a bit afraid of using this approach,
since I use many external libraries such as avr-libc and LUFA which might
use these registers.  But for any other scenario definitely a good option.

I am using avr-gcc 4.5.2.

The listing I've shown you was caused when C timer interrupt was calling
an assembler subroutine. Therefore I assume the avr-gcc compiler
didn't bother too much in checking which registers were actually used by the
assembler subroutine, hence pushing all it could. The reason, as
mentioned earlier,
was to keep the code tight.

Thanks again.

Omar

On Tue, Jan 3, 2012 at 2:21 PM, Paulo Marques <address@hidden> wrote:
> Omar Choudary wrote:
>> That is almost correct. The 2 points:
>>
>> 1. You are right that at this point you might almost do it in C. However
>> the difference is of about 20-30 cycles which is actually significant since
>> the avr-gcc introduces many more instructions to save more registers
>> than they are actually needed.
>>
>> This is an output from what avrlibc will use to protect registers:
>> --------------------
>> 610:   1f 92           push    r1
>>      612:   0f 92           push    r0
>>      614:   0f b6           in  r0, 0x3f    ; 63
>>      616:   0f 92           push    r0
>>      618:   0b b6           in  r0, 0x3b    ; 59
>>      61a:   0f 92           push    r0
>>      61c:   11 24           eor r1, r1
>>      61e:   2f 93           push    r18
>>      620:   3f 93           push    r19
>>      622:   4f 93           push    r20
>>      624:   5f 93           push    r21
>>      626:   6f 93           push    r22
>>      628:   7f 93           push    r23
>>      62a:   8f 93           push    r24
>>      62c:   9f 93           push    r25
>>      62e:   af 93           push    r26
>>      630:   bf 93           push    r27
>>      632:   ef 93           push    r30
>>      634:   ff 93           push    r31
>> --------------------
>> the same in reverse and using pop is used at the end. If you look at my
>> code you'll see that actually you save cycles.
>
> If gcc is doing this, it is a missed optimization at best (or a bug).
> From what I remember, gcc only pushed the registers you actually use
> unless you call external functions, in which case it has no option but
> to push everything.
>
> Are you sure that a function like this:
>
> volatile uint32_t counter;
>
> interrupt_function()
> {
>        counter++;
> }
>
> pushes all those registers?
>
> What compiler version are you using?
>
>> 2. Indeed there might be a bug there if the time2 interrupt modifies
>> those registers.
>> Thanks for pointing it, I was relying on the fact
>> that my interrupt saves the value but I realize that indeed the RAM value 
>> will
>> be modified within access to the 4 bytes.
>>
>> I guess a quick fix to this is to disable interrupts in the assembler 
>> functions
>> that access the ram value.
>
> Or you could have a look at the atomic.h macros which do exactly that
> while allowing you to program in C.
>
> Anyway, if you really want to optimize your counter, check if your
> device has "general purpose i/o registers" (GPIORn). These registers act
> as ports, so can be addressed with IN/OUT instructions (saving one clock
> cycle over RAM accesses) but are actually general purpose 8 bit
> registers that can be used to hold any data the application wants to use.
>
> If you look at the datasheet for the atmega168 (for instance), you'll
> see it has 3 of these registers which could hold the lower 3 bytes of
> the counter. This way you only use one register to access all of them
> and only need to push one register.
>
> Something like this (pseudo-code):
>
> push    r0
> in      r0, SREG
> push    r1
> eor     r1, r1
> push    r2
>
> sec
> in      r2, GPIOR0
> adc     r2, r1
> out     GPIOR0, r2
> in      r2, GPIOR1
> adc     r2, r1
> out     GPIOR1, r2
> in      r2, GPIOR2
> adc     r2, r1
> out     GPIOR2, r2
> lds     r2, high_counter_byte
> adc     r2, r1
> sts     high_counter_byte, r2
>
> pop     r2
> pop     r1
> out     SREG, r0
> pop     r0
> reti
>
> I hope this helps,
>
> --
> Paulo Marques
> Software Development Department - Grupo PIE, S.A.
> Phone: +351 252 290600, Fax: +351 252 290601
> Web: www.grupopie.com
>
> Pointy-Haired Boss: I don't see anything that could stand in our way.
>           Dilbert: Sanity? Reality? The laws of physics?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]