Module Name:    src
Committed By:   thorpej
Date:           Fri Jul 23 04:19:50 UTC 2021

Modified Files:
        src/sys/arch/alpha/alpha: trap.c

Log Message:
Emulate the IEEE flavors of the FIX extension instructions:
- FTOIS, FTOIT
- ITOFS, ITOFT
- SRQTS, SQRTT

Left out for now are the VAX FP flavors:
- ITOFF
- SQRTF, SQRTG


To generate a diff of this commit:
cvs rdiff -u -r1.137 -r1.138 src/sys/arch/alpha/alpha/trap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/alpha/alpha/trap.c
diff -u src/sys/arch/alpha/alpha/trap.c:1.137 src/sys/arch/alpha/alpha/trap.c:1.138
--- src/sys/arch/alpha/alpha/trap.c:1.137	Tue Jul 20 01:56:06 2021
+++ src/sys/arch/alpha/alpha/trap.c	Fri Jul 23 04:19:50 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.137 2021/07/20 01:56:06 thorpej Exp $ */
+/* $NetBSD: trap.c,v 1.138 2021/07/23 04:19:50 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2000, 2001, 2021 The NetBSD Foundation, Inc.
@@ -95,7 +95,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.137 2021/07/20 01:56:06 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.138 2021/07/23 04:19:50 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -383,6 +383,8 @@ trap(const u_long a0, const u_long a1, c
 				ksi.ksi_code = SEGV_MAPERR;
 			else if (i == SIGILL)
 				ksi.ksi_code = ILL_ILLOPC;
+			else if (i == SIGFPE)
+				ksi.ksi_code = alpha_ucode_to_ksiginfo(ucode);
 			ksi.ksi_signo = i;
 			ksi.ksi_addr =
 				(void *)l->l_md.md_tf->tf_regs[FRAME_PC];
@@ -961,6 +963,128 @@ unaligned_fixup(u_long va, u_long opcode
 	return (signo);
 }
 
+#define	EMUL_COUNT(ev)	atomic_inc_64(&(ev).ev_count)
+
+static struct evcnt emul_fix_ftoit =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "ftoit");
+static struct evcnt emul_fix_ftois =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "ftois");
+static struct evcnt emul_fix_itofs =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "itofs");
+#if 0
+static struct evcnt emul_fix_itoff =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "itoff");
+#endif
+static struct evcnt emul_fix_itoft =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "itoft");
+static struct evcnt emul_fix_sqrtt =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "sqrtt");
+static struct evcnt emul_fix_sqrts =
+    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul fix", "sqrts");
+
+EVCNT_ATTACH_STATIC(emul_fix_ftoit);
+EVCNT_ATTACH_STATIC(emul_fix_ftois);
+EVCNT_ATTACH_STATIC(emul_fix_itofs);
+#if 0
+EVCNT_ATTACH_STATIC(emul_fix_itoff);
+#endif
+EVCNT_ATTACH_STATIC(emul_fix_itoft);
+EVCNT_ATTACH_STATIC(emul_fix_sqrtt);
+EVCNT_ATTACH_STATIC(emul_fix_sqrts);
+
+static void
+emul_fix(struct lwp *l, const alpha_instruction *inst)
+{
+	union {
+		f_float f;
+		s_float s;
+		t_float t;
+	} fmem;
+	register_t *regptr;
+
+	KASSERT(l == curlwp);
+
+	/*
+	 * FIX instructions don't cause any exceptions, including
+	 * MM exceptions.  However, they are equivalent in result
+	 * to e.g. STL,LDF.  We will just assume that we can access
+	 * our kernel stack, and thus no exception checks are
+	 * required.
+	 */
+
+	kpreempt_disable();
+	if ((l->l_md.md_flags & MDLWP_FPACTIVE) == 0) {
+		fpu_load();
+	}
+	alpha_pal_wrfen(1);
+
+	if (inst->float_format.opcode == op_intmisc) {
+		regptr = irp(l, inst->float_format.fc);
+		switch (inst->float_format.function) {
+		case op_ftoit:
+			EMUL_COUNT(emul_fix_ftoit);
+			alpha_stt(inst->float_format.fa, &fmem.t);
+			if (regptr != NULL) {
+				*regptr = fmem.t.i;
+			}
+			break;
+
+		case op_ftois:
+			EMUL_COUNT(emul_fix_ftois);
+			alpha_sts(inst->float_format.fa, &fmem.s);
+			if (regptr != NULL) {
+				*regptr = (int32_t)fmem.s.i;
+			}
+			break;
+
+		default:
+			panic("%s: bad intmisc function=0x%x\n", __func__,
+			    inst->float_format.function);
+		}
+	} else if (inst->float_format.opcode == op_fix_float) {
+		regptr = irp(l, inst->float_format.fa);
+		register_t regval = (regptr != NULL) ? *regptr : 0;
+
+		switch (inst->float_format.function) {
+		case op_itofs:
+			EMUL_COUNT(emul_fix_itofs);
+			fmem.s.i = (uint32_t)regval;
+			alpha_lds(inst->float_format.fc, &fmem.s);
+			break;
+
+		/*
+		 * The Book says about ITOFF:
+		 *
+		 *	ITOFF is equivalent to the following sequence,
+		 *	except that the word swapping that LDF normally
+		 *	performs is not performed by ITOFF.
+		 *
+		 *		STL
+		 *		LDF
+		 *
+		 * ...implying that we can't actually use LDF here ??? So
+		 * we'll skip it for now.
+		 */
+
+		case op_itoft:
+			EMUL_COUNT(emul_fix_itoft);
+			fmem.t.i = regval;
+			alpha_ldt(inst->float_format.fc, &fmem.t);
+			break;
+
+		default:
+			panic("%s: bad fix_float function=0x%x\n", __func__,
+			    inst->float_format.function);
+		}
+	} else {
+		panic("%s: bad opcode=0x%02x", __func__,
+		    inst->float_format.opcode);
+	}
+
+	alpha_pal_wrfen(0);
+	kpreempt_enable();
+}
+
 static struct evcnt emul_bwx_ldbu =
     EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "emul bwx", "ldbu");
 static struct evcnt emul_bwx_ldwu =
