xref: /netbsd-src/sys/arch/vax/include/macros.h (revision 7fa608457b817eca6e0977b37f758ae064f3c99c)
1 /*	$NetBSD: macros.h,v 1.42 2007/10/17 19:57:48 garbled 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 #define _remque vax_remque
70 
71 static __inline void  __attribute__((__unused__))
72 vax_insque(void *p, void *q)
73 {
74 	__asm volatile ("insque (%0),(%1)"
75 			:
76 			: "r" (p),"r" (q)
77 			: "memory" );
78 }
79 #define _insque vax_insque
80 
81 #if 0
82 static __inline void *__attribute__((__unused__))
83 vax_memcpy(void *to, const void *from, size_t len)
84 {
85 	if (len > 65535) {
86 		__blkcpy(from, to, len);
87 	} else {
88 		__asm volatile ("movc3 %1,(%2),%0"
89 			: "=m" (*(char *)to)
90 			: "g" (len), "r" (*(const char *)from)
91 			:"r0","r1","r2","r3","r4","r5","memory","cc");
92 	}
93 	return to;
94 }
95 #define memcpy vax_memcpy
96 
97 static __inline void *__attribute__((__unused__))
98 vax_memmove(void *to, const void *from, size_t len)
99 {
100 	if (len > 65535) {
101 		__blkcpy(from, to, len);
102 	} else {
103 		__asm __volatile ("movc3 %1,%2,%0"
104 			: "=m" (*(char *)to)
105 			: "g" (len), "mo" (*(const char *)from)
106 			:"r0","r1","r2","r3","r4","r5","memory","cc");
107 	}
108 	return to;
109 }
110 #define memmove vax_memmove
111 #endif
112 
113 static __inline void *__attribute__((__unused__))
114 vax_memset(void *block, int c, size_t len)
115 {
116 	if (len > 65535) {
117 		__blkset(block, c, len);
118 	} else {
119 		__asm __volatile ("movc5 $0,(%%sp),%2,%1,%0"
120 			: "=m" (*(char *)block)
121 			:  "g" (len), "g" (c)
122 			:"r0","r1","r2","r3","r4","r5","memory","cc");
123 	}
124 	return block;
125 }
126 #define memset vax_memset
127 
128 #ifdef notdef
129 /* XXX - the return syntax of memcmp is wrong */
130 static __inline int __attribute__((__unused__))
131 memcmp(const void *b1, const void *b2, size_t len)
132 {
133 	register int ret;
134 
135 	__asm volatile("cmpc3 %3,(%1),(%2);"
136 			   "movl %%r0,%0"
137 			: "=r" (ret)
138 			: "r" (b1), "r" (b2), "r" (len)
139 			: "r0","r1","r2","r3" );
140 	return ret;
141 }
142 
143 static __inline int __attribute__((__unused__))
144 bcmp(const void *b1, const void *b2, size_t len)
145 {
146 	register int ret;
147 
148 	__asm volatile("cmpc3 %3,(%1),(%2);"
149 			   "movl %%r0,%0"
150 			: "=r" (ret)
151 			: "r" (b1), "r" (b2), "r" (len)
152 			: "r0","r1","r2","r3" );
153 	return ret;
154 }
155 
156 /* Begin nya */
157 static __inline size_t __attribute__((__unused__))
158 strlen(const char *cp)
159 {
160         register size_t ret;
161 
162         __asm volatile("locc $0,$65535,(%1);"
163 			   "subl3 %%r0,$65535,%0"
164                         : "=r" (ret)
165                         : "r" (cp)
166                         : "r0","r1","cc" );
167         return  ret;
168 }
169 
170 static __inline char * __attribute__((__unused__))
171 strcat(char *cp, const char *c2)
172 {
173         __asm volatile("locc $0,$65535,(%1);"
174 			   "subl3 %%r0,$65535,%%r2;"
175 			   "incl %%r2;"
176                            "locc $0,$65535,(%0);"
177 			   "movc3 %%r2,(%1),(%%r1)"
178                         :
179                         : "r" (cp), "r" (c2)
180                         : "r0","r1","r2","r3","r4","r5","memory","cc");
181         return  cp;
182 }
183 
184 static __inline char * __attribute__((__unused__))
185 strncat(char *cp, const char *c2, size_t count)
186 {
187         __asm volatile("locc $0,%2,(%1);"
188 			   "subl3 %%r0,%2,%%r2;"
189                            "locc $0,$65535,(%0);"
190 			   "movc3 %%r2,(%1),(%%r1);"
191 			   "movb $0,(%%r3)"
192                         :
193                         : "r" (cp), "r" (c2), "g"(count)
194                         : "r0","r1","r2","r3","r4","r5","memory","cc");
195         return  cp;
196 }
197 
198 static __inline char * __attribute__((__unused__))
199 strcpy(char *cp, const char *c2)
200 {
201         __asm volatile("locc $0,$65535,(%1);"
202 			   "subl3 %%r0,$65535,%%r2;"
203                            "movc3 %%r2,(%1),(%0);"
204 			   "movb $0,(%%r3)"
205                         :
206                         : "r" (cp), "r" (c2)
207                         : "r0","r1","r2","r3","r4","r5","memory","cc");
208         return  cp;
209 }
210 
211 static __inline char * __attribute__((__unused__))
212 strncpy(char *cp, const char *c2, size_t len)
213 {
214         __asm volatile("movl %2,%%r2;"
215 			   "locc $0,%%r2,(%1);"
216 			   "beql 1f;"
217 			   "subl3 %%r0,%2,%%r2;"
218                            "clrb (%0)[%%r2];"
219 			   "1:;"
220 			   "movc3 %%r2,(%1),(%0)"
221                         :
222                         : "r" (cp), "r" (c2), "g"(len)
223                         : "r0","r1","r2","r3","r4","r5","memory","cc");
224         return  cp;
225 }
226 
227 static __inline void *__attribute__((__unused__))
228 memchr(const void *cp, int c, size_t len)
229 {
230         void *ret;
231         __asm volatile("locc %2,%3,(%1);"
232 			   "bneq 1f;"
233 			   "clrl %%r1;"
234 			   "1:;"
235 			   "movl %%r1,%0"
236                         : "=g"(ret)
237                         : "r" (cp), "r" (c), "g"(len)
238                         : "r0","r1","cc");
239         return  ret;
240 }
241 
242 static __inline int __attribute__((__unused__))
243 strcmp(const char *cp, const char *c2)
244 {
245         register int ret;
246         __asm volatile("locc $0,$65535,(%1);"
247 			   "subl3 %%r0,$65535,%%r0;"
248 			   "incl %%r0;"
249                            "cmpc3 %%r0,(%1),(%2);"
250 			   "beql 1f;"
251 			   "movl $1,%%r2;"
252                            "cmpb (%%r1),(%%r3);"
253 			   "bcc 1f;"
254 			   "mnegl $1,%%r2;"
255 			   "1:;"
256 			   "movl %%r2,%0"
257                         : "=g"(ret)
258                         : "r" (cp), "r" (c2)
259                         : "r0","r1","r2","r3","cc");
260         return  ret;
261 }
262 #endif
263 
264 #if 0 /* unused, but no point in deleting it since it _is_ an instruction */
265 static __inline int __attribute__((__unused__))
266 locc(int mask, char *cp, size_t size){
267 	register ret;
268 
269 	__asm volatile("locc %1,%2,(%3);"
270 			   "movl %%r0,%0"
271 			: "=r" (ret)
272 			: "r" (mask),"r"(size),"r"(cp)
273 			: "r0","r1" );
274 	return	ret;
275 }
276 #endif
277 
278 static __inline int __attribute__((__unused__))
279 vax_scanc(u_int size, const u_char *cp, const u_char *table, int mask)
280 {
281 	register int ret;
282 
283 	__asm volatile("scanc %1,(%2),(%3),%4;"
284 			   "movl %%r0,%0"
285 			: "=g"(ret)
286 			: "r"(size),"r"(cp),"r"(table),"r"(mask)
287 			: "r0","r1","r2","r3" );
288 	return ret;
289 }
290 #define scanc vax_scanc
291 
292 static __inline int __attribute__((__unused__))
293 vax_skpc(int mask, size_t size, u_char *cp)
294 {
295 	register int ret;
296 
297 	__asm volatile("skpc %1,%2,(%3);"
298 			   "movl %%r0,%0"
299 			: "=g"(ret)
300 			: "r"(mask),"r"(size),"r"(cp)
301 			: "r0","r1" );
302 	return	ret;
303 }
304 #define skpc vax_skpc
305 
306 /*
307  * Set/clear a bit at a memory position; interlocked.
308  * Return 0 if already set, 1 otherwise.
309  */
310 static __inline int __attribute__((__unused__))
311 bbssi(int bitnr, long *addr)
312 {
313 	register int ret;
314 
315 	__asm volatile("clrl %%r0;"
316 			   "bbssi %1,%2,1f;"
317 			   "incl %%r0;"
318 			   "1:;"
319 			   "movl %%r0,%0"
320 		: "=&r"(ret)
321 		: "g"(bitnr),"m"(*addr)
322 		: "r0","cc","memory");
323 	return ret;
324 }
325 
326 static __inline int __attribute__((__unused__))
327 bbcci(int bitnr, long *addr)
328 {
329 	register int ret;
330 
331 	__asm volatile("clrl %%r0;"
332 			   "bbcci %1,%2,1f;"
333 			   "incl %%r0;"
334 			   "1:;"
335 			   "movl %%r0,%0"
336 		: "=&r"(ret)
337 		: "g"(bitnr),"m"(*addr)
338 		: "r0","cc","memory");
339 	return ret;
340 }
341 
342 static inline struct lwp *
343 cpu_switchto(struct lwp *oldlwp, struct lwp *newlwp)
344 {
345 	struct lwp *prevlwp;
346 	__asm volatile(
347 		"movl %1,%%r0;"
348 		"movl %2,%%r1;"
349 		"movpsl -(%%sp);"
350 		"jsb Swtchto;"
351 		"movl %%r0,%0"
352 	    : "=g"(prevlwp)
353 	    : "g" (oldlwp), "g" (newlwp)
354 	    : "r0", "r1");
355 	return prevlwp;
356 }
357 
358 /*
359  * Interlock instructions. Used both in multiprocessor environments to
360  * lock between CPUs and in uniprocessor systems when locking is required
361  * between I/O devices and the master CPU.
362  */
363 /*
364  * Insqti() locks and inserts an element into the end of a queue.
365  * Returns -1 if interlock failed, 1 if inserted OK and 0 if first in queue.
366  */
367 static __inline int __attribute__((__unused__))
368 insqti(void *entry, void *header) {
369 	register int ret;
370 
371 	__asm volatile(
372 		"	mnegl $1,%0;"
373 		"	insqti (%1),(%2);"
374 		"	bcs 1f;"		/* failed insert */
375 		"	beql 2f;"		/* jump if first entry */
376 		"	movl $1,%0;"
377 		"	brb 1f;"
378 		"2:	clrl %0;"
379 		"	1:;"
380 			: "=&g"(ret)
381 			: "r"(entry), "r"(header)
382 			: "memory");
383 
384 	return ret;
385 }
386 
387 /*
388  * Remqhi() removes an element from the head of the queue.
389  * Returns -1 if interlock failed, 0 if queue empty, address of the
390  * removed element otherwise.
391  */
392 static __inline void *__attribute__((__unused__))
393 remqhi(void *header) {
394 	register void *ret;
395 
396 	__asm volatile(
397 		"	remqhi (%1),%0;"
398 		"	bcs 1f;"		/* failed interlock */
399 		"	bvs 2f;"		/* nothing was removed */
400 		"	brb 3f;"
401 		"1:	mnegl $1,%0;"
402 		"	brb 3f;"
403 		"2:	clrl %0;"
404 		"	3:;"
405 			: "=&g"(ret)
406 			: "r"(header)
407 			: "memory");
408 
409 	return ret;
410 }
411 #define	ILCK_FAILED	-1	/* Interlock failed */
412 #define	Q_EMPTY		0	/* Queue is/was empty */
413 #define	Q_OK		1	/* Inserted OK */
414 
415 #endif	/* !_VAX_MACROS_H_ && !__lint__ */
416