1/*
2 * BK Id: SCCS/s.byteorder.h 1.8 10/11/01 13:02:49 trini
3 */
4#ifndef _PPC_BYTEORDER_H
5#define _PPC_BYTEORDER_H
6
7#include <asm/types.h>
8
9#ifdef __GNUC__
10#ifdef __KERNEL__
11
12extern __inline__ unsigned ld_le16(const volatile unsigned short *addr)
13{
14	unsigned val;
15
16	__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
17	return val;
18}
19
20extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val)
21{
22	__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
23}
24
25extern __inline__ unsigned ld_le32(const volatile unsigned *addr)
26{
27	unsigned val;
28
29	__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
30	return val;
31}
32
33extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
34{
35	__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
36}
37
38/* alas, egcs sounds like it has a bug in this code that doesn't use the
39   inline asm correctly, and can cause file corruption. Until I hear that
40   it's fixed, I can live without the extra speed. I hope. */
41
42/* The same, but returns converted value from the location pointer by addr. */
43#define __arch__swab16p(addr) ld_le16(addr)
44#define __arch__swab32p(addr) ld_le32(addr)
45
46/* The same, but do the conversion in situ, ie. put the value back to addr. */
47#define __arch__swab16s(addr) st_le16(addr,*addr)
48#define __arch__swab32s(addr) st_le32(addr,*addr)
49
50#endif /* __KERNEL__ */
51
52#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
53#  define __BYTEORDER_HAS_U64__
54#  define __SWAB_64_THRU_32__
55#endif
56
57#endif /* __GNUC__ */
58
59#include <linux/byteorder/big_endian.h>
60
61#endif /* _PPC_BYTEORDER_H */
62