avr-libc-dev
[Top][All Lists]
Advanced

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

Re: [avr-libc-dev] Can pgmspace.h __LPM_xxx__ macros become inlinefn's?


From: Bill Somerville
Subject: Re: [avr-libc-dev] Can pgmspace.h __LPM_xxx__ macros become inlinefn's?
Date: Fri, 01 Oct 2004 03:44:48 +0100

"Theodore A. Roth" wrote:
> 
> On Thu, 30 Sep 2004, Bill Somerville wrote:
> 
> > > Those seem like pretty good reasons for switching to inline functions to
> > > me.
> > >
> > > If no one comes up with a strong reason against this, I have no
> > > major objections.
> > >
> > > My only (very weak) objection is that I've found that gdb can not step
> > > over an inlined function. That makes debugging a bit of a pain some
> > > times.
> >
> > True, but this is a problem with gdb!
> 
> That's why it's a weak objection. ;-)
> 
> >
> > >
> > > Although, other advantages are type checking and the ability to step
> > > through an inline function in the debugger when you need to see what it
> > > is doing.
> > >
> > > One nit: should the function definition be "static __inline__ ..."
> > > instead of just "__inline__ ..."?
> >
> > I'm not sure on this. The gcc man page implies that static is not
> > recommended and definitely not required when C99 inline semantics are
> > implemented. Perhaps the compiler guru's can give a definiitive answer.
> 
> I don't see anywhere that using static is not recommended. Do you have a
> reference for that?

The penultimate para of the gcc man page "5.34 An Inline Function is As
Fast As a Macro" seemed to imply this, but after comments from Geoffrey
Wossum and some tests it seems that static __inline__ or extern
__inline__ are the only options in header files otherwise multiple
definitions occur.

Unfortunately this has become academic as I cannot get the inline fn's
to generate the same code as the macros, also the inline versions
sometimes are bigger. This seems to be an optimiser problem where the
register choices made around inlined fn's are not as smart as they might
be. I suspect this is a quite obscure gcc bug/feature. The gcc man page
says that inlines may generate different code from macros (both larger
and smaller).

Since I haven't found an example that generates smaller code, I suspect
that a community of embedded programmers are not going to be happy with
this change!

Here is a test program I used to show this issue:

#include <avr/io.h>
#include <avr/pgmspace.h>

static prog_uint8_t data[] = { 1, 2 };

int
main( void )
{
   return pgm_read_byte( &data[0] ) + ( pgm_read_byte( &data[1] ) - (
pgm_read_byte( &data[1] ) >> 2 ) );
}

I compiled it for at90s8515 using -O2 with macros then with inlines and
got the following results:

Macros ->
===========================================================================================
src/lpm_test.elf-avr:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:   0e c0           rjmp    .+28            ; 0x1e
   2:   28 c0           rjmp    .+80            ; 0x54
   4:   27 c0           rjmp    .+78            ; 0x54
   6:   26 c0           rjmp    .+76            ; 0x54
   8:   25 c0           rjmp    .+74            ; 0x54
   a:   24 c0           rjmp    .+72            ; 0x54
   c:   23 c0           rjmp    .+70            ; 0x54
   e:   22 c0           rjmp    .+68            ; 0x54
  10:   21 c0           rjmp    .+66            ; 0x54
  12:   20 c0           rjmp    .+64            ; 0x54
  14:   1f c0           rjmp    .+62            ; 0x54
  16:   1e c0           rjmp    .+60            ; 0x54
  18:   1d c0           rjmp    .+58            ; 0x54

0000001a <__ctors_end>:
  1a:   01 02           muls    r16, r17
  1c:   03 04           cpc     r0, r3

0000001e <__init>:
  1e:   11 24           eor     r1, r1
  20:   1f be           out     0x3f, r1        ; 63
  22:   cf e5           ldi     r28, 0x5F       ; 95
  24:   d2 e0           ldi     r29, 0x02       ; 2
  26:   de bf           out     0x3e, r29       ; 62
  28:   cd bf           out     0x3d, r28       ; 61

