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

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

RE: [avr-gcc-list] movw and asm


From: Rune Christensen
Subject: RE: [avr-gcc-list] movw and asm
Date: Wed, 6 Aug 2003 17:55:28 +0200

Hello

I have created a small file called test.c

inline unsigned long Test(unsigned long Input)
{
    unsigned long Output;

    asm
    (
        "mov %A0,%A1\n\t"
        "mov %B0,%B1\n\t"
        "mov %C0,%C1\n\t"
        "mov %D0,%D1\n\t"
        :"=r"(Output)
        :"r"(Input)
    );

    return Output;
}

Try avr-gcc -Os -S test.c

        .file   "test.c"
        .arch avr2
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
        .global __do_copy_data
        .global __do_clear_bss
        .text
.global Test
        .type   Test, @function
Test:
/* prologue: frame size=0 */
/* prologue end (size=0) */
        mov r27,r25
        mov r26,r24
        mov r25,r23
        mov r24,r22
/* #APP */
        mov r24,r24
        mov r25,r25
        mov r26,r26
        mov r27,r27

/* #NOAPP */
        mov r22,r24
        mov r23,r25
        mov r24,r26
        mov r25,r27
/* epilogue: frame size=0 */
        ret
/* epilogue end (size=1) */
/* function Test size 19 (18) */
        .size   Test, .-Test
/* File "test.c": code   19 = 0x0013 (  18), prologues   0, epilogues   1 */


Then I created the test2.c file

inline unsigned long Test(unsigned long Input)
{
    unsigned long Output;

    asm
    (
        "movw %A0,%A1\n\t"
        "movw %C0,%C1\n\t"
        :"=r"(Output)
        :"r"(Input)
    );

    return Output;
}

Output from avr-gcc -Os -S test2.c

        .file   "test2.c"
        .arch avr2
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__tmp_reg__ = 0
__zero_reg__ = 1
        .global __do_copy_data
        .global __do_clear_bss
        .text
.global Test
        .type   Test, @function
Test:
/* prologue: frame size=0 */
/* prologue end (size=0) */
        mov r27,r25
        mov r26,r24
        mov r25,r23
        mov r24,r22
/* #APP */
        movw r24,r24
        movw r26,r26

/* #NOAPP */
        mov r22,r24
        mov r23,r25
        mov r24,r26
        mov r25,r27
/* epilogue: frame size=0 */
        ret
/* epilogue end (size=1) */
/* function Test size 15 (14) */
        .size   Test, .-Test
/* File "test2.c": code   15 = 0x000f (  14), prologues   0, epilogues   1
*/

Can anyone tell me why the 8 mov are not removed by the optimization ??

The minimum solution for the example would be

_Test:
        movw r22, r22
        movw r24, r24
        ret

Best Regards
Rune Christensen

-----Original Message-----
From: James Dabbs [mailto:address@hidden
Sent: Wednesday, August 06, 2003 5:35 PM
To: 'address@hidden'; address@hidden
Subject: RE: [avr-gcc-list] movw and asm


> I found the following from the avr-libc-manual
>
> * Function call conventions:
> Arguments - allocated left to right, r25 to r8. All arguments are aligned
to
> start in even-numbered registers (odd-sized arguments, including char,
have one
> free register above them). This allows making better use of the movw
instruction
> on the enhanced core. If too many, those that don't fit are passed on the
stack. Return
> values: 8-bit in r24 (not r25!), 16-bit in r25:r24, up to 32 bits in
r22-r25, up to
> 64 bits in r18-r25. 8-bit return values are zero/sign-extended to 16 bits
by the
> caller (unsigned char is more efficient than signed char - just clr r25).
Arguments
> to functions with variable argument lists (printf etc.) are all passed on
stack, and
> char is extended to int.

Thanks Rune!  These links are helpful, and they answered my next question.
But I am still wondering about parameters passed into asm blocks.  For
instance..

inline unsigned long Test(unsigned long Input)
{
    unsigned long Output;

    Input = ((Input << 4) ^ (Input >> 5)) + Input;

    asm
    (
        "mov %A0,%A1\n\t"
        "mov %B0,%B1\n\t"
        "mov %C0,%C1\n\t"
        "mov %D0,%D1\n\t"
        :"=r"(Output)
        :"r"(Input)
    );

    Output = Output << 4;

    return Output;
}

Is there is any determinism in how the compiler arranges the 8 registers
used to hold "Output" and "Input" before it falls into the asm block?  I'm
also looking to see if there is a trick to emit conditional statements to
gas, like "if A0 and A1 are even registers and B0 and B1 are adjacent to
them then use movd" or whatever.

At this point, we met the benchmark by writing the whole routine over in
assembler.  However, I'd still like to know.  Atmel added movd to their
enhanced core.. It would be nice to be able to make use of it.



reply via email to

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