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

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

[avr-gcc-list] GCC 3.0 patches


From: Rich Neswold
Subject: [avr-gcc-list] GCC 3.0 patches
Date: Tue, 9 Oct 2001 22:30:43 -0500
User-agent: Mutt/1.2.5i

Hello,

I have a small set of patches for GCC 3.0 to make a small improvement and
fix (what I believe to be) a bug. The patch file is attached to this
message. I'd like to hear comments.

The patch file does three things:

1. Changes two instances of '|' to '||'. It turns out that the use of '|'
still worked, but I changed it to be consistent with other boolean tests
that had the same variables.

2. I noticed that when I use "-mtiny-stack", the function prologue of
main() still adds two instructions to manipulate SPH. This patch makes sure
that if your stack is only 8-bits, main() doesn't try to touch SPH (saving
4 bytes of flash).

3. The final patch is much more involved and, although it fixes my problem,
I'd like to see if anyone knows if this new behavior will break something.

It all started a few days ago...

I'm working on a little project using the 2313 processor. I have a few
global variables which are needed to hold the state of interrupt routines,
etc., etc. Since these variables are allocated in SRAM, my code space was
getting rapidly exhausted by the compiler since it took a few instructions
to update a single variable (three instructions just to increment it, for
instance!)

I saw a post here recently discussing the -ffixed-REG option. So I thought
I'd try it. I set my variable to use r10 and I compiled my code with
"-ffixed-r10". My ROM image did shrink, but it didn't work. Looking at a
disassembly, I noticed the interrupt routine had a bug.

Some test code, which shows the problem, is here:

    #include <interrupt.h>
    #include <sig-avr.h>

    register uint8_t tick asm("r10");

    SIGNAL(SIG_OVERFLOW0)
    {
        outp(inp(TCNT0) - 63, TCNT0);
        ++tick;
    }

    void tickInit(void)
    {
        tick = 0;
        outp(3, TCCR0);
        outp(-63, TCNT0);
        outp(2, TIMSK);
    }

This code, on a 4MHz processor, increments "tick" every millisecond. I
compiled it with the following command line:

        avr-gcc -pipe -g -I /usr/local/avrdev/include -Wall \
            -Wa,-a=bug.lst -c -Os -mmcu=at90s2313 -mtiny-stack \
            -fverbose-asm -ffixed-r10 bug.c

The assembly for the interrupt routine was this:

    _overflow0_:
    **** SIGNAL(SIG_OVERFLOW0)
    **** {
        push    __zero_reg__
        push    __tmp_reg__
        in      __tmp_reg__,__SREG__
        push    __tmp_reg__
        clr     __zero_reg__
        push    r10
        push    r24
    ****     outp(inp(TCNT0) - 63, TCNT0);
        in      r24,50
        subi    r24,lo8(-(-63))
        out     50,r24
    ****     ++tick;
        inc     r10             <--- now one instruction instead of 3!
    **** }
        pop     r24
        pop     r10
        pop     __tmp_reg__
        out     __SREG__,__tmp_reg__
        pop     __tmp_reg__
        pop     __zero_reg__
        reti

The code now (happily!) uses "inc r10" to bump the counter, but you'll also
notice that the interrupt routine pushes and pops r10 from the stack! So
routines that use "tick" don't see it getting updated at 1Khz. The third
portion of my patch has the interrupt prologue code check to see if a
register is in the fixed register list, and if so, doesn't push or pop it.

After rebuilding the compiler with these patches, the new assembly code
looks like this:

    _overflow0_:
    **** SIGNAL(SIG_OVERFLOW0)
    **** {
        push    __zero_reg__
        push    __tmp_reg__
        in      __tmp_reg__,__SREG__
        push    __tmp_reg__
        clr     __zero_reg__
        push    r24
    ****     outp(inp(TCNT0) - 63, TCNT0);
        in      r24,50
        subi    r24,lo8(-(-63))
        out     50,r24
    ****     ++tick;
        inc     r10
    **** }
        pop     r24
        pop     __tmp_reg__
        out     __SREG__,__tmp_reg__
        pop     __tmp_reg__
        pop     __zero_reg__
        reti

I searched the disassembly of my ROM for uses of r10 and only found mine (I
wasn't sure if avr-libc or libgcc temporarily used it.) Everything seems
fine and the code is tighter when using --ffixed-REG. I'm going to switch
over a few more globals and do some more testing.

FreeBSD users can apply these patches to Joerg Wunsch's port of the tools
by saving the attached files as:

    /usr/ports/devel/avr-gcc/files/patch-na

...and then rebuild the port.

Comments requested and welcome....

-- 
 Rich Neswold

 efax: 1.240.536.7092
  web: www.enteract.com/~rneswold/

Attachment: patch-na
Description: Text document

Attachment: pgpobDNj5KEqH.pgp
Description: PGP signature


reply via email to

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