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