cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fpudispatch.c (39189B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
      4 *
      5 * Floating-point emulation code
      6 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
      7 */
      8/*
      9 * BEGIN_DESC
     10 *
     11 *  File:
     12 *	@(#)	pa/fp/fpudispatch.c		$Revision: 1.1 $
     13 *
     14 *  Purpose:
     15 *	<<please update with a synopsis of the functionality provided by this file>>
     16 *
     17 *  External Interfaces:
     18 *	<<the following list was autogenerated, please review>>
     19 *	emfpudispatch(ir, dummy1, dummy2, fpregs)
     20 *	fpudispatch(ir, excp_code, holder, fpregs)
     21 *
     22 *  Internal Interfaces:
     23 *	<<the following list was autogenerated, please review>>
     24 *	static u_int decode_06(u_int, u_int *)
     25 *	static u_int decode_0c(u_int, u_int, u_int, u_int *)
     26 *	static u_int decode_0e(u_int, u_int, u_int, u_int *)
     27 *	static u_int decode_26(u_int, u_int *)
     28 *	static u_int decode_2e(u_int, u_int *)
     29 *	static void update_status_cbit(u_int *, u_int, u_int, u_int)
     30 *
     31 *  Theory:
     32 *	<<please update with a overview of the operation of this file>>
     33 *
     34 * END_DESC
     35*/
     36
     37#define FPUDEBUG 0
     38
     39#include "float.h"
     40#include <linux/bug.h>
     41#include <linux/kernel.h>
     42#include <asm/processor.h>
     43/* #include <sys/debug.h> */
     44/* #include <machine/sys/mdep_private.h> */
     45
     46#define COPR_INST 0x30000000
     47
     48/*
     49 * definition of extru macro.  If pos and len are constants, the compiler
     50 * will generate an extru instruction when optimized
     51 */
     52#define extru(r,pos,len)	(((r) >> (31-(pos))) & (( 1 << (len)) - 1))
     53/* definitions of bit field locations in the instruction */
     54#define fpmajorpos 5
     55#define fpr1pos	10
     56#define fpr2pos 15
     57#define fptpos	31
     58#define fpsubpos 18
     59#define fpclass1subpos 16
     60#define fpclasspos 22
     61#define fpfmtpos 20
     62#define fpdfpos 18
     63#define fpnulpos 26
     64/*
     65 * the following are the extra bits for the 0E major op
     66 */
     67#define fpxr1pos 24
     68#define fpxr2pos 19
     69#define fpxtpos 25
     70#define fpxpos 23
     71#define fp0efmtpos 20
     72/*
     73 * the following are for the multi-ops
     74 */
     75#define fprm1pos 10
     76#define fprm2pos 15
     77#define fptmpos 31
     78#define fprapos 25
     79#define fptapos 20
     80#define fpmultifmt 26
     81/*
     82 * the following are for the fused FP instructions
     83 */
     84     /* fprm1pos 10 */
     85     /* fprm2pos 15 */
     86#define fpraupos 18
     87#define fpxrm2pos 19
     88     /* fpfmtpos 20 */
     89#define fpralpos 23
     90#define fpxrm1pos 24
     91     /* fpxtpos 25 */
     92#define fpfusedsubop 26
     93     /* fptpos	31 */
     94
     95/*
     96 * offset to constant zero in the FP emulation registers
     97 */
     98#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
     99
    100/*
    101 * extract the major opcode from the instruction
    102 */
    103#define get_major(op) extru(op,fpmajorpos,6)
    104/*
    105 * extract the two bit class field from the FP instruction. The class is at bit
    106 * positions 21-22
    107 */
    108#define get_class(op) extru(op,fpclasspos,2)
    109/*
    110 * extract the 3 bit subop field.  For all but class 1 instructions, it is
    111 * located at bit positions 16-18
    112 */
    113#define get_subop(op) extru(op,fpsubpos,3)
    114/*
    115 * extract the 2 or 3 bit subop field from class 1 instructions.  It is located
    116 * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
    117 */
    118#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2)	/* PA89 (1.1) fmt */
    119#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3)	/* PA 2.0 fmt */
    120
    121/* definitions of unimplemented exceptions */
    122#define MAJOR_0C_EXCP	0x09
    123#define MAJOR_0E_EXCP	0x0b
    124#define MAJOR_06_EXCP	0x03
    125#define MAJOR_26_EXCP	0x23
    126#define MAJOR_2E_EXCP	0x2b
    127#define PA83_UNIMP_EXCP	0x01
    128
    129/*
    130 * Special Defines for TIMEX specific code
    131 */
    132
    133#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
    134#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
    135
    136/*
    137 * Static function definitions
    138 */
    139#define _PROTOTYPES
    140#if defined(_PROTOTYPES) || defined(_lint)
    141static u_int decode_0c(u_int, u_int, u_int, u_int *);
    142static u_int decode_0e(u_int, u_int, u_int, u_int *);
    143static u_int decode_06(u_int, u_int *);
    144static u_int decode_26(u_int, u_int *);
    145static u_int decode_2e(u_int, u_int *);
    146static void update_status_cbit(u_int *, u_int, u_int, u_int);
    147#else /* !_PROTOTYPES&&!_lint */
    148static u_int decode_0c();
    149static u_int decode_0e();
    150static u_int decode_06();
    151static u_int decode_26();
    152static u_int decode_2e();
    153static void update_status_cbit();
    154#endif /* _PROTOTYPES&&!_lint */
    155
    156#define VASSERT(x)
    157
    158static void parisc_linux_get_fpu_type(u_int fpregs[])
    159{
    160	/* on pa-linux the fpu type is not filled in by the
    161	 * caller; it is constructed here  
    162	 */ 
    163	if (boot_cpu_data.cpu_type == pcxs)
    164		fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG;
    165	else if (boot_cpu_data.cpu_type == pcxt ||
    166	         boot_cpu_data.cpu_type == pcxt_)
    167		fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG;
    168	else if (boot_cpu_data.cpu_type >= pcxu)
    169		fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG;
    170}
    171
    172/*
    173 * this routine will decode the excepting floating point instruction and
    174 * call the appropriate emulation routine.
    175 * It is called by decode_fpu with the following parameters:
    176 * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
    177 * where current_ir is the instruction to be emulated,
    178 * unimplemented_code is the exception_code that the hardware generated
    179 * and &Fpu_register is the address of emulated FP reg 0.
    180 */
    181u_int
    182fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
    183{
    184	u_int class, subop;
    185	u_int fpu_type_flags;
    186
    187	/* All FP emulation code assumes that ints are 4-bytes in length */
    188	VASSERT(sizeof(int) == 4);
    189
    190	parisc_linux_get_fpu_type(fpregs);
    191
    192	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
    193
    194	class = get_class(ir);
    195	if (class == 1) {
    196		if  (fpu_type_flags & PA2_0_FPU_FLAG)
    197			subop = get_subop1_PA2_0(ir);
    198		else
    199			subop = get_subop1_PA1_1(ir);
    200	}
    201	else
    202		subop = get_subop(ir);
    203
    204	if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
    205
    206	switch (excp_code) {
    207		case MAJOR_0C_EXCP:
    208		case PA83_UNIMP_EXCP:
    209			return(decode_0c(ir,class,subop,fpregs));
    210		case MAJOR_0E_EXCP:
    211			return(decode_0e(ir,class,subop,fpregs));
    212		case MAJOR_06_EXCP:
    213			return(decode_06(ir,fpregs));
    214		case MAJOR_26_EXCP:
    215			return(decode_26(ir,fpregs));
    216		case MAJOR_2E_EXCP:
    217			return(decode_2e(ir,fpregs));
    218		default:
    219			/* "crashme Night Gallery painting nr 2. (asm_crash.s).
    220			 * This was fixed for multi-user kernels, but
    221			 * workstation kernels had a panic here.  This allowed
    222			 * any arbitrary user to panic the kernel by executing
    223			 * setting the FP exception registers to strange values
    224			 * and generating an emulation trap.  The emulation and
    225			 * exception code must never be able to panic the
    226			 * kernel.
    227			 */
    228			return(UNIMPLEMENTEDEXCEPTION);
    229	}
    230}
    231
    232/*
    233 * this routine is called by $emulation_trap to emulate a coprocessor
    234 * instruction if one doesn't exist
    235 */
    236u_int
    237emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
    238{
    239	u_int class, subop, major;
    240	u_int fpu_type_flags;
    241
    242	/* All FP emulation code assumes that ints are 4-bytes in length */
    243	VASSERT(sizeof(int) == 4);
    244
    245	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
    246
    247	major = get_major(ir);
    248	class = get_class(ir);
    249	if (class == 1) {
    250		if  (fpu_type_flags & PA2_0_FPU_FLAG)
    251			subop = get_subop1_PA2_0(ir);
    252		else
    253			subop = get_subop1_PA1_1(ir);
    254	}
    255	else
    256		subop = get_subop(ir);
    257	switch (major) {
    258		case 0x0C:
    259			return(decode_0c(ir,class,subop,fpregs));
    260		case 0x0E:
    261			return(decode_0e(ir,class,subop,fpregs));
    262		case 0x06:
    263			return(decode_06(ir,fpregs));
    264		case 0x26:
    265			return(decode_26(ir,fpregs));
    266		case 0x2E:
    267			return(decode_2e(ir,fpregs));
    268		default:
    269			return(PA83_UNIMP_EXCP);
    270	}
    271}
    272	
    273
    274static u_int
    275decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
    276{
    277	u_int r1,r2,t;		/* operand register offsets */ 
    278	u_int fmt;		/* also sf for class 1 conversions */
    279	u_int  df;		/* for class 1 conversions */
    280	u_int *status;
    281	u_int retval, local_status;
    282	u_int fpu_type_flags;
    283
    284	if (ir == COPR_INST) {
    285		fpregs[0] = EMULATION_VERSION << 11;
    286		return(NOEXCEPTION);
    287	}
    288	status = &fpregs[0];	/* fp status register */
    289	local_status = fpregs[0]; /* and local copy */
    290	r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
    291	if (r1 == 0)		/* map fr0 source to constant zero */
    292		r1 = fpzeroreg;
    293	t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
    294	if (t == 0 && class != 2)	/* don't allow fr0 as a dest */
    295		return(MAJOR_0C_EXCP);
    296	fmt = extru(ir,fpfmtpos,2);	/* get fmt completer */
    297
    298	switch (class) {
    299	    case 0:
    300		switch (subop) {
    301			case 0:	/* COPR 0,0 emulated above*/
    302			case 1:
    303				return(MAJOR_0C_EXCP);
    304			case 2:	/* FCPY */
    305				switch (fmt) {
    306				    case 2: /* illegal */
    307					return(MAJOR_0C_EXCP);
    308				    case 3: /* quad */
    309					t &= ~3;  /* force to even reg #s */
    310					r1 &= ~3;
    311					fpregs[t+3] = fpregs[r1+3];
    312					fpregs[t+2] = fpregs[r1+2];
    313					fallthrough;
    314				    case 1: /* double */
    315					fpregs[t+1] = fpregs[r1+1];
    316					fallthrough;
    317				    case 0: /* single */
    318					fpregs[t] = fpregs[r1];
    319					return(NOEXCEPTION);
    320				}
    321				BUG();
    322			case 3: /* FABS */
    323				switch (fmt) {
    324				    case 2: /* illegal */
    325					return(MAJOR_0C_EXCP);
    326				    case 3: /* quad */
    327					t &= ~3;  /* force to even reg #s */
    328					r1 &= ~3;
    329					fpregs[t+3] = fpregs[r1+3];
    330					fpregs[t+2] = fpregs[r1+2];
    331					fallthrough;
    332				    case 1: /* double */
    333					fpregs[t+1] = fpregs[r1+1];
    334					fallthrough;
    335				    case 0: /* single */
    336					/* copy and clear sign bit */
    337					fpregs[t] = fpregs[r1] & 0x7fffffff;
    338					return(NOEXCEPTION);
    339				}
    340				BUG();
    341			case 6: /* FNEG */
    342				switch (fmt) {
    343				    case 2: /* illegal */
    344					return(MAJOR_0C_EXCP);
    345				    case 3: /* quad */
    346					t &= ~3;  /* force to even reg #s */
    347					r1 &= ~3;
    348					fpregs[t+3] = fpregs[r1+3];
    349					fpregs[t+2] = fpregs[r1+2];
    350					fallthrough;
    351				    case 1: /* double */
    352					fpregs[t+1] = fpregs[r1+1];
    353					fallthrough;
    354				    case 0: /* single */
    355					/* copy and invert sign bit */
    356					fpregs[t] = fpregs[r1] ^ 0x80000000;
    357					return(NOEXCEPTION);
    358				}
    359				BUG();
    360			case 7: /* FNEGABS */
    361				switch (fmt) {
    362				    case 2: /* illegal */
    363					return(MAJOR_0C_EXCP);
    364				    case 3: /* quad */
    365					t &= ~3;  /* force to even reg #s */
    366					r1 &= ~3;
    367					fpregs[t+3] = fpregs[r1+3];
    368					fpregs[t+2] = fpregs[r1+2];
    369					fallthrough;
    370				    case 1: /* double */
    371					fpregs[t+1] = fpregs[r1+1];
    372					fallthrough;
    373				    case 0: /* single */
    374					/* copy and set sign bit */
    375					fpregs[t] = fpregs[r1] | 0x80000000;
    376					return(NOEXCEPTION);
    377				}
    378				BUG();
    379			case 4: /* FSQRT */
    380				switch (fmt) {
    381				    case 0:
    382					return(sgl_fsqrt(&fpregs[r1],0,
    383						&fpregs[t],status));
    384				    case 1:
    385					return(dbl_fsqrt(&fpregs[r1],0,
    386						&fpregs[t],status));
    387				    case 2:
    388				    case 3: /* quad not implemented */
    389					return(MAJOR_0C_EXCP);
    390				}
    391				BUG();
    392			case 5: /* FRND */
    393				switch (fmt) {
    394				    case 0:
    395					return(sgl_frnd(&fpregs[r1],0,
    396						&fpregs[t],status));
    397				    case 1:
    398					return(dbl_frnd(&fpregs[r1],0,
    399						&fpregs[t],status));
    400				    case 2:
    401				    case 3: /* quad not implemented */
    402					return(MAJOR_0C_EXCP);
    403				}
    404		} /* end of switch (subop) */
    405		BUG();
    406	case 1: /* class 1 */
    407		df = extru(ir,fpdfpos,2); /* get dest format */
    408		if ((df & 2) || (fmt & 2)) {
    409			/*
    410			 * fmt's 2 and 3 are illegal of not implemented
    411			 * quad conversions
    412			 */
    413			return(MAJOR_0C_EXCP);
    414		}
    415		/*
    416		 * encode source and dest formats into 2 bits.
    417		 * high bit is source, low bit is dest.
    418		 * bit = 1 --> double precision
    419		 */
    420		fmt = (fmt << 1) | df;
    421		switch (subop) {
    422			case 0: /* FCNVFF */
    423				switch(fmt) {
    424				    case 0: /* sgl/sgl */
    425					return(MAJOR_0C_EXCP);
    426				    case 1: /* sgl/dbl */
    427					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
    428						&fpregs[t],status));
    429				    case 2: /* dbl/sgl */
    430					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
    431						&fpregs[t],status));
    432				    case 3: /* dbl/dbl */
    433					return(MAJOR_0C_EXCP);
    434				}
    435				BUG();
    436			case 1: /* FCNVXF */
    437				switch(fmt) {
    438				    case 0: /* sgl/sgl */
    439					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
    440						&fpregs[t],status));
    441				    case 1: /* sgl/dbl */
    442					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
    443						&fpregs[t],status));
    444				    case 2: /* dbl/sgl */
    445					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
    446						&fpregs[t],status));
    447				    case 3: /* dbl/dbl */
    448					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
    449						&fpregs[t],status));
    450				}
    451				BUG();
    452			case 2: /* FCNVFX */
    453				switch(fmt) {
    454				    case 0: /* sgl/sgl */
    455					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
    456						&fpregs[t],status));
    457				    case 1: /* sgl/dbl */
    458					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
    459						&fpregs[t],status));
    460				    case 2: /* dbl/sgl */
    461					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
    462						&fpregs[t],status));
    463				    case 3: /* dbl/dbl */
    464					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
    465						&fpregs[t],status));
    466				}
    467				BUG();
    468			case 3: /* FCNVFXT */
    469				switch(fmt) {
    470				    case 0: /* sgl/sgl */
    471					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
    472						&fpregs[t],status));
    473				    case 1: /* sgl/dbl */
    474					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
    475						&fpregs[t],status));
    476				    case 2: /* dbl/sgl */
    477					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
    478						&fpregs[t],status));
    479				    case 3: /* dbl/dbl */
    480					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
    481						&fpregs[t],status));
    482				}
    483				BUG();
    484			case 5: /* FCNVUF (PA2.0 only) */
    485				switch(fmt) {
    486				    case 0: /* sgl/sgl */
    487					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
    488						&fpregs[t],status));
    489				    case 1: /* sgl/dbl */
    490					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
    491						&fpregs[t],status));
    492				    case 2: /* dbl/sgl */
    493					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
    494						&fpregs[t],status));
    495				    case 3: /* dbl/dbl */
    496					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
    497						&fpregs[t],status));
    498				}
    499				BUG();
    500			case 6: /* FCNVFU (PA2.0 only) */
    501				switch(fmt) {
    502				    case 0: /* sgl/sgl */
    503					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
    504						&fpregs[t],status));
    505				    case 1: /* sgl/dbl */
    506					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
    507						&fpregs[t],status));
    508				    case 2: /* dbl/sgl */
    509					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
    510						&fpregs[t],status));
    511				    case 3: /* dbl/dbl */
    512					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
    513						&fpregs[t],status));
    514				}
    515				BUG();
    516			case 7: /* FCNVFUT (PA2.0 only) */
    517				switch(fmt) {
    518				    case 0: /* sgl/sgl */
    519					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
    520						&fpregs[t],status));
    521				    case 1: /* sgl/dbl */
    522					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
    523						&fpregs[t],status));
    524				    case 2: /* dbl/sgl */
    525					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
    526						&fpregs[t],status));
    527				    case 3: /* dbl/dbl */
    528					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
    529						&fpregs[t],status));
    530				}
    531				BUG();
    532			case 4: /* undefined */
    533				return(MAJOR_0C_EXCP);
    534		} /* end of switch subop */
    535		BUG();
    536	case 2: /* class 2 */
    537		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
    538		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
    539		if (r2 == 0)
    540			r2 = fpzeroreg;
    541		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
    542			/* FTEST if nullify bit set, otherwise FCMP */
    543			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
    544				switch (fmt) {
    545				    case 0:
    546					/*
    547					 * arg0 is not used
    548					 * second param is the t field used for
    549					 * ftest,acc and ftest,rej
    550					 * third param is the subop (y-field)
    551					 */
    552					BUG();
    553					/* Unsupported
    554					 * return(ftest(0L,extru(ir,fptpos,5),
    555					 *	 &fpregs[0],subop));
    556					 */
    557				    case 1:
    558				    case 2:
    559				    case 3:
    560					return(MAJOR_0C_EXCP);
    561				}
    562			} else {  /* FCMP */
    563				switch (fmt) {
    564				    case 0:
    565					retval = sgl_fcmp(&fpregs[r1],
    566						&fpregs[r2],extru(ir,fptpos,5),
    567						&local_status);
    568					update_status_cbit(status,local_status,
    569						fpu_type_flags, subop);
    570					return(retval);
    571				    case 1:
    572					retval = dbl_fcmp(&fpregs[r1],
    573						&fpregs[r2],extru(ir,fptpos,5),
    574						&local_status);
    575					update_status_cbit(status,local_status,
    576						fpu_type_flags, subop);
    577					return(retval);
    578				    case 2: /* illegal */
    579				    case 3: /* quad not implemented */
    580					return(MAJOR_0C_EXCP);
    581				}
    582			}
    583		}  /* end of if for PA2.0 */
    584		else {	/* PA1.0 & PA1.1 */
    585		    switch (subop) {
    586			case 2:
    587			case 3:
    588			case 4:
    589			case 5:
    590			case 6:
    591			case 7:
    592				return(MAJOR_0C_EXCP);
    593			case 0: /* FCMP */
    594				switch (fmt) {
    595				    case 0:
    596					retval = sgl_fcmp(&fpregs[r1],
    597						&fpregs[r2],extru(ir,fptpos,5),
    598						&local_status);
    599					update_status_cbit(status,local_status,
    600						fpu_type_flags, subop);
    601					return(retval);
    602				    case 1:
    603					retval = dbl_fcmp(&fpregs[r1],
    604						&fpregs[r2],extru(ir,fptpos,5),
    605						&local_status);
    606					update_status_cbit(status,local_status,
    607						fpu_type_flags, subop);
    608					return(retval);
    609				    case 2: /* illegal */
    610				    case 3: /* quad not implemented */
    611					return(MAJOR_0C_EXCP);
    612				}
    613				BUG();
    614			case 1: /* FTEST */
    615				switch (fmt) {
    616				    case 0:
    617					/*
    618					 * arg0 is not used
    619					 * second param is the t field used for
    620					 * ftest,acc and ftest,rej
    621					 * third param is the subop (y-field)
    622					 */
    623					BUG();
    624					/* unsupported
    625					 * return(ftest(0L,extru(ir,fptpos,5),
    626					 *     &fpregs[0],subop));
    627					 */
    628				    case 1:
    629				    case 2:
    630				    case 3:
    631					return(MAJOR_0C_EXCP);
    632				}
    633				BUG();
    634		    } /* end of switch subop */
    635		} /* end of else for PA1.0 & PA1.1 */
    636		BUG();
    637	case 3: /* class 3 */
    638		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
    639		if (r2 == 0)
    640			r2 = fpzeroreg;
    641		switch (subop) {
    642			case 5:
    643			case 6:
    644			case 7:
    645				return(MAJOR_0C_EXCP);
    646			
    647			case 0: /* FADD */
    648				switch (fmt) {
    649				    case 0:
    650					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
    651						&fpregs[t],status));
    652				    case 1:
    653					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
    654						&fpregs[t],status));
    655				    case 2: /* illegal */
    656				    case 3: /* quad not implemented */
    657					return(MAJOR_0C_EXCP);
    658				}
    659				BUG();
    660			case 1: /* FSUB */
    661				switch (fmt) {
    662				    case 0:
    663					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
    664						&fpregs[t],status));
    665				    case 1:
    666					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
    667						&fpregs[t],status));
    668				    case 2: /* illegal */
    669				    case 3: /* quad not implemented */
    670					return(MAJOR_0C_EXCP);
    671				}
    672				BUG();
    673			case 2: /* FMPY */
    674				switch (fmt) {
    675				    case 0:
    676					return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
    677						&fpregs[t],status));
    678				    case 1:
    679					return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
    680						&fpregs[t],status));
    681				    case 2: /* illegal */
    682				    case 3: /* quad not implemented */
    683					return(MAJOR_0C_EXCP);
    684				}
    685				BUG();
    686			case 3: /* FDIV */
    687				switch (fmt) {
    688				    case 0:
    689					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
    690						&fpregs[t],status));
    691				    case 1:
    692					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
    693						&fpregs[t],status));
    694				    case 2: /* illegal */
    695				    case 3: /* quad not implemented */
    696					return(MAJOR_0C_EXCP);
    697				}
    698				BUG();
    699			case 4: /* FREM */
    700				switch (fmt) {
    701				    case 0:
    702					return(sgl_frem(&fpregs[r1],&fpregs[r2],
    703						&fpregs[t],status));
    704				    case 1:
    705					return(dbl_frem(&fpregs[r1],&fpregs[r2],
    706						&fpregs[t],status));
    707				    case 2: /* illegal */
    708				    case 3: /* quad not implemented */
    709					return(MAJOR_0C_EXCP);
    710				}
    711				BUG();
    712		} /* end of class 3 switch */
    713	} /* end of switch(class) */
    714
    715	/* If we get here, something is really wrong! */
    716	return(MAJOR_0C_EXCP);
    717}
    718
    719static u_int
    720decode_0e(ir,class,subop,fpregs)
    721u_int ir,class,subop;
    722u_int fpregs[];
    723{
    724	u_int r1,r2,t;		/* operand register offsets */
    725	u_int fmt;		/* also sf for class 1 conversions */
    726	u_int df;		/* dest format for class 1 conversions */
    727	u_int *status;
    728	u_int retval, local_status;
    729	u_int fpu_type_flags;
    730
    731	status = &fpregs[0];
    732	local_status = fpregs[0];
    733	r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
    734	if (r1 == 0)
    735		r1 = fpzeroreg;
    736	t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
    737	if (t == 0 && class != 2)
    738		return(MAJOR_0E_EXCP);
    739	if (class < 2)		/* class 0 or 1 has 2 bit fmt */
    740		fmt = extru(ir,fpfmtpos,2);
    741	else 			/* class 2 and 3 have 1 bit fmt */
    742		fmt = extru(ir,fp0efmtpos,1);
    743	/*
    744	 * An undefined combination, double precision accessing the
    745	 * right half of a FPR, can get us into trouble.  
    746	 * Let's just force proper alignment on it.
    747	 */
    748	if (fmt == DBL) {
    749		r1 &= ~1;
    750		if (class != 1)
    751			t &= ~1;
    752	}
    753
    754	switch (class) {
    755	    case 0:
    756		switch (subop) {
    757			case 0: /* unimplemented */
    758			case 1:
    759				return(MAJOR_0E_EXCP);
    760			case 2: /* FCPY */
    761				switch (fmt) {
    762				    case 2:
    763				    case 3:
    764					return(MAJOR_0E_EXCP);
    765				    case 1: /* double */
    766					fpregs[t+1] = fpregs[r1+1];
    767					fallthrough;
    768				    case 0: /* single */
    769					fpregs[t] = fpregs[r1];
    770					return(NOEXCEPTION);
    771				}
    772				BUG();
    773			case 3: /* FABS */
    774				switch (fmt) {
    775				    case 2:
    776				    case 3:
    777					return(MAJOR_0E_EXCP);
    778				    case 1: /* double */
    779					fpregs[t+1] = fpregs[r1+1];
    780					fallthrough;
    781				    case 0: /* single */
    782					fpregs[t] = fpregs[r1] & 0x7fffffff;
    783					return(NOEXCEPTION);
    784				}
    785				BUG();
    786			case 6: /* FNEG */
    787				switch (fmt) {
    788				    case 2:
    789				    case 3:
    790					return(MAJOR_0E_EXCP);
    791				    case 1: /* double */
    792					fpregs[t+1] = fpregs[r1+1];
    793					fallthrough;
    794				    case 0: /* single */
    795					fpregs[t] = fpregs[r1] ^ 0x80000000;
    796					return(NOEXCEPTION);
    797				}
    798				BUG();
    799			case 7: /* FNEGABS */
    800				switch (fmt) {
    801				    case 2:
    802				    case 3:
    803					return(MAJOR_0E_EXCP);
    804				    case 1: /* double */
    805					fpregs[t+1] = fpregs[r1+1];
    806					fallthrough;
    807				    case 0: /* single */
    808					fpregs[t] = fpregs[r1] | 0x80000000;
    809					return(NOEXCEPTION);
    810				}
    811				BUG();
    812			case 4: /* FSQRT */
    813				switch (fmt) {
    814				    case 0:
    815					return(sgl_fsqrt(&fpregs[r1],0,
    816						&fpregs[t], status));
    817				    case 1:
    818					return(dbl_fsqrt(&fpregs[r1],0,
    819						&fpregs[t], status));
    820				    case 2:
    821				    case 3:
    822					return(MAJOR_0E_EXCP);
    823				}
    824				BUG();
    825			case 5: /* FRMD */
    826				switch (fmt) {
    827				    case 0:
    828					return(sgl_frnd(&fpregs[r1],0,
    829						&fpregs[t], status));
    830				    case 1:
    831					return(dbl_frnd(&fpregs[r1],0,
    832						&fpregs[t], status));
    833				    case 2:
    834				    case 3:
    835					return(MAJOR_0E_EXCP);
    836				}
    837		} /* end of switch (subop */
    838		BUG();
    839	case 1: /* class 1 */
    840		df = extru(ir,fpdfpos,2); /* get dest format */
    841		/*
    842		 * Fix Crashme problem (writing to 31R in double precision)
    843		 * here too.
    844		 */
    845		if (df == DBL) {
    846			t &= ~1;
    847		}
    848		if ((df & 2) || (fmt & 2))
    849			return(MAJOR_0E_EXCP);
    850		
    851		fmt = (fmt << 1) | df;
    852		switch (subop) {
    853			case 0: /* FCNVFF */
    854				switch(fmt) {
    855				    case 0: /* sgl/sgl */
    856					return(MAJOR_0E_EXCP);
    857				    case 1: /* sgl/dbl */
    858					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
    859						&fpregs[t],status));
    860				    case 2: /* dbl/sgl */
    861					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
    862						&fpregs[t],status));
    863				    case 3: /* dbl/dbl */
    864					return(MAJOR_0E_EXCP);
    865				}
    866				BUG();
    867			case 1: /* FCNVXF */
    868				switch(fmt) {
    869				    case 0: /* sgl/sgl */
    870					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
    871						&fpregs[t],status));
    872				    case 1: /* sgl/dbl */
    873					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
    874						&fpregs[t],status));
    875				    case 2: /* dbl/sgl */
    876					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
    877						&fpregs[t],status));
    878				    case 3: /* dbl/dbl */
    879					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
    880						&fpregs[t],status));
    881				}
    882				BUG();
    883			case 2: /* FCNVFX */
    884				switch(fmt) {
    885				    case 0: /* sgl/sgl */
    886					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
    887						&fpregs[t],status));
    888				    case 1: /* sgl/dbl */
    889					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
    890						&fpregs[t],status));
    891				    case 2: /* dbl/sgl */
    892					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
    893						&fpregs[t],status));
    894				    case 3: /* dbl/dbl */
    895					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
    896						&fpregs[t],status));
    897				}
    898				BUG();
    899			case 3: /* FCNVFXT */
    900				switch(fmt) {
    901				    case 0: /* sgl/sgl */
    902					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
    903						&fpregs[t],status));
    904				    case 1: /* sgl/dbl */
    905					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
    906						&fpregs[t],status));
    907				    case 2: /* dbl/sgl */
    908					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
    909						&fpregs[t],status));
    910				    case 3: /* dbl/dbl */
    911					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
    912						&fpregs[t],status));
    913				}
    914				BUG();
    915			case 5: /* FCNVUF (PA2.0 only) */
    916				switch(fmt) {
    917				    case 0: /* sgl/sgl */
    918					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
    919						&fpregs[t],status));
    920				    case 1: /* sgl/dbl */
    921					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
    922						&fpregs[t],status));
    923				    case 2: /* dbl/sgl */
    924					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
    925						&fpregs[t],status));
    926				    case 3: /* dbl/dbl */
    927					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
    928						&fpregs[t],status));
    929				}
    930				BUG();
    931			case 6: /* FCNVFU (PA2.0 only) */
    932				switch(fmt) {
    933				    case 0: /* sgl/sgl */
    934					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
    935						&fpregs[t],status));
    936				    case 1: /* sgl/dbl */
    937					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
    938						&fpregs[t],status));
    939				    case 2: /* dbl/sgl */
    940					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
    941						&fpregs[t],status));
    942				    case 3: /* dbl/dbl */
    943					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
    944						&fpregs[t],status));
    945				}
    946				BUG();
    947			case 7: /* FCNVFUT (PA2.0 only) */
    948				switch(fmt) {
    949				    case 0: /* sgl/sgl */
    950					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
    951						&fpregs[t],status));
    952				    case 1: /* sgl/dbl */
    953					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
    954						&fpregs[t],status));
    955				    case 2: /* dbl/sgl */
    956					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
    957						&fpregs[t],status));
    958				    case 3: /* dbl/dbl */
    959					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
    960						&fpregs[t],status));
    961				}
    962				BUG();
    963			case 4: /* undefined */
    964				return(MAJOR_0C_EXCP);
    965		} /* end of switch subop */
    966		BUG();
    967	case 2: /* class 2 */
    968		/*
    969		 * Be careful out there.
    970		 * Crashme can generate cases where FR31R is specified
    971		 * as the source or target of a double precision operation.
    972		 * Since we just pass the address of the floating-point
    973		 * register to the emulation routines, this can cause
    974		 * corruption of fpzeroreg.
    975		 */
    976		if (fmt == DBL)
    977			r2 = (extru(ir,fpr2pos,5)<<1);
    978		else
    979			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
    980		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
    981		if (r2 == 0)
    982			r2 = fpzeroreg;
    983		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
    984			/* FTEST if nullify bit set, otherwise FCMP */
    985			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
    986				/* not legal */
    987				return(MAJOR_0E_EXCP);
    988			} else {  /* FCMP */
    989			switch (fmt) {
    990				    /*
    991				     * fmt is only 1 bit long
    992				     */
    993				    case 0:
    994					retval = sgl_fcmp(&fpregs[r1],
    995						&fpregs[r2],extru(ir,fptpos,5),
    996						&local_status);
    997					update_status_cbit(status,local_status,
    998						fpu_type_flags, subop);
    999					return(retval);
   1000				    case 1:
   1001					retval = dbl_fcmp(&fpregs[r1],
   1002						&fpregs[r2],extru(ir,fptpos,5),
   1003						&local_status);
   1004					update_status_cbit(status,local_status,
   1005						fpu_type_flags, subop);
   1006					return(retval);
   1007				}
   1008			}
   1009		}  /* end of if for PA2.0 */
   1010		else {  /* PA1.0 & PA1.1 */
   1011		    switch (subop) {
   1012			case 1:
   1013			case 2:
   1014			case 3:
   1015			case 4:
   1016			case 5:
   1017			case 6:
   1018			case 7:
   1019				return(MAJOR_0E_EXCP);
   1020			case 0: /* FCMP */
   1021				switch (fmt) {
   1022				    /*
   1023				     * fmt is only 1 bit long
   1024				     */
   1025				    case 0:
   1026					retval = sgl_fcmp(&fpregs[r1],
   1027						&fpregs[r2],extru(ir,fptpos,5),
   1028						&local_status);
   1029					update_status_cbit(status,local_status,
   1030						fpu_type_flags, subop);
   1031					return(retval);
   1032				    case 1:
   1033					retval = dbl_fcmp(&fpregs[r1],
   1034						&fpregs[r2],extru(ir,fptpos,5),
   1035						&local_status);
   1036					update_status_cbit(status,local_status,
   1037						fpu_type_flags, subop);
   1038					return(retval);
   1039				}
   1040		    } /* end of switch subop */
   1041		} /* end of else for PA1.0 & PA1.1 */
   1042		BUG();
   1043	case 3: /* class 3 */
   1044		/*
   1045		 * Be careful out there.
   1046		 * Crashme can generate cases where FR31R is specified
   1047		 * as the source or target of a double precision operation.
   1048		 * Since we just pass the address of the floating-point
   1049		 * register to the emulation routines, this can cause
   1050		 * corruption of fpzeroreg.
   1051		 */
   1052		if (fmt == DBL)
   1053			r2 = (extru(ir,fpr2pos,5)<<1);
   1054		else
   1055			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
   1056		if (r2 == 0)
   1057			r2 = fpzeroreg;
   1058		switch (subop) {
   1059			case 5:
   1060			case 6:
   1061			case 7:
   1062				return(MAJOR_0E_EXCP);
   1063			
   1064			/*
   1065			 * Note that fmt is only 1 bit for class 3 */
   1066			case 0: /* FADD */
   1067				switch (fmt) {
   1068				    case 0:
   1069					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
   1070						&fpregs[t],status));
   1071				    case 1:
   1072					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
   1073						&fpregs[t],status));
   1074				}
   1075				BUG();
   1076			case 1: /* FSUB */
   1077				switch (fmt) {
   1078				    case 0:
   1079					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
   1080						&fpregs[t],status));
   1081				    case 1:
   1082					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
   1083						&fpregs[t],status));
   1084				}
   1085				BUG();
   1086			case 2: /* FMPY or XMPYU */
   1087				/*
   1088				 * check for integer multiply (x bit set)
   1089				 */
   1090				if (extru(ir,fpxpos,1)) {
   1091				    /*
   1092				     * emulate XMPYU
   1093				     */
   1094				    switch (fmt) {
   1095					case 0:
   1096					    /*
   1097					     * bad instruction if t specifies
   1098					     * the right half of a register
   1099					     */
   1100					    if (t & 1)
   1101						return(MAJOR_0E_EXCP);
   1102					    BUG();
   1103					    /* unsupported
   1104					     * impyu(&fpregs[r1],&fpregs[r2],
   1105						 * &fpregs[t]);
   1106					     */
   1107					    return(NOEXCEPTION);
   1108					case 1:
   1109						return(MAJOR_0E_EXCP);
   1110				    }
   1111				}
   1112				else { /* FMPY */
   1113				    switch (fmt) {
   1114				        case 0:
   1115					    return(sgl_fmpy(&fpregs[r1],
   1116					       &fpregs[r2],&fpregs[t],status));
   1117				        case 1:
   1118					    return(dbl_fmpy(&fpregs[r1],
   1119					       &fpregs[r2],&fpregs[t],status));
   1120				    }
   1121				}
   1122				BUG();
   1123			case 3: /* FDIV */
   1124				switch (fmt) {
   1125				    case 0:
   1126					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
   1127						&fpregs[t],status));
   1128				    case 1:
   1129					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
   1130						&fpregs[t],status));
   1131				}
   1132				BUG();
   1133			case 4: /* FREM */
   1134				switch (fmt) {
   1135				    case 0:
   1136					return(sgl_frem(&fpregs[r1],&fpregs[r2],
   1137						&fpregs[t],status));
   1138				    case 1:
   1139					return(dbl_frem(&fpregs[r1],&fpregs[r2],
   1140						&fpregs[t],status));
   1141				}
   1142		} /* end of class 3 switch */
   1143	} /* end of switch(class) */
   1144
   1145	/* If we get here, something is really wrong! */
   1146	return(MAJOR_0E_EXCP);
   1147}
   1148
   1149
   1150/*
   1151 * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
   1152 */
   1153static u_int
   1154decode_06(ir,fpregs)
   1155u_int ir;
   1156u_int fpregs[];
   1157{
   1158	u_int rm1, rm2, tm, ra, ta; /* operands */
   1159	u_int fmt;
   1160	u_int error = 0;
   1161	u_int status;
   1162	u_int fpu_type_flags;
   1163	union {
   1164		double dbl;
   1165		float flt;
   1166		struct { u_int i1; u_int i2; } ints;
   1167	} mtmp, atmp;
   1168
   1169
   1170	status = fpregs[0];		/* use a local copy of status reg */
   1171	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
   1172	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
   1173	if (fmt == 0) { /* DBL */
   1174		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
   1175		if (rm1 == 0)
   1176			rm1 = fpzeroreg;
   1177		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
   1178		if (rm2 == 0)
   1179			rm2 = fpzeroreg;
   1180		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
   1181		if (tm == 0)
   1182			return(MAJOR_06_EXCP);
   1183		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
   1184		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
   1185		if (ta == 0)
   1186			return(MAJOR_06_EXCP);
   1187
   1188		if  (fpu_type_flags & TIMEX_ROLEX_FPU_MASK)  {
   1189
   1190			if (ra == 0) {
   1191			 	/* special case FMPYCFXT, see sgl case below */
   1192				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
   1193					&mtmp.ints.i1,&status))
   1194					error = 1;
   1195				if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
   1196					&atmp.ints.i1,&atmp.ints.i1,&status))
   1197					error = 1;
   1198				}
   1199			else {
   1200
   1201			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
   1202					&status))
   1203				error = 1;
   1204			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
   1205					&status))
   1206				error = 1;
   1207				}
   1208			}
   1209
   1210		else
   1211
   1212			{
   1213			if (ra == 0)
   1214				ra = fpzeroreg;
   1215
   1216			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
   1217					&status))
   1218				error = 1;
   1219			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
   1220					&status))
   1221				error = 1;
   1222
   1223			}
   1224
   1225		if (error)
   1226			return(MAJOR_06_EXCP);
   1227		else {
   1228			/* copy results */
   1229			fpregs[tm] = mtmp.ints.i1;
   1230			fpregs[tm+1] = mtmp.ints.i2;
   1231			fpregs[ta] = atmp.ints.i1;
   1232			fpregs[ta+1] = atmp.ints.i2;
   1233			fpregs[0] = status;
   1234			return(NOEXCEPTION);
   1235		}
   1236	}
   1237	else { /* SGL */
   1238		/*
   1239		 * calculate offsets for single precision numbers
   1240		 * See table 6-14 in PA-89 architecture for mapping
   1241		 */
   1242		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
   1243		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
   1244
   1245		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
   1246		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
   1247
   1248		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
   1249		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
   1250
   1251		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
   1252		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
   1253
   1254		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
   1255		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
   1256		
   1257		if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
   1258			/* special case FMPYCFXT (really 0)
   1259			  * This instruction is only present on the Timex and
   1260			  * Rolex fpu's in so if it is the special case and
   1261			  * one of these fpu's we run the FMPYCFXT instruction
   1262			  */
   1263			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
   1264					&status))
   1265				error = 1;
   1266			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
   1267				&atmp.ints.i1,&status))
   1268				error = 1;
   1269		}
   1270		else {
   1271			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
   1272					&status))
   1273				error = 1;
   1274			if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
   1275					&status))
   1276				error = 1;
   1277		}
   1278		if (error)
   1279			return(MAJOR_06_EXCP);
   1280		else {
   1281			/* copy results */
   1282			fpregs[tm] = mtmp.ints.i1;
   1283			fpregs[ta] = atmp.ints.i1;
   1284			fpregs[0] = status;
   1285			return(NOEXCEPTION);
   1286		}
   1287	}
   1288}
   1289
   1290/*
   1291 * routine to decode the 26 (FMPYSUB) instruction
   1292 */
   1293static u_int
   1294decode_26(ir,fpregs)
   1295u_int ir;
   1296u_int fpregs[];
   1297{
   1298	u_int rm1, rm2, tm, ra, ta; /* operands */
   1299	u_int fmt;
   1300	u_int error = 0;
   1301	u_int status;
   1302	union {
   1303		double dbl;
   1304		float flt;
   1305		struct { u_int i1; u_int i2; } ints;
   1306	} mtmp, atmp;
   1307
   1308
   1309	status = fpregs[0];
   1310	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
   1311	if (fmt == 0) { /* DBL */
   1312		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
   1313		if (rm1 == 0)
   1314			rm1 = fpzeroreg;
   1315		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
   1316		if (rm2 == 0)
   1317			rm2 = fpzeroreg;
   1318		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
   1319		if (tm == 0)
   1320			return(MAJOR_26_EXCP);
   1321		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
   1322		if (ra == 0)
   1323			return(MAJOR_26_EXCP);
   1324		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
   1325		if (ta == 0)
   1326			return(MAJOR_26_EXCP);
   1327		
   1328		if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
   1329			error = 1;
   1330		if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
   1331			error = 1;
   1332		if (error)
   1333			return(MAJOR_26_EXCP);
   1334		else {
   1335			/* copy results */
   1336			fpregs[tm] = mtmp.ints.i1;
   1337			fpregs[tm+1] = mtmp.ints.i2;
   1338			fpregs[ta] = atmp.ints.i1;
   1339			fpregs[ta+1] = atmp.ints.i2;
   1340			fpregs[0] = status;
   1341			return(NOEXCEPTION);
   1342		}
   1343	}
   1344	else { /* SGL */
   1345		/*
   1346		 * calculate offsets for single precision numbers
   1347		 * See table 6-14 in PA-89 architecture for mapping
   1348		 */
   1349		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
   1350		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
   1351
   1352		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
   1353		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
   1354
   1355		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
   1356		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
   1357
   1358		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
   1359		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
   1360
   1361		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
   1362		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
   1363		
   1364		if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
   1365			error = 1;
   1366		if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
   1367			error = 1;
   1368		if (error)
   1369			return(MAJOR_26_EXCP);
   1370		else {
   1371			/* copy results */
   1372			fpregs[tm] = mtmp.ints.i1;
   1373			fpregs[ta] = atmp.ints.i1;
   1374			fpregs[0] = status;
   1375			return(NOEXCEPTION);
   1376		}
   1377	}
   1378
   1379}
   1380
   1381/*
   1382 * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
   1383 */
   1384static u_int
   1385decode_2e(ir,fpregs)
   1386u_int ir;
   1387u_int fpregs[];
   1388{
   1389	u_int rm1, rm2, ra, t; /* operands */
   1390	u_int fmt;
   1391
   1392	fmt = extru(ir,fpfmtpos,1);	/* get fmt completer */
   1393	if (fmt == DBL) { /* DBL */
   1394		rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
   1395		if (rm1 == 0)
   1396			rm1 = fpzeroreg;
   1397		rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
   1398		if (rm2 == 0)
   1399			rm2 = fpzeroreg;
   1400		ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
   1401		     sizeof(double)/sizeof(u_int);
   1402		if (ra == 0)
   1403			ra = fpzeroreg;
   1404		t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
   1405		if (t == 0)
   1406			return(MAJOR_2E_EXCP);
   1407
   1408		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
   1409			return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
   1410					&fpregs[ra], &fpregs[0], &fpregs[t]));
   1411		} else {
   1412			return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
   1413					&fpregs[ra], &fpregs[0], &fpregs[t]));
   1414		}
   1415	} /* end DBL */
   1416	else { /* SGL */
   1417		rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
   1418		if (rm1 == 0)
   1419			rm1 = fpzeroreg;
   1420		rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
   1421		if (rm2 == 0)
   1422			rm2 = fpzeroreg;
   1423		ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
   1424		if (ra == 0)
   1425			ra = fpzeroreg;
   1426		t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
   1427		if (t == 0)
   1428			return(MAJOR_2E_EXCP);
   1429
   1430		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
   1431			return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
   1432					&fpregs[ra], &fpregs[0], &fpregs[t]));
   1433		} else {
   1434			return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
   1435					&fpregs[ra], &fpregs[0], &fpregs[t]));
   1436		}
   1437	} /* end SGL */
   1438}
   1439
   1440/*
   1441 * update_status_cbit
   1442 *
   1443 *	This routine returns the correct FP status register value in
   1444 *	*status, based on the C-bit & V-bit returned by the FCMP
   1445 *	emulation routine in new_status.  The architecture type
   1446 *	(PA83, PA89 or PA2.0) is available in fpu_type.  The y_field
   1447 *	and the architecture type are used to determine what flavor
   1448 *	of FCMP is being emulated.
   1449 */
   1450static void
   1451update_status_cbit(status, new_status, fpu_type, y_field)
   1452u_int *status, new_status;
   1453u_int fpu_type;
   1454u_int y_field;
   1455{
   1456	/*
   1457	 * For PA89 FPU's which implement the Compare Queue and
   1458	 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
   1459	 * otherwise update the specified bit in the Compare Array.
   1460	 * Note that the y-field will always be 0 for non-PA2.0 FPU's.
   1461	 */
   1462	if ((fpu_type & TIMEX_EXTEN_FLAG) || 
   1463	    (fpu_type & ROLEX_EXTEN_FLAG) ||
   1464	    (fpu_type & PA2_0_FPU_FLAG)) {
   1465		if (y_field == 0) {
   1466			*status = ((*status & 0x04000000) >> 5) | /* old Cbit */
   1467				  ((*status & 0x003ff000) >> 1) | /* old CQ   */
   1468				  (new_status & 0xffc007ff); /* all other bits*/
   1469		} else {
   1470			*status = (*status & 0x04000000) |     /* old Cbit */
   1471				  ((new_status & 0x04000000) >> (y_field+4)) |
   1472				  (new_status & ~0x04000000 &  /* other bits */
   1473				   ~(0x04000000 >> (y_field+4)));
   1474		}
   1475	}
   1476	/* if PA83, just update the C-bit */
   1477	else {
   1478		*status = new_status;
   1479	}
   1480}