1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#ifndef __ASM_REGOPS_H__
48#define __ASM_REGOPS_H__
49
50#include <linux/types.h>
51
52#include <asm/compiler.h>
53#include <asm/war.h>
54
55#ifndef R10000_LLSC_WAR
56#define R10000_LLSC_WAR 0
57#endif
58
59#if R10000_LLSC_WAR == 1
60#define __beqz "beqzl "
61#else
62#define __beqz "beqz "
63#endif
64
65#ifndef _LINUX_TYPES_H
66typedef unsigned int u32;
67#endif
68
69
70
71
72static inline void set_value_reg32(volatile u32 *const addr,
73 u32 const mask,
74 u32 const value)
75{
76 u32 temp;
77
78 __asm__ __volatile__(
79 " .set push \n"
80 " .set arch=r4000 \n"
81 "1: ll %0, %1 # set_value_reg32 \n"
82 " and %0, %2 \n"
83 " or %0, %3 \n"
84 " sc %0, %1 \n"
85 " "__beqz"%0, 1b \n"
86 " nop \n"
87 " .set pop \n"
88 : "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
89 : "ir" (~mask), "ir" (value), GCC_OFF_SMALL_ASM() (*addr));
90}
91
92
93
94
95static inline void set_reg32(volatile u32 *const addr,
96 u32 const mask)
97{
98 u32 temp;
99
100 __asm__ __volatile__(
101 " .set push \n"
102 " .set arch=r4000 \n"
103 "1: ll %0, %1 # set_reg32 \n"
104 " or %0, %2 \n"
105 " sc %0, %1 \n"
106 " "__beqz"%0, 1b \n"
107 " nop \n"
108 " .set pop \n"
109 : "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
110 : "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
111}
112
113
114
115
116static inline void clear_reg32(volatile u32 *const addr,
117 u32 const mask)
118{
119 u32 temp;
120
121 __asm__ __volatile__(
122 " .set push \n"
123 " .set arch=r4000 \n"
124 "1: ll %0, %1 # clear_reg32 \n"
125 " and %0, %2 \n"
126 " sc %0, %1 \n"
127 " "__beqz"%0, 1b \n"
128 " nop \n"
129 " .set pop \n"
130 : "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
131 : "ir" (~mask), GCC_OFF_SMALL_ASM() (*addr));
132}
133
134
135
136
137static inline void toggle_reg32(volatile u32 *const addr,
138 u32 const mask)
139{
140 u32 temp;
141
142 __asm__ __volatile__(
143 " .set push \n"
144 " .set arch=r4000 \n"
145 "1: ll %0, %1 # toggle_reg32 \n"
146 " xor %0, %2 \n"
147 " sc %0, %1 \n"
148 " "__beqz"%0, 1b \n"
149 " nop \n"
150 " .set pop \n"
151 : "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*addr)
152 : "ir" (mask), GCC_OFF_SMALL_ASM() (*addr));
153}
154
155
156
157
158static inline u32 read_reg32(volatile u32 *const addr,
159 u32 const mask)
160{
161 u32 temp;
162
163 __asm__ __volatile__(
164 " .set push \n"
165 " .set noreorder \n"
166 " lw %0, %1 # read \n"
167 " and %0, %2 # mask \n"
168 " .set pop \n"
169 : "=&r" (temp)
170 : "m" (*addr), "ir" (mask));
171
172 return temp;
173}
174
175
176
177
178
179
180
181
182static inline u32 blocking_read_reg32(volatile u32 *const addr)
183{
184 u32 temp;
185
186 __asm__ __volatile__(
187 " .set push \n"
188 " .set noreorder \n"
189 " lw %0, %1 # read \n"
190 " move %0, %0 # block \n"
191 " .set pop \n"
192 : "=&r" (temp)
193 : "m" (*addr));
194
195 return temp;
196}
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217#define custom_read_reg32(address, tmp) \
218 __asm__ __volatile__( \
219 " .set push \n" \
220 " .set arch=r4000 \n" \
221 "1: ll %0, %1 #custom_read_reg32 \n" \
222 " .set pop \n" \
223 : "=r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address) \
224 : GCC_OFF_SMALL_ASM() (*address))
225
226#define custom_write_reg32(address, tmp) \
227 __asm__ __volatile__( \
228 " .set push \n" \
229 " .set arch=r4000 \n" \
230 " sc %0, %1 #custom_write_reg32 \n" \
231 " "__beqz"%0, 1b \n" \
232 " nop \n" \
233 " .set pop \n" \
234 : "=&r" (tmp), "=" GCC_OFF_SMALL_ASM() (*address) \
235 : "0" (tmp), GCC_OFF_SMALL_ASM() (*address))
236
237#endif
238