svn commit: r342782 - in stable/12/sys: conf powerpc/booke

Justin Hibbits jhibbits at FreeBSD.org
Sat Jan 5 04:43:23 UTC 2019


Author: jhibbits
Date: Sat Jan  5 04:43:22 2019
New Revision: 342782
URL: https://svnweb.freebsd.org/changeset/base/342782

Log:
  MFC r341751-r341752, r342025, r342107
  
  r341751:
  powerpc/SPE: Reload vector registers after efdabs/efdnabs/efdneg
  
  r341752:
  powerpc/SPE: Copy lower part of source register to target for
  efdabs/efdnabs/efdneg
  
  r342025:
  powerpcspe: Fix GPR handling in SPE exception handler
  
  r342107:
  powerpcspe: Don't require FPU_EMU for powerpcspe IEEE emulation

Modified:
  stable/12/sys/conf/files.powerpc
  stable/12/sys/powerpc/booke/spe.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/conf/files.powerpc
==============================================================================
--- stable/12/sys/conf/files.powerpc	Sat Jan  5 00:42:30 2019	(r342781)
+++ stable/12/sys/conf/files.powerpc	Sat Jan  5 04:43:22 2019	(r342782)
@@ -126,15 +126,15 @@ powerpc/cpufreq/mpc85xx_jog.c	optional	cpufreq mpc85xx
 powerpc/cpufreq/pcr.c		optional	cpufreq aim
 powerpc/cpufreq/pmcr.c		optional	cpufreq aim powerpc64
 powerpc/cpufreq/pmufreq.c	optional	cpufreq aim pmu
-powerpc/fpu/fpu_add.c		optional	fpu_emu
-powerpc/fpu/fpu_compare.c	optional	fpu_emu
-powerpc/fpu/fpu_div.c		optional	fpu_emu
+powerpc/fpu/fpu_add.c		optional	fpu_emu | powerpcspe
+powerpc/fpu/fpu_compare.c	optional	fpu_emu | powerpcspe
+powerpc/fpu/fpu_div.c		optional	fpu_emu | powerpcspe
 powerpc/fpu/fpu_emu.c		optional	fpu_emu
-powerpc/fpu/fpu_explode.c	optional	fpu_emu
-powerpc/fpu/fpu_implode.c	optional	fpu_emu
-powerpc/fpu/fpu_mul.c		optional	fpu_emu
+powerpc/fpu/fpu_explode.c	optional	fpu_emu | powerpcspe
+powerpc/fpu/fpu_implode.c	optional	fpu_emu | powerpcspe
+powerpc/fpu/fpu_mul.c		optional	fpu_emu | powerpcspe
 powerpc/fpu/fpu_sqrt.c		optional	fpu_emu
-powerpc/fpu/fpu_subr.c		optional	fpu_emu
+powerpc/fpu/fpu_subr.c		optional	fpu_emu | powerpcspe
 powerpc/mambo/mambocall.S	optional	mambo
 powerpc/mambo/mambo.c		optional	mambo
 powerpc/mambo/mambo_console.c	optional	mambo

Modified: stable/12/sys/powerpc/booke/spe.c
==============================================================================
--- stable/12/sys/powerpc/booke/spe.c	Sat Jan  5 00:42:30 2019	(r342781)
+++ stable/12/sys/powerpc/booke/spe.c	Sat Jan  5 04:43:22 2019	(r342782)
@@ -66,7 +66,6 @@ save_vec_int(struct thread *td)
 	 */
 	msr = mfmsr();
 	mtmsr(msr | PSL_VEC);
