1 /* $NetBSD: macros.h,v 1.37 2006/07/08 00:25:24 matt 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 /* Here general macros are supposed to be stored */ 42 43 static __inline int __attribute__((__unused__)) 44 vax_ffs(int reg) 45 { 46 register int val; 47 48 __asm volatile ("ffs $0,$32,%1,%0;" 49 "bneq 1f;" 50 "mnegl $1,%0;" 51 "1:;" 52 "incl %0" 53 : "=&r" (val) 54 : "r" (reg) ); 55 return val; 56 } 57 #define ffs vax_ffs 58 59 static __inline void __attribute__((__unused__)) 60 vax_remque(void *p) 61 { 62 __asm volatile ("remque (%0),%0;clrl 4(%0)" 63 : 64 : "r" (p) 65 : "memory" ); 66 } 67 #define _remque vax_remque 68 69 static __inline void __attribute__((__unused__)) 70 vax_insque(void *p, void *q) 71 { 72 __asm volatile ("insque (%0),(%1)" 73 : 74 : "r" (p),"r" (q) 75 : "memory" ); 76 } 77 #define _insque vax_insque 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 #define setrunqueue(p) \ 341 __asm volatile("movl %0,%%r0;jsb Setrq" :: "g"(p):"r0","r1","r2") 342 343 #define remrunqueue(p) \ 344 __asm volatile("movl %0,%%r0;jsb Remrq" :: "g"(p):"r0","r1","r2") 345 346 #define cpu_switch(p, newp) ({ \ 347 register int ret; \ 348 __asm volatile("movpsl -(%%sp);jsb Swtch; movl %%r0,%0" \ 349 : "=g"(ret) ::"r0","r1","r2","r3","r4","r5"); \ 350 ret; }) 351 352 #define cpu_switchto(p, newp) \ 353 __asm volatile("movpsl -(%%sp); movl %0,%%r2; jsb Swtchto" \ 354 :: "g" (newp) : "r0", "r1", "r2", "r3", "r4", "r5") 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