0000002a <__do_copy_data>:
  2a:   10 e0           ldi     r17, 0x00       ; 0
  2c:   a0 e6           ldi     r26, 0x60       ; 96
  2e:   b0 e0           ldi     r27, 0x00       ; 0
  30:   e0 e8           ldi     r30, 0x80       ; 128
  32:   f0 e0           ldi     r31, 0x00       ; 0
  34:   03 c0           rjmp    .+6             ; 0x3c

00000036 <.do_copy_data_loop>:
  36:   c8 95           lpm
  38:   31 96           adiw    r30, 0x01       ; 1
  3a:   0d 92           st      X+, r0

0000003c <.do_copy_data_start>:
  3c:   a0 36           cpi     r26, 0x60       ; 96
  3e:   b1 07           cpc     r27, r17
  40:   d1 f7           brne    .-12            ; 0x36

00000042 <__do_clear_bss>:
  42:   10 e0           ldi     r17, 0x00       ; 0
  44:   a0 e6           ldi     r26, 0x60       ; 96
  46:   b0 e0           ldi     r27, 0x00       ; 0
  48:   01 c0           rjmp    .+2             ; 0x4c

0000004a <.do_clear_bss_loop>:
  4a:   1d 92           st      X+, r1

0000004c <.do_clear_bss_start>:
  4c:   a0 36           cpi     r26, 0x60       ; 96
  4e:   b1 07           cpc     r27, r17
  50:   e1 f7           brne    .-8             ; 0x4a
  52:   01 c0           rjmp    .+2             ; 0x56

00000054 <__bad_interrupt>:
  54:   d5 cf           rjmp    .-86            ; 0x0

00000056 <main>:
static prog_uint8_t data[] = { 1, 2, 3, 4 };

int
main( void )
{
  56:   cf e5           ldi     r28, 0x5F       ; 95
  58:   d2 e0           ldi     r29, 0x02       ; 2
  5a:   de bf           out     0x3e, r29       ; 62
  5c:   cd bf           out     0x3d, r28       ; 61
   return pgm_read_byte( &data[0] ) + ( pgm_read_byte( &data[1] ) - (
pgm_read_byte( &data[1] ) >> 2 ) );
  5e:   ea e1           ldi     r30, 0x1A       ; 26
  60:   f0 e0           ldi     r31, 0x00       ; 0
  62:   c8 95           lpm
  64:   30 2d           mov     r19, r0
  66:   31 96           adiw    r30, 0x01       ; 1
  68:   c8 95           lpm
  6a:   20 2d           mov     r18, r0
  6c:   82 2f           mov     r24, r18
  6e:   99 27           eor     r25, r25
  70:   26 95           lsr     r18
  72:   26 95           lsr     r18
  74:   82 1b           sub     r24, r18
  76:   91 09           sbc     r25, r1
}
  78:   83 0f           add     r24, r19
  7a:   91 1d           adc     r25, r1
  7c:   00 c0           rjmp    .+0             ; 0x7e

0000007e <_exit>:
  7e:   ff cf           rjmp    .-2             ; 0x7e
================================================================================================

Inlines ->
================================================================================================
src/lpm_test.elf-avr:     file format elf32-avr

Disassembly of section .text:

00000000 <__vectors>:
   0:   0e c0           rjmp    .+28            ; 0x1e
   2:   28 c0           rjmp    .+80            ; 0x54
   4:   27 c0           rjmp    .+78            ; 0x54
   6:   26 c0           rjmp    .+76            ; 0x54
   8:   25 c0           rjmp    .+74            ; 0x54
   a:   24 c0           rjmp    .+72            ; 0x54
   c:   23 c0           rjmp    .+70            ; 0x54
   e:   22 c0           rjmp    .+68            ; 0x54
  10:   21 c0           rjmp    .+66            ; 0x54
  12:   20 c0           rjmp    .+64            ; 0x54
  14:   1f c0           rjmp    .+62            ; 0x54
  16:   1e c0           rjmp    .+60            ; 0x54
  18:   1d c0           rjmp    .+58            ; 0x54

0000001a <__ctors_end>:
  1a:   01 02           muls    r16, r17
  1c:   03 04           cpc     r0, r3

