File Index
Files and directories
Sign in
FILE

fpudispatch.c

File preview with syntax highlighting.

linux-6.19.14/arch/parisc/math-emu/fpudispatch.c C
   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}
~/ Read-only file preview.