[PATCH 11] SPARC: added libcpu lowlevel access and byteorder routines/definitions

Joel Sherrill joel.sherrill at OARcorp.com
Mon Feb 6 16:13:27 UTC 2012


Why are these assembly instead of inline asm macros?

On 02/06/2012 10:00 AM, Daniel Hellstrom wrote:
> On 02/06/2012 04:33 PM, Gedare Bloom wrote:
>> On Mon, Feb 6, 2012 at 9:15 AM, Daniel Hellstrom<daniel at gaisler.com>   wrote:
>>> The low level routines can be used in different occasions, it will be
>>> required when accessing PCI.
>>>
>>> Signed-off-by: Daniel Hellstrom<daniel at gaisler.com>
>>> ---
>>>    c/src/lib/libbsp/sparc/erc32/Makefile.am          |    4 +-
>>>    c/src/lib/libbsp/sparc/leon2/Makefile.am          |    1 +
>>>    c/src/lib/libbsp/sparc/leon3/Makefile.am          |    4 +-
>>>    c/src/lib/libcpu/sparc/Makefile.am                |    7 ++
>>>    c/src/lib/libcpu/sparc/access/access.S            |   65 ++++++++++++++++++++
>>>    c/src/lib/libcpu/sparc/access/access_le.c         |   32 ++++++++++
>>>    c/src/lib/libcpu/sparc/include/libcpu/access.h    |   48 +++++++++++++++
>>>    c/src/lib/libcpu/sparc/include/libcpu/byteorder.h |   66 +++++++++++++++++++++
>>>    c/src/lib/libcpu/sparc/preinstall.am              |    8 +++
>>>    9 files changed, 233 insertions(+), 2 deletions(-)
>>>    create mode 100644 c/src/lib/libcpu/sparc/access/access.S
>>>    create mode 100644 c/src/lib/libcpu/sparc/access/access_le.c
>>>    create mode 100644 c/src/lib/libcpu/sparc/include/libcpu/access.h
>>>    create mode 100644 c/src/lib/libcpu/sparc/include/libcpu/byteorder.h
>>>
>>> diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am
>>> index abe44c3..cecfe14 100644
>>> --- a/c/src/lib/libbsp/sparc/erc32/Makefile.am
>>> +++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am
>>> @@ -68,7 +68,9 @@ erc32sonic_rel_CPPFLAGS = $(AM_CPPFLAGS) $(erc32sonic_CPPFLAGS)
>>>    erc32sonic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
>>>    endif
>>>
>>> -libbsp_a_LIBADD  = ../../../libcpu/@RTEMS_CPU@/cache.rel \
>>> +libbsp_a_LIBADD  = \
>>> +    ../../../libcpu/@RTEMS_CPU@/access.rel \
>>> +    ../../../libcpu/@RTEMS_CPU@/cache.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/reg_win.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/syscall.rel
>>>    if HAS_NETWORKING
>>> diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
>>> index 9c7819c..9df3c7d 100644
>>> --- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
>>> +++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
>>> @@ -118,6 +118,7 @@ leon_open_eth_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
>>>    endif
>>>
>>>    libbsp_a_LIBADD = \
>>> +    ../../../libcpu/@RTEMS_CPU@/access.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/cache.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/reg_win.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/syscall.rel
>>> diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
>>> index 5edbe9d..8eae306 100644
>>> --- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
>>> +++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
>>> @@ -126,7 +126,9 @@ libbsp_a_SOURCES += shmsupp/addrconv.c shmsupp/getcfg.c shmsupp/lock.c \
>>>       shmsupp/mpisr.c
>>>    endif
>>>
>>> -libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/cache.rel \
>>> +libbsp_a_LIBADD = \
>>> +    ../../../libcpu/@RTEMS_CPU@/access.rel \
>>> +    ../../../libcpu/@RTEMS_CPU@/cache.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/reg_win.rel \
>>>       ../../../libcpu/@RTEMS_CPU@/syscall.rel
>>>
>>> diff --git a/c/src/lib/libcpu/sparc/Makefile.am b/c/src/lib/libcpu/sparc/Makefile.am
>>> index 7bebd94..711d6b1 100644
>>> --- a/c/src/lib/libcpu/sparc/Makefile.am
>>> +++ b/c/src/lib/libcpu/sparc/Makefile.am
>>> @@ -10,6 +10,8 @@ noinst_PROGRAMS =
>>>
>>>    include_libcpudir = $(includedir)/libcpu
>>>    include_libcpu_HEADERS = ../shared/include/cache.h
>>> +include_libcpu_HEADERS += include/libcpu/byteorder.h
>>> +include_libcpu_HEADERS += include/libcpu/access.h
>>>
>>>    noinst_PROGRAMS += cache.rel
>>>    cache_rel_SOURCES = cache/cache.c cache/cache_.h \
>>> @@ -31,5 +33,10 @@ reg_win_rel_SOURCES = reg_win/window.S
>>>    reg_win_rel_CPPFLAGS = $(AM_CPPFLAGS)
>>>    reg_win_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
>>>
>>> +noinst_PROGRAMS += access.rel
>>> +access_rel_SOURCES = access/access.S access/access_le.c
>>> +access_rel_CPPFLAGS = $(AM_CPPFLAGS)
>>> +access_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
>>> +
>>>    include $(srcdir)/preinstall.am
>>>    include $(top_srcdir)/../../../automake/local.am
>>> diff --git a/c/src/lib/libcpu/sparc/access/access.S b/c/src/lib/libcpu/sparc/access/access.S
>>> new file mode 100644
>>> index 0000000..7e69f64
>>> --- /dev/null
>>> +++ b/c/src/lib/libcpu/sparc/access/access.S
>>> @@ -0,0 +1,65 @@
>>> +/*
>>> + *  Access routines for SPARC
>>> + *
>>> + *  COPYRIGHT (c) 2011
>>> + *  Aeroflex Gaisler.
>>> + *
>>> + *  The license and distribution terms for this file may be
>>> + *  found in the file LICENSE in this distribution or at
>>> + *  http://www.rtems.com/license/LICENSE.
>>> + */
>>> +
>>> +#include<rtems/asm.h>
>>> +
>>> +       .align 4
>>> +       .seg "text"
>>> +       PUBLIC(_ld8)
>>> +       PUBLIC(_ld16)
>>> +       PUBLIC(_ld32)
>>> +       PUBLIC(_ld64)
>>> +       PUBLIC(_st8)
>>> +       PUBLIC(_st16)
>>> +       PUBLIC(_st32)
>>> +       PUBLIC(_st64)
>>> +       PUBLIC(_ld_be16)
>>> +       PUBLIC(_ld_be32)
>>> +       PUBLIC(_st_be16)
>>> +       PUBLIC(_st_be32)
>>> +
>>> +SYM(_ld8):
>>> +       retl
>>> +        ldub [%o0], %o0
>>> +
>>> +SYM(_ld_be16):
>>> +SYM(_ld16):
>>> +       retl
>>> +        lduh [%o0], %o0
>>> +
>>> +SYM(_ld_be32):
>>> +SYM(_ld32):
>>> +       retl
>>> +        ld [%o0], %o0
>>> +
>>> +SYM(_ld_be64):
>>> +SYM(_ld64):
>>> +       retl
>>> +        ldd [%o0], %o0
>>> +
>>> +SYM(_st8):
>>> +       retl
>>> +        stub %o1, [%o0]
>>> +
>>> +SYM(_st_be16):
>>> +SYM(_st16):
>>> +       retl
>>> +        stuh %o1, [%o0]
>>> +
>>> +SYM(_st_be32):
>>> +SYM(_st32):
>>> +       retl
>>> +        st %o1, [%o0]
>>> +
>>> +SYM(_st_be64):
>>> +SYM(_st64):
>>> +       retl
>>> +        std %o1, [%o0]
>> Do these functions get used somewhere I don't see?
> No they are not called until I submit my PCI patches. Perhaps it would have been better to wait with this code?
>> Do we need these defined in assembly language, maybe at least inline
>> assembly would be better to get some kind of type-checking assist from
>> the compiler?
> One can access inline functions from byteorder.h. The point with the functions is that they are the fastest way to access a specific size, using the C-compiler would make these functions be different
> with different compiler flags. I think they are the simplest ASM functions there are, even so I managed to make a copy-paste bug on the 64bit case :)
>> I suspect something is wrong with the _st64/_st_be64 function, because
>> sparc uses paired registers to store a 64-bit number the compiler will
>> pack the arguments differently and probably as o0/o1 or o2/o3.
> My bad, the 64-bit macros/code has never been executed since there as been no use-case. Thanks for reviewing! Perhaps one should remove the 64-bit access routines, however they are supported by hardware.
>
> +SYM(_st_be64):
> +SYM(_st64):
> +       mov %o2, %o3
> +       mov %o1, %o2
> +       retl
> +        std %o2, [%o0]
>
>
> I will resubmit patch.
>
>>> diff --git a/c/src/lib/libcpu/sparc/access/access_le.c b/c/src/lib/libcpu/sparc/access/access_le.c
>>> new file mode 100644
>>> index 0000000..15031cc
>>> --- /dev/null
>>> +++ b/c/src/lib/libcpu/sparc/access/access_le.c
>>> @@ -0,0 +1,32 @@
>>> +/*
>>> + *  Little-endian access routines for SPARC
>>> + *
>>> + *  COPYRIGHT (c) 2011
>>> + *  Aeroflex Gaisler.
>>> + *
>>> + *  The license and distribution terms for this file may be
>>> + *  found in the file LICENSE in this distribution or at
>>> + *  http://www.rtems.com/license/LICENSE.
>>> + */
>>> +
>>> +#include<libcpu/byteorder.h>
>>> +
>>> +uint16_t _ld_le16(uint16_t *addr)
>>> +{
>>> +       return ld_le16(addr);
>>> +}
>>> +
>>> +void _st_le16(uint16_t *addr, uint16_t val)
>>> +{
>>> +       st_le16(addr, val);
>>> +}
>>> +
>>> +uint32_t _ld_le32(uint32_t *addr)
>>> +{
>>> +       return ld_le32(addr);
>>> +}
>>> +
>>> +void _st_le32(uint32_t *addr, uint32_t val)
>>> +{
>>> +       st_le32(addr, val);
>>> +}
>>> diff --git a/c/src/lib/libcpu/sparc/include/libcpu/access.h b/c/src/lib/libcpu/sparc/include/libcpu/access.h
>>> new file mode 100644
>>> index 0000000..2d87c2a
>>> --- /dev/null
>>> +++ b/c/src/lib/libcpu/sparc/include/libcpu/access.h
>>> @@ -0,0 +1,48 @@
>>> +/*
>>> + *  access.h  - access routines for SPARC. SPARC is big endian only.
>>> + *
>>> + *  COPYRIGHT (c) 2011
>>> + *  Aeroflex Gaisler.
>>> + *
>>> + *  The license and distribution terms for this file may be
>>> + *  found in the file LICENSE in this distribution or at
>>> + *  http://www.rtems.com/license/LICENSE.
>>> + */
>>> +
>>> +#ifndef _LIBCPU_ACCESS_H
>>> +#define _LIBCPU_ACCESS_H
>>> +
>>> +#include<rtems/system.h>
>>> +#include<rtems/score/cpu.h>
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +/* "Raw" access */
>>> +extern uint8_t _ld8(uint8_t *addr);
>>> +extern void _st8(uint8_t *addr, uint8_t val);
>>> +extern uint16_t _ld16(uint16_t *addr);
>>> +extern void _st16(uint16_t *addr, uint16_t val);
>>> +extern uint32_t _ld32(uint32_t *addr);
>>> +extern void _st32(uint32_t *addr, uint32_t val);
>>> +extern uint64_t _ld64(uint64_t *addr);
>>> +extern void _st64(uint64_t *addr, uint64_t val);
>>> +
>>> +/* Aliases for Big Endian */
>>> +extern uint16_t _ld_be16(uint16_t *addr);
>>> +extern void _st_be16(uint16_t *addr, uint16_t val);
>>> +extern uint32_t _ld_be32(uint32_t *addr);
>>> +extern void _st_be32(uint32_t *addr, uint32_t val);
>>> +
>>> +/* Little endian */
>>> +extern uint16_t _ld_le16(uint16_t *addr);
>>> +extern void _st_le16(uint16_t *addr, uint16_t val);
>>> +extern uint32_t _ld_le32(uint32_t *addr);
>>> +extern void _st_le32(uint32_t *addr, uint32_t val);
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/c/src/lib/libcpu/sparc/include/libcpu/byteorder.h b/c/src/lib/libcpu/sparc/include/libcpu/byteorder.h
>>> new file mode 100644
>>> index 0000000..d626f28
>>> --- /dev/null
>>> +++ b/c/src/lib/libcpu/sparc/include/libcpu/byteorder.h
>>> @@ -0,0 +1,66 @@
>>> +/*
>>> + *  byteorder.h  - Endian conversion for SPARC. SPARC is big endian only.
>>> + *
>>> + *  COPYRIGHT (c) 2011
>>> + *  Aeroflex Gaisler.
>>> + *
>>> + *  The license and distribution terms for this file may be
>>> + *  found in the file LICENSE in this distribution or at
>>> + *  http://www.rtems.com/license/LICENSE.
>>> + */
>>> +
>>> +#ifndef _LIBCPU_BYTEORDER_H
>>> +#define _LIBCPU_BYTEORDER_H
>>> +
>>> +#include<rtems/system.h>
>>> +#include<rtems/score/cpu.h>
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +RTEMS_INLINE_ROUTINE uint16_t ld_le16(volatile uint16_t *addr)
>>> +{
>>> +       return CPU_swap_u16(*addr);
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE void st_le16(volatile uint16_t *addr, uint16_t val)
>>> +{
>>> +       *addr = CPU_swap_u16(val);
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE uint32_t ld_le32(volatile uint32_t *addr)
>>> +{
>>> +       return CPU_swap_u32(*addr);
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE void st_le32(volatile uint32_t *addr, uint32_t val)
>>> +{
>>> +       *addr = CPU_swap_u32(val);
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE uint16_t ld_be16(volatile uint16_t *addr)
>>> +{
>>> +       return *addr;
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE void st_be16(volatile uint16_t *addr, uint16_t val)
>>> +{
>>> +       *addr = val;
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE uint32_t ld_be32(volatile uint32_t *addr)
>>> +{
>>> +       return *addr;
>>> +}
>>> +
>>> +RTEMS_INLINE_ROUTINE void st_be32(volatile uint32_t *addr, uint32_t val)
>>> +{
>>> +       *addr = val;
>>> +}
>> Is there a reason for the addr argument to be volatile to these functions?
> Yes, I followed the way powerpc implemented PCI access routines. They use volatile, and I beleive it is correct since one is accessing a register, somehow the compiler must not optimize away the
> access. Please see c/src/lib/libcpu/powerpc/shared/include/byteorder.h
>
>> Why not use the functions defined above in access.h?
> access.h define functions named _FUNC, whereas byteorder.h define inline functions named FUNC.
>
> Sometimes we need to refer to access routines by function pointers and sometimes we want to optimize the code as much as possible with inlining. Bear in mind that these functions are accessed very
> often, every time a register is accessed.
>
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/c/src/lib/libcpu/sparc/preinstall.am b/c/src/lib/libcpu/sparc/preinstall.am
>>> index 412b683..2efe38b 100644
>>> --- a/c/src/lib/libcpu/sparc/preinstall.am
>>> +++ b/c/src/lib/libcpu/sparc/preinstall.am
>>> @@ -22,3 +22,11 @@ $(PROJECT_INCLUDE)/libcpu/cache.h: ../shared/include/cache.h $(PROJECT_INCLUDE)/
>>>          $(INSTALL_DATA) $<   $(PROJECT_INCLUDE)/libcpu/cache.h
>>>    PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/cache.h
>>>
>>> +$(PROJECT_INCLUDE)/libcpu/byteorder.h: include/libcpu/byteorder.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
>>> +       $(INSTALL_DATA) $<   $(PROJECT_INCLUDE)/libcpu/byteorder.h
>>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/byteorder.h
>>> +
>>> +$(PROJECT_INCLUDE)/libcpu/access.h: include/libcpu/access.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
>>> +       $(INSTALL_DATA) $<   $(PROJECT_INCLUDE)/libcpu/access.h
>>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/access.h
>>> +
>>> --
>>> 1.7.0.4
>>>
>>> _______________________________________________
>>> rtems-devel mailing list
>>> rtems-devel at rtems.org
>>> http://www.rtems.org/mailman/listinfo/rtems-devel
> _______________________________________________
> rtems-devel mailing list
> rtems-devel at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel


-- 
Joel Sherrill, Ph.D.             Director of Research&   Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
     Support Available             (256) 722-9985





More information about the devel mailing list