Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/alpha/alpha Emulate the IEEE flavors of the FIX ext...



details:   https://anonhg.NetBSD.org/src/rev/487ab61e2754
branches:  trunk
changeset: 984779:487ab61e2754
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri Jul 23 04:19:50 2021 +0000

description:
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

diffstat:

 sys/arch/alpha/alpha/trap.c |  191 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 187 insertions(+), 4 deletions(-)

diffs (233 lines):

diff -r fee959dec58e -r 487ab61e2754 sys/arch/alpha/alpha/trap.c
--- a/sys/arch/alpha/alpha/trap.c       Fri Jul 23 03:57:06 2021 +0000
+++ b/sys/arch/alpha/alpha/trap.c       Fri Jul 23 04:19:50 2021 +0000
@@ -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 @@
                                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 @@
        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_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 @@
                        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:



Home | Main Index | Thread Index | Old Index