diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/sparc/locore.s | 201 |
1 files changed, 200 insertions, 1 deletions
diff --git a/sys/arch/sparc/sparc/locore.s b/sys/arch/sparc/sparc/locore.s index ffcea8e4091..45a3863be67 100644 --- a/sys/arch/sparc/sparc/locore.s +++ b/sys/arch/sparc/sparc/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.24 1999/04/22 18:43:51 art Exp $ */ +/* $OpenBSD: locore.s,v 1.25 1999/04/22 18:47:19 art Exp $ */ /* $NetBSD: locore.s,v 1.73 1997/09/13 20:36:48 pk Exp $ */ /* @@ -4352,7 +4352,11 @@ ENTRY(switchexit) wr %g0, PSR_S|PSR_ET, %psr ! and then enable traps mov %g2, %o0 ! now ready to call kmem_free mov %g3, %o1 +#if defined(UVM) + call _uvm_km_free +#else call _kmem_free +#endif mov %g4, %o2 /* @@ -5368,6 +5372,201 @@ Lback_mopb: retl ! dst[-1] = b; stb %o4, [%o1 - 1] ! } +/* + * kcopy() is exactly like bcopy except that it set pcb_onfault such that + * when a fault occurs, it is able to return -1 to indicate this to the + * caller. + */ +ENTRY(kcopy) + sethi %hi(_cpcb), %o5 ! cpcb->pcb_onfault = Lkcerr; + ld [%o5 + %lo(_cpcb)], %o5 + set Lkcerr, %o3 + ld [%o5 + PCB_ONFAULT], %g1! save current onfault handler + st %o3, [%o5 + PCB_ONFAULT] + + cmp %o2, BCOPY_SMALL +Lkcopy_start: + bge,a Lkcopy_fancy ! if >= this many, go be fancy. + btst 7, %o0 ! (part of being fancy) + + /* + * Not much to copy, just do it a byte at a time. + */ + deccc %o2 ! while (--len >= 0) + bl 1f + EMPTY +0: + ldsb [%o0], %o4 ! *dst++ = *src++; + inc %o0 + stb %o4, [%o1] + deccc %o2 + bge 0b + inc %o1 +1: + st %g1, [%o5 + PCB_ONFAULT] ! restore onfault + retl + mov 0, %o0 ! delay slot: return success + /* NOTREACHED */ + + /* + * Plenty of data to copy, so try to do it optimally. + */ +Lkcopy_fancy: + ! check for common case first: everything lines up. +! btst 7, %o0 ! done already + bne 1f + EMPTY + btst 7, %o1 + be,a Lkcopy_doubles + dec 8, %o2 ! if all lined up, len -= 8, goto bcopy_doubes + + ! If the low bits match, we can make these line up. +1: + xor %o0, %o1, %o3 ! t = src ^ dst; + btst 1, %o3 ! if (t & 1) { + be,a 1f + btst 1, %o0 ! [delay slot: if (src & 1)] + + ! low bits do not match, must copy by bytes. +0: + ldsb [%o0], %o4 ! do { + inc %o0 ! *dst++ = *src++; + stb %o4, [%o1] + deccc %o2 + bnz 0b ! } while (--len != 0); + inc %o1 + st %g1, [%o5 + PCB_ONFAULT] ! restore onfault + retl + mov 0, %o0 ! delay slot: return success + /* NOTREACHED */ + + ! lowest bit matches, so we can copy by words, if nothing else +1: + be,a 1f ! if (src & 1) { + btst 2, %o3 ! [delay slot: if (t & 2)] + + ! although low bits match, both are 1: must copy 1 byte to align + ldsb [%o0], %o4 ! *dst++ = *src++; + inc %o0 + stb %o4, [%o1] + dec %o2 ! len--; + inc %o1 + btst 2, %o3 ! } [if (t & 2)] +1: + be,a 1f ! if (t & 2) { + btst 2, %o0 ! [delay slot: if (src & 2)] + dec 2, %o2 ! len -= 2; +0: + ldsh [%o0], %o4 ! do { + inc 2, %o0 ! dst += 2, src += 2; + sth %o4, [%o1] ! *(short *)dst = *(short *)src; + deccc 2, %o2 ! } while ((len -= 2) >= 0); + bge 0b + inc 2, %o1 + b Lkcopy_mopb ! goto mop_up_byte; + btst 1, %o2 ! } [delay slot: if (len & 1)] + /* NOTREACHED */ + + ! low two bits match, so we can copy by longwords +1: + be,a 1f ! if (src & 2) { + btst 4, %o3 ! [delay slot: if (t & 4)] + + ! although low 2 bits match, they are 10: must copy one short to align + ldsh [%o0], %o4 ! (*short *)dst = *(short *)src; + inc 2, %o0 ! dst += 2; + sth %o4, [%o1] + dec 2, %o2 ! len -= 2; + inc 2, %o1 ! src += 2; + btst 4, %o3 ! } [if (t & 4)] +1: + be,a 1f ! if (t & 4) { + btst 4, %o0 ! [delay slot: if (src & 4)] + dec 4, %o2 ! len -= 4; +0: + ld [%o0], %o4 ! do { + inc 4, %o0 ! dst += 4, src += 4; + st %o4, [%o1] ! *(int *)dst = *(int *)src; + deccc 4, %o2 ! } while ((len -= 4) >= 0); + bge 0b + inc 4, %o1 + b Lkcopy_mopw ! goto mop_up_word_and_byte; + btst 2, %o2 ! } [delay slot: if (len & 2)] + /* NOTREACHED */ + + ! low three bits match, so we can copy by doublewords +1: + be 1f ! if (src & 4) { + dec 8, %o2 ! [delay slot: len -= 8] + ld [%o0], %o4 ! *(int *)dst = *(int *)src; + inc 4, %o0 ! dst += 4, src += 4, len -= 4; + st %o4, [%o1] + dec 4, %o2 ! } + inc 4, %o1 +1: +Lkcopy_doubles: + ! swap %o4 with %o2 during doubles copy, since %o5 is verboten + mov %o2, %o4 +Lkcopy_doubles2: + ldd [%o0], %o2 ! do { + inc 8, %o0 ! dst += 8, src += 8; + std %o2, [%o1] ! *(double *)dst = *(double *)src; + deccc 8, %o4 ! } while ((len -= 8) >= 0); + bge Lkcopy_doubles2 + inc 8, %o1 + mov %o4, %o2 ! restore len + + ! check for a usual case again (save work) + btst 7, %o2 ! if ((len & 7) == 0) + be Lkcopy_done ! goto bcopy_done; + + btst 4, %o2 ! if ((len & 4)) == 0) + be,a Lkcopy_mopw ! goto mop_up_word_and_byte; + btst 2, %o2 ! [delay slot: if (len & 2)] + ld [%o0], %o4 ! *(int *)dst = *(int *)src; + inc 4, %o0 ! dst += 4; + st %o4, [%o1] + inc 4, %o1 ! src += 4; + btst 2, %o2 ! } [if (len & 2)] + +1: + ! mop up trailing word (if present) and byte (if present). +Lkcopy_mopw: + be Lkcopy_mopb ! no word, go mop up byte + btst 1, %o2 ! [delay slot: if (len & 1)] + ldsh [%o0], %o4 ! *(short *)dst = *(short *)src; + be Lkcopy_done ! if ((len & 1) == 0) goto done; + sth %o4, [%o1] + ldsb [%o0 + 2], %o4 ! dst[2] = src[2]; + stb %o4, [%o1 + 2] + st %g1, [%o5 + PCB_ONFAULT]! restore onfault + retl + mov 0, %o0 ! delay slot: return success + /* NOTREACHED */ + + ! mop up trailing byte (if present). +Lkcopy_mopb: + bne,a 1f + ldsb [%o0], %o4 + +Lkcopy_done: + st %g1, [%o5 + PCB_ONFAULT] ! restore onfault + retl + mov 0, %o0 ! delay slot: return success + /* NOTREACHED */ + +1: + stb %o4, [%o1] + st %g1, [%o5 + PCB_ONFAULT] ! restore onfault + retl + mov 0, %o0 ! delay slot: return success + /* NOTREACHED */ + +Lkcerr: + st %g1, [%o5 + PCB_ONFAULT] ! restore onfault + retl + mov EFAULT, %o0 ! delay slot: return error indicator + /* NOTREACHED */ /* * savefpstate(f) struct fpstate *f; |