-	isync();
 
 	/*
 	 * Save the vector registers and SPEFSCR to the PCB
@@ -419,6 +418,52 @@ spe_explode(struct fpemu *fe, struct fpn *fp, uint32_t
 	return (0);
 }
 
+/*
+ * Save the high word of a 64-bit GPR for manipulation in the exception handler.
+ */
+static uint32_t
+spe_save_reg_high(int reg)
+{
+	uint32_t vec[2];
+#define EVSTDW(n)   case n: __asm ("evstdw %1,0(%0)" \
+		:: "b"(vec), "n"(n)); break;
+	switch (reg) {
+	EVSTDW(0);	EVSTDW(1);	EVSTDW(2);	EVSTDW(3);
+	EVSTDW(4);	EVSTDW(5);	EVSTDW(6);	EVSTDW(7);
+	EVSTDW(8);	EVSTDW(9);	EVSTDW(10);	EVSTDW(11);
+	EVSTDW(12);	EVSTDW(13);	EVSTDW(14);	EVSTDW(15);
+	EVSTDW(16);	EVSTDW(17);	EVSTDW(18);	EVSTDW(19);
+	EVSTDW(20);	EVSTDW(21);	EVSTDW(22);	EVSTDW(23);
+	EVSTDW(24);	EVSTDW(25);	EVSTDW(26);	EVSTDW(27);
+	EVSTDW(28);	EVSTDW(29);	EVSTDW(30);	EVSTDW(31);
+	}
+#undef EVSTDW
+
+	return (vec[0]);
+}
+
+/*
+ * Load the given value into the high word of the requested register.
+ */
+static void
+spe_load_reg_high(int reg, uint32_t val)
+{
+#define	EVLDW(n)   case n: __asm __volatile("evmergelo "#n",%0,0," \
+	    :: "r"(val)); break;
+	switch (reg) {
+	EVLDW(1);	EVLDW(2);	EVLDW(3);	EVLDW(4);
+	EVLDW(5);	EVLDW(6);	EVLDW(7);	EVLDW(8);
+	EVLDW(9);	EVLDW(10);	EVLDW(11);	EVLDW(12);
+	EVLDW(13);	EVLDW(14);	EVLDW(15);	EVLDW(16);
+	EVLDW(17);	EVLDW(18);	EVLDW(19);	EVLDW(20);
+	EVLDW(21);	EVLDW(22);	EVLDW(23);	EVLDW(24);
+	EVLDW(25);	EVLDW(26);	EVLDW(27);	EVLDW(28);
+	EVLDW(29);	EVLDW(30);	EVLDW(31);	EVLDW(0);
+	}
+#undef EVLDW
+
+}
+
 void
 spe_handle_fpdata(struct trapframe *frame)
 {
@@ -426,11 +471,12 @@ spe_handle_fpdata(struct trapframe *frame)
 	struct fpn *result;
 	uint32_t instr, instr_sec_op;
 	uint32_t cr_shift, ra, rb, rd, src;
-	uint32_t high, low, res; /* For vector operations. */
+	uint32_t high, low, res, tmp; /* For vector operations. */
 	uint32_t spefscr = 0;
 	uint32_t ftod_res[2];
 	int width; /* Single, Double, Vector, Integer */
 	int err;
+	uint32_t msr;
 
 	err = fueword32((void *)frame->srr0, &instr);
 	
@@ -441,6 +487,7 @@ spe_handle_fpdata(struct trapframe *frame)
 	if ((instr >> OPC_SHIFT) != SPE_OPC)
 		return;
 
+	msr = mfmsr();
 	/*
 	 * 'cr' field is the upper 3 bits of rd.  Magically, since a) rd is 5
 	 * bits, b) each 'cr' field is 4 bits, and c) Only the 'GT' bit is
@@ -460,32 +507,35 @@ spe_handle_fpdata(struct trapframe *frame)
 	width = NONE;
 	switch (src) {
 	case SPE:
-		save_vec_nodrop(curthread);
+		mtmsr(msr | PSL_VEC);
 		switch (instr_sec_op) {
 		case EVFSABS:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] & ~(1U << 31);
+			high = spe_save_reg_high(ra) & ~(1U << 31);
 			frame->fixreg[rd] = frame->fixreg[ra] & ~(1U << 31);
+			spe_load_reg_high(rd, high);
 			break;
 		case EVFSNABS:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] | (1U << 31);
+			high = spe_save_reg_high(ra) | (1U << 31);
 			frame->fixreg[rd] = frame->fixreg[ra] | (1U << 31);
+			spe_load_reg_high(rd, high);
 			break;
 		case EVFSNEG:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] ^ (1U << 31);
+			high = spe_save_reg_high(ra) ^ (1U << 31);
 			frame->fixreg[rd] = frame->fixreg[ra] ^ (1U << 31);
+			spe_load_reg_high(rd, high);
 			break;
 		default:
 			/* High word */
 			spe_explode(&fpemu, &fpemu.fe_f1, SINGLE,
-			    curthread->td_pcb->pcb_vec.vr[ra][0], 0);
+			    spe_save_reg_high(ra), 0);
 			spe_explode(&fpemu, &fpemu.fe_f2, SINGLE,
-			    curthread->td_pcb->pcb_vec.vr[rb][0], 0);
+			    spe_save_reg_high(rb), 0);
 			high = spe_emu_instr(instr_sec_op, &fpemu, &result,
-			    &curthread->td_pcb->pcb_vec.vr[rd][0]);
+			    &tmp);
 
