Annotation of sys/arch/m88k/m88k/subr.S, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: subr.S,v 1.14 2006/11/18 22:48:44 miod Exp $ */
! 2: /*
! 3: * Mach Operating System
! 4: * Copyright (c) 1993-1992 Carnegie Mellon University
! 5: * Copyright (c) 1991 OMRON Corporation
! 6: * Copyright (c) 1996 Nivas Madhur
! 7: * Copyright (c) 1998 Steve Murphree, Jr.
! 8: * All Rights Reserved.
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and its
! 11: * documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: #include "assym.h"
! 32:
! 33: #include <sys/errno.h>
! 34:
! 35: #include <machine/asm.h>
! 36: #include <machine/trap.h>
! 37:
! 38: #ifdef M88100
! 39:
! 40: /*
! 41: * DO_LOAD_ADDRESS
! 42: *
! 43: * unsigned int do_load_word(address, supervisor_mode)
! 44: * vaddr_t address; \\ in r2
! 45: * boolean_t supervisor_mode; \\ in r3
! 46: *
! 47: * Return the word at ADDRESS (from user space if SUPERVISOR_MODE is zero,
! 48: * supervisor space if non-zero).
! 49: *
! 50: */
! 51:
! 52: ENTRY(do_load_word) /* do_load_word(address, supervisor) */
! 53: bcnd ne0,r3,1f
! 54: #ifdef ERRATA__XXX_USR
! 55: NOP
! 56: ld.usr r2,r2,r0
! 57: NOP
! 58: NOP
! 59: NOP
! 60: jmp r1
! 61: #else
! 62: jmp.n r1
! 63: ld.usr r2,r2,r0
! 64: #endif
! 65: 1: jmp.n r1
! 66: ld r2,r2,r0
! 67:
! 68: ENTRY(do_load_half) /* do_load_half(address, supervisor) */
! 69: bcnd ne0,r3,1f
! 70: #ifdef ERRATA__XXX_USR
! 71: NOP
! 72: ld.h.usr r2,r2,r0
! 73: NOP
! 74: NOP
! 75: NOP
! 76: jmp r1
! 77: #else
! 78: jmp.n r1
! 79: ld.h.usr r2,r2,r0
! 80: #endif
! 81: 1: jmp.n r1
! 82: ld.h r2,r2,r0
! 83:
! 84: ENTRY(do_load_byte) /* do_load_byte(address, supervisor) */
! 85: bcnd ne0,r3,1f
! 86: #ifdef ERRATA__XXX_USR
! 87: NOP
! 88: ld.b.usr r2,r2,r0
! 89: NOP
! 90: NOP
! 91: NOP
! 92: jmp r1
! 93: #else
! 94: jmp.n r1
! 95: ld.b.usr r2,r2,r0
! 96: #endif
! 97: 1: jmp.n r1
! 98: ld.b r2,r2,r0
! 99:
! 100: ENTRY(do_store_word) /* do_store_word(address, data, supervisor) */
! 101: bcnd ne0,r4,1f
! 102: #ifdef ERRATA__XXX_USR
! 103: NOP
! 104: st.usr r3,r2,r0
! 105: NOP
! 106: NOP
! 107: NOP
! 108: jmp r1
! 109: #else
! 110: jmp.n r1
! 111: st.usr r3,r2,r0
! 112: #endif
! 113: 1: jmp.n r1
! 114: st r3,r2,r0
! 115:
! 116: ENTRY(do_store_half) /* do_store_half(address, data, supervisor) */
! 117: bcnd ne0,r4,1f
! 118: #ifdef ERRATA__XXX_USR
! 119: NOP
! 120: st.h.usr r3,r2,r0
! 121: NOP
! 122: NOP
! 123: NOP
! 124: jmp r1
! 125: #else
! 126: jmp.n r1
! 127: st.h.usr r3,r2,r0
! 128: #endif
! 129: 1: jmp.n r1
! 130: st.h r3,r2,r0
! 131:
! 132: ENTRY(do_store_byte) /* do_store_byte(address, data, supervisor) */
! 133: bcnd ne0,r4,1f
! 134: #ifdef ERRATA__XXX_USR
! 135: NOP
! 136: st.b.usr r3,r2,r0
! 137: NOP
! 138: NOP
! 139: NOP
! 140: jmp r1
! 141: #else
! 142: jmp.n r1
! 143: st.b.usr r3,r2,r0
! 144: #endif
! 145: 1: jmp.n r1
! 146: st.b r3,r2,r0
! 147:
! 148: ENTRY(do_xmem_word) /* do_xmem_word(address, data, supervisor) */
! 149: bcnd ne0,r4,1f
! 150: #ifdef ERRATA__XXX_USR
! 151: NOP
! 152: xmem.usr r3,r2,r0
! 153: NOP
! 154: NOP
! 155: NOP
! 156: jmp r1
! 157: #else
! 158: jmp.n r1
! 159: xmem.usr r3,r2,r0
! 160: #endif
! 161: 1: jmp.n r1
! 162: xmem r3,r2,r0
! 163:
! 164: ENTRY(do_xmem_byte) /* do_xmem_byte(address, data, supervisor) */
! 165: bcnd ne0,r4,1f
! 166: #ifdef ERRATA__XXX_USR
! 167: NOP
! 168: xmem.bu.usr r3,r2,r0
! 169: NOP
! 170: NOP
! 171: NOP
! 172: jmp r1
! 173: #else
! 174: jmp.n r1
! 175: xmem.bu.usr r3,r2,r0
! 176: #endif
! 177: 1: jmp.n r1
! 178: xmem.bu r3,r2,r0
! 179:
! 180: #endif /* M88100 */
! 181:
! 182: /*
! 183: * Copy specified amount of data from user space into the kernel
! 184: * copyin(from, to, len)
! 185: * r2 == from (user source address)
! 186: * r3 == to (kernel destination address)
! 187: * r4 == length
! 188: * (r1=return addr)
! 189: */
! 190:
! 191: #define SRC r2
! 192: #define DEST r3
! 193: #define LEN r4
! 194:
! 195: ENTRY(copyin)
! 196: /* set up fault handler */
! 197: ldcr r5, CPU
! 198: ld r6, r5, CI_CURPCB
! 199: or.u r5, r0, hi16(_ASM_LABEL(Lciflt))
! 200: or r5, r5, lo16(_ASM_LABEL(Lciflt))
! 201: st r5, r6, PCB_ONFAULT /* pcb_onfault = Lciflt */
! 202:
! 203: /*
! 204: * If it's a small length (less than 8), then do byte-by-byte.
! 205: * Despite not being optimal if len is 4, and from and to
! 206: * are word-aligned, this is still faster than doing more tests
! 207: * to save an hyperthetical fraction of cycle.
! 208: */
! 209: cmp r9, LEN, 8
! 210: bb1 lt, r9, _ASM_LABEL(copyin_byte_only)
! 211:
! 212: /* If they're not aligned similarly, use byte only... */
! 213: xor r9, SRC, DEST
! 214: mask r8, r9, 0x3
! 215: bcnd ne0, r8, _ASM_LABEL(copyin_byte_only)
! 216:
! 217: /*
! 218: * At this point, we don't know if they're word aligned or not,
! 219: * but we know that what needs to be done to one to align
! 220: * it is what's needed for the other.
! 221: */
! 222: bb1 0, SRC, _ASM_LABEL(copyin_left_align_to_halfword)
! 223: ASLOCAL(copyin_left_aligned_to_halfword)
! 224: bb1 1, SRC, _ASM_LABEL(copyin_left_align_to_word)
! 225: ASLOCAL(copyin_left_aligned_to_word)
! 226: bb1 0, LEN, _ASM_LABEL(copyin_right_align_to_halfword)
! 227: ASLOCAL(copyin_right_aligned_to_halfword)
! 228: bb1 1, LEN, _ASM_LABEL(copyin_right_align_to_word)
! 229: ASLOCAL(copyin_right_aligned_to_word)
! 230:
! 231: /*
! 232: * At this point, both SRC and DEST are aligned to a word
! 233: * boundary, and LEN is a multiple of 4. We want it an even
! 234: * multiple of 4.
! 235: */
! 236: bb1.n 2, LEN, _ASM_LABEL(copyin_right_align_to_doubleword)
! 237: or r7, r0, 4
! 238:
! 239: ASLOCAL(copyin_right_aligned_to_doubleword)
! 240: #ifdef ERRATA__XXX_USR
! 241: NOP
! 242: ld.usr r5, SRC, r0
! 243: NOP
! 244: NOP
! 245: NOP
! 246: ld.usr r6, SRC, r7
! 247: NOP
! 248: NOP
! 249: NOP
! 250: #else
! 251: ld.usr r5, SRC, r0
! 252: ld.usr r6, SRC, r7
! 253: #endif
! 254: subu LEN, LEN, 8
! 255: st r5, DEST, r0
! 256: addu SRC, SRC, 8
! 257: st r6, DEST, r7
! 258: bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword)
! 259: addu DEST, DEST, 8
! 260: br.n _ASM_LABEL(Lcidone)
! 261: or r2, r0, r0 /* successful return */
! 262:
! 263: ASLOCAL(copyin_left_align_to_halfword)
! 264: #ifdef ERRATA__XXX_USR
! 265: NOP
! 266: ld.b.usr r5, SRC, r0
! 267: NOP
! 268: NOP
! 269: NOP
! 270: #else
! 271: ld.b.usr r5, SRC, r0
! 272: #endif
! 273: subu LEN, LEN, 1
! 274: st.b r5, DEST, r0
! 275: addu SRC, SRC, 1
! 276: br.n _ASM_LABEL(copyin_left_aligned_to_halfword)
! 277: addu DEST, DEST, 1
! 278:
! 279: ASLOCAL(copyin_left_align_to_word)
! 280: #ifdef ERRATA__XXX_USR
! 281: NOP
! 282: ld.h.usr r5, SRC, r0
! 283: NOP
! 284: NOP
! 285: NOP
! 286: #else
! 287: ld.h.usr r5, SRC, r0
! 288: #endif
! 289: subu LEN, LEN, 2
! 290: st.h r5, DEST, r0
! 291: addu SRC, SRC, 2
! 292: br.n _ASM_LABEL(copyin_left_aligned_to_word)
! 293: addu DEST, DEST, 2
! 294:
! 295: ASLOCAL(copyin_right_align_to_halfword)
! 296: subu LEN, LEN, 1
! 297: #ifdef ERRATA__XXX_USR
! 298: NOP
! 299: ld.b.usr r5, SRC, LEN
! 300: NOP
! 301: NOP
! 302: NOP
! 303: #else
! 304: ld.b.usr r5, SRC, LEN
! 305: #endif
! 306: br.n _ASM_LABEL(copyin_right_aligned_to_halfword)
! 307: st.b r5, DEST, LEN
! 308:
! 309: ASLOCAL(copyin_right_align_to_word)
! 310: subu LEN, LEN, 2
! 311: #ifdef ERRATA__XXX_USR
! 312: NOP
! 313: ld.h.usr r5, SRC, LEN
! 314: NOP
! 315: NOP
! 316: NOP
! 317: #else
! 318: ld.h.usr r5, SRC, LEN
! 319: #endif
! 320: br.n _ASM_LABEL(copyin_right_aligned_to_word)
! 321: st.h r5, DEST, LEN
! 322:
! 323: ASLOCAL(copyin_right_align_to_doubleword)
! 324: subu LEN, LEN, 4
! 325: #ifdef ERRATA__XXX_USR
! 326: NOP
! 327: ld.usr r5, SRC, LEN
! 328: NOP
! 329: NOP
! 330: NOP
! 331: #else
! 332: ld.usr r5, SRC, LEN
! 333: #endif
! 334: bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword)
! 335: st r5, DEST, LEN
! 336: br.n _ASM_LABEL(Lcidone)
! 337: or r2, r0, r0 /* successful return */
! 338:
! 339: ASLOCAL(copyin_byte_only)
! 340: bcnd eq0, LEN, 2f
! 341: 1:
! 342: subu LEN, LEN, 1
! 343: #ifdef ERRATA__XXX_USR
! 344: NOP
! 345: ld.b.usr r5, SRC, LEN
! 346: NOP
! 347: NOP
! 348: NOP
! 349: #else
! 350: ld.b.usr r5, SRC, LEN
! 351: #endif
! 352: bcnd.n ne0, LEN, 1b
! 353: st.b r5, DEST, LEN
! 354: 2:
! 355: or r2, r0, r0 /* successful return */
! 356: /* FALLTHROUGH */
! 357:
! 358: ASLOCAL(Lcidone)
! 359: ldcr r5, CPU
! 360: ld r6, r5, CI_CURPCB
! 361: jmp.n r1
! 362: st r0,r6,PCB_ONFAULT
! 363:
! 364: ASLOCAL(Lciflt)
! 365: br.n _ASM_LABEL(Lcidone)
! 366: or r2, r0, EFAULT /* return fault */
! 367:
! 368: #undef SRC
! 369: #undef DEST
! 370: #undef LEN
! 371:
! 372: /*######################################################################*/
! 373: /*######################################################################*/
! 374:
! 375: /*
! 376: * Copy a null terminated string from the user space to the kernel
! 377: * address space.
! 378: *
! 379: * copyinstr(from, to, maxlen, &lencopied)
! 380: * r2 == from
! 381: * r3 == to
! 382: * r4 == maxlen
! 383: * r5 == len actually transferred (includes the terminating NUL!!!)
! 384: * r6 & r7 - used as temporaries
! 385: */
! 386: #define SRC r2
! 387: #define DEST r3
! 388: #define CNT r4
! 389: #define LEN r5
! 390:
! 391: ENTRY(copyinstr)
! 392:
! 393: /* setup fault handler */
! 394: ldcr r6, CPU
! 395: ld r7, r6, CI_CURPCB
! 396: or.u r6, r0, hi16(_ASM_LABEL(Lcisflt))
! 397: or r6, r6, lo16(_ASM_LABEL(Lcisflt))
! 398: st r6, r7, PCB_ONFAULT
! 399: or r6, r0, 0
! 400: bcnd lt0, CNT, _ASM_LABEL(Lcisflt)
! 401: bcnd eq0, CNT, _ASM_LABEL(Lcistoolong)
! 402: 1:
! 403: #ifdef ERRATA__XXX_USR
! 404: NOP
! 405: ld.bu.usr r7, SRC, r6
! 406: NOP
! 407: NOP
! 408: NOP
! 409: #else
! 410: ld.bu.usr r7, SRC, r6
! 411: #endif
! 412: st.b r7, DEST, r6
! 413: bcnd.n eq0, r7, 2f /* all done */
! 414: addu r6, r6, 1
! 415: cmp r7, r6, CNT
! 416: bb1 lt, r7, 1b
! 417:
! 418: ASLOCAL(Lcistoolong)
! 419: or r2, r0, ENAMETOOLONG /* overflow */
! 420:
! 421: ASLOCAL(Lcisnull)
! 422: bcnd eq0,r6, _ASM_LABEL(Lcisdone) /* do not attempt to clear last byte */
! 423: /* if we did not write to the string */
! 424: subu r6, r6, 1
! 425: st.b r0, DEST, r6 /* clear last byte */
! 426: br.n _ASM_LABEL(Lcisdone)
! 427: addu r6, r6, 1
! 428: 2: /* all done */
! 429: or r2, r0, 0
! 430:
! 431: ASLOCAL(Lcisdone)
! 432: bcnd eq0, LEN, 3f
! 433: st r6, r0, LEN
! 434: 3:
! 435: ldcr r5, CPU
! 436: ld r6, r5, CI_CURPCB
! 437: jmp.n r1
! 438: st r0,r6,PCB_ONFAULT /* clear the handler */
! 439:
! 440: ASLOCAL(Lcisflt)
! 441: br.n _ASM_LABEL(Lcisnull)
! 442: or r2, r0, EFAULT /* return fault */
! 443:
! 444: #undef SRC
! 445: #undef DEST
! 446: #undef CNT
! 447: #undef LEN
! 448:
! 449: /*
! 450: * Copy specified amount of data from kernel to the user space
! 451: * Copyout(from, to, len)
! 452: * r2 == from (kernel source address)
! 453: * r3 == to (user destination address)
! 454: * r4 == length
! 455: */
! 456:
! 457: #define SRC r2
! 458: #define DEST r3
! 459: #define LEN r4
! 460:
! 461: ENTRY(copyout)
! 462: /* setup fault handler */
! 463: ldcr r5, CPU
! 464: ld r6, r5, CI_CURPCB
! 465: or.u r5, r0, hi16(_ASM_LABEL(Lcoflt))
! 466: or r5, r5, lo16(_ASM_LABEL(Lcoflt))
! 467: st r5, r6, PCB_ONFAULT /* pcb_onfault = Lcoflt */
! 468:
! 469: /*
! 470: * If it's a small length (less than 8), then do byte-by-byte.
! 471: * Despite not being optimal if len is 4, and from and to
! 472: * are word-aligned, this is still faster than doing more tests
! 473: * to save an hyperthetical fraction of cycle.
! 474: */
! 475: cmp r9, LEN, 8
! 476: bb1 lt, r9, _ASM_LABEL(copyout_byte_only)
! 477:
! 478: /* If they're not aligned similarly, use byte only... */
! 479: xor r9, SRC, DEST
! 480: mask r8, r9, 0x3
! 481: bcnd ne0, r8, _ASM_LABEL(copyout_byte_only)
! 482:
! 483: /*
! 484: * At this point, we don't know if they're word aligned or not,
! 485: * but we know that what needs to be done to one to align
! 486: * it is what's needed for the other.
! 487: */
! 488: bb1 0, SRC, _ASM_LABEL(copyout_left_align_to_halfword)
! 489: ASLOCAL(copyout_left_aligned_to_halfword)
! 490: bb1 1, SRC, _ASM_LABEL(copyout_left_align_to_word)
! 491: ASLOCAL(copyout_left_aligned_to_word)
! 492: bb1 0, LEN, _ASM_LABEL(copyout_right_align_to_halfword)
! 493: ASLOCAL(copyout_right_aligned_to_halfword)
! 494: bb1 1, LEN, _ASM_LABEL(copyout_right_align_to_word)
! 495: ASLOCAL(copyout_right_aligned_to_word)
! 496:
! 497: /*
! 498: * At this point, both SRC and DEST are aligned to a word
! 499: * boundary, and LEN is a multiple of 4. We want it an even
! 500: * multiple of 4.
! 501: */
! 502: bb1.n 2, LEN, _ASM_LABEL(copyout_right_align_to_doubleword)
! 503: or r7, r0, 4
! 504:
! 505: ASLOCAL(copyout_right_aligned_to_doubleword)
! 506: ld r5, SRC, r0
! 507: ld r6, SRC, r7
! 508: subu LEN, LEN, 8
! 509: #ifdef ERRATA__XXX_USR
! 510: NOP
! 511: st.usr r5, DEST, r0
! 512: NOP
! 513: NOP
! 514: NOP
! 515: #else
! 516: st.usr r5, DEST, r0
! 517: #endif
! 518: addu SRC, SRC, 8
! 519: #ifdef ERRATA__XXX_USR
! 520: NOP
! 521: st.usr r6, DEST, r7
! 522: NOP
! 523: NOP
! 524: NOP
! 525: #else
! 526: st.usr r6, DEST, r7
! 527: #endif
! 528: bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
! 529: addu DEST, DEST, 8
! 530: or r2, r0, r0 /* successful return */
! 531: br _ASM_LABEL(Lcodone)
! 532:
! 533: /***************************************************/
! 534: ASLOCAL(copyout_left_align_to_halfword)
! 535: ld.b r5, SRC, r0
! 536: subu LEN, LEN, 1
! 537: #ifdef ERRATA__XXX_USR
! 538: NOP
! 539: st.b.usr r5, DEST, r0
! 540: NOP
! 541: NOP
! 542: NOP
! 543: #else
! 544: st.b.usr r5, DEST, r0
! 545: #endif
! 546: addu SRC, SRC, 1
! 547: br.n _ASM_LABEL(copyout_left_aligned_to_halfword)
! 548: addu DEST, DEST, 1
! 549:
! 550: ASLOCAL(copyout_left_align_to_word)
! 551: ld.h r5, SRC, r0
! 552: subu LEN, LEN, 2
! 553: #ifdef ERRATA__XXX_USR
! 554: NOP
! 555: st.h.usr r5, DEST, r0
! 556: NOP
! 557: NOP
! 558: NOP
! 559: #else
! 560: st.h.usr r5, DEST, r0
! 561: #endif
! 562: addu SRC, SRC, 2
! 563: br.n _ASM_LABEL(copyout_left_aligned_to_word)
! 564: addu DEST, DEST, 2
! 565:
! 566: ASLOCAL(copyout_right_align_to_halfword)
! 567: subu LEN, LEN, 1
! 568: ld.b r5, SRC, LEN
! 569: #ifdef ERRATA__XXX_USR
! 570: NOP
! 571: st.b.usr r5, DEST, LEN
! 572: NOP
! 573: NOP
! 574: NOP
! 575: br _ASM_LABEL(copyout_right_aligned_to_halfword)
! 576: #else
! 577: br.n _ASM_LABEL(copyout_right_aligned_to_halfword)
! 578: st.b.usr r5, DEST, LEN
! 579: #endif
! 580:
! 581: ASLOCAL(copyout_right_align_to_word)
! 582: subu LEN, LEN, 2
! 583: ld.h r5, SRC, LEN
! 584: #ifdef ERRATA__XXX_USR
! 585: NOP
! 586: st.h.usr r5, DEST, LEN
! 587: NOP
! 588: NOP
! 589: NOP
! 590: br _ASM_LABEL(copyout_right_aligned_to_word)
! 591: #else
! 592: br.n _ASM_LABEL(copyout_right_aligned_to_word)
! 593: st.h.usr r5, DEST, LEN
! 594: #endif
! 595:
! 596: ASLOCAL(copyout_right_align_to_doubleword)
! 597: subu LEN, LEN, 4
! 598: ld r5, SRC, LEN
! 599: #ifdef ERRATA__XXX_USR
! 600: NOP
! 601: st.usr r5, DEST, LEN
! 602: NOP
! 603: NOP
! 604: NOP
! 605: bcnd ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
! 606: #else
! 607: bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
! 608: st.usr r5, DEST, LEN
! 609: #endif
! 610: br.n _ASM_LABEL(Lcodone)
! 611: or r2, r0, r0 /* successful return */
! 612:
! 613: ASLOCAL(copyout_byte_only)
! 614: bcnd eq0, LEN, 2f
! 615: 1:
! 616: subu LEN, LEN, 1
! 617: ld.b r5, SRC, LEN
! 618: #ifdef ERRATA__XXX_USR
! 619: NOP
! 620: st.b.usr r5, DEST, LEN
! 621: NOP
! 622: NOP
! 623: NOP
! 624: bcnd ne0, LEN, 1b
! 625: #else
! 626: bcnd.n ne0, LEN, 1b
! 627: st.b.usr r5, DEST, LEN
! 628: #endif
! 629:
! 630: 2:
! 631: or r2, r0, r0 /* successful return */
! 632: /* FALLTHROUGH */
! 633:
! 634: ASLOCAL(Lcodone)
! 635: ldcr r5, CPU
! 636: ld r6, r5, CI_CURPCB
! 637: jmp.n r1
! 638: st r0,r6,PCB_ONFAULT /* clear the handler */
! 639:
! 640: ASLOCAL(Lcoflt)
! 641: br.n _ASM_LABEL(Lcodone)
! 642: or r2, r0, EFAULT /* return fault */
! 643:
! 644: #undef SRC
! 645: #undef DEST
! 646: #undef LEN
! 647:
! 648: /*
! 649: * Copy a null terminated string from the kernel space to the user
! 650: * address space.
! 651: *
! 652: * copyoutstr(from, to, maxlen, &lencopied)
! 653: * r2 == from
! 654: * r3 == to
! 655: * r4 == maxlen that can be copied
! 656: * r5 == len actually copied (including the terminating NUL!!!)
! 657: */
! 658:
! 659: #define SRC r2
! 660: #define DEST r3
! 661: #define CNT r4
! 662: #define LEN r5
! 663:
! 664: ENTRY(copyoutstr)
! 665: /* setup fault handler */
! 666: ldcr r6, CPU
! 667: ld r7, r6, CI_CURPCB
! 668: or.u r6, r0, hi16(_ASM_LABEL(Lcosflt))
! 669: or r6, r6, lo16(_ASM_LABEL(Lcosflt))
! 670: st r6, r7, PCB_ONFAULT
! 671: bcnd lt0, CNT, _ASM_LABEL(Lcosflt)
! 672: bcnd eq0, CNT, _ASM_LABEL(Lcosdone)
! 673: or r6, r0, 0
! 674: 1:
! 675: ld.bu r7, SRC, r6
! 676: #ifdef ERRATA__XXX_USR
! 677: NOP
! 678: st.b.usr r7, DEST, r6
! 679: NOP
! 680: NOP
! 681: NOP
! 682: #else
! 683: st.b.usr r7, DEST, r6
! 684: #endif
! 685: bcnd.n eq0, r7, 2f /* all done */
! 686: addu r6, r6, 1
! 687: cmp r7, r6, CNT
! 688: bb1 lt, r7, 1b
! 689: br.n _ASM_LABEL(Lcosdone)
! 690: or r2, r0, ENAMETOOLONG
! 691: 2:
! 692: br.n _ASM_LABEL(Lcosdone)
! 693: or r2, r0, 0
! 694:
! 695: ASLOCAL(Lcosflt)
! 696: br.n _ASM_LABEL(Lcosdone)
! 697: or r2, r0, EFAULT
! 698:
! 699: ASLOCAL(Lcosdone)
! 700: bcnd eq0, LEN, 3f
! 701: st r6, r0, LEN
! 702: 3:
! 703: ldcr r5, CPU
! 704: ld r6, r5, CI_CURPCB
! 705: jmp.n r1
! 706: st r0,r6,PCB_ONFAULT /* clear the handler */
! 707:
! 708: #undef SRC
! 709: #undef DEST
! 710: #undef CNT
! 711: #undef LEN
! 712:
! 713: /*######################################################################*/
! 714:
! 715: /*
! 716: * kcopy(const void *src, void *dst, size_t len);
! 717: *
! 718: * Copy len bytes from src to dst, aborting if we encounter a page fault.
! 719: */
! 720: ENTRY(kcopy)
! 721: ldcr r5, CPU
! 722: ld r6, r5, CI_CURPCB
! 723: or.u r5, r0, hi16(_ASM_LABEL(kcopy_fault))
! 724: or r5, r5, lo16(_ASM_LABEL(kcopy_fault))
! 725: st r5, r6, PCB_ONFAULT /* pcb_onfault = kcopy_fault */
! 726: bcnd le0,r4,_ASM_LABEL(kcopy_out) /* nothing to do if <= 0 */
! 727: /*
! 728: * check position of source and destination data
! 729: */
! 730: cmp r9,r2,r3 /* compare source address to destination */
! 731: bb1 eq,r9,_ASM_LABEL(kcopy_out) /* nothing to do if equal */
! 732: bb1 lo,r9,_ASM_LABEL(kcopy_reverse) /* reverse copy if src < dest */
! 733: /*
! 734: * source address is greater than destination address, copy forward
! 735: */
! 736: cmp r9,r4,16 /* see if we have at least 16 bytes */
! 737: bb1 lt,r9,_ASM_LABEL(kf_byte_copy) /* copy bytes for small length */
! 738: /*
! 739: * determine copy strategy based on alignment of source and destination
! 740: */
! 741: mask r6,r2,3 /* get 2 low order bits of source address */
! 742: mask r7,r3,3 /* get 2 low order bits of destintation addr */
! 743: mak r6,r6,0<4> /* convert source bits to table offset */
! 744: mak r7,r7,0<2> /* convert destination bits to table offset */
! 745: or.u r12,r0,hi16(_ASM_LABEL(kf_strat))
! 746: or r12,r12,lo16(_ASM_LABEL(kf_strat))
! 747: addu r6,r6,r7 /* compute final table offset for strategy */
! 748: ld r12,r12,r6 /* load the strategy routine */
! 749: jmp r12 /* branch to strategy routine */
! 750:
! 751: /*
! 752: * Copy three bytes from src to destination then copy words
! 753: */
! 754: ASLOCAL(kf_3byte_word_copy)
! 755: ld.bu r6,r2,0 /* load byte from source */
! 756: ld.bu r7,r2,1 /* load byte from source */
! 757: ld.bu r8,r2,2 /* load byte from source */
! 758: st.b r6,r3,0 /* store byte to destination */
! 759: st.b r7,r3,1 /* store byte to destination */
! 760: st.b r8,r3,2 /* store byte to destination */
! 761: addu r2,r2,3 /* increment source pointer */
! 762: addu r3,r3,3 /* increment destination pointer */
! 763: br.n _ASM_LABEL(kf_word_copy) /* copy full words */
! 764: subu r4,r4,3 /* decrement length */
! 765:
! 766: /*
! 767: * Copy 1 halfword from src to destination then copy words
! 768: */
! 769: ASLOCAL(kf_1half_word_copy)
! 770: ld.hu r6,r2,0 /* load half-word from source */
! 771: st.h r6,r3,0 /* store half-word to destination */
! 772: addu r2,r2,2 /* increment source pointer */
! 773: addu r3,r3,2 /* increment destination pointer */
! 774: br.n _ASM_LABEL(kf_word_copy) /* copy full words */
! 775: subu r4,r4,2 /* decrement remaining length */
! 776:
! 777: /*
! 778: * Copy 1 byte from src to destination then copy words
! 779: */
! 780: ASLOCAL(kf_1byte_word_copy)
! 781: ld.bu r6,r2,0 /* load 1 byte from source */
! 782: st.b r6,r3,0 /* store 1 byte to destination */
! 783: addu r2,r2,1 /* increment source pointer */
! 784: addu r3,r3,1 /* increment destination pointer */
! 785: subu r4,r4,1 /* decrement remaining length */
! 786: /* fall through to word copy */
! 787: /*
! 788: * Copy as many full words as possible, 4 words per loop
! 789: */
! 790: ASLOCAL(kf_word_copy)
! 791: cmp r10,r4,16 /* see if we have 16 bytes remaining */
! 792: bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */
! 793: ld r6,r2,0 /* load first word */
! 794: ld r7,r2,4 /* load second word */
! 795: ld r8,r2,8 /* load third word */
! 796: ld r9,r2,12 /* load fourth word */
! 797: st r6,r3,0 /* store first word */
! 798: st r7,r3,4 /* store second word */
! 799: st r8,r3,8 /* store third word */
! 800: st r9,r3,12 /* store fourth word */
! 801: addu r2,r2,16 /* increment source pointer */
! 802: addu r3,r3,16 /* increment destination pointer */
! 803: br.n _ASM_LABEL(kf_word_copy) /* copy another block */
! 804: subu r4,r4,16 /* decrement remaining length */
! 805:
! 806: ASLOCAL(kf_1byte_half_copy)
! 807: ld.bu r6,r2,0 /* load 1 byte from source */
! 808: st.b r6,r3,0 /* store 1 byte to destination */
! 809: addu r2,r2,1 /* increment source pointer */
! 810: addu r3,r3,1 /* increment destination pointer */
! 811: subu r4,r4,1 /* decrement remaining length */
! 812: /* fall through to half copy */
! 813:
! 814: ASLOCAL(kf_half_copy)
! 815: cmp r10,r4,16 /* see if we have 16 bytes remaining */
! 816: bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */
! 817: ld.hu r6,r2,0 /* load first half-word */
! 818: ld.hu r7,r2,2 /* load second half-word */
! 819: ld.hu r8,r2,4 /* load third half-word */
! 820: ld.hu r9,r2,6 /* load fourth half-word */
! 821: ld.hu r10,r2,8 /* load fifth half-word */
! 822: ld.hu r11,r2,10 /* load sixth half-word */
! 823: ld.hu r12,r2,12 /* load seventh half-word */
! 824: ld.hu r13,r2,14 /* load eighth half-word */
! 825: st.h r6,r3,0 /* store first half-word */
! 826: st.h r7,r3,2 /* store second half-word */
! 827: st.h r8,r3,4 /* store third half-word */
! 828: st.h r9,r3,6 /* store fourth half-word */
! 829: st.h r10,r3,8 /* store fifth half-word */
! 830: st.h r11,r3,10 /* store sixth half-word */
! 831: st.h r12,r3,12 /* store seventh half-word */
! 832: st.h r13,r3,14 /* store eighth half-word */
! 833: addu r2,r2,16 /* increment source pointer */
! 834: addu r3,r3,16 /* increment destination pointer */
! 835: br.n _ASM_LABEL(kf_half_copy) /* copy another block */
! 836: subu r4,r4,16 /* decrement remaining length */
! 837:
! 838: ASLOCAL(kf_byte_copy)
! 839: bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */
! 840: ld.bu r6,r2,0 /* load byte from source */
! 841: st.b r6,r3,0 /* store byte in destination */
! 842: addu r2,r2,1 /* increment source pointer */
! 843: addu r3,r3,1 /* increment destination pointer */
! 844: br.n _ASM_LABEL(kf_byte_copy) /* branch for next byte */
! 845: subu r4,r4,1 /* decrement remaining length */
! 846:
! 847: /*
! 848: * source address is less than destination address, copy in reverse
! 849: */
! 850: ASLOCAL(kcopy_reverse)
! 851: /*
! 852: * start copy pointers at end of data
! 853: */
! 854: addu r2,r2,r4 /* start source at end of data */
! 855: addu r3,r3,r4 /* start destination at end of data */
! 856: /*
! 857: * check for short data
! 858: */
! 859: cmp r9,r4,16 /* see if we have at least 16 bytes */
! 860: bb1 lt,r9,_ASM_LABEL(kr_byte_copy) /* copy bytes for small data length */
! 861: /*
! 862: * determine copy strategy based on alignment of source and destination
! 863: */
! 864: mask r6,r2,3 /* get 2 low order bits of source address */
! 865: mask r7,r3,3 /* get 2 low order bits of destintation addr */
! 866: mak r6,r6,0<4> /* convert source bits to table offset */
! 867: mak r7,r7,0<2> /* convert destination bits to table offset */
! 868: or.u r12,r0,hi16(_ASM_LABEL(kr_strat))
! 869: or r12,r12,lo16(_ASM_LABEL(kr_strat))
! 870: addu r6,r6,r7 /* compute final table offset for strategy */
! 871: ld r12,r12,r6 /* load the strategy routine */
! 872: jmp r12 /* branch to strategy routine */
! 873:
! 874: /*
! 875: * Copy three bytes from src to destination then copy words
! 876: */
! 877: ASLOCAL(kr_3byte_word_copy)
! 878: subu r2,r2,3 /* decrement source pointer */
! 879: subu r3,r3,3 /* decrement destination pointer */
! 880: ld.bu r6,r2,0 /* load byte from source */
! 881: ld.bu r7,r2,1 /* load byte from source */
! 882: ld.bu r8,r2,2 /* load byte from source */
! 883: st.b r6,r3,0 /* store byte to destination */
! 884: st.b r7,r3,1 /* store byte to destination */
! 885: st.b r8,r3,2 /* store byte to destination */
! 886: br.n _ASM_LABEL(kr_word_copy) /* copy full words */
! 887: subu r4,r4,3 /* decrement length */
! 888:
! 889: /*
! 890: * Copy 1 halfword from src to destination then copy words
! 891: */
! 892: ASLOCAL(kr_1half_word_copy)
! 893: subu r2,r2,2 /* decrement source pointer */
! 894: subu r3,r3,2 /* decrement destination pointer */
! 895: ld.hu r6,r2,0 /* load half-word from source */
! 896: st.h r6,r3,0 /* store half-word to destination */
! 897: br.n _ASM_LABEL(kr_word_copy) /* copy full words */
! 898: subu r4,r4,2 /* decrement remaining length */
! 899:
! 900: /*
! 901: * Copy 1 byte from src to destination then copy words
! 902: */
! 903: ASLOCAL(kr_1byte_word_copy)
! 904: subu r2,r2,1 /* decrement source pointer */
! 905: subu r3,r3,1 /* decrement destination pointer */
! 906: ld.bu r6,r2,0 /* load 1 byte from source */
! 907: st.b r6,r3,0 /* store 1 byte to destination */
! 908: subu r4,r4,1 /* decrement remaining length */
! 909: /* fall through to word copy */
! 910: /*
! 911: * Copy as many full words as possible, 4 words per loop
! 912: */
! 913: ASLOCAL(kr_word_copy)
! 914: cmp r10,r4,16 /* see if we have 16 bytes remaining */
! 915: bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */
! 916: subu r2,r2,16 /* decrement source pointer */
! 917: subu r3,r3,16 /* decrement destination pointer */
! 918: ld r6,r2,0 /* load first word */
! 919: ld r7,r2,4 /* load second word */
! 920: ld r8,r2,8 /* load third word */
! 921: ld r9,r2,12 /* load fourth word */
! 922: st r6,r3,0 /* store first word */
! 923: st r7,r3,4 /* store second word */
! 924: st r8,r3,8 /* store third word */
! 925: st r9,r3,12 /* store fourth word */
! 926: br.n _ASM_LABEL(kr_word_copy) /* copy another block */
! 927: subu r4,r4,16 /* decrement remaining length */
! 928:
! 929: ASLOCAL(kr_1byte_half_copy)
! 930: subu r2,r2,1 /* decrement source pointer */
! 931: subu r3,r3,1 /* decrement destination pointer */
! 932: ld.bu r6,r2,0 /* load 1 byte from source */
! 933: st.b r6,r3,0 /* store 1 byte to destination */
! 934: subu r4,r4,1 /* decrement remaining length */
! 935: /* fall through to half copy */
! 936:
! 937: ASLOCAL(kr_half_copy)
! 938: cmp r10,r4,16 /* see if we have 16 bytes remaining */
! 939: bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */
! 940: subu r2,r2,16 /* decrement source pointer */
! 941: subu r3,r3,16 /* decrement destination pointer */
! 942: ld.hu r6,r2,0 /* load first half-word */
! 943: ld.hu r7,r2,2 /* load second half-word */
! 944: ld.hu r8,r2,4 /* load third half-word */
! 945: ld.hu r9,r2,6 /* load fourth half-word */
! 946: ld.hu r10,r2,8 /* load fifth half-word */
! 947: ld.hu r11,r2,10 /* load sixth half-word */
! 948: ld.hu r12,r2,12 /* load seventh half-word */
! 949: ld.hu r13,r2,14 /* load eighth half-word */
! 950: st.h r6,r3,0 /* store first half-word */
! 951: st.h r7,r3,2 /* store second half-word */
! 952: st.h r8,r3,4 /* store third half-word */
! 953: st.h r9,r3,6 /* store fourth half-word */
! 954: st.h r10,r3,8 /* store fifth half-word */
! 955: st.h r11,r3,10 /* store sixth half-word */
! 956: st.h r12,r3,12 /* store seventh half-word */
! 957: st.h r13,r3,14 /* store eighth half-word */
! 958: br.n _ASM_LABEL(kr_half_copy) /* copy another block */
! 959: subu r4,r4,16 /* decrement remaining length */
! 960:
! 961: ASLOCAL(kr_byte_copy)
! 962: bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */
! 963: subu r2,r2,1 /* decrement source pointer */
! 964: subu r3,r3,1 /* decrement destination pointer */
! 965: ld.bu r6,r2,0 /* load byte from source */
! 966: st.b r6,r3,0 /* store byte in destination */
! 967: br.n _ASM_LABEL(kr_byte_copy) /* branch for next byte */
! 968: subu r4,r4,1 /* decrement remaining length */
! 969:
! 970: ASLOCAL(kcopy_out)
! 971: or r2, r0, 0 /* return success */
! 972: ASLOCAL(kcopy_out_fault)
! 973: ldcr r5, CPU
! 974: ld r6, r5, CI_CURPCB
! 975: jmp.n r1 /* all done, return to caller */
! 976: st r0, r6, PCB_ONFAULT /* clear the handler */
! 977:
! 978: ASLOCAL(kcopy_fault)
! 979: br.n _ASM_LABEL(kcopy_out_fault)
! 980: or r2, r0, EFAULT /* return fault */
! 981:
! 982: data
! 983: align 4
! 984: ASLOCAL(kf_strat)
! 985: word _ASM_LABEL(kf_word_copy)
! 986: word _ASM_LABEL(kf_byte_copy)
! 987: word _ASM_LABEL(kf_half_copy)
! 988: word _ASM_LABEL(kf_byte_copy)
! 989: word _ASM_LABEL(kf_byte_copy)
! 990: word _ASM_LABEL(kf_3byte_word_copy)
! 991: word _ASM_LABEL(kf_byte_copy)
! 992: word _ASM_LABEL(kf_1byte_half_copy)
! 993: word _ASM_LABEL(kf_half_copy)
! 994: word _ASM_LABEL(kf_byte_copy)
! 995: word _ASM_LABEL(kf_1half_word_copy)
! 996: word _ASM_LABEL(kf_byte_copy)
! 997: word _ASM_LABEL(kf_byte_copy)
! 998: word _ASM_LABEL(kf_1byte_half_copy)
! 999: word _ASM_LABEL(kf_byte_copy)
! 1000: word _ASM_LABEL(kf_1byte_word_copy)
! 1001:
! 1002: ASLOCAL(kr_strat)
! 1003: word _ASM_LABEL(kr_word_copy)
! 1004: word _ASM_LABEL(kr_byte_copy)
! 1005: word _ASM_LABEL(kr_half_copy)
! 1006: word _ASM_LABEL(kr_byte_copy)
! 1007: word _ASM_LABEL(kr_byte_copy)
! 1008: word _ASM_LABEL(kr_1byte_word_copy)
! 1009: word _ASM_LABEL(kr_byte_copy)
! 1010: word _ASM_LABEL(kr_1byte_half_copy)
! 1011: word _ASM_LABEL(kr_half_copy)
! 1012: word _ASM_LABEL(kr_byte_copy)
! 1013: word _ASM_LABEL(kr_1half_word_copy)
! 1014: word _ASM_LABEL(kr_byte_copy)
! 1015: word _ASM_LABEL(kr_byte_copy)
! 1016: word _ASM_LABEL(kr_1byte_half_copy)
! 1017: word _ASM_LABEL(kr_byte_copy)
! 1018: word _ASM_LABEL(kr_3byte_word_copy)
! 1019:
! 1020: /*
! 1021: * non-local goto
! 1022: * int setjmp(label_t *);
! 1023: * void longjmp(label_t*);
! 1024: */
! 1025: ENTRY(setjmp)
! 1026: st r1,r2,0
! 1027: st r14,r2,4
! 1028: st r15,r2,2*4
! 1029: st r16,r2,3*4
! 1030: st r17,r2,4*4
! 1031: st r18,r2,5*4
! 1032: st r19,r2,6*4
! 1033: st r20,r2,7*4
! 1034: st r21,r2,8*4
! 1035: st r22,r2,9*4
! 1036: st r23,r2,10*4
! 1037: st r24,r2,11*4
! 1038: st r25,r2,12*4
! 1039: st r26,r2,13*4
! 1040: st r27,r2,14*4
! 1041: st r28,r2,15*4
! 1042: st r29,r2,16*4
! 1043: st r30,r2,17*4
! 1044: st r31,r2,18*4
! 1045: jmp.n r1
! 1046: or r2,r0,r0
! 1047:
! 1048: ENTRY(longjmp)
! 1049: ld r1,r2,0
! 1050: ld r14,r2,4
! 1051: ld r15,r2,2*4
! 1052: ld r16,r2,3*4
! 1053: ld r17,r2,4*4
! 1054: ld r18,r2,5*4
! 1055: ld r19,r2,6*4
! 1056: ld r20,r2,7*4
! 1057: ld r21,r2,8*4
! 1058: ld r22,r2,9*4
! 1059: ld r23,r2,10*4
! 1060: ld r24,r2,11*4
! 1061: ld r25,r2,12*4
! 1062: ld r26,r2,13*4
! 1063: ld r27,r2,14*4
! 1064: ld r28,r2,15*4
! 1065: ld r29,r2,16*4
! 1066: ld r30,r2,17*4
! 1067: ld r31,r2,18*4
! 1068: jmp.n r1
! 1069: or r2,r0,1
! 1070:
! 1071: /*
! 1072: * Signal trampoline code.
! 1073: * The kernel arranges for the handler to be invoked directly, and return
! 1074: * here.
! 1075: */
! 1076: GLOBAL(sigcode) /* r31 points to sigframe */
! 1077: ld r2, r31, 0 /* pick sigcontext* */
! 1078: or r13, r0, SYS_sigreturn
! 1079: tb0 0, r0, 128 /* syscall trap, calling sigreturn */
! 1080: NOP | failure return
! 1081: #ifdef dontbother /* sigreturn will not return unless it fails */
! 1082: NOP | success return
! 1083: #endif
! 1084: or r13, r0, SYS_exit
! 1085: tb0 0, r0, 128 /* syscall trap, exit */
! 1086: /*
! 1087: * this never returns, but we need to provide fetchable instructions
! 1088: * for the 88100 pipeline.
! 1089: */
! 1090: NOP
! 1091: NOP
! 1092: GLOBAL(esigcode)
CVSweb