Home | History | Annotate | Line # | Download | only in include
      1 /*	$NetBSD: macros.h,v 1.46 2017/05/22 17:12:11 ragge 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  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28  /* All bugs are subject to removal without further notice */
     29 
     30 #if !defined(_VAX_MACROS_H_) && !defined(__lint__)
     31 #define _VAX_MACROS_H_
     32 
     33 void	__blkset(void *, int, size_t);
     34 void	__blkcpy(const void *, void *, size_t);
     35 
     36 #if !__GNUC_PREREQ__(4, 1)
     37 /* Here general macros are supposed to be stored */
     38 
     39 static __inline int __attribute__((__unused__))
     40 vax_ffs(int reg)
     41 {
     42 	register int val;
     43 
     44 	__asm volatile ("ffs $0,$32,%1,%0;"
     45 			    "bneq 1f;"
     46 			    "mnegl $1,%0;"
     47 			    "1:;"
     48 			    "incl %0"
     49 			: "=&r" (val)
     50 			: "r" (reg) );
     51 	return	val;
     52 }
     53 #define ffs vax_ffs
     54 #endif
     55 
     56 static __inline void __attribute__((__unused__))
     57 vax_remque(void *p)
     58 {
     59 	__asm volatile ("remque (%0),%0;clrl 4(%0)"
     60 			:
     61 			: "r" (p)
     62 			: "memory" );
     63 }
     64 
     65 static __inline void  __attribute__((__unused__))
     66 vax_insque(void *p, void *q)
     67 {
     68 	__asm volatile ("insque (%0),(%1)"
     69 			:
     70 			: "r" (p),"r" (q)
     71 			: "memory" );
     72 }
     73 
     74 #if 0
     75 static __inline void *__attribute__((__unused__))
     76 vax_memcpy(void *to, const void *from, size_t len)
     77 {
     78 	if (len > 65535) {
     79 		__blkcpy(from, to, len);
     80 	} else {
     81 		__asm volatile ("movc3 %1,(%2),%0"
     82 			: "=m" (*(char *)to)
     83 			: "g" (len), "r" (*(const char *)from)
     84 			:"r0","r1","r2","r3","r4","r5","memory","cc");
     85 	}
     86 	return to;
     87 }
     88 #define memcpy vax_memcpy
     89 
     90 static __inline void *__attribute__((__unused__))
     91 vax_memmove(void *to, const void *from, size_t len)
     92 {
     93 	if (len > 65535) {
     94 		__blkcpy(from, to, len);
     95 	} else {
     96 		__asm __volatile ("movc3 %1,%2,%0"
     97 			: "=m" (*(char *)to)
     98 			: "g" (len), "mo" (*(const char *)from)
     99 			:"r0","r1","r2","r3","r4","r5","memory","cc");
    100 	}
    101 	return to;
    102 }
    103 #define memmove vax_memmove
    104 
    105 static __inline void *__attribute__((__unused__))
    106 vax_memset(void *block, int c, size_t len)
    107 {
    108 	if (len > 65535) {
    109 		__blkset(block, c, len);
    110 	} else {
    111 		__asm __volatile ("movc5 $0,(%%sp),%2,%1,%0"
    112 			: "=m" (*(char *)block)
    113 			:  "g" (len), "g" (c)
    114 			:"r0","r1","r2","r3","r4","r5","memory","cc");
    115 	}
    116 	return block;
    117 }
    118 #define memset vax_memset
    119 #endif
    120 
    121 #ifdef notdef
    122 /* XXX - the return syntax of memcmp is wrong */
    123 static __inline int __attribute__((__unused__))
    124 memcmp(const void *b1, const void *b2, size_t len)
    125 {
    126 	register int ret;
    127 
    128 	__asm volatile("cmpc3 %3,(%1),(%2);"
    129 			   "movl %%r0,%0"
    130 			: "=r" (ret)
    131 			: "r" (b1), "r" (b2), "r" (len)
    132 			: "r0","r1","r2","r3" );
    133 	return ret;
    134 }
    135 
    136 static __inline int __attribute__((__unused__))
    137 bcmp(const void *b1, const void *b2, size_t len)
    138 {
    139 	register int ret;
    140 
    141 	__asm volatile("cmpc3 %3,(%1),(%2);"
    142 			   "movl %%r0,%0"
    143 			: "=r" (ret)
    144 			: "r" (b1), "r" (b2), "r" (len)
    145 			: "r0","r1","r2","r3" );
    146 	return ret;
    147 }
    148 
    149 /* Begin nya */
    150 static __inline size_t __attribute__((__unused__))
    151 strlen(const char *cp)
    152 {
    153         register size_t ret;
    154 
    155         __asm volatile("locc $0,$65535,(%1);"
    156 			   "subl3 %%r0,$65535,%0"
    157                         : "=r" (ret)
    158                         : "r" (cp)
    159                         : "r0","r1","cc" );
    160         return  ret;
    161 }
    162 
    163 static __inline char * __attribute__((__unused__))
    164 strcat(char *cp, const char *c2)
    165 {
    166         __asm volatile("locc $0,$65535,(%1);"
    167 			   "subl3 %%r0,$65535,%%r2;"
    168 			   "incl %%r2;"
    169                            "locc $0,$65535,(%0);"
    170 			   "movc3 %%r2,(%1),(%%r1)"
    171                         :
    172                         : "r" (cp), "r" (c2)
    173                         : "r0","r1","r2","r3","r4","r5","memory","cc");
    174         return  cp;
    175 }
    176 
    177 static __inline char * __attribute__((__unused__))
    178 strncat(char *cp, const char *c2, size_t count)
    179 {
    180         __asm volatile("locc $0,%2,(%1);"
    181 			   "subl3 %%r0,%2,%%r2;"
    182                            "locc $0,$65535,(%0);"
    183 			   "movc3 %%r2,(%1),(%%r1);"
    184 			   "movb $0,(%%r3)"
    185                         :
    186                         : "r" (cp), "r" (c2), "g"(count)
    187                         : "r0","r1","r2","r3","r4","r5","memory","cc");
    188         return  cp;
    189 }
    190 
    191 static __inline char * __attribute__((__unused__))
    192 strcpy(char *cp, const char *c2)
    193 {
    194         __asm volatile("locc $0,$65535,(%1);"
    195 			   "subl3 %%r0,$65535,%%r2;"
    196                            "movc3 %%r2,(%1),(%0);"
    197 			   "movb $0,(%%r3)"
    198                         :
    199                         : "r" (cp), "r" (c2)
    200                         : "r0","r1","r2","r3","r4","r5","memory","cc");
    201         return  cp;
    202 }
    203 
    204 static __inline char * __attribute__((__unused__))
    205 strncpy(char *cp, const char *c2, size_t len)
    206 {
    207         __asm volatile("movl %2,%%r2;"
    208 			   "locc $0,%%r2,(%1);"
    209 			   "beql 1f;"
    210 			   "subl3 %%r0,%2,%%r2;"
    211                            "clrb (%0)[%%r2];"
    212 			   "1:;"
    213 			   "movc3 %%r2,(%1),(%0)"
    214                         :
    215                         : "r" (cp), "r" (c2), "g"(len)
    216                         : "r0","r1","r2","r3","r4","r5","memory","cc");
    217         return  cp;
    218 }
    219 
    220 static __inline void *__attribute__((__unused__))
    221 memchr(const void *cp, int c, size_t len)
    222 {
    223         void *ret;
    224         __asm volatile("locc %2,%3,(%1);"
    225 			   "bneq 1f;"
    226 			   "clrl %%r1;"
    227 			   "1:;"
    228 			   "movl %%r1,%0"
    229                         : "=g"(ret)
    230                         : "r" (cp), "r" (c), "g"(len)
    231                         : "r0","r1","cc");
    232         return  ret;
    233 }
    234 
    235 static __inline int __attribute__((__unused__))
    236 strcmp(const char *cp, const char *c2)
    237 {
    238         register int ret;
    239         __asm volatile("locc $0,$65535,(%1);"
    240 			   "subl3 %%r0,$65535,%%r0;"
    241 			   "incl %%r0;"
    242                            "cmpc3 %%r0,(%1),(%2);"
    243 			   "beql 1f;"
    244 			   "movl $1,%%r2;"
    245                            "cmpb (%%r1),(%%r3);"
    246 			   "bcc 1f;"
    247 			   "mnegl $1,%%r2;"
    248 			   "1:;"
    249 			   "movl %%r2,%0"
    250                         : "=g"(ret)
    251                         : "r" (cp), "r" (c2)
    252                         : "r0","r1","r2","r3","cc");
    253         return  ret;
    254 }
    255 #endif
    256 
    257 #if 0 /* unused, but no point in deleting it since it _is_ an instruction */
    258 static __inline int __attribute__((__unused__))
    259 locc(int mask, char *cp, size_t size){
    260 	register ret;
    261 
    262 	__asm volatile("locc %1,%2,(%3);"
    263 			   "movl %%r0,%0"
    264 			: "=r" (ret)
    265 			: "r" (mask),"r"(size),"r"(cp)
    266 			: "r0","r1" );
    267 	return	ret;
    268 }
    269 #endif
    270 
    271 static __inline int __attribute__((__unused__))
    272 vax_scanc(u_int size, const u_char *cp, const u_char *table, int mask)
    273 {
    274 	register int ret;
    275 
    276 	__asm volatile("scanc %1,(%2),(%3),%4;"
    277 			   "movl %%r0,%0"
    278 			: "=g"(ret)
    279 			: "r"(size),"r"(cp),"r"(table),"r"(mask)
    280 			: "r0","r1","r2","r3" );
    281 	return ret;
    282 }
    283 #define scanc vax_scanc
    284 
    285 static __inline int __attribute__((__unused__))
    286 vax_skpc(int mask, size_t size, u_char *cp)
    287 {
    288 	register int ret;
    289 
    290 	__asm volatile("skpc %1,%2,(%3);"
    291 			   "movl %%r0,%0"
    292 			: "=g"(ret)
    293 			: "r"(mask),"r"(size),"r"(cp)
    294 			: "r0","r1" );
    295 	return	ret;
    296 }
    297 #define skpc vax_skpc
    298 
    299 /*
    300  * Set/clear a bit at a memory position; interlocked.
    301  * Return 0 if already set, 1 otherwise.
    302  */
    303 static __inline int __attribute__((__unused__))
    304 bbssi(int bitnr, long *addr)
    305 {
    306 	register int ret;
    307 
    308 	__asm volatile("clrl %%r0;"
    309 			   "bbssi %1,%2,1f;"
    310 			   "incl %%r0;"
    311 			   "1:;"
    312 			   "movl %%r0,%0"
    313 		: "=&r"(ret)
    314 		: "g"(bitnr),"m"(*addr)
    315 		: "r0","cc","memory");
    316 	return ret;
    317 }
    318 
    319 static __inline int __attribute__((__unused__))
    320 bbcci(int bitnr, long *addr)
    321 {
    322 	register int ret;
    323 
    324 	__asm volatile("clrl %%r0;"
    325 			   "bbcci %1,%2,1f;"
    326 			   "incl %%r0;"
    327 			   "1:;"
    328 			   "movl %%r0,%0"
    329 		: "=&r"(ret)
    330 		: "g"(bitnr),"m"(*addr)
    331 		: "r0","cc","memory");
    332 	return ret;
    333 }
    334 
    335 static inline struct lwp *
    336 cpu_switchto(struct lwp *oldlwp, struct lwp *newlwp, bool returning)
    337 {
    338 	struct lwp *prevlwp;
    339 	__asm volatile(
    340 		"movl %1,%%r0;"
    341 		"movl %2,%%r1;"
    342 		"movpsl -(%%sp);"
    343 		"jsb Swtchto;"
    344 		"movl %%r0,%0"
    345 	    : "=g"(prevlwp)
    346 	    : "g" (oldlwp), "g" (newlwp)
    347 	    : "r0", "r1");
    348 	return prevlwp;
    349 }
    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_ && !__lint__ */
    409