@@ -992,8 +1116,6 @@ EVCNT_ATTACH_STATIC(emul_cix_ctpop);
 EVCNT_ATTACH_STATIC(emul_cix_ctlz);
 EVCNT_ATTACH_STATIC(emul_cix_cttz);
 
-#define	EMUL_COUNT(ev)	atomic_inc_64(&(ev).ev_count)
-
 /*
  * Reserved/unimplemented instruction (opDec fault) handler
  *
@@ -1195,6 +1317,67 @@ handle_opdec(struct lwp *l, u_long *ucod
 			break;
 		}
 
+		/*
+		 * FTOIS and FTOIT are in Floating Operate format according
+		 * to The Book, which is nearly identical to the Reg Operate
+		 * format, but the function field of those overlaps the
+		 * "zero" and "sbz" fields and the FTOIS and FTOIT function
+		 * codes conviently has zero bits in those fields.
+		 */
+		if ((inst.float_format.function == op_ftoit ||
+		     inst.float_format.function == op_ftois) &&
+		    inst.float_format.fb == 31) {
+			/*
+			 * These FIX instructions can't cause any exceptions,
+			 * including MM exceptions.
+			 */
+			emul_fix(l, &inst);
+			break;
+		}
+
+		goto sigill;
+
+	case op_fix_float:
+		if ((inst.float_format.function == op_itofs ||
+		     /* ITOFF is a bit more complicated; skip it for now. */
+		     /* inst.float_format.function == op_itoff || */
+		     inst.float_format.function == op_itoft) &&
+		    inst.float_format.fb == 31) {
+			/*
+			 * These FIX instructions can't cause any exceptions,
+			 * including MM exceptions.
+			 */
+			emul_fix(l, &inst);
+			break;
+		}
+
+		/*
+		 * The SQRT function encodings are explained in a nice
+		 * chart in fp_complete.c -- go read it.
+		 *
+		 * We only handle the IEEE variants here; we do not have
+		 * a VAX softfloat library.
+		 */
+		if (inst.float_detail.opclass == 11 /* IEEE SQRT */ &&
+		    inst.float_detail.fa == 31      /* Fa must be $f31 */ &&
+		    (inst.float_detail.src == 0     /* SQRTS (S_float) */ ||
+		     inst.float_detail.src == 2     /* SQRTT (T_float) */)) {
+			if (inst.float_detail.src == 0) {
+				EMUL_COUNT(emul_fix_sqrts);
+			} else {
+				EMUL_COUNT(emul_fix_sqrtt);
+			}
+			sig = alpha_fp_complete_at(inst_pc, l, ucodep);
+			if (sig) {
+				if (sig == SIGSEGV) {
+					memaddr = inst_pc;
+					goto sigsegv;
+				}
+				return sig;
+			}
+			break;
+		}
+
 		goto sigill;
 
 	default:

Reply via email to