summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc/sparc/locore.s201
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;