0000001e <__init>:
  1e:   11 24           eor     r1, r1
  20:   1f be           out     0x3f, r1        ; 63
  22:   cf e5           ldi     r28, 0x5F       ; 95
  24:   d2 e0           ldi     r29, 0x02       ; 2
  26:   de bf           out     0x3e, r29       ; 62
  28:   cd bf           out     0x3d, r28       ; 61

0000002a <__do_copy_data>:
  2a:   10 e0           ldi     r17, 0x00       ; 0
  2c:   a0 e6           ldi     r26, 0x60       ; 96
  2e:   b0 e0           ldi     r27, 0x00       ; 0
  30:   e4 e8           ldi     r30, 0x84       ; 132
  32:   f0 e0           ldi     r31, 0x00       ; 0
  34:   03 c0           rjmp    .+6             ; 0x3c

00000036 <.do_copy_data_loop>:
  36:   c8 95           lpm
  38:   31 96           adiw    r30, 0x01       ; 1
  3a:   0d 92           st      X+, r0

0000003c <.do_copy_data_start>:
  3c:   a0 36           cpi     r26, 0x60       ; 96
  3e:   b1 07           cpc     r27, r17
  40:   d1 f7           brne    .-12            ; 0x36

00000042 <__do_clear_bss>:
  42:   10 e0           ldi     r17, 0x00       ; 0
  44:   a0 e6           ldi     r26, 0x60       ; 96
  46:   b0 e0           ldi     r27, 0x00       ; 0
  48:   01 c0           rjmp    .+2             ; 0x4c

0000004a <.do_clear_bss_loop>:
  4a:   1d 92           st      X+, r1

0000004c <.do_clear_bss_start>:
  4c:   a0 36           cpi     r26, 0x60       ; 96
  4e:   b1 07           cpc     r27, r17
  50:   e1 f7           brne    .-8             ; 0x4a
  52:   01 c0           rjmp    .+2             ; 0x56

00000054 <__bad_interrupt>:
  54:   d5 cf           rjmp    .-86            ; 0x0

00000056 <main>:
static prog_uint8_t data[] = { 1, 2, 3, 4 };

