Home | History | Annotate | Line # | Download | only in hppa
fpu.c revision 1.6
      1  1.6       chs /*	$NetBSD: fpu.c,v 1.6 2004/06/15 16:29:01 chs Exp $	*/
      2  1.1  fredette 
      3  1.1  fredette /*
      4  1.1  fredette  * Copyright (c) 2002 The NetBSD Foundation, Inc.
      5  1.1  fredette  * All rights reserved.
      6  1.1  fredette  *
      7  1.1  fredette  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  fredette  * by Matthew Fredette.
      9  1.1  fredette  *
     10  1.1  fredette  * Redistribution and use in source and binary forms, with or without
     11  1.1  fredette  * modification, are permitted provided that the following conditions
     12  1.1  fredette  * are met:
     13  1.1  fredette  * 1. Redistributions of source code must retain the above copyright
     14  1.1  fredette  *    notice, this list of conditions and the following disclaimer.
     15  1.1  fredette  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  fredette  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  fredette  *    documentation and/or other materials provided with the distribution.
     18  1.1  fredette  * 3. All advertising materials mentioning features or use of this software
     19  1.1  fredette  *    must display the following acknowledgement:
     20  1.1  fredette  *        This product includes software developed by the NetBSD
     21  1.1  fredette  *        Foundation, Inc. and its contributors.
     22  1.1  fredette  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  fredette  *    contributors may be used to endorse or promote products derived
     24  1.1  fredette  *    from this software without specific prior written permission.
     25  1.1  fredette  *
     26  1.1  fredette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  fredette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  fredette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  fredette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  fredette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  fredette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  fredette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  fredette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  fredette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  fredette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  fredette  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  fredette  */
     38  1.1  fredette 
     39  1.1  fredette /*
     40  1.1  fredette  * FPU handling for NetBSD/hppa.
     41  1.1  fredette  */
     42  1.1  fredette 
     43  1.1  fredette #include <sys/cdefs.h>
     44  1.6       chs __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.6 2004/06/15 16:29:01 chs Exp $");
     45  1.1  fredette 
     46  1.1  fredette #include <sys/param.h>
     47  1.1  fredette #include <sys/systm.h>
     48  1.1  fredette #include <sys/proc.h>
     49  1.1  fredette #include <sys/signalvar.h>
     50  1.1  fredette #include <sys/user.h>
     51  1.1  fredette 
     52  1.1  fredette #include <machine/cpu.h>
     53  1.1  fredette #include <machine/cpufunc.h>
     54  1.1  fredette #include <machine/frame.h>
     55  1.1  fredette #include <machine/reg.h>
     56  1.1  fredette 
     57  1.1  fredette #include <hppa/hppa/machdep.h>
     58  1.1  fredette 
     59  1.1  fredette #include "../spmath/float.h"
     60  1.1  fredette #include "../spmath/fpudispatch.h"
     61  1.1  fredette 
     62  1.1  fredette /* Some macros representing opcodes. */
     63  1.1  fredette #define OPCODE_NOP	0x08000240
     64  1.1  fredette #define OPCODE_COPR_0_0	0x30000000
     65  1.1  fredette 
     66  1.1  fredette /* Some macros representing fields in load/store opcodes. */
     67  1.1  fredette #define	OPCODE_CMPLT_S	0x00002000
     68  1.1  fredette #define	OPCODE_CMPLT_M	0x00000020
     69  1.1  fredette #define	OPCODE_CMPLT_SM	(OPCODE_CMPLT_S | OPCODE_CMPLT_M)
     70  1.1  fredette #define	OPCODE_CMPLT_MB	OPCODE_CMPLT_M
     71  1.1  fredette #define	OPCODE_CMPLT_MA	(OPCODE_CMPLT_S | OPCODE_CMPLT_M)
     72  1.1  fredette #define	OPCODE_CMPLT	(OPCODE_CMPLT_S | OPCODE_CMPLT_M)
     73  1.1  fredette #define	OPCODE_DOUBLE	0x08000000
     74  1.1  fredette #define	OPCODE_STORE	0x00000200
     75  1.1  fredette #define OPCODE_INDEXED	0x00001000
     76  1.1  fredette 
     77  1.1  fredette /* This is nonzero iff we're using a hardware FPU. */
     78  1.1  fredette int fpu_present;
     79  1.1  fredette 
     80  1.1  fredette /* If we have any FPU, this is its version. */
     81  1.1  fredette u_int fpu_version;
     82  1.1  fredette 
     83  1.1  fredette /* The number of times we have had to switch the FPU context. */
     84  1.1  fredette u_int fpu_csw;
     85  1.1  fredette 
     86  1.1  fredette /* The U-space physical address of the proc in the FPU, or zero. */
     87  1.1  fredette paddr_t fpu_cur_uspace;
     88  1.1  fredette 
     89  1.1  fredette /* In locore.S, this swaps states in and out of the FPU. */
     90  1.6       chs void hppa_fpu_swap(struct pcb *, struct pcb *);
     91  1.1  fredette 
     92  1.5  drochner /* XXX see trap.c */
     93  1.5  drochner void hppa_trapsignal_hack(struct lwp *, int, u_long);
     94  1.5  drochner 
     95  1.1  fredette #ifdef FPEMUL
     96  1.1  fredette /*
     97  1.1  fredette  * Given a trapframe and a general register number, the
     98  1.1  fredette  * FRAME_REG macro returns a pointer to that general
     99  1.1  fredette  * register.  The _frame_reg_positions array is a lookup
    100  1.1  fredette  * table, since the general registers aren't in order
    101  1.1  fredette  * in a trapframe.
    102  1.1  fredette  *
    103  1.1  fredette  * NB: this more or less assumes that all members of
    104  1.1  fredette  * struct trapframe are u_ints.
    105  1.1  fredette  */
    106  1.1  fredette #define FRAME_REG(f, reg, r0)	\
    107  1.1  fredette 	((reg) == 0 ? (&r0) : ((&(f)->tf_t1) + _frame_reg_positions[reg]))
    108  1.1  fredette #define _FRAME_POSITION(f)	\
    109  1.1  fredette 	((&((struct trapframe *) 0)->f) - (&((struct trapframe *) 0)->tf_t1))
    110  1.1  fredette const int _frame_reg_positions[32] = {
    111  1.1  fredette 	-1,				/* r0 */
    112  1.1  fredette 	_FRAME_POSITION(tf_r1),
    113  1.1  fredette 	_FRAME_POSITION(tf_rp),		/* r2 */
    114  1.1  fredette 	_FRAME_POSITION(tf_r3),
    115  1.1  fredette 	_FRAME_POSITION(tf_r4),
    116  1.1  fredette 	_FRAME_POSITION(tf_r5),
    117  1.1  fredette 	_FRAME_POSITION(tf_r6),
    118  1.1  fredette 	_FRAME_POSITION(tf_r7),
    119  1.1  fredette 	_FRAME_POSITION(tf_r8),
    120  1.1  fredette 	_FRAME_POSITION(tf_r9),
    121  1.1  fredette 	_FRAME_POSITION(tf_r10),
    122  1.1  fredette 	_FRAME_POSITION(tf_r11),
    123  1.1  fredette 	_FRAME_POSITION(tf_r12),
    124  1.1  fredette 	_FRAME_POSITION(tf_r13),
    125  1.1  fredette 	_FRAME_POSITION(tf_r14),
    126  1.1  fredette 	_FRAME_POSITION(tf_r15),
    127  1.1  fredette 	_FRAME_POSITION(tf_r16),
    128  1.1  fredette 	_FRAME_POSITION(tf_r17),
    129  1.1  fredette 	_FRAME_POSITION(tf_r18),
    130  1.1  fredette 	_FRAME_POSITION(tf_t4),		/* r19 */
    131  1.1  fredette 	_FRAME_POSITION(tf_t3),		/* r20 */
    132  1.1  fredette 	_FRAME_POSITION(tf_t2),		/* r21 */
    133  1.1  fredette 	_FRAME_POSITION(tf_t1),		/* r22 */
    134  1.1  fredette 	_FRAME_POSITION(tf_arg3),	/* r23 */
    135  1.1  fredette 	_FRAME_POSITION(tf_arg2),	/* r24 */
    136  1.1  fredette 	_FRAME_POSITION(tf_arg1),	/* r25 */
    137  1.1  fredette 	_FRAME_POSITION(tf_arg0),	/* r26 */
    138  1.1  fredette 	_FRAME_POSITION(tf_dp),		/* r27 */
    139  1.1  fredette 	_FRAME_POSITION(tf_ret0),	/* r28 */
    140  1.1  fredette 	_FRAME_POSITION(tf_ret1),	/* r29 */
    141  1.1  fredette 	_FRAME_POSITION(tf_sp),		/* r30 */
    142  1.1  fredette 	_FRAME_POSITION(tf_r31),
    143  1.1  fredette };
    144  1.1  fredette #endif /* FPEMUL */
    145  1.1  fredette 
    146  1.1  fredette /*
    147  1.1  fredette  * Bootstraps the FPU.
    148  1.1  fredette  */
    149  1.1  fredette void
    150  1.1  fredette hppa_fpu_bootstrap(u_int ccr_enable)
    151  1.1  fredette {
    152  1.1  fredette 	u_int32_t junk[2];
    153  1.1  fredette 	u_int32_t version[2];
    154  1.1  fredette 	extern u_int hppa_fpu_nop0;
    155  1.1  fredette 	extern u_int hppa_fpu_nop1;
    156  1.1  fredette 
    157  1.1  fredette 	/* See if we have a present and functioning hardware FPU. */
    158  1.1  fredette 	fpu_present = (ccr_enable & HPPA_FPUS) == HPPA_FPUS;
    159  1.1  fredette 
    160  1.1  fredette 	/* Initialize the FPU and get its version. */
    161  1.1  fredette 	if (fpu_present) {
    162  1.1  fredette 
    163  1.1  fredette 		/*
    164  1.1  fredette 		 * To somewhat optimize the emulation
    165  1.1  fredette 		 * assist trap handling and context
    166  1.1  fredette 		 * switching (to save them from having
    167  1.1  fredette 	 	 * to always load and check fpu_present),
    168  1.1  fredette 		 * there are two instructions in locore.S
    169  1.1  fredette 		 * that are replaced with nops when
    170  1.1  fredette 		 * there is a hardware FPU.
    171  1.1  fredette 	 	 */
    172  1.1  fredette 		hppa_fpu_nop0 = OPCODE_NOP;
    173  1.1  fredette 		hppa_fpu_nop1 = OPCODE_NOP;
    174  1.1  fredette 		fcacheall();
    175  1.1  fredette 
    176  1.1  fredette 		/*
    177  1.1  fredette 		 * We track what process has the FPU,
    178  1.1  fredette 		 * and how many times we have to swap
    179  1.1  fredette 		 * in and out.
    180  1.1  fredette 		 */
    181  1.1  fredette 
    182  1.1  fredette 		/*
    183  1.1  fredette 		 * The PA-RISC 1.1 Architecture manual is
    184  1.1  fredette 		 * pretty clear that the copr,0,0 must be
    185  1.1  fredette 		 * wrapped in double word stores of fr0,
    186  1.1  fredette 		 * otherwise its operation is undefined.
    187  1.1  fredette 		 */
    188  1.1  fredette 		__asm __volatile(
    189  1.1  fredette 			"	ldo	%0, %%r22	\n"
    190  1.1  fredette 			"	fstds	%%fr0, 0(%%r22)	\n"
    191  1.1  fredette 			"	ldo	%1, %%r22	\n"
    192  1.1  fredette 			"	copr,0,0		\n"
    193  1.1  fredette 			"	fstds	%%fr0, 0(%%r22)	\n"
    194  1.1  fredette 			: "=m" (junk), "=m" (version) : : "r22");
    195  1.1  fredette 
    196  1.1  fredette 		/*
    197  1.1  fredette 		 * Now mark that no process has the FPU,
    198  1.1  fredette 		 * and disable it, so the first time it
    199  1.1  fredette 		 * gets used the process' state gets
    200  1.1  fredette 		 * swapped in.
    201  1.1  fredette 		 */
    202  1.1  fredette 		fpu_csw = 0;
    203  1.1  fredette 		fpu_cur_uspace = 0;
    204  1.1  fredette 		mtctl(ccr_enable & (CCR_MASK ^ HPPA_FPUS), CR_CCR);
    205  1.1  fredette 	}
    206  1.1  fredette #ifdef FPEMUL
    207  1.1  fredette 	else
    208  1.1  fredette 		/*
    209  1.1  fredette 		 * XXX This is a hack - to avoid
    210  1.1  fredette 		 * having to set up the emulator so
    211  1.1  fredette 		 * it can work for one instruction for
    212  1.1  fredette 		 * proc0, we dispatch the copr,0,0 opcode
    213  1.1  fredette 		 * into the emulator directly.
    214  1.1  fredette 		 */
    215  1.1  fredette 		decode_0c(OPCODE_COPR_0_0, 0, 0, version);
    216  1.1  fredette #endif /* FPEMUL */
    217  1.1  fredette 	fpu_version = version[0];
    218  1.1  fredette }
    219  1.1  fredette 
    220  1.1  fredette /*
    221  1.2       chs  * If the given LWP has its state in the FPU,
    222  1.2       chs  * flush that state out into the LWP's PCB.
    223  1.1  fredette  */
    224  1.1  fredette void
    225  1.2       chs hppa_fpu_flush(struct lwp *l)
    226  1.1  fredette {
    227  1.2       chs 	struct trapframe *tf = l->l_md.md_regs;
    228  1.1  fredette 
    229  1.1  fredette 	/*
    230  1.2       chs 	 * If we have a hardware FPU, and this process'
    231  1.2       chs 	 * state is currently in it, swap it out.
    232  1.2       chs 	 */
    233  1.2       chs 
    234  1.6       chs 	if (!fpu_present || fpu_cur_uspace == 0 ||
    235  1.6       chs 	    fpu_cur_uspace != tf->tf_cr30) {
    236  1.6       chs 		return;
    237  1.6       chs 	}
    238  1.6       chs 
    239  1.6       chs 	hppa_fpu_swap(&l->l_addr->u_pcb, NULL);
    240  1.6       chs 	fpu_cur_uspace = 0;
    241  1.1  fredette }
    242  1.1  fredette 
    243  1.1  fredette #ifdef FPEMUL
    244  1.1  fredette 
    245  1.1  fredette /*
    246  1.1  fredette  * This emulates a coprocessor load/store instruction.
    247  1.1  fredette  */
    248  1.4       chs static int hppa_fpu_ls(struct trapframe *, struct lwp *);
    249  1.1  fredette static int
    250  1.2       chs hppa_fpu_ls(struct trapframe *frame, struct lwp *l)
    251  1.1  fredette {
    252  1.1  fredette 	u_int inst, inst_b, inst_x, inst_s, inst_t;
    253  1.1  fredette 	int log2size;
    254  1.1  fredette 	u_int *base;
    255  1.1  fredette 	u_int offset, index, im5;
    256  1.1  fredette 	void *fpreg;
    257  1.1  fredette 	u_int r0 = 0;
    258  1.6       chs 	int error;
    259  1.6       chs 
    260  1.1  fredette 	/*
    261  1.1  fredette 	 * Get the instruction that we're emulating,
    262  1.1  fredette 	 * and break it down.  Using HP bit notation,
    263  1.1  fredette 	 * b is a five-bit field starting at bit 10,
    264  1.1  fredette 	 * x is a five-bit field starting at bit 15,
    265  1.1  fredette 	 * s is a two-bit field starting at bit 17,
    266  1.1  fredette 	 * and t is a two-bit field starting at bit 31.
    267  1.1  fredette 	 */
    268  1.1  fredette 	inst = frame->tf_iir;
    269  1.1  fredette 	__asm __volatile(
    270  1.1  fredette 		"	extru %4, 10, 5, %1	\n"
    271  1.1  fredette 		"	extru %4, 15, 5, %2	\n"
    272  1.1  fredette 		"	extru %4, 17, 2, %3	\n"
    273  1.1  fredette 		"	extru %4, 31, 5, %4	\n"
    274  1.1  fredette 		: "=r" (inst_b), "=r" (inst_x), "=r" (inst_s), "=r" (inst_t)
    275  1.1  fredette 		: "r" (inst));
    276  1.1  fredette 
    277  1.1  fredette 	/*
    278  1.1  fredette 	 * The space must be the user's space, else we
    279  1.1  fredette 	 * segfault.
    280  1.1  fredette 	 */
    281  1.2       chs 	if (inst_s != l->l_addr->u_pcb.pcb_space)
    282  1.1  fredette 		return (EFAULT);
    283  1.1  fredette 
    284  1.1  fredette 	/* See whether or not this is a doubleword load/store. */
    285  1.1  fredette 	log2size = (inst & OPCODE_DOUBLE) ? 3 : 2;
    286  1.1  fredette 
    287  1.1  fredette 	/* Get the floating point register. */
    288  1.2       chs 	fpreg = ((caddr_t)l->l_addr->u_pcb.pcb_fpregs) + (inst_t << log2size);
    289  1.1  fredette 
    290  1.1  fredette 	/* Get the base register. */
    291  1.1  fredette 	base = FRAME_REG(frame, inst_b, r0);
    292  1.1  fredette 
    293  1.1  fredette 	/* Dispatch on whether or not this is an indexed load/store. */
    294  1.1  fredette 	if (inst & OPCODE_INDEXED) {
    295  1.1  fredette 
    296  1.1  fredette 		/* Get the index register value. */
    297  1.1  fredette 		index = *FRAME_REG(frame, inst_x, r0);
    298  1.1  fredette 
    299  1.1  fredette 		/* Dispatch on the completer. */
    300  1.1  fredette 		switch (inst & OPCODE_CMPLT) {
    301  1.1  fredette 		case OPCODE_CMPLT_S:
    302  1.1  fredette 			offset = *base + (index << log2size);
    303  1.1  fredette 			break;
    304  1.1  fredette 		case OPCODE_CMPLT_M:
    305  1.1  fredette 			offset = *base;
    306  1.1  fredette 			*base = *base + index;
    307  1.1  fredette 			break;
    308  1.1  fredette 		case OPCODE_CMPLT_SM:
    309  1.1  fredette 			offset = *base;
    310  1.1  fredette 			*base = *base + (index << log2size);
    311  1.1  fredette 			break;
    312  1.1  fredette 		default:
    313  1.1  fredette 			offset = *base + index;
    314  1.1  fredette 			break;
    315  1.1  fredette 		}
    316  1.1  fredette 	} else {
    317  1.1  fredette 
    318  1.1  fredette 		/* Do a low_sign_ext(x, 5). */
    319  1.1  fredette 		im5 = inst_x >> 1;
    320  1.1  fredette 		if (inst_x & 1)
    321  1.1  fredette 			im5 |= 0xfffffff0;
    322  1.1  fredette 
    323  1.1  fredette 		/* Dispatch on the completer. */
    324  1.1  fredette 		switch (inst & OPCODE_CMPLT) {
    325  1.1  fredette 		case OPCODE_CMPLT_MB:
    326  1.1  fredette 			offset = *base + im5;
    327  1.1  fredette 			*base = *base + im5;
    328  1.1  fredette 			break;
    329  1.1  fredette 		case OPCODE_CMPLT_MA:
    330  1.1  fredette 			offset = *base;
    331  1.1  fredette 			*base = *base + im5;
    332  1.1  fredette 			break;
    333  1.1  fredette 		default:
    334  1.1  fredette 			offset = *base + im5;
    335  1.1  fredette 			break;
    336  1.1  fredette 		}
    337  1.1  fredette 	}
    338  1.1  fredette 
    339  1.1  fredette 	/*
    340  1.1  fredette 	 * The offset we calculated must be the same as the
    341  1.1  fredette 	 * offset in the IOR.
    342  1.1  fredette 	 */
    343  1.1  fredette 	KASSERT(offset == frame->tf_ior);
    344  1.1  fredette 
    345  1.1  fredette 	/* Perform the load or store. */
    346  1.6       chs 	error = (inst & OPCODE_STORE) ?
    347  1.1  fredette 		copyout(fpreg, (void *) offset, 1 << log2size) :
    348  1.1  fredette 		copyin((const void *) offset, fpreg, 1 << log2size);
    349  1.6       chs 	fdcache(HPPA_SID_KERNEL, (vaddr_t)fpreg,
    350  1.6       chs 		sizeof(l->l_addr->u_pcb.pcb_fpregs));
    351  1.6       chs 	return error;
    352  1.1  fredette }
    353  1.1  fredette 
    354  1.1  fredette /*
    355  1.1  fredette  * This is called to emulate an instruction.
    356  1.1  fredette  */
    357  1.1  fredette void
    358  1.2       chs hppa_fpu_emulate(struct trapframe *frame, struct lwp *l)
    359  1.1  fredette {
    360  1.1  fredette 	u_int inst, opcode, class, sub;
    361  1.1  fredette 	u_int *fpregs;
    362  1.1  fredette 	int exception;
    363  1.1  fredette 
    364  1.1  fredette 	/*
    365  1.1  fredette 	 * If the process' state is in any hardware FPU,
    366  1.1  fredette 	 * flush it out - we need to operate on it.
    367  1.1  fredette 	 */
    368  1.2       chs 	hppa_fpu_flush(l);
    369  1.1  fredette 
    370  1.1  fredette 	/*
    371  1.1  fredette 	 * Get the instruction that we're emulating,
    372  1.1  fredette 	 * and break it down.  Using HP bit notation,
    373  1.1  fredette 	 * the class is a two-bit field starting at
    374  1.1  fredette 	 * bit 22, the opcode is a 6-bit field starting
    375  1.1  fredette 	 * at bit 5, and sub for a class 1 instruction
    376  1.1  fredette 	 * is a two bit field starting at bit 16, else
    377  1.1  fredette 	 * it is a three bit field starting at bit 18.
    378  1.1  fredette 	 */
    379  1.1  fredette 	inst = frame->tf_iir;
    380  1.1  fredette 	__asm __volatile(
    381  1.1  fredette 		"	extru %3, 22, 2, %1	\n"
    382  1.1  fredette 		"	extru %3, 5, 6, %0	\n"
    383  1.1  fredette 		"	extru %3, 18, 3, %2	\n"
    384  1.1  fredette 		"	comib,<> 1, %1, 0	\n"
    385  1.1  fredette 		"	extru %3, 16, 2, %2	\n"
    386  1.1  fredette 		: "=r" (opcode), "=r" (class), "=r" (sub)
    387  1.1  fredette 		: "r" (inst));
    388  1.1  fredette 
    389  1.2       chs 	/* Get this LWP's FPU registers. */
    390  1.2       chs 	fpregs = (u_int *) l->l_addr->u_pcb.pcb_fpregs;
    391  1.1  fredette 
    392  1.1  fredette 	/* Dispatch on the opcode. */
    393  1.1  fredette 	switch (opcode) {
    394  1.1  fredette 	case 0x09:
    395  1.1  fredette 	case 0x0b:
    396  1.2       chs 		if (hppa_fpu_ls(frame, l) != 0)
    397  1.5  drochner 			hppa_trapsignal_hack(l, SIGSEGV, frame->tf_iioq_head);
    398  1.1  fredette 		return;
    399  1.1  fredette 	case 0x0c:
    400  1.1  fredette 		exception = decode_0c(inst, class, sub, fpregs);
    401  1.1  fredette 		break;
    402  1.1  fredette 	case 0x0e:
    403  1.1  fredette 		exception = decode_0e(inst, class, sub, fpregs);
    404  1.1  fredette 		break;
    405  1.1  fredette 	case 0x06:
    406  1.1  fredette 		exception = decode_06(inst, fpregs);
    407  1.1  fredette 		break;
    408  1.1  fredette 	case 0x26:
    409  1.1  fredette 		exception = decode_26(inst, fpregs);
    410  1.1  fredette 		break;
    411  1.1  fredette 	default:
    412  1.1  fredette 		exception = UNIMPLEMENTEDEXCEPTION;
    413  1.1  fredette 		break;
    414  1.1  fredette         }
    415  1.1  fredette 
    416  1.6       chs 	fdcache(HPPA_SID_KERNEL, (vaddr_t)fpregs,
    417  1.6       chs 		sizeof(l->l_addr->u_pcb.pcb_fpregs));
    418  1.1  fredette 	if (exception)
    419  1.5  drochner 		hppa_trapsignal_hack(l, (exception & UNIMPLEMENTEDEXCEPTION) ?
    420  1.1  fredette 			SIGILL : SIGFPE, frame->tf_iioq_head);
    421  1.1  fredette }
    422  1.1  fredette 
    423  1.1  fredette #endif /* FPEMUL */
    424