xref: /netbsd-src/sys/arch/vax/include/macros.h (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: macros.h,v 1.44 2007/11/22 23:02:05 plunky Exp $	*/
2 
3 /*
4  * Copyright (c) 1994, 1998, 2000 Ludd, University of Lule}, Sweden.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *     This product includes software developed at Ludd, University of Lule}.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33  /* All bugs are subject to removal without further notice */
34 
35 #if !defined(_VAX_MACROS_H_) && !defined(__lint__)
36 #define _VAX_MACROS_H_
37 
38 void	__blkset(void *, int, size_t);
39 void	__blkcpy(const void *, void *, size_t);
40 
41 #if !__GNUC_PREREQ__(4, 1)
42 /* Here general macros are supposed to be stored */
43 
44 static __inline int __attribute__((__unused__))
45 vax_ffs(int reg)
46 {
47 	register int val;
48 
49 	__asm volatile ("ffs $0,$32,%1,%0;"
50 			    "bneq 1f;"
51 			    "mnegl $1,%0;"
52 			    "1:;"
53 			    "incl %0"
54 			: "=&r" (val)
55 			: "r" (reg) );
56 	return	val;
57 }
58 #define ffs vax_ffs
59 #endif
60 
61 static __inline void __attribute__((__unused__))
62 vax_remque(void *p)
63 {
64 	__asm volatile ("remque (%0),%0;clrl 4(%0)"
65 			:
66 			: "r" (p)
67 			: "memory" );
68 }
69 
70 static __inline void  __attribute__((__unused__))
71 vax_insque(void *p, void *q)
72 {
73 	__asm volatile ("insque (%0),(%1)"
74 			:
75 			: "r" (p),"r" (q)
76 			: "memory" );
77 }
78 
79 #if 0
80 static __inline void *__attribute__((__unused__))
81 vax_memcpy(void *to, const void *from, size_t len)
82 {
83 	if (len > 65535) {
84 		__blkcpy(from, to, len);
85 	} else {
86 		__asm volatile ("movc3 %1,(%2),%0"
87 			: "=m" (*(char *)to)
88 			: "g" (len), "r" (*(const char *)from)
89 			:"r0","r1","r2","r3","r4","r5","memory","cc");
90 	}
91 	return to;
92 }
93 #define memcpy vax_memcpy
94 
95 static __inline void *__attribute__((__unused__))
96 vax_memmove(void *to, const void *from, size_t len)
97 {
98 	if (len > 65535) {
99 		__blkcpy(from, to, len);
100 	} else {
101 		__asm __volatile ("movc3 %1,%2,%0"
102 			: "=m" (*(char *)to)
103 			: "g" (len), "mo" (*(const char *)from)
104 			:"r0","r1","r2","r3","r4","r5","memory","cc");
105 	}
106 	return to;
107 }
108 #define memmove vax_memmove
109 #endif
110 
111 static __inline void *__attribute__((__unused__))
112 vax_memset(void *block, int c, size_t len)
113 {
114 	if (len > 65535) {
115 		__blkset(block, c, len);
116 	} else {
117 		__asm __volatile ("movc5 $0,(%%sp),%2,%1,%0"
118 			: "=m" (*(char *)block)
119 			:  "g" (len), "g" (c)
120 			:"r0","r1","r2","r3","r4","r5","memory","cc");
121 	}
122 	return block;
123 }
124 #define memset vax_memset
125 
126 #ifdef notdef
127 /* XXX - the return syntax of memcmp is wrong */
128 static __inline int __attribute__((__unused__))
129 memcmp(const void *b1, const void *b2, size_t len)
130 {
131 	register int ret;
132 
133 	__asm volatile("cmpc3 %3,(%1),(%2);"
134 			   "movl %%r0,%0"
135 			: "=r" (ret)
136 			: "r" (b1), "r" (b2), "r" (len)
137 			: "r0","r1","r2","r3" );
138 	return ret;
139 }
140 
141 static __inline int __attribute__((__unused__))
142 bcmp(const void *b1, const void *b2, size_t len)
143 {
144 	register int ret;
145 
146 	__asm volatile("cmpc3 %3,(%1),(%2);"
147 			   "movl %%r0,%0"
148 			: "=r" (ret)
149 			: "r" (b1), "r" (b2), "r" (len)
150 			: "r0","r1","r2","r3" );
151 	return ret;
152 }
153 
154 /* Begin nya */
155 static __inline size_t __attribute__((__unused__))
156 strlen(const char *cp)
157 {
158         register size_t ret;
159 
160         __asm volatile("locc $0,$65535,(%1);"
161 			   "subl3 %%r0,$65535,%0"
162                         : "=r" (ret)
163                         : "r" (cp)
164                         : "r0","r1","cc" );
165         return  ret;
166 }
167 
168 static __inline char * __attribute__((__unused__))
169 strcat(char *cp, const char *c2)
170 {
171         __asm volatile("locc $0,$65535,(%1);"
172 			   "subl3 %%r0,$65535,%%r2;"
173 			   "incl %%r2;"
174                            "locc $0,$65535,(%0);"
175 			   "movc3 %%r2,(%1),(%%r1)"
176                         :
177                         : "r" (cp), "r" (c2)
178                         : "r0","r1","r2","r3","r4","r5","memory","cc");
179         return  cp;
180 }
181 
182 static __inline char * __attribute__((__unused__))
183 strncat(char *cp, const char *c2, size_t count)
184 {
185         __asm volatile("locc $0,%2,(%1);"
186 			   "subl3 %%r0,%2,%%r2;"
187                            "locc $0,$65535,(%0);"
188 			   "movc3 %%r2,(%1),(%%r1);"
189 			   "movb $0,(%%r3)"
190                         :
191                         : "r" (cp), "r" (c2), "g"(count)
192                         : "r0","r1","r2","r3","r4","r5","memory","cc");
193         return  cp;
194 }
195 
196 static __inline char * __attribute__((__unused__))
197 strcpy(char *cp, const char *c2)
198 {
199         __asm volatile("locc $0,$65535,(%1);"
200 			   "subl3 %%r0,$65535,%%r2;"
201                            "movc3 %%r2,(%1),(%0);"
202 			   "movb $0,(%%r3)"
203                         :
204                         : "r" (cp), "r" (c2)
205                         : "r0","r1","r2","r3","r4","r5","memory","cc");
206         return  cp;
207 }
208 
209 static __inline char * __attribute__((__unused__))
210 strncpy(char *cp, const char *c2, size_t len)
211 {
212         __asm volatile("movl %2,%%r2;"
213 			   "locc $0,%%r2,(%1);"
214 			   "beql 1f;"
215 			   "subl3 %%r0,%2,%%r2;"
216                            "clrb (%0)[%%r2];"
217 			   "1:;"
218 			   "movc3 %%r2,(%1),(%0)"
219                         :
220                         : "r" (cp), "r" (c2), "g"(len)
221                         : "r0","r1","r2","r3","r4","r5","memory","cc");
222         return  cp;
223 }
224 
225 static __inline void *__attribute__((__unused__))
226 memchr(const void *cp, int c, size_t len)
227 {
228         void *ret;
229         __asm volatile("locc %2,%3,(%1);"
230 			   "bneq 1f;"
231 			   "clrl %%r1;"
232 			   "1:;"
233 			   "movl %%r1,%0"
234                         : "=g"(ret)
235                         : "r" (cp), "r" (c), "g"(len)
236                         : "r0","r1","cc");
237         return  ret;
238 }
239 
240 static __inline int __attribute__((__unused__))
241 strcmp(const char *cp, const char *c2)
242 {
243         register int ret;
244         __asm volatile("locc $0,$65535,(%1);"
245 			   "subl3 %%r0,$65535,%%r0;"
246 			   "incl %%r0;"
247                            "cmpc3 %%r0,(%1),(%2);"
248 			   "beql 1f;"
249 			   "movl $1,%%r2;"
250                            "cmpb (%%r1),(%%r3);"
251 			   "bcc 1f;"
252 			   "mnegl $1,%%r2;"
253 			   "1:;"
254 			   "movl %%r2,%0"
255                         : "=g"(ret)
256                         : "r" (cp), "r" (c2)
257                         : "r0","r1","r2","r3","cc");
258         return  ret;
259 }
260 #endif
261 
262 #if 0 /* unused, but no point in deleting it since it _is_ an instruction */
263 static __inline int __attribute__((__unused__))
264 locc(int mask, char *cp, size_t size){
265 	register ret;
266 
267 	__asm volatile("locc %1,%2,(%3);"
268 			   "movl %%r0,%0"
269 			: "=r" (ret)
270 			: "r" (mask),"r"(size),"r"(cp)
271 			: "r0","r1" );
272 	return	ret;
273 }
274 #endif
275 
276 static __inline int __attribute__((__unused__))
277 vax_scanc(u_int size, const u_char *cp, const u_char *table, int mask)
278 {
279 	register int ret;
280 
281 	__asm volatile("scanc %1,(%2),(%3),%4;"
282 			   "movl %%r0,%0"
283 			: "=g"(ret)
284 			: "r"(size),"r"(cp),"r"(table),"r"(mask)
285 			: "r0","r1","r2","r3" );
286 	return ret;
287 }
288 #define scanc vax_scanc
289 
290 static __inline int __attribute__((__unused__))
291 vax_skpc(int mask, size_t size, u_char *cp)
292 {
293 	register int ret;
294 
295 	__asm volatile("skpc %1,%2,(%3);"
296 			   "movl %%r0,%0"
297 			: "=g"(ret)
298 			: "r"(mask),"r"(size),"r"(cp)
299 			: "r0","r1" );
300 	return	ret;
301 }
302 #define skpc vax_skpc
303 
304 /*
305  * Set/clear a bit at a memory position; interlocked.
306  * Return 0 if already set, 1 otherwise.
307  */
308 static __inline int __attribute__((__unused__))
309 bbssi(int bitnr, long *addr)
310 {
311 	register int ret;
312 
313 	__asm volatile("clrl %%r0;"
314 			   "bbssi %1,%2,1f;"
315 			   "incl %%r0;"
316 			   "1:;"
317 			   "movl %%r0,%0"
318 		: "=&r"(ret)
319 		: "g"(bitnr),"m"(*addr)
320 		: "r0","cc","memory");
321 	return ret;
322 }
323 
324 static __inline int __attribute__((__unused__))
325 bbcci(int bitnr, long *addr)
326 {
327 	register int ret;
328 
329 	__asm volatile("clrl %%r0;"
330 			   "bbcci %1,%2,1f;"
331 			   "incl %%r0;"
332 			   "1:;"
333 			   "movl %%r0,%0"
334 		: "=&r"(ret)
335 		: "g"(bitnr),"m"(*addr)
336 		: "r0","cc","memory");
337 	return ret;
338 }
339 
340 static inline struct lwp *
341 cpu_switchto(struct lwp *oldlwp, struct lwp *newlwp, bool returning)
342 {
343 	struct lwp *prevlwp;
344 	__asm volatile(
345 		"movl %1,%%r0;"
346 		"movl %2,%%r1;"
347 		"movpsl -(%%sp);"
348 		"jsb Swtchto;"
349 		"movl %%r0,%0"
350 	    : "=g"(prevlwp)
351 	    : "g" (oldlwp), "g" (newlwp)
352 	    : "r0", "r1");
353 	return prevlwp;
354 }
355 
356 /*
357  * Interlock instructions. Used both in multiprocessor environments to
358  * lock between CPUs and in uniprocessor systems when locking is required
359  * between I/O devices and the master CPU.
360  */
361 /*
362  * Insqti() locks and inserts an element into the end of a queue.
363  * Returns -1 if interlock failed, 1 if inserted OK and 0 if first in queue.
364  */
365 static __inline int __attribute__((__unused__))
366 insqti(void *entry, void *header) {
367 	register int ret;
368 
369 	__asm volatile(
370 		"	mnegl $1,%0;"
371 		"	insqti (%1),(%2);"
372 		"	bcs 1f;"		/* failed insert */
373 		"	beql 2f;"		/* jump if first entry */
374 		"	movl $1,%0;"
375 		"	brb 1f;"
376 		"2:	clrl %0;"
377 		"	1:;"
378 			: "=&g"(ret)
379 			: "r"(entry), "r"(header)
380 			: "memory");
381 
382 	return ret;
383 }
384 
385 /*
386  * Remqhi() removes an element from the head of the queue.
387  * Returns -1 if interlock failed, 0 if queue empty, address of the
388  * removed element otherwise.
389  */
390 static __inline void *__attribute__((__unused__))
391 remqhi(void *header) {
392 	register void *ret;
393 
394 	__asm volatile(
395 		"	remqhi (%1),%0;"
396 		"	bcs 1f;"		/* failed interlock */
397 		"	bvs 2f;"		/* nothing was removed */
398 		"	brb 3f;"
399 		"1:	mnegl $1,%0;"
400 		"	brb 3f;"
401 		"2:	clrl %0;"
402 		"	3:;"
403 			: "=&g"(ret)
404 			: "r"(header)
405 			: "memory");
406 
407 	return ret;
408 }
409 #define	ILCK_FAILED	-1	/* Interlock failed */
410 #define	Q_EMPTY		0	/* Queue is/was empty */
411 #define	Q_OK		1	/* Inserted OK */
412 
413 #endif	/* !_VAX_MACROS_H_ && !__lint__ */
414