xref: /openbmc/linux/arch/parisc/math-emu/fpudispatch.c (revision 660662f857bc342b287572789b2494d0614e001d)
1*660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Floating-point emulation code
61da177e4SLinus Torvalds  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds  * BEGIN_DESC
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  File:
121da177e4SLinus Torvalds  *	@(#)	pa/fp/fpudispatch.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	<<please update with a synopsis of the functionality provided by this file>>
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	<<the following list was autogenerated, please review>>
191da177e4SLinus Torvalds  *	emfpudispatch(ir, dummy1, dummy2, fpregs)
201da177e4SLinus Torvalds  *	fpudispatch(ir, excp_code, holder, fpregs)
211da177e4SLinus Torvalds  *
221da177e4SLinus Torvalds  *  Internal Interfaces:
231da177e4SLinus Torvalds  *	<<the following list was autogenerated, please review>>
241da177e4SLinus Torvalds  *	static u_int decode_06(u_int, u_int *)
251da177e4SLinus Torvalds  *	static u_int decode_0c(u_int, u_int, u_int, u_int *)
261da177e4SLinus Torvalds  *	static u_int decode_0e(u_int, u_int, u_int, u_int *)
271da177e4SLinus Torvalds  *	static u_int decode_26(u_int, u_int *)
281da177e4SLinus Torvalds  *	static u_int decode_2e(u_int, u_int *)
291da177e4SLinus Torvalds  *	static void update_status_cbit(u_int *, u_int, u_int, u_int)
301da177e4SLinus Torvalds  *
311da177e4SLinus Torvalds  *  Theory:
321da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
331da177e4SLinus Torvalds  *
341da177e4SLinus Torvalds  * END_DESC
351da177e4SLinus Torvalds */
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds #define FPUDEBUG 0
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds #include "float.h"
4050af5eadSPaul Gortmaker #include <linux/bug.h>
411da177e4SLinus Torvalds #include <linux/kernel.h>
421da177e4SLinus Torvalds #include <asm/processor.h>
431da177e4SLinus Torvalds /* #include <sys/debug.h> */
441da177e4SLinus Torvalds /* #include <machine/sys/mdep_private.h> */
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds #define COPR_INST 0x30000000
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds /*
491da177e4SLinus Torvalds  * definition of extru macro.  If pos and len are constants, the compiler
501da177e4SLinus Torvalds  * will generate an extru instruction when optimized
511da177e4SLinus Torvalds  */
521da177e4SLinus Torvalds #define extru(r,pos,len)	(((r) >> (31-(pos))) & (( 1 << (len)) - 1))
531da177e4SLinus Torvalds /* definitions of bit field locations in the instruction */
541da177e4SLinus Torvalds #define fpmajorpos 5
551da177e4SLinus Torvalds #define fpr1pos	10
561da177e4SLinus Torvalds #define fpr2pos 15
571da177e4SLinus Torvalds #define fptpos	31
581da177e4SLinus Torvalds #define fpsubpos 18
591da177e4SLinus Torvalds #define fpclass1subpos 16
601da177e4SLinus Torvalds #define fpclasspos 22
611da177e4SLinus Torvalds #define fpfmtpos 20
621da177e4SLinus Torvalds #define fpdfpos 18
631da177e4SLinus Torvalds #define fpnulpos 26
641da177e4SLinus Torvalds /*
651da177e4SLinus Torvalds  * the following are the extra bits for the 0E major op
661da177e4SLinus Torvalds  */
671da177e4SLinus Torvalds #define fpxr1pos 24
681da177e4SLinus Torvalds #define fpxr2pos 19
691da177e4SLinus Torvalds #define fpxtpos 25
701da177e4SLinus Torvalds #define fpxpos 23
711da177e4SLinus Torvalds #define fp0efmtpos 20
721da177e4SLinus Torvalds /*
731da177e4SLinus Torvalds  * the following are for the multi-ops
741da177e4SLinus Torvalds  */
751da177e4SLinus Torvalds #define fprm1pos 10
761da177e4SLinus Torvalds #define fprm2pos 15
771da177e4SLinus Torvalds #define fptmpos 31
781da177e4SLinus Torvalds #define fprapos 25
791da177e4SLinus Torvalds #define fptapos 20
801da177e4SLinus Torvalds #define fpmultifmt 26
811da177e4SLinus Torvalds /*
821da177e4SLinus Torvalds  * the following are for the fused FP instructions
831da177e4SLinus Torvalds  */
841da177e4SLinus Torvalds      /* fprm1pos 10 */
851da177e4SLinus Torvalds      /* fprm2pos 15 */
861da177e4SLinus Torvalds #define fpraupos 18
871da177e4SLinus Torvalds #define fpxrm2pos 19
881da177e4SLinus Torvalds      /* fpfmtpos 20 */
891da177e4SLinus Torvalds #define fpralpos 23
901da177e4SLinus Torvalds #define fpxrm1pos 24
911da177e4SLinus Torvalds      /* fpxtpos 25 */
921da177e4SLinus Torvalds #define fpfusedsubop 26
931da177e4SLinus Torvalds      /* fptpos	31 */
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds /*
961da177e4SLinus Torvalds  * offset to constant zero in the FP emulation registers
971da177e4SLinus Torvalds  */
981da177e4SLinus Torvalds #define fpzeroreg (32*sizeof(double)/sizeof(u_int))
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds /*
1011da177e4SLinus Torvalds  * extract the major opcode from the instruction
1021da177e4SLinus Torvalds  */
1031da177e4SLinus Torvalds #define get_major(op) extru(op,fpmajorpos,6)
1041da177e4SLinus Torvalds /*
1051da177e4SLinus Torvalds  * extract the two bit class field from the FP instruction. The class is at bit
1061da177e4SLinus Torvalds  * positions 21-22
1071da177e4SLinus Torvalds  */
1081da177e4SLinus Torvalds #define get_class(op) extru(op,fpclasspos,2)
1091da177e4SLinus Torvalds /*
1101da177e4SLinus Torvalds  * extract the 3 bit subop field.  For all but class 1 instructions, it is
1111da177e4SLinus Torvalds  * located at bit positions 16-18
1121da177e4SLinus Torvalds  */
1131da177e4SLinus Torvalds #define get_subop(op) extru(op,fpsubpos,3)
1141da177e4SLinus Torvalds /*
1151da177e4SLinus Torvalds  * extract the 2 or 3 bit subop field from class 1 instructions.  It is located
1161da177e4SLinus Torvalds  * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
1171da177e4SLinus Torvalds  */
1181da177e4SLinus Torvalds #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2)	/* PA89 (1.1) fmt */
1191da177e4SLinus Torvalds #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3)	/* PA 2.0 fmt */
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds /* definitions of unimplemented exceptions */
1221da177e4SLinus Torvalds #define MAJOR_0C_EXCP	0x09
1231da177e4SLinus Torvalds #define MAJOR_0E_EXCP	0x0b
1241da177e4SLinus Torvalds #define MAJOR_06_EXCP	0x03
1251da177e4SLinus Torvalds #define MAJOR_26_EXCP	0x23
1261da177e4SLinus Torvalds #define MAJOR_2E_EXCP	0x2b
1271da177e4SLinus Torvalds #define PA83_UNIMP_EXCP	0x01
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds /*
1301da177e4SLinus Torvalds  * Special Defines for TIMEX specific code
1311da177e4SLinus Torvalds  */
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
1341da177e4SLinus Torvalds #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds  * Static function definitions
1381da177e4SLinus Torvalds  */
1391da177e4SLinus Torvalds #define _PROTOTYPES
1401da177e4SLinus Torvalds #if defined(_PROTOTYPES) || defined(_lint)
1411da177e4SLinus Torvalds static u_int decode_0c(u_int, u_int, u_int, u_int *);
1421da177e4SLinus Torvalds static u_int decode_0e(u_int, u_int, u_int, u_int *);
1431da177e4SLinus Torvalds static u_int decode_06(u_int, u_int *);
1441da177e4SLinus Torvalds static u_int decode_26(u_int, u_int *);
1451da177e4SLinus Torvalds static u_int decode_2e(u_int, u_int *);
1461da177e4SLinus Torvalds static void update_status_cbit(u_int *, u_int, u_int, u_int);
1471da177e4SLinus Torvalds #else /* !_PROTOTYPES&&!_lint */
1481da177e4SLinus Torvalds static u_int decode_0c();
1491da177e4SLinus Torvalds static u_int decode_0e();
1501da177e4SLinus Torvalds static u_int decode_06();
1511da177e4SLinus Torvalds static u_int decode_26();
1521da177e4SLinus Torvalds static u_int decode_2e();
1531da177e4SLinus Torvalds static void update_status_cbit();
1541da177e4SLinus Torvalds #endif /* _PROTOTYPES&&!_lint */
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds #define VASSERT(x)
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds static void parisc_linux_get_fpu_type(u_int fpregs[])
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds 	/* on pa-linux the fpu type is not filled in by the
1611da177e4SLinus Torvalds 	 * caller; it is constructed here
1621da177e4SLinus Torvalds 	 */
1631da177e4SLinus Torvalds 	if (boot_cpu_data.cpu_type == pcxs)
1641da177e4SLinus Torvalds 		fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
1651da177e4SLinus Torvalds 	else if (boot_cpu_data.cpu_type == pcxt ||
1661da177e4SLinus Torvalds 	         boot_cpu_data.cpu_type == pcxt_)
1671da177e4SLinus Torvalds 		fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
1681da177e4SLinus Torvalds 	else if (boot_cpu_data.cpu_type >= pcxu)
1691da177e4SLinus Torvalds 		fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
1701da177e4SLinus Torvalds }
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds /*
1731da177e4SLinus Torvalds  * this routine will decode the excepting floating point instruction and
17490afe0a9SAndrea Gelmini  * call the appropriate emulation routine.
1751da177e4SLinus Torvalds  * It is called by decode_fpu with the following parameters:
1761da177e4SLinus Torvalds  * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
1771da177e4SLinus Torvalds  * where current_ir is the instruction to be emulated,
1781da177e4SLinus Torvalds  * unimplemented_code is the exception_code that the hardware generated
1791da177e4SLinus Torvalds  * and &Fpu_register is the address of emulated FP reg 0.
1801da177e4SLinus Torvalds  */
1811da177e4SLinus Torvalds u_int
1821da177e4SLinus Torvalds fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
1831da177e4SLinus Torvalds {
1841da177e4SLinus Torvalds 	u_int class, subop;
1851da177e4SLinus Torvalds 	u_int fpu_type_flags;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	/* All FP emulation code assumes that ints are 4-bytes in length */
1881da177e4SLinus Torvalds 	VASSERT(sizeof(int) == 4);
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	parisc_linux_get_fpu_type(fpregs);
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds 	class = get_class(ir);
1951da177e4SLinus Torvalds 	if (class == 1) {
1961da177e4SLinus Torvalds 		if  (fpu_type_flags & PA2_0_FPU_FLAG)
1971da177e4SLinus Torvalds 			subop = get_subop1_PA2_0(ir);
1981da177e4SLinus Torvalds 		else
1991da177e4SLinus Torvalds 			subop = get_subop1_PA1_1(ir);
2001da177e4SLinus Torvalds 	}
2011da177e4SLinus Torvalds 	else
2021da177e4SLinus Torvalds 		subop = get_subop(ir);
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds 	if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds 	switch (excp_code) {
2071da177e4SLinus Torvalds 		case MAJOR_0C_EXCP:
2081da177e4SLinus Torvalds 		case PA83_UNIMP_EXCP:
2091da177e4SLinus Torvalds 			return(decode_0c(ir,class,subop,fpregs));
2101da177e4SLinus Torvalds 		case MAJOR_0E_EXCP:
2111da177e4SLinus Torvalds 			return(decode_0e(ir,class,subop,fpregs));
2121da177e4SLinus Torvalds 		case MAJOR_06_EXCP:
2131da177e4SLinus Torvalds 			return(decode_06(ir,fpregs));
2141da177e4SLinus Torvalds 		case MAJOR_26_EXCP:
2151da177e4SLinus Torvalds 			return(decode_26(ir,fpregs));
2161da177e4SLinus Torvalds 		case MAJOR_2E_EXCP:
2171da177e4SLinus Torvalds 			return(decode_2e(ir,fpregs));
2181da177e4SLinus Torvalds 		default:
2191da177e4SLinus Torvalds 			/* "crashme Night Gallery painting nr 2. (asm_crash.s).
2201da177e4SLinus Torvalds 			 * This was fixed for multi-user kernels, but
2211da177e4SLinus Torvalds 			 * workstation kernels had a panic here.  This allowed
2221da177e4SLinus Torvalds 			 * any arbitrary user to panic the kernel by executing
2231da177e4SLinus Torvalds 			 * setting the FP exception registers to strange values
2241da177e4SLinus Torvalds 			 * and generating an emulation trap.  The emulation and
2251da177e4SLinus Torvalds 			 * exception code must never be able to panic the
2261da177e4SLinus Torvalds 			 * kernel.
2271da177e4SLinus Torvalds 			 */
2281da177e4SLinus Torvalds 			return(UNIMPLEMENTEDEXCEPTION);
2291da177e4SLinus Torvalds 	}
2301da177e4SLinus Torvalds }
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds /*
2331da177e4SLinus Torvalds  * this routine is called by $emulation_trap to emulate a coprocessor
2341da177e4SLinus Torvalds  * instruction if one doesn't exist
2351da177e4SLinus Torvalds  */
2361da177e4SLinus Torvalds u_int
2371da177e4SLinus Torvalds emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
2381da177e4SLinus Torvalds {
2391da177e4SLinus Torvalds 	u_int class, subop, major;
2401da177e4SLinus Torvalds 	u_int fpu_type_flags;
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds 	/* All FP emulation code assumes that ints are 4-bytes in length */
2431da177e4SLinus Torvalds 	VASSERT(sizeof(int) == 4);
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds 	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds 	major = get_major(ir);
2481da177e4SLinus Torvalds 	class = get_class(ir);
2491da177e4SLinus Torvalds 	if (class == 1) {
2501da177e4SLinus Torvalds 		if  (fpu_type_flags & PA2_0_FPU_FLAG)
2511da177e4SLinus Torvalds 			subop = get_subop1_PA2_0(ir);
2521da177e4SLinus Torvalds 		else
2531da177e4SLinus Torvalds 			subop = get_subop1_PA1_1(ir);
2541da177e4SLinus Torvalds 	}
2551da177e4SLinus Torvalds 	else
2561da177e4SLinus Torvalds 		subop = get_subop(ir);
2571da177e4SLinus Torvalds 	switch (major) {
2581da177e4SLinus Torvalds 		case 0x0C:
2591da177e4SLinus Torvalds 			return(decode_0c(ir,class,subop,fpregs));
2601da177e4SLinus Torvalds 		case 0x0E:
2611da177e4SLinus Torvalds 			return(decode_0e(ir,class,subop,fpregs));
2621da177e4SLinus Torvalds 		case 0x06:
2631da177e4SLinus Torvalds 			return(decode_06(ir,fpregs));
2641da177e4SLinus Torvalds 		case 0x26:
2651da177e4SLinus Torvalds 			return(decode_26(ir,fpregs));
2661da177e4SLinus Torvalds 		case 0x2E:
2671da177e4SLinus Torvalds 			return(decode_2e(ir,fpregs));
2681da177e4SLinus Torvalds 		default:
2691da177e4SLinus Torvalds 			return(PA83_UNIMP_EXCP);
2701da177e4SLinus Torvalds 	}
2711da177e4SLinus Torvalds }
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds static u_int
2751da177e4SLinus Torvalds decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
2761da177e4SLinus Torvalds {
2771da177e4SLinus Torvalds 	u_int r1,r2,t;		/* operand register offsets */
2781da177e4SLinus Torvalds 	u_int fmt;		/* also sf for class 1 conversions */
2791da177e4SLinus Torvalds 	u_int  df;		/* for class 1 conversions */
2801da177e4SLinus Torvalds 	u_int *status;
2811da177e4SLinus Torvalds 	u_int retval, local_status;
2821da177e4SLinus Torvalds 	u_int fpu_type_flags;
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 	if (ir == COPR_INST) {
2851da177e4SLinus Torvalds 		fpregs[0] = EMULATION_VERSION << 11;
2861da177e4SLinus Torvalds 		return(NOEXCEPTION);
2871da177e4SLinus Torvalds 	}
2881da177e4SLinus Torvalds 	status = &fpregs[0];	/* fp status register */
2891da177e4SLinus Torvalds 	local_status = fpregs[0]; /* and local copy */
2901da177e4SLinus Torvalds 	r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
2911da177e4SLinus Torvalds 	if (r1 == 0)		/* map fr0 source to constant zero */
2921da177e4SLinus Torvalds 		r1 = fpzeroreg;
2931da177e4SLinus Torvalds 	t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
2941da177e4SLinus Torvalds 	if (t == 0 && class != 2)	/* don't allow fr0 as a dest */
2951da177e4SLinus Torvalds 		return(MAJOR_0C_EXCP);
2961da177e4SLinus Torvalds 	fmt = extru(ir,fpfmtpos,2);	/* get fmt completer */
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds 	switch (class) {
2991da177e4SLinus Torvalds 	    case 0:
3001da177e4SLinus Torvalds 		switch (subop) {
3011da177e4SLinus Torvalds 			case 0:	/* COPR 0,0 emulated above*/
3021da177e4SLinus Torvalds 			case 1:
3031da177e4SLinus Torvalds 				return(MAJOR_0C_EXCP);
3041da177e4SLinus Torvalds 			case 2:	/* FCPY */
3051da177e4SLinus Torvalds 				switch (fmt) {
3061da177e4SLinus Torvalds 				    case 2: /* illegal */
3071da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3081da177e4SLinus Torvalds 				    case 3: /* quad */
3091da177e4SLinus Torvalds 					t &= ~3;  /* force to even reg #s */
3101da177e4SLinus Torvalds 					r1 &= ~3;
3111da177e4SLinus Torvalds 					fpregs[t+3] = fpregs[r1+3];
3121da177e4SLinus Torvalds 					fpregs[t+2] = fpregs[r1+2];
3131da177e4SLinus Torvalds 				    case 1: /* double */
3141da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
3151da177e4SLinus Torvalds 				    case 0: /* single */
3161da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1];
3171da177e4SLinus Torvalds 					return(NOEXCEPTION);
3181da177e4SLinus Torvalds 				}
3191da177e4SLinus Torvalds 			case 3: /* FABS */
3201da177e4SLinus Torvalds 				switch (fmt) {
3211da177e4SLinus Torvalds 				    case 2: /* illegal */
3221da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3231da177e4SLinus Torvalds 				    case 3: /* quad */
3241da177e4SLinus Torvalds 					t &= ~3;  /* force to even reg #s */
3251da177e4SLinus Torvalds 					r1 &= ~3;
3261da177e4SLinus Torvalds 					fpregs[t+3] = fpregs[r1+3];
3271da177e4SLinus Torvalds 					fpregs[t+2] = fpregs[r1+2];
3281da177e4SLinus Torvalds 				    case 1: /* double */
3291da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
3301da177e4SLinus Torvalds 				    case 0: /* single */
3311da177e4SLinus Torvalds 					/* copy and clear sign bit */
3321da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] & 0x7fffffff;
3331da177e4SLinus Torvalds 					return(NOEXCEPTION);
3341da177e4SLinus Torvalds 				}
3351da177e4SLinus Torvalds 			case 6: /* FNEG */
3361da177e4SLinus Torvalds 				switch (fmt) {
3371da177e4SLinus Torvalds 				    case 2: /* illegal */
3381da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3391da177e4SLinus Torvalds 				    case 3: /* quad */
3401da177e4SLinus Torvalds 					t &= ~3;  /* force to even reg #s */
3411da177e4SLinus Torvalds 					r1 &= ~3;
3421da177e4SLinus Torvalds 					fpregs[t+3] = fpregs[r1+3];
3431da177e4SLinus Torvalds 					fpregs[t+2] = fpregs[r1+2];
3441da177e4SLinus Torvalds 				    case 1: /* double */
3451da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
3461da177e4SLinus Torvalds 				    case 0: /* single */
3471da177e4SLinus Torvalds 					/* copy and invert sign bit */
3481da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] ^ 0x80000000;
3491da177e4SLinus Torvalds 					return(NOEXCEPTION);
3501da177e4SLinus Torvalds 				}
3511da177e4SLinus Torvalds 			case 7: /* FNEGABS */
3521da177e4SLinus Torvalds 				switch (fmt) {
3531da177e4SLinus Torvalds 				    case 2: /* illegal */
3541da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3551da177e4SLinus Torvalds 				    case 3: /* quad */
3561da177e4SLinus Torvalds 					t &= ~3;  /* force to even reg #s */
3571da177e4SLinus Torvalds 					r1 &= ~3;
3581da177e4SLinus Torvalds 					fpregs[t+3] = fpregs[r1+3];
3591da177e4SLinus Torvalds 					fpregs[t+2] = fpregs[r1+2];
3601da177e4SLinus Torvalds 				    case 1: /* double */
3611da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
3621da177e4SLinus Torvalds 				    case 0: /* single */
3631da177e4SLinus Torvalds 					/* copy and set sign bit */
3641da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] | 0x80000000;
3651da177e4SLinus Torvalds 					return(NOEXCEPTION);
3661da177e4SLinus Torvalds 				}
3671da177e4SLinus Torvalds 			case 4: /* FSQRT */
3681da177e4SLinus Torvalds 				switch (fmt) {
3691da177e4SLinus Torvalds 				    case 0:
3701da177e4SLinus Torvalds 					return(sgl_fsqrt(&fpregs[r1],0,
3711da177e4SLinus Torvalds 						&fpregs[t],status));
3721da177e4SLinus Torvalds 				    case 1:
3731da177e4SLinus Torvalds 					return(dbl_fsqrt(&fpregs[r1],0,
3741da177e4SLinus Torvalds 						&fpregs[t],status));
3751da177e4SLinus Torvalds 				    case 2:
3761da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
3771da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3781da177e4SLinus Torvalds 				}
3791da177e4SLinus Torvalds 			case 5: /* FRND */
3801da177e4SLinus Torvalds 				switch (fmt) {
3811da177e4SLinus Torvalds 				    case 0:
3821da177e4SLinus Torvalds 					return(sgl_frnd(&fpregs[r1],0,
3831da177e4SLinus Torvalds 						&fpregs[t],status));
3841da177e4SLinus Torvalds 				    case 1:
3851da177e4SLinus Torvalds 					return(dbl_frnd(&fpregs[r1],0,
3861da177e4SLinus Torvalds 						&fpregs[t],status));
3871da177e4SLinus Torvalds 				    case 2:
3881da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
3891da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
3901da177e4SLinus Torvalds 				}
3911da177e4SLinus Torvalds 		} /* end of switch (subop) */
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds 	case 1: /* class 1 */
3941da177e4SLinus Torvalds 		df = extru(ir,fpdfpos,2); /* get dest format */
3951da177e4SLinus Torvalds 		if ((df & 2) || (fmt & 2)) {
3961da177e4SLinus Torvalds 			/*
3971da177e4SLinus Torvalds 			 * fmt's 2 and 3 are illegal of not implemented
3981da177e4SLinus Torvalds 			 * quad conversions
3991da177e4SLinus Torvalds 			 */
4001da177e4SLinus Torvalds 			return(MAJOR_0C_EXCP);
4011da177e4SLinus Torvalds 		}
4021da177e4SLinus Torvalds 		/*
4031da177e4SLinus Torvalds 		 * encode source and dest formats into 2 bits.
4041da177e4SLinus Torvalds 		 * high bit is source, low bit is dest.
4051da177e4SLinus Torvalds 		 * bit = 1 --> double precision
4061da177e4SLinus Torvalds 		 */
4071da177e4SLinus Torvalds 		fmt = (fmt << 1) | df;
4081da177e4SLinus Torvalds 		switch (subop) {
4091da177e4SLinus Torvalds 			case 0: /* FCNVFF */
4101da177e4SLinus Torvalds 				switch(fmt) {
4111da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4121da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
4131da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4141da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
4151da177e4SLinus Torvalds 						&fpregs[t],status));
4161da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4171da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
4181da177e4SLinus Torvalds 						&fpregs[t],status));
4191da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4201da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
4211da177e4SLinus Torvalds 				}
4221da177e4SLinus Torvalds 			case 1: /* FCNVXF */
4231da177e4SLinus Torvalds 				switch(fmt) {
4241da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4251da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
4261da177e4SLinus Torvalds 						&fpregs[t],status));
4271da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4281da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
4291da177e4SLinus Torvalds 						&fpregs[t],status));
4301da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4311da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
4321da177e4SLinus Torvalds 						&fpregs[t],status));
4331da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4341da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
4351da177e4SLinus Torvalds 						&fpregs[t],status));
4361da177e4SLinus Torvalds 				}
4371da177e4SLinus Torvalds 			case 2: /* FCNVFX */
4381da177e4SLinus Torvalds 				switch(fmt) {
4391da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4401da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
4411da177e4SLinus Torvalds 						&fpregs[t],status));
4421da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4431da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
4441da177e4SLinus Torvalds 						&fpregs[t],status));
4451da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4461da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
4471da177e4SLinus Torvalds 						&fpregs[t],status));
4481da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4491da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
4501da177e4SLinus Torvalds 						&fpregs[t],status));
4511da177e4SLinus Torvalds 				}
4521da177e4SLinus Torvalds 			case 3: /* FCNVFXT */
4531da177e4SLinus Torvalds 				switch(fmt) {
4541da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4551da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
4561da177e4SLinus Torvalds 						&fpregs[t],status));
4571da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4581da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
4591da177e4SLinus Torvalds 						&fpregs[t],status));
4601da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4611da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
4621da177e4SLinus Torvalds 						&fpregs[t],status));
4631da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4641da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
4651da177e4SLinus Torvalds 						&fpregs[t],status));
4661da177e4SLinus Torvalds 				}
4671da177e4SLinus Torvalds 			case 5: /* FCNVUF (PA2.0 only) */
4681da177e4SLinus Torvalds 				switch(fmt) {
4691da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4701da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
4711da177e4SLinus Torvalds 						&fpregs[t],status));
4721da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4731da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
4741da177e4SLinus Torvalds 						&fpregs[t],status));
4751da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4761da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
4771da177e4SLinus Torvalds 						&fpregs[t],status));
4781da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4791da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
4801da177e4SLinus Torvalds 						&fpregs[t],status));
4811da177e4SLinus Torvalds 				}
4821da177e4SLinus Torvalds 			case 6: /* FCNVFU (PA2.0 only) */
4831da177e4SLinus Torvalds 				switch(fmt) {
4841da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
4851da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
4861da177e4SLinus Torvalds 						&fpregs[t],status));
4871da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
4881da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
4891da177e4SLinus Torvalds 						&fpregs[t],status));
4901da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
4911da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
4921da177e4SLinus Torvalds 						&fpregs[t],status));
4931da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
4941da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
4951da177e4SLinus Torvalds 						&fpregs[t],status));
4961da177e4SLinus Torvalds 				}
4971da177e4SLinus Torvalds 			case 7: /* FCNVFUT (PA2.0 only) */
4981da177e4SLinus Torvalds 				switch(fmt) {
4991da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
5001da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
5011da177e4SLinus Torvalds 						&fpregs[t],status));
5021da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
5031da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
5041da177e4SLinus Torvalds 						&fpregs[t],status));
5051da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
5061da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
5071da177e4SLinus Torvalds 						&fpregs[t],status));
5081da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
5091da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
5101da177e4SLinus Torvalds 						&fpregs[t],status));
5111da177e4SLinus Torvalds 				}
5121da177e4SLinus Torvalds 			case 4: /* undefined */
5131da177e4SLinus Torvalds 				return(MAJOR_0C_EXCP);
5141da177e4SLinus Torvalds 		} /* end of switch subop */
5151da177e4SLinus Torvalds 
5161da177e4SLinus Torvalds 	case 2: /* class 2 */
5171da177e4SLinus Torvalds 		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
5181da177e4SLinus Torvalds 		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
5191da177e4SLinus Torvalds 		if (r2 == 0)
5201da177e4SLinus Torvalds 			r2 = fpzeroreg;
5211da177e4SLinus Torvalds 		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
5221da177e4SLinus Torvalds 			/* FTEST if nullify bit set, otherwise FCMP */
5231da177e4SLinus Torvalds 			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
5241da177e4SLinus Torvalds 				switch (fmt) {
5251da177e4SLinus Torvalds 				    case 0:
5261da177e4SLinus Torvalds 					/*
5271da177e4SLinus Torvalds 					 * arg0 is not used
5281da177e4SLinus Torvalds 					 * second param is the t field used for
5291da177e4SLinus Torvalds 					 * ftest,acc and ftest,rej
5301da177e4SLinus Torvalds 					 * third param is the subop (y-field)
5311da177e4SLinus Torvalds 					 */
5321da177e4SLinus Torvalds 					BUG();
5331da177e4SLinus Torvalds 					/* Unsupported
5341da177e4SLinus Torvalds 					 * return(ftest(0L,extru(ir,fptpos,5),
5351da177e4SLinus Torvalds 					 *	 &fpregs[0],subop));
5361da177e4SLinus Torvalds 					 */
5371da177e4SLinus Torvalds 				    case 1:
5381da177e4SLinus Torvalds 				    case 2:
5391da177e4SLinus Torvalds 				    case 3:
5401da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
5411da177e4SLinus Torvalds 				}
5421da177e4SLinus Torvalds 			} else {  /* FCMP */
5431da177e4SLinus Torvalds 				switch (fmt) {
5441da177e4SLinus Torvalds 				    case 0:
5451da177e4SLinus Torvalds 					retval = sgl_fcmp(&fpregs[r1],
5461da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
5471da177e4SLinus Torvalds 						&local_status);
5481da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
5491da177e4SLinus Torvalds 						fpu_type_flags, subop);
5501da177e4SLinus Torvalds 					return(retval);
5511da177e4SLinus Torvalds 				    case 1:
5521da177e4SLinus Torvalds 					retval = dbl_fcmp(&fpregs[r1],
5531da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
5541da177e4SLinus Torvalds 						&local_status);
5551da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
5561da177e4SLinus Torvalds 						fpu_type_flags, subop);
5571da177e4SLinus Torvalds 					return(retval);
5581da177e4SLinus Torvalds 				    case 2: /* illegal */
5591da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
5601da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
5611da177e4SLinus Torvalds 				}
5621da177e4SLinus Torvalds 			}
5631da177e4SLinus Torvalds 		}  /* end of if for PA2.0 */
5641da177e4SLinus Torvalds 		else {	/* PA1.0 & PA1.1 */
5651da177e4SLinus Torvalds 		    switch (subop) {
5661da177e4SLinus Torvalds 			case 2:
5671da177e4SLinus Torvalds 			case 3:
5681da177e4SLinus Torvalds 			case 4:
5691da177e4SLinus Torvalds 			case 5:
5701da177e4SLinus Torvalds 			case 6:
5711da177e4SLinus Torvalds 			case 7:
5721da177e4SLinus Torvalds 				return(MAJOR_0C_EXCP);
5731da177e4SLinus Torvalds 			case 0: /* FCMP */
5741da177e4SLinus Torvalds 				switch (fmt) {
5751da177e4SLinus Torvalds 				    case 0:
5761da177e4SLinus Torvalds 					retval = sgl_fcmp(&fpregs[r1],
5771da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
5781da177e4SLinus Torvalds 						&local_status);
5791da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
5801da177e4SLinus Torvalds 						fpu_type_flags, subop);
5811da177e4SLinus Torvalds 					return(retval);
5821da177e4SLinus Torvalds 				    case 1:
5831da177e4SLinus Torvalds 					retval = dbl_fcmp(&fpregs[r1],
5841da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
5851da177e4SLinus Torvalds 						&local_status);
5861da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
5871da177e4SLinus Torvalds 						fpu_type_flags, subop);
5881da177e4SLinus Torvalds 					return(retval);
5891da177e4SLinus Torvalds 				    case 2: /* illegal */
5901da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
5911da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
5921da177e4SLinus Torvalds 				}
5931da177e4SLinus Torvalds 			case 1: /* FTEST */
5941da177e4SLinus Torvalds 				switch (fmt) {
5951da177e4SLinus Torvalds 				    case 0:
5961da177e4SLinus Torvalds 					/*
5971da177e4SLinus Torvalds 					 * arg0 is not used
5981da177e4SLinus Torvalds 					 * second param is the t field used for
5991da177e4SLinus Torvalds 					 * ftest,acc and ftest,rej
6001da177e4SLinus Torvalds 					 * third param is the subop (y-field)
6011da177e4SLinus Torvalds 					 */
6021da177e4SLinus Torvalds 					BUG();
6031da177e4SLinus Torvalds 					/* unsupported
6041da177e4SLinus Torvalds 					 * return(ftest(0L,extru(ir,fptpos,5),
6051da177e4SLinus Torvalds 					 *     &fpregs[0],subop));
6061da177e4SLinus Torvalds 					 */
6071da177e4SLinus Torvalds 				    case 1:
6081da177e4SLinus Torvalds 				    case 2:
6091da177e4SLinus Torvalds 				    case 3:
6101da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6111da177e4SLinus Torvalds 				}
6121da177e4SLinus Torvalds 		    } /* end of switch subop */
6131da177e4SLinus Torvalds 		} /* end of else for PA1.0 & PA1.1 */
6141da177e4SLinus Torvalds 	case 3: /* class 3 */
6151da177e4SLinus Torvalds 		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
6161da177e4SLinus Torvalds 		if (r2 == 0)
6171da177e4SLinus Torvalds 			r2 = fpzeroreg;
6181da177e4SLinus Torvalds 		switch (subop) {
6191da177e4SLinus Torvalds 			case 5:
6201da177e4SLinus Torvalds 			case 6:
6211da177e4SLinus Torvalds 			case 7:
6221da177e4SLinus Torvalds 				return(MAJOR_0C_EXCP);
6231da177e4SLinus Torvalds 
6241da177e4SLinus Torvalds 			case 0: /* FADD */
6251da177e4SLinus Torvalds 				switch (fmt) {
6261da177e4SLinus Torvalds 				    case 0:
6271da177e4SLinus Torvalds 					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
6281da177e4SLinus Torvalds 						&fpregs[t],status));
6291da177e4SLinus Torvalds 				    case 1:
6301da177e4SLinus Torvalds 					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
6311da177e4SLinus Torvalds 						&fpregs[t],status));
6321da177e4SLinus Torvalds 				    case 2: /* illegal */
6331da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
6341da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6351da177e4SLinus Torvalds 				}
6361da177e4SLinus Torvalds 			case 1: /* FSUB */
6371da177e4SLinus Torvalds 				switch (fmt) {
6381da177e4SLinus Torvalds 				    case 0:
6391da177e4SLinus Torvalds 					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
6401da177e4SLinus Torvalds 						&fpregs[t],status));
6411da177e4SLinus Torvalds 				    case 1:
6421da177e4SLinus Torvalds 					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
6431da177e4SLinus Torvalds 						&fpregs[t],status));
6441da177e4SLinus Torvalds 				    case 2: /* illegal */
6451da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
6461da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6471da177e4SLinus Torvalds 				}
6481da177e4SLinus Torvalds 			case 2: /* FMPY */
6491da177e4SLinus Torvalds 				switch (fmt) {
6501da177e4SLinus Torvalds 				    case 0:
6511da177e4SLinus Torvalds 					return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
6521da177e4SLinus Torvalds 						&fpregs[t],status));
6531da177e4SLinus Torvalds 				    case 1:
6541da177e4SLinus Torvalds 					return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
6551da177e4SLinus Torvalds 						&fpregs[t],status));
6561da177e4SLinus Torvalds 				    case 2: /* illegal */
6571da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
6581da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6591da177e4SLinus Torvalds 				}
6601da177e4SLinus Torvalds 			case 3: /* FDIV */
6611da177e4SLinus Torvalds 				switch (fmt) {
6621da177e4SLinus Torvalds 				    case 0:
6631da177e4SLinus Torvalds 					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
6641da177e4SLinus Torvalds 						&fpregs[t],status));
6651da177e4SLinus Torvalds 				    case 1:
6661da177e4SLinus Torvalds 					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
6671da177e4SLinus Torvalds 						&fpregs[t],status));
6681da177e4SLinus Torvalds 				    case 2: /* illegal */
6691da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
6701da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6711da177e4SLinus Torvalds 				}
6721da177e4SLinus Torvalds 			case 4: /* FREM */
6731da177e4SLinus Torvalds 				switch (fmt) {
6741da177e4SLinus Torvalds 				    case 0:
6751da177e4SLinus Torvalds 					return(sgl_frem(&fpregs[r1],&fpregs[r2],
6761da177e4SLinus Torvalds 						&fpregs[t],status));
6771da177e4SLinus Torvalds 				    case 1:
6781da177e4SLinus Torvalds 					return(dbl_frem(&fpregs[r1],&fpregs[r2],
6791da177e4SLinus Torvalds 						&fpregs[t],status));
6801da177e4SLinus Torvalds 				    case 2: /* illegal */
6811da177e4SLinus Torvalds 				    case 3: /* quad not implemented */
6821da177e4SLinus Torvalds 					return(MAJOR_0C_EXCP);
6831da177e4SLinus Torvalds 				}
6841da177e4SLinus Torvalds 		} /* end of class 3 switch */
6851da177e4SLinus Torvalds 	} /* end of switch(class) */
6861da177e4SLinus Torvalds 
6871da177e4SLinus Torvalds 	/* If we get here, something is really wrong! */
6881da177e4SLinus Torvalds 	return(MAJOR_0C_EXCP);
6891da177e4SLinus Torvalds }
6901da177e4SLinus Torvalds 
6911da177e4SLinus Torvalds static u_int
6921da177e4SLinus Torvalds decode_0e(ir,class,subop,fpregs)
6931da177e4SLinus Torvalds u_int ir,class,subop;
6941da177e4SLinus Torvalds u_int fpregs[];
6951da177e4SLinus Torvalds {
6961da177e4SLinus Torvalds 	u_int r1,r2,t;		/* operand register offsets */
6971da177e4SLinus Torvalds 	u_int fmt;		/* also sf for class 1 conversions */
6981da177e4SLinus Torvalds 	u_int df;		/* dest format for class 1 conversions */
6991da177e4SLinus Torvalds 	u_int *status;
7001da177e4SLinus Torvalds 	u_int retval, local_status;
7011da177e4SLinus Torvalds 	u_int fpu_type_flags;
7021da177e4SLinus Torvalds 
7031da177e4SLinus Torvalds 	status = &fpregs[0];
7041da177e4SLinus Torvalds 	local_status = fpregs[0];
7051da177e4SLinus Torvalds 	r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
7061da177e4SLinus Torvalds 	if (r1 == 0)
7071da177e4SLinus Torvalds 		r1 = fpzeroreg;
7081da177e4SLinus Torvalds 	t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
7091da177e4SLinus Torvalds 	if (t == 0 && class != 2)
7101da177e4SLinus Torvalds 		return(MAJOR_0E_EXCP);
7111da177e4SLinus Torvalds 	if (class < 2)		/* class 0 or 1 has 2 bit fmt */
7121da177e4SLinus Torvalds 		fmt = extru(ir,fpfmtpos,2);
7131da177e4SLinus Torvalds 	else 			/* class 2 and 3 have 1 bit fmt */
7141da177e4SLinus Torvalds 		fmt = extru(ir,fp0efmtpos,1);
7151da177e4SLinus Torvalds 	/*
7161da177e4SLinus Torvalds 	 * An undefined combination, double precision accessing the
7171da177e4SLinus Torvalds 	 * right half of a FPR, can get us into trouble.
7181da177e4SLinus Torvalds 	 * Let's just force proper alignment on it.
7191da177e4SLinus Torvalds 	 */
7201da177e4SLinus Torvalds 	if (fmt == DBL) {
7211da177e4SLinus Torvalds 		r1 &= ~1;
7221da177e4SLinus Torvalds 		if (class != 1)
7231da177e4SLinus Torvalds 			t &= ~1;
7241da177e4SLinus Torvalds 	}
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds 	switch (class) {
7271da177e4SLinus Torvalds 	    case 0:
7281da177e4SLinus Torvalds 		switch (subop) {
7291da177e4SLinus Torvalds 			case 0: /* unimplemented */
7301da177e4SLinus Torvalds 			case 1:
7311da177e4SLinus Torvalds 				return(MAJOR_0E_EXCP);
7321da177e4SLinus Torvalds 			case 2: /* FCPY */
7331da177e4SLinus Torvalds 				switch (fmt) {
7341da177e4SLinus Torvalds 				    case 2:
7351da177e4SLinus Torvalds 				    case 3:
7361da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7371da177e4SLinus Torvalds 				    case 1: /* double */
7381da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
7391da177e4SLinus Torvalds 				    case 0: /* single */
7401da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1];
7411da177e4SLinus Torvalds 					return(NOEXCEPTION);
7421da177e4SLinus Torvalds 				}
7431da177e4SLinus Torvalds 			case 3: /* FABS */
7441da177e4SLinus Torvalds 				switch (fmt) {
7451da177e4SLinus Torvalds 				    case 2:
7461da177e4SLinus Torvalds 				    case 3:
7471da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7481da177e4SLinus Torvalds 				    case 1: /* double */
7491da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
7501da177e4SLinus Torvalds 				    case 0: /* single */
7511da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] & 0x7fffffff;
7521da177e4SLinus Torvalds 					return(NOEXCEPTION);
7531da177e4SLinus Torvalds 				}
7541da177e4SLinus Torvalds 			case 6: /* FNEG */
7551da177e4SLinus Torvalds 				switch (fmt) {
7561da177e4SLinus Torvalds 				    case 2:
7571da177e4SLinus Torvalds 				    case 3:
7581da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7591da177e4SLinus Torvalds 				    case 1: /* double */
7601da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
7611da177e4SLinus Torvalds 				    case 0: /* single */
7621da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] ^ 0x80000000;
7631da177e4SLinus Torvalds 					return(NOEXCEPTION);
7641da177e4SLinus Torvalds 				}
7651da177e4SLinus Torvalds 			case 7: /* FNEGABS */
7661da177e4SLinus Torvalds 				switch (fmt) {
7671da177e4SLinus Torvalds 				    case 2:
7681da177e4SLinus Torvalds 				    case 3:
7691da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7701da177e4SLinus Torvalds 				    case 1: /* double */
7711da177e4SLinus Torvalds 					fpregs[t+1] = fpregs[r1+1];
7721da177e4SLinus Torvalds 				    case 0: /* single */
7731da177e4SLinus Torvalds 					fpregs[t] = fpregs[r1] | 0x80000000;
7741da177e4SLinus Torvalds 					return(NOEXCEPTION);
7751da177e4SLinus Torvalds 				}
7761da177e4SLinus Torvalds 			case 4: /* FSQRT */
7771da177e4SLinus Torvalds 				switch (fmt) {
7781da177e4SLinus Torvalds 				    case 0:
7791da177e4SLinus Torvalds 					return(sgl_fsqrt(&fpregs[r1],0,
7801da177e4SLinus Torvalds 						&fpregs[t], status));
7811da177e4SLinus Torvalds 				    case 1:
7821da177e4SLinus Torvalds 					return(dbl_fsqrt(&fpregs[r1],0,
7831da177e4SLinus Torvalds 						&fpregs[t], status));
7841da177e4SLinus Torvalds 				    case 2:
7851da177e4SLinus Torvalds 				    case 3:
7861da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7871da177e4SLinus Torvalds 				}
7881da177e4SLinus Torvalds 			case 5: /* FRMD */
7891da177e4SLinus Torvalds 				switch (fmt) {
7901da177e4SLinus Torvalds 				    case 0:
7911da177e4SLinus Torvalds 					return(sgl_frnd(&fpregs[r1],0,
7921da177e4SLinus Torvalds 						&fpregs[t], status));
7931da177e4SLinus Torvalds 				    case 1:
7941da177e4SLinus Torvalds 					return(dbl_frnd(&fpregs[r1],0,
7951da177e4SLinus Torvalds 						&fpregs[t], status));
7961da177e4SLinus Torvalds 				    case 2:
7971da177e4SLinus Torvalds 				    case 3:
7981da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
7991da177e4SLinus Torvalds 				}
8001da177e4SLinus Torvalds 		} /* end of switch (subop */
8011da177e4SLinus Torvalds 
8021da177e4SLinus Torvalds 	case 1: /* class 1 */
8031da177e4SLinus Torvalds 		df = extru(ir,fpdfpos,2); /* get dest format */
8041da177e4SLinus Torvalds 		/*
8051da177e4SLinus Torvalds 		 * Fix Crashme problem (writing to 31R in double precision)
8061da177e4SLinus Torvalds 		 * here too.
8071da177e4SLinus Torvalds 		 */
8081da177e4SLinus Torvalds 		if (df == DBL) {
8091da177e4SLinus Torvalds 			t &= ~1;
8101da177e4SLinus Torvalds 		}
8111da177e4SLinus Torvalds 		if ((df & 2) || (fmt & 2))
8121da177e4SLinus Torvalds 			return(MAJOR_0E_EXCP);
8131da177e4SLinus Torvalds 
8141da177e4SLinus Torvalds 		fmt = (fmt << 1) | df;
8151da177e4SLinus Torvalds 		switch (subop) {
8161da177e4SLinus Torvalds 			case 0: /* FCNVFF */
8171da177e4SLinus Torvalds 				switch(fmt) {
8181da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8191da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
8201da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8211da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
8221da177e4SLinus Torvalds 						&fpregs[t],status));
8231da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8241da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
8251da177e4SLinus Torvalds 						&fpregs[t],status));
8261da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
8271da177e4SLinus Torvalds 					return(MAJOR_0E_EXCP);
8281da177e4SLinus Torvalds 				}
8291da177e4SLinus Torvalds 			case 1: /* FCNVXF */
8301da177e4SLinus Torvalds 				switch(fmt) {
8311da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8321da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
8331da177e4SLinus Torvalds 						&fpregs[t],status));
8341da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8351da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
8361da177e4SLinus Torvalds 						&fpregs[t],status));
8371da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8381da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
8391da177e4SLinus Torvalds 						&fpregs[t],status));
8401da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
8411da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
8421da177e4SLinus Torvalds 						&fpregs[t],status));
8431da177e4SLinus Torvalds 				}
8441da177e4SLinus Torvalds 			case 2: /* FCNVFX */
8451da177e4SLinus Torvalds 				switch(fmt) {
8461da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8471da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
8481da177e4SLinus Torvalds 						&fpregs[t],status));
8491da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8501da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
8511da177e4SLinus Torvalds 						&fpregs[t],status));
8521da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8531da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
8541da177e4SLinus Torvalds 						&fpregs[t],status));
8551da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
8561da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
8571da177e4SLinus Torvalds 						&fpregs[t],status));
8581da177e4SLinus Torvalds 				}
8591da177e4SLinus Torvalds 			case 3: /* FCNVFXT */
8601da177e4SLinus Torvalds 				switch(fmt) {
8611da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8621da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
8631da177e4SLinus Torvalds 						&fpregs[t],status));
8641da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8651da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
8661da177e4SLinus Torvalds 						&fpregs[t],status));
8671da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8681da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
8691da177e4SLinus Torvalds 						&fpregs[t],status));
8701da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
8711da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
8721da177e4SLinus Torvalds 						&fpregs[t],status));
8731da177e4SLinus Torvalds 				}
8741da177e4SLinus Torvalds 			case 5: /* FCNVUF (PA2.0 only) */
8751da177e4SLinus Torvalds 				switch(fmt) {
8761da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8771da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
8781da177e4SLinus Torvalds 						&fpregs[t],status));
8791da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8801da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
8811da177e4SLinus Torvalds 						&fpregs[t],status));
8821da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8831da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
8841da177e4SLinus Torvalds 						&fpregs[t],status));
8851da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
8861da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
8871da177e4SLinus Torvalds 						&fpregs[t],status));
8881da177e4SLinus Torvalds 				}
8891da177e4SLinus Torvalds 			case 6: /* FCNVFU (PA2.0 only) */
8901da177e4SLinus Torvalds 				switch(fmt) {
8911da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
8921da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
8931da177e4SLinus Torvalds 						&fpregs[t],status));
8941da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
8951da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
8961da177e4SLinus Torvalds 						&fpregs[t],status));
8971da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
8981da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
8991da177e4SLinus Torvalds 						&fpregs[t],status));
9001da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
9011da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
9021da177e4SLinus Torvalds 						&fpregs[t],status));
9031da177e4SLinus Torvalds 				}
9041da177e4SLinus Torvalds 			case 7: /* FCNVFUT (PA2.0 only) */
9051da177e4SLinus Torvalds 				switch(fmt) {
9061da177e4SLinus Torvalds 				    case 0: /* sgl/sgl */
9071da177e4SLinus Torvalds 					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
9081da177e4SLinus Torvalds 						&fpregs[t],status));
9091da177e4SLinus Torvalds 				    case 1: /* sgl/dbl */
9101da177e4SLinus Torvalds 					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
9111da177e4SLinus Torvalds 						&fpregs[t],status));
9121da177e4SLinus Torvalds 				    case 2: /* dbl/sgl */
9131da177e4SLinus Torvalds 					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
9141da177e4SLinus Torvalds 						&fpregs[t],status));
9151da177e4SLinus Torvalds 				    case 3: /* dbl/dbl */
9161da177e4SLinus Torvalds 					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
9171da177e4SLinus Torvalds 						&fpregs[t],status));
9181da177e4SLinus Torvalds 				}
9191da177e4SLinus Torvalds 			case 4: /* undefined */
9201da177e4SLinus Torvalds 				return(MAJOR_0C_EXCP);
9211da177e4SLinus Torvalds 		} /* end of switch subop */
9221da177e4SLinus Torvalds 	case 2: /* class 2 */
9231da177e4SLinus Torvalds 		/*
9241da177e4SLinus Torvalds 		 * Be careful out there.
9251da177e4SLinus Torvalds 		 * Crashme can generate cases where FR31R is specified
9261da177e4SLinus Torvalds 		 * as the source or target of a double precision operation.
9271da177e4SLinus Torvalds 		 * Since we just pass the address of the floating-point
9281da177e4SLinus Torvalds 		 * register to the emulation routines, this can cause
9291da177e4SLinus Torvalds 		 * corruption of fpzeroreg.
9301da177e4SLinus Torvalds 		 */
9311da177e4SLinus Torvalds 		if (fmt == DBL)
9321da177e4SLinus Torvalds 			r2 = (extru(ir,fpr2pos,5)<<1);
9331da177e4SLinus Torvalds 		else
9341da177e4SLinus Torvalds 			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
9351da177e4SLinus Torvalds 		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
9361da177e4SLinus Torvalds 		if (r2 == 0)
9371da177e4SLinus Torvalds 			r2 = fpzeroreg;
9381da177e4SLinus Torvalds 		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
9391da177e4SLinus Torvalds 			/* FTEST if nullify bit set, otherwise FCMP */
9401da177e4SLinus Torvalds 			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
9411da177e4SLinus Torvalds 				/* not legal */
9421da177e4SLinus Torvalds 				return(MAJOR_0E_EXCP);
9431da177e4SLinus Torvalds 			} else {  /* FCMP */
9441da177e4SLinus Torvalds 			switch (fmt) {
9451da177e4SLinus Torvalds 				    /*
9461da177e4SLinus Torvalds 				     * fmt is only 1 bit long
9471da177e4SLinus Torvalds 				     */
9481da177e4SLinus Torvalds 				    case 0:
9491da177e4SLinus Torvalds 					retval = sgl_fcmp(&fpregs[r1],
9501da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
9511da177e4SLinus Torvalds 						&local_status);
9521da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
9531da177e4SLinus Torvalds 						fpu_type_flags, subop);
9541da177e4SLinus Torvalds 					return(retval);
9551da177e4SLinus Torvalds 				    case 1:
9561da177e4SLinus Torvalds 					retval = dbl_fcmp(&fpregs[r1],
9571da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
9581da177e4SLinus Torvalds 						&local_status);
9591da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
9601da177e4SLinus Torvalds 						fpu_type_flags, subop);
9611da177e4SLinus Torvalds 					return(retval);
9621da177e4SLinus Torvalds 				}
9631da177e4SLinus Torvalds 			}
9641da177e4SLinus Torvalds 		}  /* end of if for PA2.0 */
9651da177e4SLinus Torvalds 		else {  /* PA1.0 & PA1.1 */
9661da177e4SLinus Torvalds 		    switch (subop) {
9671da177e4SLinus Torvalds 			case 1:
9681da177e4SLinus Torvalds 			case 2:
9691da177e4SLinus Torvalds 			case 3:
9701da177e4SLinus Torvalds 			case 4:
9711da177e4SLinus Torvalds 			case 5:
9721da177e4SLinus Torvalds 			case 6:
9731da177e4SLinus Torvalds 			case 7:
9741da177e4SLinus Torvalds 				return(MAJOR_0E_EXCP);
9751da177e4SLinus Torvalds 			case 0: /* FCMP */
9761da177e4SLinus Torvalds 				switch (fmt) {
9771da177e4SLinus Torvalds 				    /*
9781da177e4SLinus Torvalds 				     * fmt is only 1 bit long
9791da177e4SLinus Torvalds 				     */
9801da177e4SLinus Torvalds 				    case 0:
9811da177e4SLinus Torvalds 					retval = sgl_fcmp(&fpregs[r1],
9821da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
9831da177e4SLinus Torvalds 						&local_status);
9841da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
9851da177e4SLinus Torvalds 						fpu_type_flags, subop);
9861da177e4SLinus Torvalds 					return(retval);
9871da177e4SLinus Torvalds 				    case 1:
9881da177e4SLinus Torvalds 					retval = dbl_fcmp(&fpregs[r1],
9891da177e4SLinus Torvalds 						&fpregs[r2],extru(ir,fptpos,5),
9901da177e4SLinus Torvalds 						&local_status);
9911da177e4SLinus Torvalds 					update_status_cbit(status,local_status,
9921da177e4SLinus Torvalds 						fpu_type_flags, subop);
9931da177e4SLinus Torvalds 					return(retval);
9941da177e4SLinus Torvalds 				}
9951da177e4SLinus Torvalds 		    } /* end of switch subop */
9961da177e4SLinus Torvalds 		} /* end of else for PA1.0 & PA1.1 */
9971da177e4SLinus Torvalds 	case 3: /* class 3 */
9981da177e4SLinus Torvalds 		/*
9991da177e4SLinus Torvalds 		 * Be careful out there.
10001da177e4SLinus Torvalds 		 * Crashme can generate cases where FR31R is specified
10011da177e4SLinus Torvalds 		 * as the source or target of a double precision operation.
10021da177e4SLinus Torvalds 		 * Since we just pass the address of the floating-point
10031da177e4SLinus Torvalds 		 * register to the emulation routines, this can cause
10041da177e4SLinus Torvalds 		 * corruption of fpzeroreg.
10051da177e4SLinus Torvalds 		 */
10061da177e4SLinus Torvalds 		if (fmt == DBL)
10071da177e4SLinus Torvalds 			r2 = (extru(ir,fpr2pos,5)<<1);
10081da177e4SLinus Torvalds 		else
10091da177e4SLinus Torvalds 			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
10101da177e4SLinus Torvalds 		if (r2 == 0)
10111da177e4SLinus Torvalds 			r2 = fpzeroreg;
10121da177e4SLinus Torvalds 		switch (subop) {
10131da177e4SLinus Torvalds 			case 5:
10141da177e4SLinus Torvalds 			case 6:
10151da177e4SLinus Torvalds 			case 7:
10161da177e4SLinus Torvalds 				return(MAJOR_0E_EXCP);
10171da177e4SLinus Torvalds 
10181da177e4SLinus Torvalds 			/*
10191da177e4SLinus Torvalds 			 * Note that fmt is only 1 bit for class 3 */
10201da177e4SLinus Torvalds 			case 0: /* FADD */
10211da177e4SLinus Torvalds 				switch (fmt) {
10221da177e4SLinus Torvalds 				    case 0:
10231da177e4SLinus Torvalds 					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
10241da177e4SLinus Torvalds 						&fpregs[t],status));
10251da177e4SLinus Torvalds 				    case 1:
10261da177e4SLinus Torvalds 					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
10271da177e4SLinus Torvalds 						&fpregs[t],status));
10281da177e4SLinus Torvalds 				}
10291da177e4SLinus Torvalds 			case 1: /* FSUB */
10301da177e4SLinus Torvalds 				switch (fmt) {
10311da177e4SLinus Torvalds 				    case 0:
10321da177e4SLinus Torvalds 					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
10331da177e4SLinus Torvalds 						&fpregs[t],status));
10341da177e4SLinus Torvalds 				    case 1:
10351da177e4SLinus Torvalds 					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
10361da177e4SLinus Torvalds 						&fpregs[t],status));
10371da177e4SLinus Torvalds 				}
10381da177e4SLinus Torvalds 			case 2: /* FMPY or XMPYU */
10391da177e4SLinus Torvalds 				/*
10401da177e4SLinus Torvalds 				 * check for integer multiply (x bit set)
10411da177e4SLinus Torvalds 				 */
10421da177e4SLinus Torvalds 				if (extru(ir,fpxpos,1)) {
10431da177e4SLinus Torvalds 				    /*
10441da177e4SLinus Torvalds 				     * emulate XMPYU
10451da177e4SLinus Torvalds 				     */
10461da177e4SLinus Torvalds 				    switch (fmt) {
10471da177e4SLinus Torvalds 					case 0:
10481da177e4SLinus Torvalds 					    /*
10491da177e4SLinus Torvalds 					     * bad instruction if t specifies
10501da177e4SLinus Torvalds 					     * the right half of a register
10511da177e4SLinus Torvalds 					     */
10521da177e4SLinus Torvalds 					    if (t & 1)
10531da177e4SLinus Torvalds 						return(MAJOR_0E_EXCP);
10541da177e4SLinus Torvalds 					    BUG();
10551da177e4SLinus Torvalds 					    /* unsupported
10561da177e4SLinus Torvalds 					     * impyu(&fpregs[r1],&fpregs[r2],
10571da177e4SLinus Torvalds 						 * &fpregs[t]);
10581da177e4SLinus Torvalds 					     */
10591da177e4SLinus Torvalds 					    return(NOEXCEPTION);
10601da177e4SLinus Torvalds 					case 1:
10611da177e4SLinus Torvalds 						return(MAJOR_0E_EXCP);
10621da177e4SLinus Torvalds 				    }
10631da177e4SLinus Torvalds 				}
10641da177e4SLinus Torvalds 				else { /* FMPY */
10651da177e4SLinus Torvalds 				    switch (fmt) {
10661da177e4SLinus Torvalds 				        case 0:
10671da177e4SLinus Torvalds 					    return(sgl_fmpy(&fpregs[r1],
10681da177e4SLinus Torvalds 					       &fpregs[r2],&fpregs[t],status));
10691da177e4SLinus Torvalds 				        case 1:
10701da177e4SLinus Torvalds 					    return(dbl_fmpy(&fpregs[r1],
10711da177e4SLinus Torvalds 					       &fpregs[r2],&fpregs[t],status));
10721da177e4SLinus Torvalds 				    }
10731da177e4SLinus Torvalds 				}
10741da177e4SLinus Torvalds 			case 3: /* FDIV */
10751da177e4SLinus Torvalds 				switch (fmt) {
10761da177e4SLinus Torvalds 				    case 0:
10771da177e4SLinus Torvalds 					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
10781da177e4SLinus Torvalds 						&fpregs[t],status));
10791da177e4SLinus Torvalds 				    case 1:
10801da177e4SLinus Torvalds 					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
10811da177e4SLinus Torvalds 						&fpregs[t],status));
10821da177e4SLinus Torvalds 				}
10831da177e4SLinus Torvalds 			case 4: /* FREM */
10841da177e4SLinus Torvalds 				switch (fmt) {
10851da177e4SLinus Torvalds 				    case 0:
10861da177e4SLinus Torvalds 					return(sgl_frem(&fpregs[r1],&fpregs[r2],
10871da177e4SLinus Torvalds 						&fpregs[t],status));
10881da177e4SLinus Torvalds 				    case 1:
10891da177e4SLinus Torvalds 					return(dbl_frem(&fpregs[r1],&fpregs[r2],
10901da177e4SLinus Torvalds 						&fpregs[t],status));
10911da177e4SLinus Torvalds 				}
10921da177e4SLinus Torvalds 		} /* end of class 3 switch */
10931da177e4SLinus Torvalds 	} /* end of switch(class) */
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds 	/* If we get here, something is really wrong! */
10961da177e4SLinus Torvalds 	return(MAJOR_0E_EXCP);
10971da177e4SLinus Torvalds }
10981da177e4SLinus Torvalds 
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds /*
11011da177e4SLinus Torvalds  * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
11021da177e4SLinus Torvalds  */
11031da177e4SLinus Torvalds static u_int
11041da177e4SLinus Torvalds decode_06(ir,fpregs)
11051da177e4SLinus Torvalds u_int ir;
11061da177e4SLinus Torvalds u_int fpregs[];
11071da177e4SLinus Torvalds {
11081da177e4SLinus Torvalds 	u_int rm1, rm2, tm, ra, ta; /* operands */
11091da177e4SLinus Torvalds 	u_int fmt;
11101da177e4SLinus Torvalds 	u_int error = 0;
11111da177e4SLinus Torvalds 	u_int status;
11121da177e4SLinus Torvalds 	u_int fpu_type_flags;
11131da177e4SLinus Torvalds 	union {
11141da177e4SLinus Torvalds 		double dbl;
11151da177e4SLinus Torvalds 		float flt;
11161da177e4SLinus Torvalds 		struct { u_int i1; u_int i2; } ints;
11171da177e4SLinus Torvalds 	} mtmp, atmp;
11181da177e4SLinus Torvalds 
11191da177e4SLinus Torvalds 
11201da177e4SLinus Torvalds 	status = fpregs[0];		/* use a local copy of status reg */
11211da177e4SLinus Torvalds 	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
11221da177e4SLinus Torvalds 	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
11231da177e4SLinus Torvalds 	if (fmt == 0) { /* DBL */
11241da177e4SLinus Torvalds 		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
11251da177e4SLinus Torvalds 		if (rm1 == 0)
11261da177e4SLinus Torvalds 			rm1 = fpzeroreg;
11271da177e4SLinus Torvalds 		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
11281da177e4SLinus Torvalds 		if (rm2 == 0)
11291da177e4SLinus Torvalds 			rm2 = fpzeroreg;
11301da177e4SLinus Torvalds 		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
11311da177e4SLinus Torvalds 		if (tm == 0)
11321da177e4SLinus Torvalds 			return(MAJOR_06_EXCP);
11331da177e4SLinus Torvalds 		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
11341da177e4SLinus Torvalds 		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
11351da177e4SLinus Torvalds 		if (ta == 0)
11361da177e4SLinus Torvalds 			return(MAJOR_06_EXCP);
11371da177e4SLinus Torvalds 
11381da177e4SLinus Torvalds 		if  (fpu_type_flags & TIMEX_ROLEX_FPU_MASK)  {
11391da177e4SLinus Torvalds 
11401da177e4SLinus Torvalds 			if (ra == 0) {
11411da177e4SLinus Torvalds 			 	/* special case FMPYCFXT, see sgl case below */
11421da177e4SLinus Torvalds 				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
11431da177e4SLinus Torvalds 					&mtmp.ints.i1,&status))
11441da177e4SLinus Torvalds 					error = 1;
11451da177e4SLinus Torvalds 				if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
11461da177e4SLinus Torvalds 					&atmp.ints.i1,&atmp.ints.i1,&status))
11471da177e4SLinus Torvalds 					error = 1;
11481da177e4SLinus Torvalds 				}
11491da177e4SLinus Torvalds 			else {
11501da177e4SLinus Torvalds 
11511da177e4SLinus Torvalds 			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
11521da177e4SLinus Torvalds 					&status))
11531da177e4SLinus Torvalds 				error = 1;
11541da177e4SLinus Torvalds 			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
11551da177e4SLinus Torvalds 					&status))
11561da177e4SLinus Torvalds 				error = 1;
11571da177e4SLinus Torvalds 				}
11581da177e4SLinus Torvalds 			}
11591da177e4SLinus Torvalds 
11601da177e4SLinus Torvalds 		else
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds 			{
11631da177e4SLinus Torvalds 			if (ra == 0)
11641da177e4SLinus Torvalds 				ra = fpzeroreg;
11651da177e4SLinus Torvalds 
11661da177e4SLinus Torvalds 			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
11671da177e4SLinus Torvalds 					&status))
11681da177e4SLinus Torvalds 				error = 1;
11691da177e4SLinus Torvalds 			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
11701da177e4SLinus Torvalds 					&status))
11711da177e4SLinus Torvalds 				error = 1;
11721da177e4SLinus Torvalds 
11731da177e4SLinus Torvalds 			}
11741da177e4SLinus Torvalds 
11751da177e4SLinus Torvalds 		if (error)
11761da177e4SLinus Torvalds 			return(MAJOR_06_EXCP);
11771da177e4SLinus Torvalds 		else {
11781da177e4SLinus Torvalds 			/* copy results */
11791da177e4SLinus Torvalds 			fpregs[tm] = mtmp.ints.i1;
11801da177e4SLinus Torvalds 			fpregs[tm+1] = mtmp.ints.i2;
11811da177e4SLinus Torvalds 			fpregs[ta] = atmp.ints.i1;
11821da177e4SLinus Torvalds 			fpregs[ta+1] = atmp.ints.i2;
11831da177e4SLinus Torvalds 			fpregs[0] = status;
11841da177e4SLinus Torvalds 			return(NOEXCEPTION);
11851da177e4SLinus Torvalds 		}
11861da177e4SLinus Torvalds 	}
11871da177e4SLinus Torvalds 	else { /* SGL */
11881da177e4SLinus Torvalds 		/*
11891da177e4SLinus Torvalds 		 * calculate offsets for single precision numbers
11901da177e4SLinus Torvalds 		 * See table 6-14 in PA-89 architecture for mapping
11911da177e4SLinus Torvalds 		 */
11921da177e4SLinus Torvalds 		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
11931da177e4SLinus Torvalds 		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
11941da177e4SLinus Torvalds 
11951da177e4SLinus Torvalds 		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
11961da177e4SLinus Torvalds 		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
11991da177e4SLinus Torvalds 		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
12001da177e4SLinus Torvalds 
12011da177e4SLinus Torvalds 		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
12021da177e4SLinus Torvalds 		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
12031da177e4SLinus Torvalds 
12041da177e4SLinus Torvalds 		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
12051da177e4SLinus Torvalds 		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
12061da177e4SLinus Torvalds 
12071da177e4SLinus Torvalds 		if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
12081da177e4SLinus Torvalds 			/* special case FMPYCFXT (really 0)
12091da177e4SLinus Torvalds 			  * This instruction is only present on the Timex and
12101da177e4SLinus Torvalds 			  * Rolex fpu's in so if it is the special case and
12111da177e4SLinus Torvalds 			  * one of these fpu's we run the FMPYCFXT instruction
12121da177e4SLinus Torvalds 			  */
12131da177e4SLinus Torvalds 			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12141da177e4SLinus Torvalds 					&status))
12151da177e4SLinus Torvalds 				error = 1;
12161da177e4SLinus Torvalds 			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
12171da177e4SLinus Torvalds 				&atmp.ints.i1,&status))
12181da177e4SLinus Torvalds 				error = 1;
12191da177e4SLinus Torvalds 		}
12201da177e4SLinus Torvalds 		else {
12211da177e4SLinus Torvalds 			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
12221da177e4SLinus Torvalds 					&status))
12231da177e4SLinus Torvalds 				error = 1;
12241da177e4SLinus Torvalds 			if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
12251da177e4SLinus Torvalds 					&status))
12261da177e4SLinus Torvalds 				error = 1;
12271da177e4SLinus Torvalds 		}
12281da177e4SLinus Torvalds 		if (error)
12291da177e4SLinus Torvalds 			return(MAJOR_06_EXCP);
12301da177e4SLinus Torvalds 		else {
12311da177e4SLinus Torvalds 			/* copy results */
12321da177e4SLinus Torvalds 			fpregs[tm] = mtmp.ints.i1;
12331da177e4SLinus Torvalds 			fpregs[ta] = atmp.ints.i1;
12341da177e4SLinus Torvalds 			fpregs[0] = status;
12351da177e4SLinus Torvalds 			return(NOEXCEPTION);
12361da177e4SLinus Torvalds 		}
12371da177e4SLinus Torvalds 	}
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds /*
12411da177e4SLinus Torvalds  * routine to decode the 26 (FMPYSUB) instruction
12421da177e4SLinus Torvalds  */
12431da177e4SLinus Torvalds static u_int
12441da177e4SLinus Torvalds decode_26(ir,fpregs)
12451da177e4SLinus Torvalds u_int ir;
12461da177e4SLinus Torvalds u_int fpregs[];
12471da177e4SLinus Torvalds {
12481da177e4SLinus Torvalds 	u_int rm1, rm2, tm, ra, ta; /* operands */
12491da177e4SLinus Torvalds 	u_int fmt;
12501da177e4SLinus Torvalds 	u_int error = 0;
12511da177e4SLinus Torvalds 	u_int status;
12521da177e4SLinus Torvalds 	union {
12531da177e4SLinus Torvalds 		double dbl;
12541da177e4SLinus Torvalds 		float flt;
12551da177e4SLinus Torvalds 		struct { u_int i1; u_int i2; } ints;
12561da177e4SLinus Torvalds 	} mtmp, atmp;
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 
12591da177e4SLinus Torvalds 	status = fpregs[0];
12601da177e4SLinus Torvalds 	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
12611da177e4SLinus Torvalds 	if (fmt == 0) { /* DBL */
12621da177e4SLinus Torvalds 		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
12631da177e4SLinus Torvalds 		if (rm1 == 0)
12641da177e4SLinus Torvalds 			rm1 = fpzeroreg;
12651da177e4SLinus Torvalds 		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
12661da177e4SLinus Torvalds 		if (rm2 == 0)
12671da177e4SLinus Torvalds 			rm2 = fpzeroreg;
12681da177e4SLinus Torvalds 		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
12691da177e4SLinus Torvalds 		if (tm == 0)
12701da177e4SLinus Torvalds 			return(MAJOR_26_EXCP);
12711da177e4SLinus Torvalds 		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
12721da177e4SLinus Torvalds 		if (ra == 0)
12731da177e4SLinus Torvalds 			return(MAJOR_26_EXCP);
12741da177e4SLinus Torvalds 		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
12751da177e4SLinus Torvalds 		if (ta == 0)
12761da177e4SLinus Torvalds 			return(MAJOR_26_EXCP);
12771da177e4SLinus Torvalds 
12781da177e4SLinus Torvalds 		if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
12791da177e4SLinus Torvalds 			error = 1;
12801da177e4SLinus Torvalds 		if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
12811da177e4SLinus Torvalds 			error = 1;
12821da177e4SLinus Torvalds 		if (error)
12831da177e4SLinus Torvalds 			return(MAJOR_26_EXCP);
12841da177e4SLinus Torvalds 		else {
12851da177e4SLinus Torvalds 			/* copy results */
12861da177e4SLinus Torvalds 			fpregs[tm] = mtmp.ints.i1;
12871da177e4SLinus Torvalds 			fpregs[tm+1] = mtmp.ints.i2;
12881da177e4SLinus Torvalds 			fpregs[ta] = atmp.ints.i1;
12891da177e4SLinus Torvalds 			fpregs[ta+1] = atmp.ints.i2;
12901da177e4SLinus Torvalds 			fpregs[0] = status;
12911da177e4SLinus Torvalds 			return(NOEXCEPTION);
12921da177e4SLinus Torvalds 		}
12931da177e4SLinus Torvalds 	}
12941da177e4SLinus Torvalds 	else { /* SGL */
12951da177e4SLinus Torvalds 		/*
12961da177e4SLinus Torvalds 		 * calculate offsets for single precision numbers
12971da177e4SLinus Torvalds 		 * See table 6-14 in PA-89 architecture for mapping
12981da177e4SLinus Torvalds 		 */
12991da177e4SLinus Torvalds 		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
13001da177e4SLinus Torvalds 		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
13011da177e4SLinus Torvalds 
13021da177e4SLinus Torvalds 		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
13031da177e4SLinus Torvalds 		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
13041da177e4SLinus Torvalds 
13051da177e4SLinus Torvalds 		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
13061da177e4SLinus Torvalds 		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
13071da177e4SLinus Torvalds 
13081da177e4SLinus Torvalds 		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
13091da177e4SLinus Torvalds 		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds 		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
13121da177e4SLinus Torvalds 		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
13131da177e4SLinus Torvalds 
13141da177e4SLinus Torvalds 		if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
13151da177e4SLinus Torvalds 			error = 1;
13161da177e4SLinus Torvalds 		if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
13171da177e4SLinus Torvalds 			error = 1;
13181da177e4SLinus Torvalds 		if (error)
13191da177e4SLinus Torvalds 			return(MAJOR_26_EXCP);
13201da177e4SLinus Torvalds 		else {
13211da177e4SLinus Torvalds 			/* copy results */
13221da177e4SLinus Torvalds 			fpregs[tm] = mtmp.ints.i1;
13231da177e4SLinus Torvalds 			fpregs[ta] = atmp.ints.i1;
13241da177e4SLinus Torvalds 			fpregs[0] = status;
13251da177e4SLinus Torvalds 			return(NOEXCEPTION);
13261da177e4SLinus Torvalds 		}
13271da177e4SLinus Torvalds 	}
13281da177e4SLinus Torvalds 
13291da177e4SLinus Torvalds }
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds /*
13321da177e4SLinus Torvalds  * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
13331da177e4SLinus Torvalds  */
13341da177e4SLinus Torvalds static u_int
13351da177e4SLinus Torvalds decode_2e(ir,fpregs)
13361da177e4SLinus Torvalds u_int ir;
13371da177e4SLinus Torvalds u_int fpregs[];
13381da177e4SLinus Torvalds {
13391da177e4SLinus Torvalds 	u_int rm1, rm2, ra, t; /* operands */
13401da177e4SLinus Torvalds 	u_int fmt;
13411da177e4SLinus Torvalds 
13421da177e4SLinus Torvalds 	fmt = extru(ir,fpfmtpos,1);	/* get fmt completer */
13431da177e4SLinus Torvalds 	if (fmt == DBL) { /* DBL */
13441da177e4SLinus Torvalds 		rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
13451da177e4SLinus Torvalds 		if (rm1 == 0)
13461da177e4SLinus Torvalds 			rm1 = fpzeroreg;
13471da177e4SLinus Torvalds 		rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
13481da177e4SLinus Torvalds 		if (rm2 == 0)
13491da177e4SLinus Torvalds 			rm2 = fpzeroreg;
13501da177e4SLinus Torvalds 		ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
13511da177e4SLinus Torvalds 		     sizeof(double)/sizeof(u_int);
13521da177e4SLinus Torvalds 		if (ra == 0)
13531da177e4SLinus Torvalds 			ra = fpzeroreg;
13541da177e4SLinus Torvalds 		t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
13551da177e4SLinus Torvalds 		if (t == 0)
13561da177e4SLinus Torvalds 			return(MAJOR_2E_EXCP);
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
13591da177e4SLinus Torvalds 			return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
13601da177e4SLinus Torvalds 					&fpregs[ra], &fpregs[0], &fpregs[t]));
13611da177e4SLinus Torvalds 		} else {
13621da177e4SLinus Torvalds 			return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
13631da177e4SLinus Torvalds 					&fpregs[ra], &fpregs[0], &fpregs[t]));
13641da177e4SLinus Torvalds 		}
13651da177e4SLinus Torvalds 	} /* end DBL */
13661da177e4SLinus Torvalds 	else { /* SGL */
13671da177e4SLinus Torvalds 		rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
13681da177e4SLinus Torvalds 		if (rm1 == 0)
13691da177e4SLinus Torvalds 			rm1 = fpzeroreg;
13701da177e4SLinus Torvalds 		rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
13711da177e4SLinus Torvalds 		if (rm2 == 0)
13721da177e4SLinus Torvalds 			rm2 = fpzeroreg;
13731da177e4SLinus Torvalds 		ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
13741da177e4SLinus Torvalds 		if (ra == 0)
13751da177e4SLinus Torvalds 			ra = fpzeroreg;
13761da177e4SLinus Torvalds 		t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
13771da177e4SLinus Torvalds 		if (t == 0)
13781da177e4SLinus Torvalds 			return(MAJOR_2E_EXCP);
13791da177e4SLinus Torvalds 
13801da177e4SLinus Torvalds 		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
13811da177e4SLinus Torvalds 			return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
13821da177e4SLinus Torvalds 					&fpregs[ra], &fpregs[0], &fpregs[t]));
13831da177e4SLinus Torvalds 		} else {
13841da177e4SLinus Torvalds 			return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
13851da177e4SLinus Torvalds 					&fpregs[ra], &fpregs[0], &fpregs[t]));
13861da177e4SLinus Torvalds 		}
13871da177e4SLinus Torvalds 	} /* end SGL */
13881da177e4SLinus Torvalds }
13891da177e4SLinus Torvalds 
13901da177e4SLinus Torvalds /*
13911da177e4SLinus Torvalds  * update_status_cbit
13921da177e4SLinus Torvalds  *
13931da177e4SLinus Torvalds  *	This routine returns the correct FP status register value in
13941da177e4SLinus Torvalds  *	*status, based on the C-bit & V-bit returned by the FCMP
13951da177e4SLinus Torvalds  *	emulation routine in new_status.  The architecture type
13961da177e4SLinus Torvalds  *	(PA83, PA89 or PA2.0) is available in fpu_type.  The y_field
13971da177e4SLinus Torvalds  *	and the architecture type are used to determine what flavor
13981da177e4SLinus Torvalds  *	of FCMP is being emulated.
13991da177e4SLinus Torvalds  */
14001da177e4SLinus Torvalds static void
14011da177e4SLinus Torvalds update_status_cbit(status, new_status, fpu_type, y_field)
14021da177e4SLinus Torvalds u_int *status, new_status;
14031da177e4SLinus Torvalds u_int fpu_type;
14041da177e4SLinus Torvalds u_int y_field;
14051da177e4SLinus Torvalds {
14061da177e4SLinus Torvalds 	/*
14071da177e4SLinus Torvalds 	 * For PA89 FPU's which implement the Compare Queue and
14081da177e4SLinus Torvalds 	 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
14091da177e4SLinus Torvalds 	 * otherwise update the specified bit in the Compare Array.
14101da177e4SLinus Torvalds 	 * Note that the y-field will always be 0 for non-PA2.0 FPU's.
14111da177e4SLinus Torvalds 	 */
14121da177e4SLinus Torvalds 	if ((fpu_type & TIMEX_EXTEN_FLAG) ||
14131da177e4SLinus Torvalds 	    (fpu_type & ROLEX_EXTEN_FLAG) ||
14141da177e4SLinus Torvalds 	    (fpu_type & PA2_0_FPU_FLAG)) {
14151da177e4SLinus Torvalds 		if (y_field == 0) {
14161da177e4SLinus Torvalds 			*status = ((*status & 0x04000000) >> 5) | /* old Cbit */
14171da177e4SLinus Torvalds 				  ((*status & 0x003ff000) >> 1) | /* old CQ   */
14181da177e4SLinus Torvalds 				  (new_status & 0xffc007ff); /* all other bits*/
14191da177e4SLinus Torvalds 		} else {
14201da177e4SLinus Torvalds 			*status = (*status & 0x04000000) |     /* old Cbit */
14211da177e4SLinus Torvalds 				  ((new_status & 0x04000000) >> (y_field+4)) |
14221da177e4SLinus Torvalds 				  (new_status & ~0x04000000 &  /* other bits */
14231da177e4SLinus Torvalds 				   ~(0x04000000 >> (y_field+4)));
14241da177e4SLinus Torvalds 		}
14251da177e4SLinus Torvalds 	}
14261da177e4SLinus Torvalds 	/* if PA83, just update the C-bit */
14271da177e4SLinus Torvalds 	else {
14281da177e4SLinus Torvalds 		*status = new_status;
14291da177e4SLinus Torvalds 	}
14301da177e4SLinus Torvalds }
1431