int
main( void )
{
  56:   cf e5           ldi     r28, 0x5F       ; 95
  58:   d2 e0           ldi     r29, 0x02       ; 2
  5a:   de bf           out     0x3e, r29       ; 62
  5c:   cd bf           out     0x3d, r28       ; 61
uint8_t
__LPM_classic__ (prog_uint8_t const * const __addr)
{
    uint8_t __result;
    __asm__
  5e:   ea e1           ldi     r30, 0x1A       ; 26
  60:   f0 e0           ldi     r31, 0x00       ; 0
  62:   c8 95           lpm
  64:   40 2d           mov     r20, r0
  66:   31 96           adiw    r30, 0x01       ; 1
  68:   c8 95           lpm
  6a:   80 2d           mov     r24, r0
  6c:   28 2f           mov     r18, r24
  6e:   33 27           eor     r19, r19
  70:   82 2f           mov     r24, r18
  72:   99 27           eor     r25, r25
  74:   26 95           lsr     r18
  76:   26 95           lsr     r18
  78:   82 1b           sub     r24, r18
  7a:   91 09           sbc     r25, r1
   return pgm_read_byte( &data[0] ) + ( pgm_read_byte( &data[1] ) - (
pgm_read_byte( &data[1] ) >> 2 ) );
}
  7c:   84 0f           add     r24, r20
  7e:   91 1d           adc     r25, r1
  80:   00 c0           rjmp    .+0             ; 0x82

00000082 <_exit>:
  82:   ff cf           rjmp    .-2             ; 0x82
================================================================================================

In the inline version the second LPM result does an unnecessary register
shuffle that the macro version avoids. Note that the first LPM is OK so
the compiler can get it right sometimes.

> 
> ---
> Ted Roth
> PGP Key ID: 0x18F846E9
> Jabber ID: address@hidden

Bill Somerville

Index: include/avr/pgmspace.h
===================================================================
RCS file: /cvsroot/avr-libc/avr-libc/include/avr/pgmspace.h,v
retrieving revision 1.22
diff -u -r1.22 pgmspace.h
--- include/avr/pgmspace.h      19 Sep 2004 19:11:06 -0000      1.22
+++ include/avr/pgmspace.h      1 Oct 2004 02:27:33 -0000
@@ -81,6 +81,10 @@
 #define __ATTR_PURE__ __attribute__((__pure__))
 #endif
 
+#ifndef __ATTR_ALWAYS_INLINE__
+#define __ATTR_ALWAYS_INLINE__ __attribute__((__always_inline__))
+#endif
+
 #define PROGMEM __ATTR_PROGMEM__
 
 #ifdef __cplusplus
@@ -121,105 +125,123 @@
 
 #define PSTR(s) ({static char __c[] PROGMEM = (s); &__c[0];})
 
-#define __LPM_classic__(addr)   \
-({                              \
-    uint16_t __addr16 = (uint16_t)(addr); \
-    uint8_t __result;           \
-    __asm__                     \
-    (                           \
-        "lpm" "\n\t"            \
-        "mov %0, r0" "\n\t"     \
-        : "=r" (__result)       \
-        : "z" (__addr16)        \
-        : "r0"                  \
-    );                          \
-    __result;                   \
-})
+static __inline__ uint8_t __LPM_classic__ (prog_uint8_t const * const
__addr) __ATTR_ALWAYS_INLINE__;
+static __inline__ uint8_t __LPM_enhanced__ (prog_uint8_t const * const
__addr) __ATTR_ALWAYS_INLINE__;
+static __inline__ uint16_t __LPM_word_classic__ (prog_uint16_t const *
__addr) __ATTR_ALWAYS_INLINE__;
+static __inline__ uint16_t __LPM_word_enhanced__ (prog_uint16_t const *
__addr) __ATTR_ALWAYS_INLINE__;
+
+static __inline__
+uint8_t
+__LPM_classic__ (prog_uint8_t const * const __addr)
+{
+    uint8_t __result;
+    __asm__
+    (
+        "lpm" "\n\t"
+        "mov %0, r0" "\n\t"
+        : "=r" (__result)
+        : "z" (__addr)
+        : "r0"
+    );
+    return __result;
+}
 
-#define __LPM_enhanced__(addr)  \
-({                              \
-    uint16_t __addr16 = (uint16_t)(addr); \
-    uint8_t __result;           \
-    __asm__                     \
-    (                           \
-        "lpm %0, Z" "\n\t"      \
-        : "=r" (__result)       \
-        : "z" (__addr16)        \
-    );                          \
-    __result;                   \
-})
+static __inline__
+uint8_t
+__LPM_enhanced__ (prog_uint8_t const * const __addr)
+{
+    uint8_t __result;
+    __asm__
+    (
+        "lpm %0, Z" "\n\t"
+        : "=r" (__result)
+        : "z" (__addr)
+    );
+    return __result;
+}
 
-#define __LPM_word_classic__(addr)          \
-({                                          \
-    uint16_t __addr16 = (uint16_t)(addr);   \
-    uint16_t __result;                      \
-    __asm__                                 \
-    (                                       \
-        "lpm"           "\n\t"              \
-        "mov %A0, r0"   "\n\t"              \
-        "adiw r30, 1"   "\n\t"              \
-        "lpm"           "\n\t"              \
-        "mov %B0, r0"   "\n\t"              \
-        : "=r" (__result), "=z" (__addr16)  \
-        : "1" (__addr16)                    \
-        : "r0"                              \
-    );                                      \
-    __result;                               \
-})
+static __inline__
+uint16_t
+__LPM_word_classic__ (prog_uint16_t const * __addr)
+{
+    uint16_t __result;
+    __asm__
+    (
+        "lpm"           "\n\t"
+        "mov %A0, r0"   "\n\t"
+        "adiw r30, 1"   "\n\t"
+        "lpm"           "\n\t"
+        "mov %B0, r0"   "\n\t"
+        : "=r" (__result), "=z" (__addr)
+        : "1" (__addr)
+        : "r0"
+    );
+    return __result;
+}
 
-#define __LPM_word_enhanced__(addr)         \
-({                                          \
-    uint16_t __addr16 = (uint16_t)(addr);   \
-    uint16_t __result;                      \
-    __asm__                                 \
-    (                                       \
-        "lpm %A0, Z+"   "\n\t"              \
-        "lpm %B0, Z"    "\n\t"              \
-        : "=r" (__result), "=z" (__addr16)  \
-        : "1" (__addr16)                    \
-    );                                      \
-    __result;                               \
-})
+static __inline__
+uint16_t
+__LPM_word_enhanced__ (prog_uint16_t const * __addr)
+{
+    uint16_t __result;
+    __asm__
+    (
+        "lpm %A0, Z+"   "\n\t"
+        "lpm %B0, Z"    "\n\t"
+        : "=r" (__result), "=z" (__addr)
+        : "1" (__addr)
+    );
+    return __result;
+}
 
-#define __LPM_dword_classic__(addr)         \
-({                                          \
-    uint16_t __addr16 = (uint16_t)(addr);   \
-    uint32_t __result;                      \
-    __asm__                                 \
-    (                                       \
-        "lpm"           "\n\t"              \
-        "mov %A0, r0"   "\n\t"              \
-        "adiw r30, 1"   "\n\t"              \
-        "lpm"           "\n\t"              \
-        "mov %B0, r0"   "\n\t"              \
-        "adiw r30, 1"   "\n\t"              \
-        "lpm"           "\n\t"              \
-        "mov %C0, r0"   "\n\t"              \
-        "adiw r30, 1"   "\n\t"              \
-        "lpm"           "\n\t"              \
-        "mov %D0, r0"   "\n\t"              \
-        : "=r" (__result), "=z" (__addr16)  \
-        : "1" (__addr16)                    \
-        : "r0"                              \
-    );                                      \
-    __result;                               \
-})
+#if defined(__HAS_INT32_T__)
 
-#define __LPM_dword_enhanced__(addr)        \
-({                                          \
-    uint16_t __addr16 = (uint16_t)(addr);   \
-    uint32_t __result;                      \
-    __asm__                                 \
-    (                                       \
-        "lpm %A0, Z+"   "\n\t"              \
-        "lpm %B0, Z+"   "\n\t"              \
-        "lpm %C0, Z+"   "\n\t"              \
-        "lpm %D0, Z"    "\n\t"              \
-        : "=r" (__result), "=z" (__addr16)  \
-        : "1" (__addr16)                    \
-    );                                      \
-    __result;                               \
-})
+static __inline__ uint32_t __LPM_dword_classic__ (prog_uint32_t const *
__addr) __ATTR_ALWAYS_INLINE__;
+static __inline__ uint32_t __LPM_dword_enhanced__ (prog_uint32_t const
* __addr) __ATTR_ALWAYS_INLINE__;
+
+static __inline__
+uint32_t
+__LPM_dword_classic__ (prog_uint32_t const * __addr)
+{
+    uint32_t __result;
+    __asm__
+    (
+        "lpm"           "\n\t"
+        "mov %A0, r0"   "\n\t"
+        "adiw r30, 1"   "\n\t"
+        "lpm"           "\n\t"
+        "mov %B0, r0"   "\n\t"
+        "adiw r30, 1"   "\n\t"
+        "lpm"           "\n\t"
+        "mov %C0, r0"   "\n\t"
+        "adiw r30, 1"   "\n\t"
+        "lpm"           "\n\t"
+        "mov %D0, r0"   "\n\t"
+        : "=r" (__result), "=z" (__addr)
+        : "1" (__addr)
+        : "r0"
+    );
+    return __result;
+}
+
+static __inline__
+uint32_t
+__LPM_dword_enhanced__ (prog_uint32_t const * __addr)
+{
+    uint32_t __result;
+    __asm__
+    (
+        "lpm %A0, Z+"   "\n\t"
+        "lpm %B0, Z+"   "\n\t"
+        "lpm %C0, Z+"   "\n\t"
+        "lpm %D0, Z"    "\n\t"
+        : "=r" (__result), "=z" (__addr)
+        : "1" (__addr)
+    );
+    return __result;
+}
+
+#endif /* __HAS_INT32_T__ */
 
 #if defined (__AVR_ENHANCED__)
 #define __LPM(addr)         __LPM_enhanced__(addr)
@@ -237,7 +259,7 @@
     \note The address is a byte address.
     The address is in the program space. */
 
-#define pgm_read_byte_near(address_short)
__LPM((uint16_t)(address_short))
+#define pgm_read_byte_near(address_short) (uint8_t)__LPM(address_short)
 
 /** \ingroup avr_pgmspace
     \def pgm_read_word_near(address_short)
@@ -245,7 +267,7 @@
     \note The address is a byte address. 
     The address is in the program space. */
 
-#define pgm_read_word_near(address_short)
__LPM_word((uint16_t)(address_short))
+#define pgm_read_word_near(address_short) __LPM_word(address_short)
 
 /** \ingroup avr_pgmspace
     \def pgm_read_dword_near(address_short)
@@ -253,8 +275,7 @@
     \note The address is a byte address. 
     The address is in the program space. */
 
-#define pgm_read_dword_near(address_short) \
-    __LPM_dword((uint16_t)(address_short))
+#define pgm_read_dword_near(address_short) __LPM_dword(address_short)
 
 #if defined(RAMPZ) && !defined(__USING_MINT8)
 
@@ -266,140 +287,153 @@
 
 /* The classic functions are needed for ATmega103. */
 
-#define __ELPM_classic__(addr)      \
-({                                  \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint8_t __result;               \
-    __asm__                         \
-    (                               \
-        "out %2, %C1" "\n\t"        \
-        "mov r31, %B1" "\n\t"       \
-        "mov r30, %A1" "\n\t"       \
-        "elpm" "\n\t"               \
-        "mov %0, r0" "\n\t"         \
-        : "=r" (__result)           \
-        : "r" (__addr32),           \
-          "I" (_SFR_IO_ADDR(RAMPZ)) \
-        : "r0", "r30", "r31"        \
-    );                              \
-    __result;                       \
-})
+static __inline__ uint8_t __ELPM_classic__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+static __inline__ uint8_t __ELPM_enhanced__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+static __inline__ uint16_t __ELPM_word_classic__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+static __inline__ uint16_t __ELPM_word_enhanced__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+static __inline__ uint32_t __ELPM_dword_classic__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+static __inline__ uint32_t __ELPM_dword_enhanced__ (uint32_t __addr)
__ATTR_ALWAYS_INLINE__;
+
+static __inline__
+uint8_t
+__ELPM_classic__ (uint32_t __addr)
+{
+    uint8_t __result;
+    __asm__
+    (
+        "out %2, %C1" "\n\t"
+        "mov r31, %B1" "\n\t"
+        "mov r30, %A1" "\n\t"
+        "elpm" "\n\t"
+        "mov %0, r0" "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r0", "r30", "r31"
+    );
+    return __result;
+}
 
-#define __ELPM_enhanced__(addr)     \
-({                                  \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint8_t __result;               \
-    __asm__                         \
-    (                               \
-        "out %2, %C1" "\n\t"        \
-        "movw r30, %1" "\n\t"       \
-        "elpm %0, Z+" "\n\t"        \
-        : "=r" (__result)           \
-        : "r" (__addr32),           \
-          "I" (_SFR_IO_ADDR(RAMPZ)) \
-        : "r30", "r31"              \
-    );                              \
-    __result;                       \
-})
+static __inline__
+uint8_t
+__ELPM_enhanced__ (uint32_t __addr)
+{
+    uint8_t __result;
+    __asm__
+    (
+        "out %2, %C1" "\n\t"
+        "movw r30, %1" "\n\t"
+        "elpm %0, Z+" "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r30", "r31"
+    );
+    return __result;
+}
 
-#define __ELPM_word_classic__(addr)     \
-({                                      \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint16_t __result;                  \
-    __asm__                             \
-    (                                   \
-        "out %2, %C1"   "\n\t"          \
-        "mov r31, %B1"  "\n\t"          \
-        "mov r30, %A1"  "\n\t"          \
-        "elpm"          "\n\t"          \
-        "mov %A0, r0"   "\n\t"          \
-        "in r0, %2"     "\n\t"          \
-        "adiw r30, 1"   "\n\t"          \
-        "adc r0, __zero_reg__" "\n\t"   \
-        "out %2, r0"    "\n\t"          \
-        "elpm"          "\n\t"          \
-        "mov %B0, r0"   "\n\t"          \
-        : "=r" (__result)               \
-        : "r" (__addr32),               \
-          "I" (_SFR_IO_ADDR(RAMPZ))     \
-        : "r0", "r30", "r31"            \
-    );                                  \
-    __result;                           \
-})
+static __inline__
+uint16_t
+__ELPM_word_classic__ (uint32_t __addr)
+{
+    uint16_t __result;
+    __asm__
+    (
+        "out %2, %C1"   "\n\t"
+        "mov r31, %B1"  "\n\t"
+        "mov r30, %A1"  "\n\t"
+        "elpm"          "\n\t"
+        "mov %A0, r0"   "\n\t"
+        "in r0, %2"     "\n\t"
+        "adiw r30, 1"   "\n\t"
+        "adc r0, __zero_reg__" "\n\t"
+        "out %2, r0"    "\n\t"
+        "elpm"          "\n\t"
+        "mov %B0, r0"   "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r0", "r30", "r31"
+    );
+    return __result;
+}
 
-#define __ELPM_word_enhanced__(addr)    \
-({                                      \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint16_t __result;                  \
-    __asm__                             \
-    (                                   \
-        "out %2, %C1"   "\n\t"          \
-        "movw r30, %1"  "\n\t"          \
-        "elpm %A0, Z+"  "\n\t"          \
-        "elpm %B0, Z"   "\n\t"          \
-        : "=r" (__result)               \
-        : "r" (__addr32),               \
-          "I" (_SFR_IO_ADDR(RAMPZ))     \
-        : "r30", "r31"                  \
-    );                                  \
-    __result;                           \
-})
+static __inline__
+uint16_t
+__ELPM_word_enhanced__ (uint32_t __addr)
+{
+    uint16_t __result;
+    __asm__
+    (
+        "out %2, %C1"   "\n\t"
+        "movw r30, %1"  "\n\t"
+        "elpm %A0, Z+"  "\n\t"
+        "elpm %B0, Z"   "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r30", "r31"
+    );
+    return __result;
+}
 
-#define __ELPM_dword_classic__(addr)      \
-({                                        \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint32_t __result;                    \
-    __asm__                               \
-    (                                     \
-        "out %2, %C1"          "\n\t"     \
-        "mov r31, %B1"         "\n\t"     \
-        "mov r30, %A1"         "\n\t"     \
-        "elpm"                 "\n\t"     \
-        "mov %A0, r0"          "\n\t"     \
-        "in r0, %2"            "\n\t"     \
-        "adiw r30, 1"          "\n\t"     \
-        "adc r0, __zero_reg__" "\n\t"     \
-        "out %2, r0"           "\n\t"     \
-        "elpm"                 "\n\t"     \
-        "mov %B0, r0"          "\n\t"     \
-        "in r0, %2"            "\n\t"     \
-        "adiw r30, 1"          "\n\t"     \
-        "adc r0, __zero_reg__" "\n\t"     \
-        "out %2, r0"           "\n\t"     \
-        "elpm"                 "\n\t"     \
-        "mov %C0, r0"          "\n\t"     \
-        "in r0, %2"            "\n\t"     \
-        "adiw r30, 1"          "\n\t"     \
-        "adc r0, __zero_reg__" "\n\t"     \
-        "out %2, r0"           "\n\t"     \
-        "elpm"                 "\n\t"     \
-        "mov %D0, r0"          "\n\t"     \
-        : "=r" (__result)                 \
-        : "r" (__addr32),                 \
-          "I" (_SFR_IO_ADDR(RAMPZ))       \
-        : "r0", "r30", "r31"              \
-    );                                    \
-    __result;                             \
-})
+static __inline__
+uint32_t
+__ELPM_dword_classic__ (uint32_t __addr)
+{
+    uint32_t __result;
+    __asm__
+    (
+        "out %2, %C1"          "\n\t"
+        "mov r31, %B1"         "\n\t"
+        "mov r30, %A1"         "\n\t"
+        "elpm"                 "\n\t"
+        "mov %A0, r0"          "\n\t"
+        "in r0, %2"            "\n\t"
+        "adiw r30, 1"          "\n\t"
+        "adc r0, __zero_reg__" "\n\t"
+        "out %2, r0"           "\n\t"
+        "elpm"                 "\n\t"
+        "mov %B0, r0"          "\n\t"
+        "in r0, %2"            "\n\t"
+        "adiw r30, 1"          "\n\t"
+        "adc r0, __zero_reg__" "\n\t"
+        "out %2, r0"           "\n\t"
+        "elpm"                 "\n\t"
+        "mov %C0, r0"          "\n\t"
+        "in r0, %2"            "\n\t"
+        "adiw r30, 1"          "\n\t"
+        "adc r0, __zero_reg__" "\n\t"
+        "out %2, r0"           "\n\t"
+        "elpm"                 "\n\t"
+        "mov %D0, r0"          "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r0", "r30", "r31"
+    );
+    return __result;
+}
 
-#define __ELPM_dword_enhanced__(addr)     \
-({                                        \
-    uint32_t __addr32 = (uint32_t)(addr); \
-    uint32_t __result;                    \
-    __asm__                               \
-    (                                     \
-        "out %2, %C1"   "\n\t"            \
-        "movw r30, %1"  "\n\t"            \
-        "elpm %A0, Z+"  "\n\t"            \
-        "elpm %B0, Z+"  "\n\t"            \
-        "elpm %C0, Z+"  "\n\t"            \
-        "elpm %D0, Z"   "\n\t"            \
-        : "=r" (__result)                 \
-        : "r" (__addr32),                 \
-          "I" (_SFR_IO_ADDR(RAMPZ))       \
-        : "r30", "r31"                    \
-    );                                    \
-    __result;                             \
+static __inline__
+uint32_t
+__ELPM_dword_enhanced__ (uint32_t __addr)
+{
+    uint32_t __result;
+    __asm__
+    (
+        "out %2, %C1"   "\n\t"
+        "movw r30, %1"  "\n\t"
+        "elpm %A0, Z+"  "\n\t"
+        "elpm %B0, Z+"  "\n\t"
+        "elpm %C0, Z+"  "\n\t"
+        "elpm %D0, Z"   "\n\t"
+        : "=r" (__result)
+        : "r" (__addr),
+          "I" (_SFR_IO_ADDR(RAMPZ))
+        : "r30", "r31"
+    );
+    return __result;
 })
 
 #if defined (__AVR_ENHANCED__)
@@ -419,7 +453,7 @@
     \note The address is a byte address. 
     The address is in the program space. */
 
-#define pgm_read_byte_far(address_long) 
__ELPM((uint32_t)(address_long))
+#define pgm_read_byte_far(address_long)  __ELPM(address_long)
 
 /** \ingroup avr_pgmspace
     \def pgm_read_word_far(address_long)
@@ -428,7 +462,7 @@
     \note The address is a byte address.
     The address is in the program space. */
 
-#define pgm_read_word_far(address_long) 
__ELPM_word((uint32_t)(address_long))
+#define pgm_read_word_far(address_long)  __ELPM_word(address_long)
 
 /** \ingroup avr_pgmspace
     \def pgm_read_dword_far(address_long)
@@ -437,7 +471,7 @@
     \note The address is a byte address.
     The address is in the program space. */
 
-#define pgm_read_dword_far(address_long)
__ELPM_dword((uint32_t)(address_long))
+#define pgm_read_dword_far(address_long) __ELPM_dword(address_long)
 
 #endif /* RAMPZ and ! __USING_MINT8 */




reply via email to

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