[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] How to reserve registers
From: |
Paulo Marques |
Subject: |
Re: [avr-gcc-list] How to reserve registers |
Date: |
Tue, 03 Jan 2012 14:21:20 +0000 |
User-agent: |
Thunderbird 2.0.0.23 (X11/20090817) |
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?
Re: [avr-gcc-list] How to reserve registers, Volker Kuhlmann, 2012/01/03