162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Floating-point emulation code
662306a36Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * BEGIN_DESC
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  File:
1262306a36Sopenharmony_ci *	@(#)	pa/fp/fpudispatch.c		$Revision: 1.1 $
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  Purpose:
1562306a36Sopenharmony_ci *	<<please update with a synopsis of the functionality provided by this file>>
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *  External Interfaces:
1862306a36Sopenharmony_ci *	<<the following list was autogenerated, please review>>
1962306a36Sopenharmony_ci *	emfpudispatch(ir, dummy1, dummy2, fpregs)
2062306a36Sopenharmony_ci *	fpudispatch(ir, excp_code, holder, fpregs)
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci *  Internal Interfaces:
2362306a36Sopenharmony_ci *	<<the following list was autogenerated, please review>>
2462306a36Sopenharmony_ci *	static u_int decode_06(u_int, u_int *)
2562306a36Sopenharmony_ci *	static u_int decode_0c(u_int, u_int, u_int, u_int *)
2662306a36Sopenharmony_ci *	static u_int decode_0e(u_int, u_int, u_int, u_int *)
2762306a36Sopenharmony_ci *	static u_int decode_26(u_int, u_int *)
2862306a36Sopenharmony_ci *	static u_int decode_2e(u_int, u_int *)
2962306a36Sopenharmony_ci *	static void update_status_cbit(u_int *, u_int, u_int, u_int)
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci *  Theory:
3262306a36Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * END_DESC
3562306a36Sopenharmony_ci*/
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define FPUDEBUG 0
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "float.h"
4062306a36Sopenharmony_ci#include <linux/bug.h>
4162306a36Sopenharmony_ci#include <linux/kernel.h>
4262306a36Sopenharmony_ci#include <asm/processor.h>
4362306a36Sopenharmony_ci/* #include <sys/debug.h> */
4462306a36Sopenharmony_ci/* #include <machine/sys/mdep_private.h> */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define COPR_INST 0x30000000
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/*
4962306a36Sopenharmony_ci * definition of extru macro.  If pos and len are constants, the compiler
5062306a36Sopenharmony_ci * will generate an extru instruction when optimized
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_ci#define extru(r,pos,len)	(((r) >> (31-(pos))) & (( 1 << (len)) - 1))
5362306a36Sopenharmony_ci/* definitions of bit field locations in the instruction */
5462306a36Sopenharmony_ci#define fpmajorpos 5
5562306a36Sopenharmony_ci#define fpr1pos	10
5662306a36Sopenharmony_ci#define fpr2pos 15
5762306a36Sopenharmony_ci#define fptpos	31
5862306a36Sopenharmony_ci#define fpsubpos 18
5962306a36Sopenharmony_ci#define fpclass1subpos 16
6062306a36Sopenharmony_ci#define fpclasspos 22
6162306a36Sopenharmony_ci#define fpfmtpos 20
6262306a36Sopenharmony_ci#define fpdfpos 18
6362306a36Sopenharmony_ci#define fpnulpos 26
6462306a36Sopenharmony_ci/*
6562306a36Sopenharmony_ci * the following are the extra bits for the 0E major op
6662306a36Sopenharmony_ci */
6762306a36Sopenharmony_ci#define fpxr1pos 24
6862306a36Sopenharmony_ci#define fpxr2pos 19
6962306a36Sopenharmony_ci#define fpxtpos 25
7062306a36Sopenharmony_ci#define fpxpos 23
7162306a36Sopenharmony_ci#define fp0efmtpos 20
7262306a36Sopenharmony_ci/*
7362306a36Sopenharmony_ci * the following are for the multi-ops
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_ci#define fprm1pos 10
7662306a36Sopenharmony_ci#define fprm2pos 15
7762306a36Sopenharmony_ci#define fptmpos 31
7862306a36Sopenharmony_ci#define fprapos 25
7962306a36Sopenharmony_ci#define fptapos 20
8062306a36Sopenharmony_ci#define fpmultifmt 26
8162306a36Sopenharmony_ci/*
8262306a36Sopenharmony_ci * the following are for the fused FP instructions
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_ci     /* fprm1pos 10 */
8562306a36Sopenharmony_ci     /* fprm2pos 15 */
8662306a36Sopenharmony_ci#define fpraupos 18
8762306a36Sopenharmony_ci#define fpxrm2pos 19
8862306a36Sopenharmony_ci     /* fpfmtpos 20 */
8962306a36Sopenharmony_ci#define fpralpos 23
9062306a36Sopenharmony_ci#define fpxrm1pos 24
9162306a36Sopenharmony_ci     /* fpxtpos 25 */
9262306a36Sopenharmony_ci#define fpfusedsubop 26
9362306a36Sopenharmony_ci     /* fptpos	31 */
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * offset to constant zero in the FP emulation registers
9762306a36Sopenharmony_ci */
9862306a36Sopenharmony_ci#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/*
10162306a36Sopenharmony_ci * extract the major opcode from the instruction
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_ci#define get_major(op) extru(op,fpmajorpos,6)
10462306a36Sopenharmony_ci/*
10562306a36Sopenharmony_ci * extract the two bit class field from the FP instruction. The class is at bit
10662306a36Sopenharmony_ci * positions 21-22
10762306a36Sopenharmony_ci */
10862306a36Sopenharmony_ci#define get_class(op) extru(op,fpclasspos,2)
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * extract the 3 bit subop field.  For all but class 1 instructions, it is
11162306a36Sopenharmony_ci * located at bit positions 16-18
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_ci#define get_subop(op) extru(op,fpsubpos,3)
11462306a36Sopenharmony_ci/*
11562306a36Sopenharmony_ci * extract the 2 or 3 bit subop field from class 1 instructions.  It is located
11662306a36Sopenharmony_ci * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_ci#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2)	/* PA89 (1.1) fmt */
11962306a36Sopenharmony_ci#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3)	/* PA 2.0 fmt */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* definitions of unimplemented exceptions */
12262306a36Sopenharmony_ci#define MAJOR_0C_EXCP	0x09
12362306a36Sopenharmony_ci#define MAJOR_0E_EXCP	0x0b
12462306a36Sopenharmony_ci#define MAJOR_06_EXCP	0x03
12562306a36Sopenharmony_ci#define MAJOR_26_EXCP	0x23
12662306a36Sopenharmony_ci#define MAJOR_2E_EXCP	0x2b
12762306a36Sopenharmony_ci#define PA83_UNIMP_EXCP	0x01
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci * Special Defines for TIMEX specific code
13162306a36Sopenharmony_ci */
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
13462306a36Sopenharmony_ci#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/*
13762306a36Sopenharmony_ci * Static function definitions
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_ci#define _PROTOTYPES
14062306a36Sopenharmony_ci#if defined(_PROTOTYPES) || defined(_lint)
14162306a36Sopenharmony_cistatic u_int decode_0c(u_int, u_int, u_int, u_int *);
14262306a36Sopenharmony_cistatic u_int decode_0e(u_int, u_int, u_int, u_int *);
14362306a36Sopenharmony_cistatic u_int decode_06(u_int, u_int *);
14462306a36Sopenharmony_cistatic u_int decode_26(u_int, u_int *);
14562306a36Sopenharmony_cistatic u_int decode_2e(u_int, u_int *);
14662306a36Sopenharmony_cistatic void update_status_cbit(u_int *, u_int, u_int, u_int);
14762306a36Sopenharmony_ci#else /* !_PROTOTYPES&&!_lint */
14862306a36Sopenharmony_cistatic u_int decode_0c();
14962306a36Sopenharmony_cistatic u_int decode_0e();
15062306a36Sopenharmony_cistatic u_int decode_06();
15162306a36Sopenharmony_cistatic u_int decode_26();
15262306a36Sopenharmony_cistatic u_int decode_2e();
15362306a36Sopenharmony_cistatic void update_status_cbit();
15462306a36Sopenharmony_ci#endif /* _PROTOTYPES&&!_lint */
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci#define VASSERT(x)
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic void parisc_linux_get_fpu_type(u_int fpregs[])
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	/* on pa-linux the fpu type is not filled in by the
16162306a36Sopenharmony_ci	 * caller; it is constructed here
16262306a36Sopenharmony_ci	 */
16362306a36Sopenharmony_ci	if (boot_cpu_data.cpu_type == pcxs)
16462306a36Sopenharmony_ci		fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
16562306a36Sopenharmony_ci	else if (boot_cpu_data.cpu_type == pcxt ||
16662306a36Sopenharmony_ci	         boot_cpu_data.cpu_type == pcxt_)
16762306a36Sopenharmony_ci		fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
16862306a36Sopenharmony_ci	else if (boot_cpu_data.cpu_type >= pcxu)
16962306a36Sopenharmony_ci		fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci * this routine will decode the excepting floating point instruction and
17462306a36Sopenharmony_ci * call the appropriate emulation routine.
17562306a36Sopenharmony_ci * It is called by decode_fpu with the following parameters:
17662306a36Sopenharmony_ci * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
17762306a36Sopenharmony_ci * where current_ir is the instruction to be emulated,
17862306a36Sopenharmony_ci * unimplemented_code is the exception_code that the hardware generated
17962306a36Sopenharmony_ci * and &Fpu_register is the address of emulated FP reg 0.
18062306a36Sopenharmony_ci */
18162306a36Sopenharmony_ciu_int
18262306a36Sopenharmony_cifpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	u_int class, subop;
18562306a36Sopenharmony_ci	u_int fpu_type_flags;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* All FP emulation code assumes that ints are 4-bytes in length */
18862306a36Sopenharmony_ci	VASSERT(sizeof(int) == 4);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	parisc_linux_get_fpu_type(fpregs);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	class = get_class(ir);
19562306a36Sopenharmony_ci	if (class == 1) {
19662306a36Sopenharmony_ci		if  (fpu_type_flags & PA2_0_FPU_FLAG)
19762306a36Sopenharmony_ci			subop = get_subop1_PA2_0(ir);
19862306a36Sopenharmony_ci		else
19962306a36Sopenharmony_ci			subop = get_subop1_PA1_1(ir);
20062306a36Sopenharmony_ci	}
20162306a36Sopenharmony_ci	else
20262306a36Sopenharmony_ci		subop = get_subop(ir);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	switch (excp_code) {
20762306a36Sopenharmony_ci		case MAJOR_0C_EXCP:
20862306a36Sopenharmony_ci		case PA83_UNIMP_EXCP:
20962306a36Sopenharmony_ci			return(decode_0c(ir,class,subop,fpregs));
21062306a36Sopenharmony_ci		case MAJOR_0E_EXCP:
21162306a36Sopenharmony_ci			return(decode_0e(ir,class,subop,fpregs));
21262306a36Sopenharmony_ci		case MAJOR_06_EXCP:
21362306a36Sopenharmony_ci			return(decode_06(ir,fpregs));
21462306a36Sopenharmony_ci		case MAJOR_26_EXCP:
21562306a36Sopenharmony_ci			return(decode_26(ir,fpregs));
21662306a36Sopenharmony_ci		case MAJOR_2E_EXCP:
21762306a36Sopenharmony_ci			return(decode_2e(ir,fpregs));
21862306a36Sopenharmony_ci		default:
21962306a36Sopenharmony_ci			/* "crashme Night Gallery painting nr 2. (asm_crash.s).
22062306a36Sopenharmony_ci			 * This was fixed for multi-user kernels, but
22162306a36Sopenharmony_ci			 * workstation kernels had a panic here.  This allowed
22262306a36Sopenharmony_ci			 * any arbitrary user to panic the kernel by executing
22362306a36Sopenharmony_ci			 * setting the FP exception registers to strange values
22462306a36Sopenharmony_ci			 * and generating an emulation trap.  The emulation and
22562306a36Sopenharmony_ci			 * exception code must never be able to panic the
22662306a36Sopenharmony_ci			 * kernel.
22762306a36Sopenharmony_ci			 */
22862306a36Sopenharmony_ci			return(UNIMPLEMENTEDEXCEPTION);
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/*
23362306a36Sopenharmony_ci * this routine is called by $emulation_trap to emulate a coprocessor
23462306a36Sopenharmony_ci * instruction if one doesn't exist
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_ciu_int
23762306a36Sopenharmony_ciemfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	u_int class, subop, major;
24062306a36Sopenharmony_ci	u_int fpu_type_flags;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	/* All FP emulation code assumes that ints are 4-bytes in length */
24362306a36Sopenharmony_ci	VASSERT(sizeof(int) == 4);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	major = get_major(ir);
24862306a36Sopenharmony_ci	class = get_class(ir);
24962306a36Sopenharmony_ci	if (class == 1) {
25062306a36Sopenharmony_ci		if  (fpu_type_flags & PA2_0_FPU_FLAG)
25162306a36Sopenharmony_ci			subop = get_subop1_PA2_0(ir);
25262306a36Sopenharmony_ci		else
25362306a36Sopenharmony_ci			subop = get_subop1_PA1_1(ir);
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci	else
25662306a36Sopenharmony_ci		subop = get_subop(ir);
25762306a36Sopenharmony_ci	switch (major) {
25862306a36Sopenharmony_ci		case 0x0C:
25962306a36Sopenharmony_ci			return(decode_0c(ir,class,subop,fpregs));
26062306a36Sopenharmony_ci		case 0x0E:
26162306a36Sopenharmony_ci			return(decode_0e(ir,class,subop,fpregs));
26262306a36Sopenharmony_ci		case 0x06:
26362306a36Sopenharmony_ci			return(decode_06(ir,fpregs));
26462306a36Sopenharmony_ci		case 0x26:
26562306a36Sopenharmony_ci			return(decode_26(ir,fpregs));
26662306a36Sopenharmony_ci		case 0x2E:
26762306a36Sopenharmony_ci			return(decode_2e(ir,fpregs));
26862306a36Sopenharmony_ci		default:
26962306a36Sopenharmony_ci			return(PA83_UNIMP_EXCP);
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic u_int
27562306a36Sopenharmony_cidecode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	u_int r1,r2,t;		/* operand register offsets */
27862306a36Sopenharmony_ci	u_int fmt;		/* also sf for class 1 conversions */
27962306a36Sopenharmony_ci	u_int  df;		/* for class 1 conversions */
28062306a36Sopenharmony_ci	u_int *status;
28162306a36Sopenharmony_ci	u_int retval, local_status;
28262306a36Sopenharmony_ci	u_int fpu_type_flags;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	if (ir == COPR_INST) {
28562306a36Sopenharmony_ci		fpregs[0] = EMULATION_VERSION << 11;
28662306a36Sopenharmony_ci		return(NOEXCEPTION);
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	status = &fpregs[0];	/* fp status register */
28962306a36Sopenharmony_ci	local_status = fpregs[0]; /* and local copy */
29062306a36Sopenharmony_ci	r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
29162306a36Sopenharmony_ci	if (r1 == 0)		/* map fr0 source to constant zero */
29262306a36Sopenharmony_ci		r1 = fpzeroreg;
29362306a36Sopenharmony_ci	t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
29462306a36Sopenharmony_ci	if (t == 0 && class != 2)	/* don't allow fr0 as a dest */
29562306a36Sopenharmony_ci		return(MAJOR_0C_EXCP);
29662306a36Sopenharmony_ci	fmt = extru(ir,fpfmtpos,2);	/* get fmt completer */
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	switch (class) {
29962306a36Sopenharmony_ci	    case 0:
30062306a36Sopenharmony_ci		switch (subop) {
30162306a36Sopenharmony_ci			case 0:	/* COPR 0,0 emulated above*/
30262306a36Sopenharmony_ci			case 1:
30362306a36Sopenharmony_ci				return(MAJOR_0C_EXCP);
30462306a36Sopenharmony_ci			case 2:	/* FCPY */
30562306a36Sopenharmony_ci				switch (fmt) {
30662306a36Sopenharmony_ci				    case 2: /* illegal */
30762306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
30862306a36Sopenharmony_ci				    case 3: /* quad */
30962306a36Sopenharmony_ci					t &= ~3;  /* force to even reg #s */
31062306a36Sopenharmony_ci					r1 &= ~3;
31162306a36Sopenharmony_ci					fpregs[t+3] = fpregs[r1+3];
31262306a36Sopenharmony_ci					fpregs[t+2] = fpregs[r1+2];
31362306a36Sopenharmony_ci					fallthrough;
31462306a36Sopenharmony_ci				    case 1: /* double */
31562306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
31662306a36Sopenharmony_ci					fallthrough;
31762306a36Sopenharmony_ci				    case 0: /* single */
31862306a36Sopenharmony_ci					fpregs[t] = fpregs[r1];
31962306a36Sopenharmony_ci					return(NOEXCEPTION);
32062306a36Sopenharmony_ci				}
32162306a36Sopenharmony_ci				BUG();
32262306a36Sopenharmony_ci			case 3: /* FABS */
32362306a36Sopenharmony_ci				switch (fmt) {
32462306a36Sopenharmony_ci				    case 2: /* illegal */
32562306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
32662306a36Sopenharmony_ci				    case 3: /* quad */
32762306a36Sopenharmony_ci					t &= ~3;  /* force to even reg #s */
32862306a36Sopenharmony_ci					r1 &= ~3;
32962306a36Sopenharmony_ci					fpregs[t+3] = fpregs[r1+3];
33062306a36Sopenharmony_ci					fpregs[t+2] = fpregs[r1+2];
33162306a36Sopenharmony_ci					fallthrough;
33262306a36Sopenharmony_ci				    case 1: /* double */
33362306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
33462306a36Sopenharmony_ci					fallthrough;
33562306a36Sopenharmony_ci				    case 0: /* single */
33662306a36Sopenharmony_ci					/* copy and clear sign bit */
33762306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] & 0x7fffffff;
33862306a36Sopenharmony_ci					return(NOEXCEPTION);
33962306a36Sopenharmony_ci				}
34062306a36Sopenharmony_ci				BUG();
34162306a36Sopenharmony_ci			case 6: /* FNEG */
34262306a36Sopenharmony_ci				switch (fmt) {
34362306a36Sopenharmony_ci				    case 2: /* illegal */
34462306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
34562306a36Sopenharmony_ci				    case 3: /* quad */
34662306a36Sopenharmony_ci					t &= ~3;  /* force to even reg #s */
34762306a36Sopenharmony_ci					r1 &= ~3;
34862306a36Sopenharmony_ci					fpregs[t+3] = fpregs[r1+3];
34962306a36Sopenharmony_ci					fpregs[t+2] = fpregs[r1+2];
35062306a36Sopenharmony_ci					fallthrough;
35162306a36Sopenharmony_ci				    case 1: /* double */
35262306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
35362306a36Sopenharmony_ci					fallthrough;
35462306a36Sopenharmony_ci				    case 0: /* single */
35562306a36Sopenharmony_ci					/* copy and invert sign bit */
35662306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] ^ 0x80000000;
35762306a36Sopenharmony_ci					return(NOEXCEPTION);
35862306a36Sopenharmony_ci				}
35962306a36Sopenharmony_ci				BUG();
36062306a36Sopenharmony_ci			case 7: /* FNEGABS */
36162306a36Sopenharmony_ci				switch (fmt) {
36262306a36Sopenharmony_ci				    case 2: /* illegal */
36362306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
36462306a36Sopenharmony_ci				    case 3: /* quad */
36562306a36Sopenharmony_ci					t &= ~3;  /* force to even reg #s */
36662306a36Sopenharmony_ci					r1 &= ~3;
36762306a36Sopenharmony_ci					fpregs[t+3] = fpregs[r1+3];
36862306a36Sopenharmony_ci					fpregs[t+2] = fpregs[r1+2];
36962306a36Sopenharmony_ci					fallthrough;
37062306a36Sopenharmony_ci				    case 1: /* double */
37162306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
37262306a36Sopenharmony_ci					fallthrough;
37362306a36Sopenharmony_ci				    case 0: /* single */
37462306a36Sopenharmony_ci					/* copy and set sign bit */
37562306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] | 0x80000000;
37662306a36Sopenharmony_ci					return(NOEXCEPTION);
37762306a36Sopenharmony_ci				}
37862306a36Sopenharmony_ci				BUG();
37962306a36Sopenharmony_ci			case 4: /* FSQRT */
38062306a36Sopenharmony_ci				switch (fmt) {
38162306a36Sopenharmony_ci				    case 0:
38262306a36Sopenharmony_ci					return(sgl_fsqrt(&fpregs[r1],0,
38362306a36Sopenharmony_ci						&fpregs[t],status));
38462306a36Sopenharmony_ci				    case 1:
38562306a36Sopenharmony_ci					return(dbl_fsqrt(&fpregs[r1],0,
38662306a36Sopenharmony_ci						&fpregs[t],status));
38762306a36Sopenharmony_ci				    case 2:
38862306a36Sopenharmony_ci				    case 3: /* quad not implemented */
38962306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
39062306a36Sopenharmony_ci				}
39162306a36Sopenharmony_ci				BUG();
39262306a36Sopenharmony_ci			case 5: /* FRND */
39362306a36Sopenharmony_ci				switch (fmt) {
39462306a36Sopenharmony_ci				    case 0:
39562306a36Sopenharmony_ci					return(sgl_frnd(&fpregs[r1],0,
39662306a36Sopenharmony_ci						&fpregs[t],status));
39762306a36Sopenharmony_ci				    case 1:
39862306a36Sopenharmony_ci					return(dbl_frnd(&fpregs[r1],0,
39962306a36Sopenharmony_ci						&fpregs[t],status));
40062306a36Sopenharmony_ci				    case 2:
40162306a36Sopenharmony_ci				    case 3: /* quad not implemented */
40262306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
40362306a36Sopenharmony_ci				}
40462306a36Sopenharmony_ci		} /* end of switch (subop) */
40562306a36Sopenharmony_ci		BUG();
40662306a36Sopenharmony_ci	case 1: /* class 1 */
40762306a36Sopenharmony_ci		df = extru(ir,fpdfpos,2); /* get dest format */
40862306a36Sopenharmony_ci		if ((df & 2) || (fmt & 2)) {
40962306a36Sopenharmony_ci			/*
41062306a36Sopenharmony_ci			 * fmt's 2 and 3 are illegal of not implemented
41162306a36Sopenharmony_ci			 * quad conversions
41262306a36Sopenharmony_ci			 */
41362306a36Sopenharmony_ci			return(MAJOR_0C_EXCP);
41462306a36Sopenharmony_ci		}
41562306a36Sopenharmony_ci		/*
41662306a36Sopenharmony_ci		 * encode source and dest formats into 2 bits.
41762306a36Sopenharmony_ci		 * high bit is source, low bit is dest.
41862306a36Sopenharmony_ci		 * bit = 1 --> double precision
41962306a36Sopenharmony_ci		 */
42062306a36Sopenharmony_ci		fmt = (fmt << 1) | df;
42162306a36Sopenharmony_ci		switch (subop) {
42262306a36Sopenharmony_ci			case 0: /* FCNVFF */
42362306a36Sopenharmony_ci				switch(fmt) {
42462306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
42562306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
42662306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
42762306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
42862306a36Sopenharmony_ci						&fpregs[t],status));
42962306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
43062306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
43162306a36Sopenharmony_ci						&fpregs[t],status));
43262306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
43362306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
43462306a36Sopenharmony_ci				}
43562306a36Sopenharmony_ci				BUG();
43662306a36Sopenharmony_ci			case 1: /* FCNVXF */
43762306a36Sopenharmony_ci				switch(fmt) {
43862306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
43962306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
44062306a36Sopenharmony_ci						&fpregs[t],status));
44162306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
44262306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
44362306a36Sopenharmony_ci						&fpregs[t],status));
44462306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
44562306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
44662306a36Sopenharmony_ci						&fpregs[t],status));
44762306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
44862306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
44962306a36Sopenharmony_ci						&fpregs[t],status));
45062306a36Sopenharmony_ci				}
45162306a36Sopenharmony_ci				BUG();
45262306a36Sopenharmony_ci			case 2: /* FCNVFX */
45362306a36Sopenharmony_ci				switch(fmt) {
45462306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
45562306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
45662306a36Sopenharmony_ci						&fpregs[t],status));
45762306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
45862306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
45962306a36Sopenharmony_ci						&fpregs[t],status));
46062306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
46162306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
46262306a36Sopenharmony_ci						&fpregs[t],status));
46362306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
46462306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
46562306a36Sopenharmony_ci						&fpregs[t],status));
46662306a36Sopenharmony_ci				}
46762306a36Sopenharmony_ci				BUG();
46862306a36Sopenharmony_ci			case 3: /* FCNVFXT */
46962306a36Sopenharmony_ci				switch(fmt) {
47062306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
47162306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
47262306a36Sopenharmony_ci						&fpregs[t],status));
47362306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
47462306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
47562306a36Sopenharmony_ci						&fpregs[t],status));
47662306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
47762306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
47862306a36Sopenharmony_ci						&fpregs[t],status));
47962306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
48062306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
48162306a36Sopenharmony_ci						&fpregs[t],status));
48262306a36Sopenharmony_ci				}
48362306a36Sopenharmony_ci				BUG();
48462306a36Sopenharmony_ci			case 5: /* FCNVUF (PA2.0 only) */
48562306a36Sopenharmony_ci				switch(fmt) {
48662306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
48762306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
48862306a36Sopenharmony_ci						&fpregs[t],status));
48962306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
49062306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
49162306a36Sopenharmony_ci						&fpregs[t],status));
49262306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
49362306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
49462306a36Sopenharmony_ci						&fpregs[t],status));
49562306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
49662306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
49762306a36Sopenharmony_ci						&fpregs[t],status));
49862306a36Sopenharmony_ci				}
49962306a36Sopenharmony_ci				BUG();
50062306a36Sopenharmony_ci			case 6: /* FCNVFU (PA2.0 only) */
50162306a36Sopenharmony_ci				switch(fmt) {
50262306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
50362306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
50462306a36Sopenharmony_ci						&fpregs[t],status));
50562306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
50662306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
50762306a36Sopenharmony_ci						&fpregs[t],status));
50862306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
50962306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
51062306a36Sopenharmony_ci						&fpregs[t],status));
51162306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
51262306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
51362306a36Sopenharmony_ci						&fpregs[t],status));
51462306a36Sopenharmony_ci				}
51562306a36Sopenharmony_ci				BUG();
51662306a36Sopenharmony_ci			case 7: /* FCNVFUT (PA2.0 only) */
51762306a36Sopenharmony_ci				switch(fmt) {
51862306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
51962306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
52062306a36Sopenharmony_ci						&fpregs[t],status));
52162306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
52262306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
52362306a36Sopenharmony_ci						&fpregs[t],status));
52462306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
52562306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
52662306a36Sopenharmony_ci						&fpregs[t],status));
52762306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
52862306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
52962306a36Sopenharmony_ci						&fpregs[t],status));
53062306a36Sopenharmony_ci				}
53162306a36Sopenharmony_ci				BUG();
53262306a36Sopenharmony_ci			case 4: /* undefined */
53362306a36Sopenharmony_ci				return(MAJOR_0C_EXCP);
53462306a36Sopenharmony_ci		} /* end of switch subop */
53562306a36Sopenharmony_ci		BUG();
53662306a36Sopenharmony_ci	case 2: /* class 2 */
53762306a36Sopenharmony_ci		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
53862306a36Sopenharmony_ci		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
53962306a36Sopenharmony_ci		if (r2 == 0)
54062306a36Sopenharmony_ci			r2 = fpzeroreg;
54162306a36Sopenharmony_ci		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
54262306a36Sopenharmony_ci			/* FTEST if nullify bit set, otherwise FCMP */
54362306a36Sopenharmony_ci			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
54462306a36Sopenharmony_ci				switch (fmt) {
54562306a36Sopenharmony_ci				    case 0:
54662306a36Sopenharmony_ci					/*
54762306a36Sopenharmony_ci					 * arg0 is not used
54862306a36Sopenharmony_ci					 * second param is the t field used for
54962306a36Sopenharmony_ci					 * ftest,acc and ftest,rej
55062306a36Sopenharmony_ci					 * third param is the subop (y-field)
55162306a36Sopenharmony_ci					 */
55262306a36Sopenharmony_ci					BUG();
55362306a36Sopenharmony_ci					/* Unsupported
55462306a36Sopenharmony_ci					 * return(ftest(0L,extru(ir,fptpos,5),
55562306a36Sopenharmony_ci					 *	 &fpregs[0],subop));
55662306a36Sopenharmony_ci					 */
55762306a36Sopenharmony_ci				    case 1:
55862306a36Sopenharmony_ci				    case 2:
55962306a36Sopenharmony_ci				    case 3:
56062306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
56162306a36Sopenharmony_ci				}
56262306a36Sopenharmony_ci			} else {  /* FCMP */
56362306a36Sopenharmony_ci				switch (fmt) {
56462306a36Sopenharmony_ci				    case 0:
56562306a36Sopenharmony_ci					retval = sgl_fcmp(&fpregs[r1],
56662306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
56762306a36Sopenharmony_ci						&local_status);
56862306a36Sopenharmony_ci					update_status_cbit(status,local_status,
56962306a36Sopenharmony_ci						fpu_type_flags, subop);
57062306a36Sopenharmony_ci					return(retval);
57162306a36Sopenharmony_ci				    case 1:
57262306a36Sopenharmony_ci					retval = dbl_fcmp(&fpregs[r1],
57362306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
57462306a36Sopenharmony_ci						&local_status);
57562306a36Sopenharmony_ci					update_status_cbit(status,local_status,
57662306a36Sopenharmony_ci						fpu_type_flags, subop);
57762306a36Sopenharmony_ci					return(retval);
57862306a36Sopenharmony_ci				    case 2: /* illegal */
57962306a36Sopenharmony_ci				    case 3: /* quad not implemented */
58062306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
58162306a36Sopenharmony_ci				}
58262306a36Sopenharmony_ci			}
58362306a36Sopenharmony_ci		}  /* end of if for PA2.0 */
58462306a36Sopenharmony_ci		else {	/* PA1.0 & PA1.1 */
58562306a36Sopenharmony_ci		    switch (subop) {
58662306a36Sopenharmony_ci			case 2:
58762306a36Sopenharmony_ci			case 3:
58862306a36Sopenharmony_ci			case 4:
58962306a36Sopenharmony_ci			case 5:
59062306a36Sopenharmony_ci			case 6:
59162306a36Sopenharmony_ci			case 7:
59262306a36Sopenharmony_ci				return(MAJOR_0C_EXCP);
59362306a36Sopenharmony_ci			case 0: /* FCMP */
59462306a36Sopenharmony_ci				switch (fmt) {
59562306a36Sopenharmony_ci				    case 0:
59662306a36Sopenharmony_ci					retval = sgl_fcmp(&fpregs[r1],
59762306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
59862306a36Sopenharmony_ci						&local_status);
59962306a36Sopenharmony_ci					update_status_cbit(status,local_status,
60062306a36Sopenharmony_ci						fpu_type_flags, subop);
60162306a36Sopenharmony_ci					return(retval);
60262306a36Sopenharmony_ci				    case 1:
60362306a36Sopenharmony_ci					retval = dbl_fcmp(&fpregs[r1],
60462306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
60562306a36Sopenharmony_ci						&local_status);
60662306a36Sopenharmony_ci					update_status_cbit(status,local_status,
60762306a36Sopenharmony_ci						fpu_type_flags, subop);
60862306a36Sopenharmony_ci					return(retval);
60962306a36Sopenharmony_ci				    case 2: /* illegal */
61062306a36Sopenharmony_ci				    case 3: /* quad not implemented */
61162306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
61262306a36Sopenharmony_ci				}
61362306a36Sopenharmony_ci				BUG();
61462306a36Sopenharmony_ci			case 1: /* FTEST */
61562306a36Sopenharmony_ci				switch (fmt) {
61662306a36Sopenharmony_ci				    case 0:
61762306a36Sopenharmony_ci					/*
61862306a36Sopenharmony_ci					 * arg0 is not used
61962306a36Sopenharmony_ci					 * second param is the t field used for
62062306a36Sopenharmony_ci					 * ftest,acc and ftest,rej
62162306a36Sopenharmony_ci					 * third param is the subop (y-field)
62262306a36Sopenharmony_ci					 */
62362306a36Sopenharmony_ci					BUG();
62462306a36Sopenharmony_ci					/* unsupported
62562306a36Sopenharmony_ci					 * return(ftest(0L,extru(ir,fptpos,5),
62662306a36Sopenharmony_ci					 *     &fpregs[0],subop));
62762306a36Sopenharmony_ci					 */
62862306a36Sopenharmony_ci				    case 1:
62962306a36Sopenharmony_ci				    case 2:
63062306a36Sopenharmony_ci				    case 3:
63162306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
63262306a36Sopenharmony_ci				}
63362306a36Sopenharmony_ci				BUG();
63462306a36Sopenharmony_ci		    } /* end of switch subop */
63562306a36Sopenharmony_ci		} /* end of else for PA1.0 & PA1.1 */
63662306a36Sopenharmony_ci		BUG();
63762306a36Sopenharmony_ci	case 3: /* class 3 */
63862306a36Sopenharmony_ci		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
63962306a36Sopenharmony_ci		if (r2 == 0)
64062306a36Sopenharmony_ci			r2 = fpzeroreg;
64162306a36Sopenharmony_ci		switch (subop) {
64262306a36Sopenharmony_ci			case 5:
64362306a36Sopenharmony_ci			case 6:
64462306a36Sopenharmony_ci			case 7:
64562306a36Sopenharmony_ci				return(MAJOR_0C_EXCP);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci			case 0: /* FADD */
64862306a36Sopenharmony_ci				switch (fmt) {
64962306a36Sopenharmony_ci				    case 0:
65062306a36Sopenharmony_ci					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
65162306a36Sopenharmony_ci						&fpregs[t],status));
65262306a36Sopenharmony_ci				    case 1:
65362306a36Sopenharmony_ci					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
65462306a36Sopenharmony_ci						&fpregs[t],status));
65562306a36Sopenharmony_ci				    case 2: /* illegal */
65662306a36Sopenharmony_ci				    case 3: /* quad not implemented */
65762306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
65862306a36Sopenharmony_ci				}
65962306a36Sopenharmony_ci				BUG();
66062306a36Sopenharmony_ci			case 1: /* FSUB */
66162306a36Sopenharmony_ci				switch (fmt) {
66262306a36Sopenharmony_ci				    case 0:
66362306a36Sopenharmony_ci					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
66462306a36Sopenharmony_ci						&fpregs[t],status));
66562306a36Sopenharmony_ci				    case 1:
66662306a36Sopenharmony_ci					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
66762306a36Sopenharmony_ci						&fpregs[t],status));
66862306a36Sopenharmony_ci				    case 2: /* illegal */
66962306a36Sopenharmony_ci				    case 3: /* quad not implemented */
67062306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
67162306a36Sopenharmony_ci				}
67262306a36Sopenharmony_ci				BUG();
67362306a36Sopenharmony_ci			case 2: /* FMPY */
67462306a36Sopenharmony_ci				switch (fmt) {
67562306a36Sopenharmony_ci				    case 0:
67662306a36Sopenharmony_ci					return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
67762306a36Sopenharmony_ci						&fpregs[t],status));
67862306a36Sopenharmony_ci				    case 1:
67962306a36Sopenharmony_ci					return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
68062306a36Sopenharmony_ci						&fpregs[t],status));
68162306a36Sopenharmony_ci				    case 2: /* illegal */
68262306a36Sopenharmony_ci				    case 3: /* quad not implemented */
68362306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
68462306a36Sopenharmony_ci				}
68562306a36Sopenharmony_ci				BUG();
68662306a36Sopenharmony_ci			case 3: /* FDIV */
68762306a36Sopenharmony_ci				switch (fmt) {
68862306a36Sopenharmony_ci				    case 0:
68962306a36Sopenharmony_ci					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
69062306a36Sopenharmony_ci						&fpregs[t],status));
69162306a36Sopenharmony_ci				    case 1:
69262306a36Sopenharmony_ci					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
69362306a36Sopenharmony_ci						&fpregs[t],status));
69462306a36Sopenharmony_ci				    case 2: /* illegal */
69562306a36Sopenharmony_ci				    case 3: /* quad not implemented */
69662306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
69762306a36Sopenharmony_ci				}
69862306a36Sopenharmony_ci				BUG();
69962306a36Sopenharmony_ci			case 4: /* FREM */
70062306a36Sopenharmony_ci				switch (fmt) {
70162306a36Sopenharmony_ci				    case 0:
70262306a36Sopenharmony_ci					return(sgl_frem(&fpregs[r1],&fpregs[r2],
70362306a36Sopenharmony_ci						&fpregs[t],status));
70462306a36Sopenharmony_ci				    case 1:
70562306a36Sopenharmony_ci					return(dbl_frem(&fpregs[r1],&fpregs[r2],
70662306a36Sopenharmony_ci						&fpregs[t],status));
70762306a36Sopenharmony_ci				    case 2: /* illegal */
70862306a36Sopenharmony_ci				    case 3: /* quad not implemented */
70962306a36Sopenharmony_ci					return(MAJOR_0C_EXCP);
71062306a36Sopenharmony_ci				}
71162306a36Sopenharmony_ci				BUG();
71262306a36Sopenharmony_ci		} /* end of class 3 switch */
71362306a36Sopenharmony_ci	} /* end of switch(class) */
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* If we get here, something is really wrong! */
71662306a36Sopenharmony_ci	return(MAJOR_0C_EXCP);
71762306a36Sopenharmony_ci}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_cistatic u_int
72062306a36Sopenharmony_cidecode_0e(ir,class,subop,fpregs)
72162306a36Sopenharmony_ciu_int ir,class,subop;
72262306a36Sopenharmony_ciu_int fpregs[];
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	u_int r1,r2,t;		/* operand register offsets */
72562306a36Sopenharmony_ci	u_int fmt;		/* also sf for class 1 conversions */
72662306a36Sopenharmony_ci	u_int df;		/* dest format for class 1 conversions */
72762306a36Sopenharmony_ci	u_int *status;
72862306a36Sopenharmony_ci	u_int retval, local_status;
72962306a36Sopenharmony_ci	u_int fpu_type_flags;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	status = &fpregs[0];
73262306a36Sopenharmony_ci	local_status = fpregs[0];
73362306a36Sopenharmony_ci	r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
73462306a36Sopenharmony_ci	if (r1 == 0)
73562306a36Sopenharmony_ci		r1 = fpzeroreg;
73662306a36Sopenharmony_ci	t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
73762306a36Sopenharmony_ci	if (t == 0 && class != 2)
73862306a36Sopenharmony_ci		return(MAJOR_0E_EXCP);
73962306a36Sopenharmony_ci	if (class < 2)		/* class 0 or 1 has 2 bit fmt */
74062306a36Sopenharmony_ci		fmt = extru(ir,fpfmtpos,2);
74162306a36Sopenharmony_ci	else 			/* class 2 and 3 have 1 bit fmt */
74262306a36Sopenharmony_ci		fmt = extru(ir,fp0efmtpos,1);
74362306a36Sopenharmony_ci	/*
74462306a36Sopenharmony_ci	 * An undefined combination, double precision accessing the
74562306a36Sopenharmony_ci	 * right half of a FPR, can get us into trouble.
74662306a36Sopenharmony_ci	 * Let's just force proper alignment on it.
74762306a36Sopenharmony_ci	 */
74862306a36Sopenharmony_ci	if (fmt == DBL) {
74962306a36Sopenharmony_ci		r1 &= ~1;
75062306a36Sopenharmony_ci		if (class != 1)
75162306a36Sopenharmony_ci			t &= ~1;
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	switch (class) {
75562306a36Sopenharmony_ci	    case 0:
75662306a36Sopenharmony_ci		switch (subop) {
75762306a36Sopenharmony_ci			case 0: /* unimplemented */
75862306a36Sopenharmony_ci			case 1:
75962306a36Sopenharmony_ci				return(MAJOR_0E_EXCP);
76062306a36Sopenharmony_ci			case 2: /* FCPY */
76162306a36Sopenharmony_ci				switch (fmt) {
76262306a36Sopenharmony_ci				    case 2:
76362306a36Sopenharmony_ci				    case 3:
76462306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
76562306a36Sopenharmony_ci				    case 1: /* double */
76662306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
76762306a36Sopenharmony_ci					fallthrough;
76862306a36Sopenharmony_ci				    case 0: /* single */
76962306a36Sopenharmony_ci					fpregs[t] = fpregs[r1];
77062306a36Sopenharmony_ci					return(NOEXCEPTION);
77162306a36Sopenharmony_ci				}
77262306a36Sopenharmony_ci				BUG();
77362306a36Sopenharmony_ci			case 3: /* FABS */
77462306a36Sopenharmony_ci				switch (fmt) {
77562306a36Sopenharmony_ci				    case 2:
77662306a36Sopenharmony_ci				    case 3:
77762306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
77862306a36Sopenharmony_ci				    case 1: /* double */
77962306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
78062306a36Sopenharmony_ci					fallthrough;
78162306a36Sopenharmony_ci				    case 0: /* single */
78262306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] & 0x7fffffff;
78362306a36Sopenharmony_ci					return(NOEXCEPTION);
78462306a36Sopenharmony_ci				}
78562306a36Sopenharmony_ci				BUG();
78662306a36Sopenharmony_ci			case 6: /* FNEG */
78762306a36Sopenharmony_ci				switch (fmt) {
78862306a36Sopenharmony_ci				    case 2:
78962306a36Sopenharmony_ci				    case 3:
79062306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
79162306a36Sopenharmony_ci				    case 1: /* double */
79262306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
79362306a36Sopenharmony_ci					fallthrough;
79462306a36Sopenharmony_ci				    case 0: /* single */
79562306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] ^ 0x80000000;
79662306a36Sopenharmony_ci					return(NOEXCEPTION);
79762306a36Sopenharmony_ci				}
79862306a36Sopenharmony_ci				BUG();
79962306a36Sopenharmony_ci			case 7: /* FNEGABS */
80062306a36Sopenharmony_ci				switch (fmt) {
80162306a36Sopenharmony_ci				    case 2:
80262306a36Sopenharmony_ci				    case 3:
80362306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
80462306a36Sopenharmony_ci				    case 1: /* double */
80562306a36Sopenharmony_ci					fpregs[t+1] = fpregs[r1+1];
80662306a36Sopenharmony_ci					fallthrough;
80762306a36Sopenharmony_ci				    case 0: /* single */
80862306a36Sopenharmony_ci					fpregs[t] = fpregs[r1] | 0x80000000;
80962306a36Sopenharmony_ci					return(NOEXCEPTION);
81062306a36Sopenharmony_ci				}
81162306a36Sopenharmony_ci				BUG();
81262306a36Sopenharmony_ci			case 4: /* FSQRT */
81362306a36Sopenharmony_ci				switch (fmt) {
81462306a36Sopenharmony_ci				    case 0:
81562306a36Sopenharmony_ci					return(sgl_fsqrt(&fpregs[r1],0,
81662306a36Sopenharmony_ci						&fpregs[t], status));
81762306a36Sopenharmony_ci				    case 1:
81862306a36Sopenharmony_ci					return(dbl_fsqrt(&fpregs[r1],0,
81962306a36Sopenharmony_ci						&fpregs[t], status));
82062306a36Sopenharmony_ci				    case 2:
82162306a36Sopenharmony_ci				    case 3:
82262306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
82362306a36Sopenharmony_ci				}
82462306a36Sopenharmony_ci				BUG();
82562306a36Sopenharmony_ci			case 5: /* FRMD */
82662306a36Sopenharmony_ci				switch (fmt) {
82762306a36Sopenharmony_ci				    case 0:
82862306a36Sopenharmony_ci					return(sgl_frnd(&fpregs[r1],0,
82962306a36Sopenharmony_ci						&fpregs[t], status));
83062306a36Sopenharmony_ci				    case 1:
83162306a36Sopenharmony_ci					return(dbl_frnd(&fpregs[r1],0,
83262306a36Sopenharmony_ci						&fpregs[t], status));
83362306a36Sopenharmony_ci				    case 2:
83462306a36Sopenharmony_ci				    case 3:
83562306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
83662306a36Sopenharmony_ci				}
83762306a36Sopenharmony_ci		} /* end of switch (subop */
83862306a36Sopenharmony_ci		BUG();
83962306a36Sopenharmony_ci	case 1: /* class 1 */
84062306a36Sopenharmony_ci		df = extru(ir,fpdfpos,2); /* get dest format */
84162306a36Sopenharmony_ci		/*
84262306a36Sopenharmony_ci		 * Fix Crashme problem (writing to 31R in double precision)
84362306a36Sopenharmony_ci		 * here too.
84462306a36Sopenharmony_ci		 */
84562306a36Sopenharmony_ci		if (df == DBL) {
84662306a36Sopenharmony_ci			t &= ~1;
84762306a36Sopenharmony_ci		}
84862306a36Sopenharmony_ci		if ((df & 2) || (fmt & 2))
84962306a36Sopenharmony_ci			return(MAJOR_0E_EXCP);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci		fmt = (fmt << 1) | df;
85262306a36Sopenharmony_ci		switch (subop) {
85362306a36Sopenharmony_ci			case 0: /* FCNVFF */
85462306a36Sopenharmony_ci				switch(fmt) {
85562306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
85662306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
85762306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
85862306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
85962306a36Sopenharmony_ci						&fpregs[t],status));
86062306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
86162306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
86262306a36Sopenharmony_ci						&fpregs[t],status));
86362306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
86462306a36Sopenharmony_ci					return(MAJOR_0E_EXCP);
86562306a36Sopenharmony_ci				}
86662306a36Sopenharmony_ci				BUG();
86762306a36Sopenharmony_ci			case 1: /* FCNVXF */
86862306a36Sopenharmony_ci				switch(fmt) {
86962306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
87062306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
87162306a36Sopenharmony_ci						&fpregs[t],status));
87262306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
87362306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
87462306a36Sopenharmony_ci						&fpregs[t],status));
87562306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
87662306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
87762306a36Sopenharmony_ci						&fpregs[t],status));
87862306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
87962306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
88062306a36Sopenharmony_ci						&fpregs[t],status));
88162306a36Sopenharmony_ci				}
88262306a36Sopenharmony_ci				BUG();
88362306a36Sopenharmony_ci			case 2: /* FCNVFX */
88462306a36Sopenharmony_ci				switch(fmt) {
88562306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
88662306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
88762306a36Sopenharmony_ci						&fpregs[t],status));
88862306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
88962306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
89062306a36Sopenharmony_ci						&fpregs[t],status));
89162306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
89262306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
89362306a36Sopenharmony_ci						&fpregs[t],status));
89462306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
89562306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
89662306a36Sopenharmony_ci						&fpregs[t],status));
89762306a36Sopenharmony_ci				}
89862306a36Sopenharmony_ci				BUG();
89962306a36Sopenharmony_ci			case 3: /* FCNVFXT */
90062306a36Sopenharmony_ci				switch(fmt) {
90162306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
90262306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
90362306a36Sopenharmony_ci						&fpregs[t],status));
90462306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
90562306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
90662306a36Sopenharmony_ci						&fpregs[t],status));
90762306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
90862306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
90962306a36Sopenharmony_ci						&fpregs[t],status));
91062306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
91162306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
91262306a36Sopenharmony_ci						&fpregs[t],status));
91362306a36Sopenharmony_ci				}
91462306a36Sopenharmony_ci				BUG();
91562306a36Sopenharmony_ci			case 5: /* FCNVUF (PA2.0 only) */
91662306a36Sopenharmony_ci				switch(fmt) {
91762306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
91862306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
91962306a36Sopenharmony_ci						&fpregs[t],status));
92062306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
92162306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
92262306a36Sopenharmony_ci						&fpregs[t],status));
92362306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
92462306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
92562306a36Sopenharmony_ci						&fpregs[t],status));
92662306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
92762306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
92862306a36Sopenharmony_ci						&fpregs[t],status));
92962306a36Sopenharmony_ci				}
93062306a36Sopenharmony_ci				BUG();
93162306a36Sopenharmony_ci			case 6: /* FCNVFU (PA2.0 only) */
93262306a36Sopenharmony_ci				switch(fmt) {
93362306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
93462306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
93562306a36Sopenharmony_ci						&fpregs[t],status));
93662306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
93762306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
93862306a36Sopenharmony_ci						&fpregs[t],status));
93962306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
94062306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
94162306a36Sopenharmony_ci						&fpregs[t],status));
94262306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
94362306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
94462306a36Sopenharmony_ci						&fpregs[t],status));
94562306a36Sopenharmony_ci				}
94662306a36Sopenharmony_ci				BUG();
94762306a36Sopenharmony_ci			case 7: /* FCNVFUT (PA2.0 only) */
94862306a36Sopenharmony_ci				switch(fmt) {
94962306a36Sopenharmony_ci				    case 0: /* sgl/sgl */
95062306a36Sopenharmony_ci					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
95162306a36Sopenharmony_ci						&fpregs[t],status));
95262306a36Sopenharmony_ci				    case 1: /* sgl/dbl */
95362306a36Sopenharmony_ci					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
95462306a36Sopenharmony_ci						&fpregs[t],status));
95562306a36Sopenharmony_ci				    case 2: /* dbl/sgl */
95662306a36Sopenharmony_ci					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
95762306a36Sopenharmony_ci						&fpregs[t],status));
95862306a36Sopenharmony_ci				    case 3: /* dbl/dbl */
95962306a36Sopenharmony_ci					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
96062306a36Sopenharmony_ci						&fpregs[t],status));
96162306a36Sopenharmony_ci				}
96262306a36Sopenharmony_ci				BUG();
96362306a36Sopenharmony_ci			case 4: /* undefined */
96462306a36Sopenharmony_ci				return(MAJOR_0C_EXCP);
96562306a36Sopenharmony_ci		} /* end of switch subop */
96662306a36Sopenharmony_ci		BUG();
96762306a36Sopenharmony_ci	case 2: /* class 2 */
96862306a36Sopenharmony_ci		/*
96962306a36Sopenharmony_ci		 * Be careful out there.
97062306a36Sopenharmony_ci		 * Crashme can generate cases where FR31R is specified
97162306a36Sopenharmony_ci		 * as the source or target of a double precision operation.
97262306a36Sopenharmony_ci		 * Since we just pass the address of the floating-point
97362306a36Sopenharmony_ci		 * register to the emulation routines, this can cause
97462306a36Sopenharmony_ci		 * corruption of fpzeroreg.
97562306a36Sopenharmony_ci		 */
97662306a36Sopenharmony_ci		if (fmt == DBL)
97762306a36Sopenharmony_ci			r2 = (extru(ir,fpr2pos,5)<<1);
97862306a36Sopenharmony_ci		else
97962306a36Sopenharmony_ci			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
98062306a36Sopenharmony_ci		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
98162306a36Sopenharmony_ci		if (r2 == 0)
98262306a36Sopenharmony_ci			r2 = fpzeroreg;
98362306a36Sopenharmony_ci		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
98462306a36Sopenharmony_ci			/* FTEST if nullify bit set, otherwise FCMP */
98562306a36Sopenharmony_ci			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
98662306a36Sopenharmony_ci				/* not legal */
98762306a36Sopenharmony_ci				return(MAJOR_0E_EXCP);
98862306a36Sopenharmony_ci			} else {  /* FCMP */
98962306a36Sopenharmony_ci			switch (fmt) {
99062306a36Sopenharmony_ci				    /*
99162306a36Sopenharmony_ci				     * fmt is only 1 bit long
99262306a36Sopenharmony_ci				     */
99362306a36Sopenharmony_ci				    case 0:
99462306a36Sopenharmony_ci					retval = sgl_fcmp(&fpregs[r1],
99562306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
99662306a36Sopenharmony_ci						&local_status);
99762306a36Sopenharmony_ci					update_status_cbit(status,local_status,
99862306a36Sopenharmony_ci						fpu_type_flags, subop);
99962306a36Sopenharmony_ci					return(retval);
100062306a36Sopenharmony_ci				    case 1:
100162306a36Sopenharmony_ci					retval = dbl_fcmp(&fpregs[r1],
100262306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
100362306a36Sopenharmony_ci						&local_status);
100462306a36Sopenharmony_ci					update_status_cbit(status,local_status,
100562306a36Sopenharmony_ci						fpu_type_flags, subop);
100662306a36Sopenharmony_ci					return(retval);
100762306a36Sopenharmony_ci				}
100862306a36Sopenharmony_ci			}
100962306a36Sopenharmony_ci		}  /* end of if for PA2.0 */
101062306a36Sopenharmony_ci		else {  /* PA1.0 & PA1.1 */
101162306a36Sopenharmony_ci		    switch (subop) {
101262306a36Sopenharmony_ci			case 1:
101362306a36Sopenharmony_ci			case 2:
101462306a36Sopenharmony_ci			case 3:
101562306a36Sopenharmony_ci			case 4:
101662306a36Sopenharmony_ci			case 5:
101762306a36Sopenharmony_ci			case 6:
101862306a36Sopenharmony_ci			case 7:
101962306a36Sopenharmony_ci				return(MAJOR_0E_EXCP);
102062306a36Sopenharmony_ci			case 0: /* FCMP */
102162306a36Sopenharmony_ci				switch (fmt) {
102262306a36Sopenharmony_ci				    /*
102362306a36Sopenharmony_ci				     * fmt is only 1 bit long
102462306a36Sopenharmony_ci				     */
102562306a36Sopenharmony_ci				    case 0:
102662306a36Sopenharmony_ci					retval = sgl_fcmp(&fpregs[r1],
102762306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
102862306a36Sopenharmony_ci						&local_status);
102962306a36Sopenharmony_ci					update_status_cbit(status,local_status,
103062306a36Sopenharmony_ci						fpu_type_flags, subop);
103162306a36Sopenharmony_ci					return(retval);
103262306a36Sopenharmony_ci				    case 1:
103362306a36Sopenharmony_ci					retval = dbl_fcmp(&fpregs[r1],
103462306a36Sopenharmony_ci						&fpregs[r2],extru(ir,fptpos,5),
103562306a36Sopenharmony_ci						&local_status);
103662306a36Sopenharmony_ci					update_status_cbit(status,local_status,
103762306a36Sopenharmony_ci						fpu_type_flags, subop);
103862306a36Sopenharmony_ci					return(retval);
103962306a36Sopenharmony_ci				}
104062306a36Sopenharmony_ci		    } /* end of switch subop */
104162306a36Sopenharmony_ci		} /* end of else for PA1.0 & PA1.1 */
104262306a36Sopenharmony_ci		BUG();
104362306a36Sopenharmony_ci	case 3: /* class 3 */
104462306a36Sopenharmony_ci		/*
104562306a36Sopenharmony_ci		 * Be careful out there.
104662306a36Sopenharmony_ci		 * Crashme can generate cases where FR31R is specified
104762306a36Sopenharmony_ci		 * as the source or target of a double precision operation.
104862306a36Sopenharmony_ci		 * Since we just pass the address of the floating-point
104962306a36Sopenharmony_ci		 * register to the emulation routines, this can cause
105062306a36Sopenharmony_ci		 * corruption of fpzeroreg.
105162306a36Sopenharmony_ci		 */
105262306a36Sopenharmony_ci		if (fmt == DBL)
105362306a36Sopenharmony_ci			r2 = (extru(ir,fpr2pos,5)<<1);
105462306a36Sopenharmony_ci		else
105562306a36Sopenharmony_ci			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
105662306a36Sopenharmony_ci		if (r2 == 0)
105762306a36Sopenharmony_ci			r2 = fpzeroreg;
105862306a36Sopenharmony_ci		switch (subop) {
105962306a36Sopenharmony_ci			case 5:
106062306a36Sopenharmony_ci			case 6:
106162306a36Sopenharmony_ci			case 7:
106262306a36Sopenharmony_ci				return(MAJOR_0E_EXCP);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci			/*
106562306a36Sopenharmony_ci			 * Note that fmt is only 1 bit for class 3 */
106662306a36Sopenharmony_ci			case 0: /* FADD */
106762306a36Sopenharmony_ci				switch (fmt) {
106862306a36Sopenharmony_ci				    case 0:
106962306a36Sopenharmony_ci					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
107062306a36Sopenharmony_ci						&fpregs[t],status));
107162306a36Sopenharmony_ci				    case 1:
107262306a36Sopenharmony_ci					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
107362306a36Sopenharmony_ci						&fpregs[t],status));
107462306a36Sopenharmony_ci				}
107562306a36Sopenharmony_ci				BUG();
107662306a36Sopenharmony_ci			case 1: /* FSUB */
107762306a36Sopenharmony_ci				switch (fmt) {
107862306a36Sopenharmony_ci				    case 0:
107962306a36Sopenharmony_ci					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
108062306a36Sopenharmony_ci						&fpregs[t],status));
108162306a36Sopenharmony_ci				    case 1:
108262306a36Sopenharmony_ci					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
108362306a36Sopenharmony_ci						&fpregs[t],status));
108462306a36Sopenharmony_ci				}
108562306a36Sopenharmony_ci				BUG();
108662306a36Sopenharmony_ci			case 2: /* FMPY or XMPYU */
108762306a36Sopenharmony_ci				/*
108862306a36Sopenharmony_ci				 * check for integer multiply (x bit set)
108962306a36Sopenharmony_ci				 */
109062306a36Sopenharmony_ci				if (extru(ir,fpxpos,1)) {
109162306a36Sopenharmony_ci				    /*
109262306a36Sopenharmony_ci				     * emulate XMPYU
109362306a36Sopenharmony_ci				     */
109462306a36Sopenharmony_ci				    switch (fmt) {
109562306a36Sopenharmony_ci					case 0:
109662306a36Sopenharmony_ci					    /*
109762306a36Sopenharmony_ci					     * bad instruction if t specifies
109862306a36Sopenharmony_ci					     * the right half of a register
109962306a36Sopenharmony_ci					     */
110062306a36Sopenharmony_ci					    if (t & 1)
110162306a36Sopenharmony_ci						return(MAJOR_0E_EXCP);
110262306a36Sopenharmony_ci					    BUG();
110362306a36Sopenharmony_ci					    /* unsupported
110462306a36Sopenharmony_ci					     * impyu(&fpregs[r1],&fpregs[r2],
110562306a36Sopenharmony_ci						 * &fpregs[t]);
110662306a36Sopenharmony_ci					     */
110762306a36Sopenharmony_ci					    return(NOEXCEPTION);
110862306a36Sopenharmony_ci					case 1:
110962306a36Sopenharmony_ci						return(MAJOR_0E_EXCP);
111062306a36Sopenharmony_ci				    }
111162306a36Sopenharmony_ci				}
111262306a36Sopenharmony_ci				else { /* FMPY */
111362306a36Sopenharmony_ci				    switch (fmt) {
111462306a36Sopenharmony_ci				        case 0:
111562306a36Sopenharmony_ci					    return(sgl_fmpy(&fpregs[r1],
111662306a36Sopenharmony_ci					       &fpregs[r2],&fpregs[t],status));
111762306a36Sopenharmony_ci				        case 1:
111862306a36Sopenharmony_ci					    return(dbl_fmpy(&fpregs[r1],
111962306a36Sopenharmony_ci					       &fpregs[r2],&fpregs[t],status));
112062306a36Sopenharmony_ci				    }
112162306a36Sopenharmony_ci				}
112262306a36Sopenharmony_ci				BUG();
112362306a36Sopenharmony_ci			case 3: /* FDIV */
112462306a36Sopenharmony_ci				switch (fmt) {
112562306a36Sopenharmony_ci				    case 0:
112662306a36Sopenharmony_ci					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
112762306a36Sopenharmony_ci						&fpregs[t],status));
112862306a36Sopenharmony_ci				    case 1:
112962306a36Sopenharmony_ci					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
113062306a36Sopenharmony_ci						&fpregs[t],status));
113162306a36Sopenharmony_ci				}
113262306a36Sopenharmony_ci				BUG();
113362306a36Sopenharmony_ci			case 4: /* FREM */
113462306a36Sopenharmony_ci				switch (fmt) {
113562306a36Sopenharmony_ci				    case 0:
113662306a36Sopenharmony_ci					return(sgl_frem(&fpregs[r1],&fpregs[r2],
113762306a36Sopenharmony_ci						&fpregs[t],status));
113862306a36Sopenharmony_ci				    case 1:
113962306a36Sopenharmony_ci					return(dbl_frem(&fpregs[r1],&fpregs[r2],
114062306a36Sopenharmony_ci						&fpregs[t],status));
114162306a36Sopenharmony_ci				}
114262306a36Sopenharmony_ci		} /* end of class 3 switch */
114362306a36Sopenharmony_ci	} /* end of switch(class) */
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	/* If we get here, something is really wrong! */
114662306a36Sopenharmony_ci	return(MAJOR_0E_EXCP);
114762306a36Sopenharmony_ci}
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci/*
115162306a36Sopenharmony_ci * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
115262306a36Sopenharmony_ci */
115362306a36Sopenharmony_cistatic u_int
115462306a36Sopenharmony_cidecode_06(ir,fpregs)
115562306a36Sopenharmony_ciu_int ir;
115662306a36Sopenharmony_ciu_int fpregs[];
115762306a36Sopenharmony_ci{
115862306a36Sopenharmony_ci	u_int rm1, rm2, tm, ra, ta; /* operands */
115962306a36Sopenharmony_ci	u_int fmt;
116062306a36Sopenharmony_ci	u_int error = 0;
116162306a36Sopenharmony_ci	u_int status;
116262306a36Sopenharmony_ci	u_int fpu_type_flags;
116362306a36Sopenharmony_ci	union {
116462306a36Sopenharmony_ci		double dbl;
116562306a36Sopenharmony_ci		float flt;
116662306a36Sopenharmony_ci		struct { u_int i1; u_int i2; } ints;
116762306a36Sopenharmony_ci	} mtmp, atmp;
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	status = fpregs[0];		/* use a local copy of status reg */
117162306a36Sopenharmony_ci	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
117262306a36Sopenharmony_ci	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
117362306a36Sopenharmony_ci	if (fmt == 0) { /* DBL */
117462306a36Sopenharmony_ci		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
117562306a36Sopenharmony_ci		if (rm1 == 0)
117662306a36Sopenharmony_ci			rm1 = fpzeroreg;
117762306a36Sopenharmony_ci		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
117862306a36Sopenharmony_ci		if (rm2 == 0)
117962306a36Sopenharmony_ci			rm2 = fpzeroreg;
118062306a36Sopenharmony_ci		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
118162306a36Sopenharmony_ci		if (tm == 0)
118262306a36Sopenharmony_ci			return(MAJOR_06_EXCP);
118362306a36Sopenharmony_ci		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
118462306a36Sopenharmony_ci		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
118562306a36Sopenharmony_ci		if (ta == 0)
118662306a36Sopenharmony_ci			return(MAJOR_06_EXCP);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci		if  (fpu_type_flags & TIMEX_ROLEX_FPU_MASK)  {
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci			if (ra == 0) {
119162306a36Sopenharmony_ci			 	/* special case FMPYCFXT, see sgl case below */
119262306a36Sopenharmony_ci				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
119362306a36Sopenharmony_ci					&mtmp.ints.i1,&status))
119462306a36Sopenharmony_ci					error = 1;
119562306a36Sopenharmony_ci				if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
119662306a36Sopenharmony_ci					&atmp.ints.i1,&atmp.ints.i1,&status))
119762306a36Sopenharmony_ci					error = 1;
119862306a36Sopenharmony_ci				}
119962306a36Sopenharmony_ci			else {
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
120262306a36Sopenharmony_ci					&status))
120362306a36Sopenharmony_ci				error = 1;
120462306a36Sopenharmony_ci			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
120562306a36Sopenharmony_ci					&status))
120662306a36Sopenharmony_ci				error = 1;
120762306a36Sopenharmony_ci				}
120862306a36Sopenharmony_ci			}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci		else
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci			{
121362306a36Sopenharmony_ci			if (ra == 0)
121462306a36Sopenharmony_ci				ra = fpzeroreg;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
121762306a36Sopenharmony_ci					&status))
121862306a36Sopenharmony_ci				error = 1;
121962306a36Sopenharmony_ci			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
122062306a36Sopenharmony_ci					&status))
122162306a36Sopenharmony_ci				error = 1;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci			}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci		if (error)
122662306a36Sopenharmony_ci			return(MAJOR_06_EXCP);
122762306a36Sopenharmony_ci		else {
122862306a36Sopenharmony_ci			/* copy results */
122962306a36Sopenharmony_ci			fpregs[tm] = mtmp.ints.i1;
123062306a36Sopenharmony_ci			fpregs[tm+1] = mtmp.ints.i2;
123162306a36Sopenharmony_ci			fpregs[ta] = atmp.ints.i1;
123262306a36Sopenharmony_ci			fpregs[ta+1] = atmp.ints.i2;
123362306a36Sopenharmony_ci			fpregs[0] = status;
123462306a36Sopenharmony_ci			return(NOEXCEPTION);
123562306a36Sopenharmony_ci		}
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci	else { /* SGL */
123862306a36Sopenharmony_ci		/*
123962306a36Sopenharmony_ci		 * calculate offsets for single precision numbers
124062306a36Sopenharmony_ci		 * See table 6-14 in PA-89 architecture for mapping
124162306a36Sopenharmony_ci		 */
124262306a36Sopenharmony_ci		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
124362306a36Sopenharmony_ci		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
124662306a36Sopenharmony_ci		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
124962306a36Sopenharmony_ci		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
125262306a36Sopenharmony_ci		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
125562306a36Sopenharmony_ci		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci		if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
125862306a36Sopenharmony_ci			/* special case FMPYCFXT (really 0)
125962306a36Sopenharmony_ci			  * This instruction is only present on the Timex and
126062306a36Sopenharmony_ci			  * Rolex fpu's in so if it is the special case and
126162306a36Sopenharmony_ci			  * one of these fpu's we run the FMPYCFXT instruction
126262306a36Sopenharmony_ci			  */
126362306a36Sopenharmony_ci			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
126462306a36Sopenharmony_ci					&status))
126562306a36Sopenharmony_ci				error = 1;
126662306a36Sopenharmony_ci			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
126762306a36Sopenharmony_ci				&atmp.ints.i1,&status))
126862306a36Sopenharmony_ci				error = 1;
126962306a36Sopenharmony_ci		}
127062306a36Sopenharmony_ci		else {
127162306a36Sopenharmony_ci			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
127262306a36Sopenharmony_ci					&status))
127362306a36Sopenharmony_ci				error = 1;
127462306a36Sopenharmony_ci			if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
127562306a36Sopenharmony_ci					&status))
127662306a36Sopenharmony_ci				error = 1;
127762306a36Sopenharmony_ci		}
127862306a36Sopenharmony_ci		if (error)
127962306a36Sopenharmony_ci			return(MAJOR_06_EXCP);
128062306a36Sopenharmony_ci		else {
128162306a36Sopenharmony_ci			/* copy results */
128262306a36Sopenharmony_ci			fpregs[tm] = mtmp.ints.i1;
128362306a36Sopenharmony_ci			fpregs[ta] = atmp.ints.i1;
128462306a36Sopenharmony_ci			fpregs[0] = status;
128562306a36Sopenharmony_ci			return(NOEXCEPTION);
128662306a36Sopenharmony_ci		}
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci/*
129162306a36Sopenharmony_ci * routine to decode the 26 (FMPYSUB) instruction
129262306a36Sopenharmony_ci */
129362306a36Sopenharmony_cistatic u_int
129462306a36Sopenharmony_cidecode_26(ir,fpregs)
129562306a36Sopenharmony_ciu_int ir;
129662306a36Sopenharmony_ciu_int fpregs[];
129762306a36Sopenharmony_ci{
129862306a36Sopenharmony_ci	u_int rm1, rm2, tm, ra, ta; /* operands */
129962306a36Sopenharmony_ci	u_int fmt;
130062306a36Sopenharmony_ci	u_int error = 0;
130162306a36Sopenharmony_ci	u_int status;
130262306a36Sopenharmony_ci	union {
130362306a36Sopenharmony_ci		double dbl;
130462306a36Sopenharmony_ci		float flt;
130562306a36Sopenharmony_ci		struct { u_int i1; u_int i2; } ints;
130662306a36Sopenharmony_ci	} mtmp, atmp;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	status = fpregs[0];
131062306a36Sopenharmony_ci	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
131162306a36Sopenharmony_ci	if (fmt == 0) { /* DBL */
131262306a36Sopenharmony_ci		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
131362306a36Sopenharmony_ci		if (rm1 == 0)
131462306a36Sopenharmony_ci			rm1 = fpzeroreg;
131562306a36Sopenharmony_ci		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
131662306a36Sopenharmony_ci		if (rm2 == 0)
131762306a36Sopenharmony_ci			rm2 = fpzeroreg;
131862306a36Sopenharmony_ci		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
131962306a36Sopenharmony_ci		if (tm == 0)
132062306a36Sopenharmony_ci			return(MAJOR_26_EXCP);
132162306a36Sopenharmony_ci		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
132262306a36Sopenharmony_ci		if (ra == 0)
132362306a36Sopenharmony_ci			return(MAJOR_26_EXCP);
132462306a36Sopenharmony_ci		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
132562306a36Sopenharmony_ci		if (ta == 0)
132662306a36Sopenharmony_ci			return(MAJOR_26_EXCP);
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci		if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
132962306a36Sopenharmony_ci			error = 1;
133062306a36Sopenharmony_ci		if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
133162306a36Sopenharmony_ci			error = 1;
133262306a36Sopenharmony_ci		if (error)
133362306a36Sopenharmony_ci			return(MAJOR_26_EXCP);
133462306a36Sopenharmony_ci		else {
133562306a36Sopenharmony_ci			/* copy results */
133662306a36Sopenharmony_ci			fpregs[tm] = mtmp.ints.i1;
133762306a36Sopenharmony_ci			fpregs[tm+1] = mtmp.ints.i2;
133862306a36Sopenharmony_ci			fpregs[ta] = atmp.ints.i1;
133962306a36Sopenharmony_ci			fpregs[ta+1] = atmp.ints.i2;
134062306a36Sopenharmony_ci			fpregs[0] = status;
134162306a36Sopenharmony_ci			return(NOEXCEPTION);
134262306a36Sopenharmony_ci		}
134362306a36Sopenharmony_ci	}
134462306a36Sopenharmony_ci	else { /* SGL */
134562306a36Sopenharmony_ci		/*
134662306a36Sopenharmony_ci		 * calculate offsets for single precision numbers
134762306a36Sopenharmony_ci		 * See table 6-14 in PA-89 architecture for mapping
134862306a36Sopenharmony_ci		 */
134962306a36Sopenharmony_ci		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
135062306a36Sopenharmony_ci		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
135362306a36Sopenharmony_ci		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
135662306a36Sopenharmony_ci		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
135962306a36Sopenharmony_ci		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
136262306a36Sopenharmony_ci		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci		if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
136562306a36Sopenharmony_ci			error = 1;
136662306a36Sopenharmony_ci		if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
136762306a36Sopenharmony_ci			error = 1;
136862306a36Sopenharmony_ci		if (error)
136962306a36Sopenharmony_ci			return(MAJOR_26_EXCP);
137062306a36Sopenharmony_ci		else {
137162306a36Sopenharmony_ci			/* copy results */
137262306a36Sopenharmony_ci			fpregs[tm] = mtmp.ints.i1;
137362306a36Sopenharmony_ci			fpregs[ta] = atmp.ints.i1;
137462306a36Sopenharmony_ci			fpregs[0] = status;
137562306a36Sopenharmony_ci			return(NOEXCEPTION);
137662306a36Sopenharmony_ci		}
137762306a36Sopenharmony_ci	}
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ci}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci/*
138262306a36Sopenharmony_ci * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
138362306a36Sopenharmony_ci */
138462306a36Sopenharmony_cistatic u_int
138562306a36Sopenharmony_cidecode_2e(ir,fpregs)
138662306a36Sopenharmony_ciu_int ir;
138762306a36Sopenharmony_ciu_int fpregs[];
138862306a36Sopenharmony_ci{
138962306a36Sopenharmony_ci	u_int rm1, rm2, ra, t; /* operands */
139062306a36Sopenharmony_ci	u_int fmt;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	fmt = extru(ir,fpfmtpos,1);	/* get fmt completer */
139362306a36Sopenharmony_ci	if (fmt == DBL) { /* DBL */
139462306a36Sopenharmony_ci		rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
139562306a36Sopenharmony_ci		if (rm1 == 0)
139662306a36Sopenharmony_ci			rm1 = fpzeroreg;
139762306a36Sopenharmony_ci		rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
139862306a36Sopenharmony_ci		if (rm2 == 0)
139962306a36Sopenharmony_ci			rm2 = fpzeroreg;
140062306a36Sopenharmony_ci		ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
140162306a36Sopenharmony_ci		     sizeof(double)/sizeof(u_int);
140262306a36Sopenharmony_ci		if (ra == 0)
140362306a36Sopenharmony_ci			ra = fpzeroreg;
140462306a36Sopenharmony_ci		t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
140562306a36Sopenharmony_ci		if (t == 0)
140662306a36Sopenharmony_ci			return(MAJOR_2E_EXCP);
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
140962306a36Sopenharmony_ci			return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
141062306a36Sopenharmony_ci					&fpregs[ra], &fpregs[0], &fpregs[t]));
141162306a36Sopenharmony_ci		} else {
141262306a36Sopenharmony_ci			return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
141362306a36Sopenharmony_ci					&fpregs[ra], &fpregs[0], &fpregs[t]));
141462306a36Sopenharmony_ci		}
141562306a36Sopenharmony_ci	} /* end DBL */
141662306a36Sopenharmony_ci	else { /* SGL */
141762306a36Sopenharmony_ci		rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
141862306a36Sopenharmony_ci		if (rm1 == 0)
141962306a36Sopenharmony_ci			rm1 = fpzeroreg;
142062306a36Sopenharmony_ci		rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
142162306a36Sopenharmony_ci		if (rm2 == 0)
142262306a36Sopenharmony_ci			rm2 = fpzeroreg;
142362306a36Sopenharmony_ci		ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
142462306a36Sopenharmony_ci		if (ra == 0)
142562306a36Sopenharmony_ci			ra = fpzeroreg;
142662306a36Sopenharmony_ci		t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
142762306a36Sopenharmony_ci		if (t == 0)
142862306a36Sopenharmony_ci			return(MAJOR_2E_EXCP);
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
143162306a36Sopenharmony_ci			return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
143262306a36Sopenharmony_ci					&fpregs[ra], &fpregs[0], &fpregs[t]));
143362306a36Sopenharmony_ci		} else {
143462306a36Sopenharmony_ci			return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
143562306a36Sopenharmony_ci					&fpregs[ra], &fpregs[0], &fpregs[t]));
143662306a36Sopenharmony_ci		}
143762306a36Sopenharmony_ci	} /* end SGL */
143862306a36Sopenharmony_ci}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci/*
144162306a36Sopenharmony_ci * update_status_cbit
144262306a36Sopenharmony_ci *
144362306a36Sopenharmony_ci *	This routine returns the correct FP status register value in
144462306a36Sopenharmony_ci *	*status, based on the C-bit & V-bit returned by the FCMP
144562306a36Sopenharmony_ci *	emulation routine in new_status.  The architecture type
144662306a36Sopenharmony_ci *	(PA83, PA89 or PA2.0) is available in fpu_type.  The y_field
144762306a36Sopenharmony_ci *	and the architecture type are used to determine what flavor
144862306a36Sopenharmony_ci *	of FCMP is being emulated.
144962306a36Sopenharmony_ci */
145062306a36Sopenharmony_cistatic void
145162306a36Sopenharmony_ciupdate_status_cbit(status, new_status, fpu_type, y_field)
145262306a36Sopenharmony_ciu_int *status, new_status;
145362306a36Sopenharmony_ciu_int fpu_type;
145462306a36Sopenharmony_ciu_int y_field;
145562306a36Sopenharmony_ci{
145662306a36Sopenharmony_ci	/*
145762306a36Sopenharmony_ci	 * For PA89 FPU's which implement the Compare Queue and
145862306a36Sopenharmony_ci	 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
145962306a36Sopenharmony_ci	 * otherwise update the specified bit in the Compare Array.
146062306a36Sopenharmony_ci	 * Note that the y-field will always be 0 for non-PA2.0 FPU's.
146162306a36Sopenharmony_ci	 */
146262306a36Sopenharmony_ci	if ((fpu_type & TIMEX_EXTEN_FLAG) ||
146362306a36Sopenharmony_ci	    (fpu_type & ROLEX_EXTEN_FLAG) ||
146462306a36Sopenharmony_ci	    (fpu_type & PA2_0_FPU_FLAG)) {
146562306a36Sopenharmony_ci		if (y_field == 0) {
146662306a36Sopenharmony_ci			*status = ((*status & 0x04000000) >> 5) | /* old Cbit */
146762306a36Sopenharmony_ci				  ((*status & 0x003ff000) >> 1) | /* old CQ   */
146862306a36Sopenharmony_ci				  (new_status & 0xffc007ff); /* all other bits*/
146962306a36Sopenharmony_ci		} else {
147062306a36Sopenharmony_ci			*status = (*status & 0x04000000) |     /* old Cbit */
147162306a36Sopenharmony_ci				  ((new_status & 0x04000000) >> (y_field+4)) |
147262306a36Sopenharmony_ci				  (new_status & ~0x04000000 &  /* other bits */
147362306a36Sopenharmony_ci				   ~(0x04000000 >> (y_field+4)));
147462306a36Sopenharmony_ci		}
147562306a36Sopenharmony_ci	}
147662306a36Sopenharmony_ci	/* if PA83, just update the C-bit */
147762306a36Sopenharmony_ci	else {
147862306a36Sopenharmony_ci		*status = new_status;
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci}
1481