+			if (high < 0)
+				spe_load_reg_high(rd, tmp);
+
 			spefscr = fpscr_to_spefscr(fpemu.fe_cx) << 16;
 			/* Clear the fpemu to start over on the lower bits. */
 			memset(&fpemu, 0, sizeof(fpemu));
@@ -508,7 +558,6 @@ spe_handle_fpdata(struct trapframe *frame)
 				width = VECTOR;
 			break;
 		}
-		enable_vec(curthread);
 		goto end;
 
 	case SPFP:
@@ -524,8 +573,7 @@ spe_handle_fpdata(struct trapframe *frame)
 			break;
 		case EFSCFD:
 			spe_explode(&fpemu, &fpemu.fe_f3, DOUBLE,
-			    curthread->td_pcb->pcb_vec.vr[rb][0],
-			    frame->fixreg[rb]);
+			    spe_save_reg_high(rb), frame->fixreg[rb]);
 			result = &fpemu.fe_f3;
 			width = SINGLE;
 			break;
@@ -538,19 +586,22 @@ spe_handle_fpdata(struct trapframe *frame)
 		}
 		break;
 	case DPFP:
-		save_vec_nodrop(curthread);
+		mtmsr(msr | PSL_VEC);
 		switch (instr_sec_op) {
 		case EFDABS:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] & ~(1U << 31);
+			high = spe_save_reg_high(ra) & ~(1U << 31);
+			frame->fixreg[rd] = frame->fixreg[ra];
+			spe_load_reg_high(rd, high);
 			break;
 		case EFDNABS:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] | (1U << 31);
+			high = spe_save_reg_high(ra) | (1U << 31);
+			frame->fixreg[rd] = frame->fixreg[ra];
+			spe_load_reg_high(rd, high);
 			break;
 		case EFDNEG:
-			curthread->td_pcb->pcb_vec.vr[rd][0] = 
-				curthread->td_pcb->pcb_vec.vr[ra][0] ^ (1U << 31);
+			high = spe_save_reg_high(ra) ^ (1U << 31);
+			frame->fixreg[rd] = frame->fixreg[ra];
+			spe_load_reg_high(rd, high);
 			break;
 		case EFDCFS:
 			spe_explode(&fpemu, &fpemu.fe_f3, SINGLE,
@@ -560,11 +611,9 @@ spe_handle_fpdata(struct trapframe *frame)
 			break;
 		default:
 			spe_explode(&fpemu, &fpemu.fe_f1, DOUBLE,
-			    curthread->td_pcb->pcb_vec.vr[ra][0],
-			    frame->fixreg[ra]);
+			    spe_save_reg_high(ra), frame->fixreg[ra]);
 			spe_explode(&fpemu, &fpemu.fe_f2, DOUBLE,
-			    curthread->td_pcb->pcb_vec.vr[rb][0],
-			    frame->fixreg[rb]);
+			    spe_save_reg_high(rb), frame->fixreg[rb]);
 			width = DOUBLE;
 		}
 		break;
@@ -603,10 +652,8 @@ spe_handle_fpdata(struct trapframe *frame)
 			frame->fixreg[rd] = fpu_ftos(&fpemu, result);
 			break;
 		case DOUBLE:
-			curthread->td_pcb->pcb_vec.vr[rd][0] =
-			    fpu_ftod(&fpemu, result, ftod_res);
+			spe_load_reg_high(rd, fpu_ftod(&fpemu, result, ftod_res));
 			frame->fixreg[rd] = ftod_res[1];
-			enable_vec(curthread);
 			break;
 		default:
 			panic("Unknown storage width %d", width);
@@ -618,6 +665,7 @@ end:
 	spefscr |= (mfspr(SPR_SPEFSCR) & ~SPEFSCR_FINVS);
 	mtspr(SPR_SPEFSCR, spefscr);
 	frame->srr0 += 4;
+	mtmsr(msr);
 
 	return;
 }


More information about the svn-src-all mailing list