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