OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-mips/] [unaligned.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1276 phoenix
/*
2
 * This file is subject to the terms and conditions of the GNU General Public
3
 * License.  See the file "COPYING" in the main directory of this archive
4
 * for more details.
5
 *
6
 * Copyright (C) 1996, 1999, 2000 by Ralf Baechle
7
 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8
 */
9
#ifndef _ASM_UNALIGNED_H
10
#define _ASM_UNALIGNED_H
11
 
12
extern void __get_unaligned_bad_length(void);
13
extern void __put_unaligned_bad_length(void);
14
 
15
/*
16
 * Load double unaligned.
17
 *
18
 * This could have been implemented in plain C like IA64 but egcs 1.0.3a
19
 * inflates this to 23 instructions ...
20
 */
21
static inline unsigned long long __ldq_u(const unsigned long long * __addr)
22
{
23
        unsigned long long __res;
24
 
25
        __asm__("ulw\t%0, %1\n\t"
26
                "ulw\t%D0, 4+%1"
27
                : "=&r" (__res)
28
                : "m" (*__addr));
29
 
30
        return __res;
31
}
32
 
33
/*
34
 * Load word unaligned.
35
 */
36
static inline unsigned long __ldl_u(const unsigned int * __addr)
37
{
38
        unsigned long __res;
39
 
40
        __asm__("ulw\t%0,%1"
41
                : "=&r" (__res)
42
                : "m" (*__addr));
43
 
44
        return __res;
45
}
46
 
47
/*
48
 * Load halfword unaligned.
49
 */
50
static inline unsigned long __ldw_u(const unsigned short * __addr)
51
{
52
        unsigned long __res;
53
 
54
        __asm__("ulh\t%0,%1"
55
                : "=&r" (__res)
56
                : "m" (*__addr));
57
 
58
        return __res;
59
}
60
 
61
/*
62
 * Store doubleword ununaligned.
63
 */
64
static inline void __stq_u(unsigned long __val, unsigned long long * __addr)
65
{
66
        __asm__("usw\t%1, %0\n\t"
67
                "usw\t%D1, 4+%0"
68
                : "=m" (*__addr)
69
                : "r" (__val));
70
}
71
 
72
/*
73
 * Store long ununaligned.
74
 */
75
static inline void __stl_u(unsigned long __val, unsigned int * __addr)
76
{
77
        __asm__("usw\t%1, %0"
78
                : "=m" (*__addr)
79
                : "r" (__val));
80
}
81
 
82
/*
83
 * Store word ununaligned.
84
 */
85
static inline void __stw_u(unsigned long __val, unsigned short * __addr)
86
{
87
        __asm__("ush\t%1, %0"
88
                : "=m" (*__addr)
89
                : "r" (__val));
90
}
91
 
92
/*
93
 * get_unaligned - get value from possibly mis-aligned location
94
 * @ptr: pointer to value
95
 *
96
 * This macro should be used for accessing values larger in size than
97
 * single bytes at locations that are expected to be improperly aligned,
98
 * e.g. retrieving a u16 value from a location not u16-aligned.
99
 *
100
 * Note that unaligned accesses can be very expensive on some architectures.
101
 */
102
#define get_unaligned(ptr)                                              \
103
({                                                                      \
104
        __typeof__(*(ptr)) __val;                                       \
105
                                                                        \
106
        switch (sizeof(*(ptr))) {                                       \
107
        case 1:                                                         \
108
                __val = *(const unsigned char *)ptr;                    \
109
                break;                                                  \
110
        case 2:                                                         \
111
                __val = __ldw_u((const unsigned short *)ptr);           \
112
                break;                                                  \
113
        case 4:                                                         \
114
                __val = __ldl_u((const unsigned int *)ptr);             \
115
                break;                                                  \
116
        case 8:                                                         \
117
                __val = __ldq_u((const unsigned long long *)ptr);       \
118
                break;                                                  \
119
        default:                                                        \
120
                __get_unaligned_bad_length();                           \
121
                break;                                                  \
122
        }                                                               \
123
                                                                        \
124
        __val;                                                          \
125
})
126
 
127
/*
128
 * put_unaligned - put value to a possibly mis-aligned location
129
 * @val: value to place
130
 * @ptr: pointer to location
131
 *
132
 * This macro should be used for placing values larger in size than
133
 * single bytes at locations that are expected to be improperly aligned,
134
 * e.g. writing a u16 value to a location not u16-aligned.
135
 *
136
 * Note that unaligned accesses can be very expensive on some architectures.
137
 */
138
#define put_unaligned(val,ptr)                                          \
139
do {                                                                    \
140
        switch (sizeof(*(ptr))) {                                       \
141
        case 1:                                                         \
142
                *(unsigned char *)(ptr) = (val);                        \
143
                break;                                                  \
144
        case 2:                                                         \
145
                __stw_u(val, (unsigned short *)(ptr));                  \
146
                break;                                                  \
147
        case 4:                                                         \
148
                __stl_u(val, (unsigned int *)(ptr));                    \
149
                break;                                                  \
150
        case 8:                                                         \
151
                __stq_u(val, (unsigned long long *)(ptr));              \
152
                break;                                                  \
153
        default:                                                        \
154
                __put_unaligned_bad_length();                           \
155
                break;                                                  \
156
        }                                                               \
157
} while(0)
158
 
159
#endif /* _ASM_UNALIGNED_H */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.