git: 9front

Download patch

ref: b61aa839cb99b4acc60aa14a6c9bbaa3bb70cd99
parent: 1f08c7cf58c519b971eee3b7b78080ff16939373
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 29 20:26:33 EDT 2015

sgi: preserve R27 in setregisters(), use setregisters() in noted()

GEVector() saves the exception return PC in Ureg.r27 which needs
to be preserved.

there should be no reason for the user to change the status
register from noted() eigther, so we now just use setregisters()
in noted() to restore previous general purpose registers. this
means that CU1 will always be off after noted() because notify()
has disabled the FPU on entry and set fpstatus to FPinactive
if it was on. once user starts using FPU again, it will trap and
restore fpu registers.

--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -576,22 +576,6 @@
 }
 
 /*
- * Check that status is OK to return from note.
- */
-int
-validstatus(ulong kstatus, ulong ustatus)
-{
-//	if((kstatus & (INTMASK|KX|SX|UX)) != (ustatus & (INTMASK|KX|SX|UX)))
-	if((kstatus & INTMASK) != (ustatus & INTMASK))
-		return 0;
-	if((ustatus&(KSU|ERL|EXL|IE)) != (KUSER|EXL|IE))
-		return 0;
-	if(ustatus & (0xFFFF0000&~CU1))	/* no CU3, CU2, CU0, RP, FR, RE, DS */
-		return 0;
-	return 1;
-}
-
-/*
  * Return user to state before notify(); called from user's handler.
  */
 void
@@ -613,20 +597,13 @@
 	nur = up->ureg;
 
 	oureg = (ulong)nur;
-	if((oureg & (BY2WD-1))
-	|| !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+	if((oureg & (BY2WD-1)) || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
 		pprint("bad up->ureg in noted or call to noted() when not notified\n");
 		qunlock(&up->debug);
 		pexit("Suicide", 0);
 	}
 
-	if(0 && !validstatus(kur->status, nur->status)) {
-		qunlock(&up->debug);
-		pprint("bad noted ureg status %#lux\n", nur->status);
-		pexit("Suicide", 0);
-	}
-
-	memmove(kur, up->ureg, sizeof(Ureg));
+	setregisters(kur, (char*)kur, (char*)up->ureg, sizeof(Ureg));
 	switch(arg0) {
 	case NCONT:
 	case NRSTR:				/* only used by APE */
@@ -873,10 +850,12 @@
 void
 setregisters(Ureg *xp, char *pureg, char *uva, int n)
 {
-	ulong status;
+	ulong status, r27;
 
+	r27 = xp->r27;			/* return PC for GEVector() */
 	status = xp->status;
 	memmove(pureg, uva, n);
+	xp->r27 = r27;
 	xp->status = status;
 }
 
--