xref: /linux/arch/parisc/math-emu/fpudispatch.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
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)
141 static u_int decode_0c(u_int, u_int, u_int, u_int *);
142 static u_int decode_0e(u_int, u_int, u_int, u_int *);
143 static u_int decode_06(u_int, u_int *);
144 static u_int decode_26(u_int, u_int *);
145 static u_int decode_2e(u_int, u_int *);
146 static void update_status_cbit(u_int *, u_int, u_int, u_int);
147 #else /* !_PROTOTYPES&&!_lint */
148 static u_int decode_0c();
149 static u_int decode_0e();
150 static u_int decode_06();
151 static u_int decode_26();
152 static u_int decode_2e();
153 static void update_status_cbit();
154 #endif /* _PROTOTYPES&&!_lint */
155 
156 #define VASSERT(x)
157 
parisc_linux_get_fpu_type(u_int fpregs[])158 static 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  */
181 u_int
fpudispatch(u_int ir,u_int excp_code,u_int holder,u_int fpregs[])182 fpudispatch(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  */
236 u_int
emfpudispatch(u_int ir,u_int dummy1,u_int dummy2,u_int fpregs[])237 emfpudispatch(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 
274 static u_int
decode_0c(u_int ir,u_int class,u_int subop,u_int fpregs[])275 decode_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 
719 static u_int
decode_0e(ir,class,subop,fpregs)720 decode_0e(ir,class,subop,fpregs)
721 u_int ir,class,subop;
722 u_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  */
1153 static u_int
decode_06(ir,fpregs)1154 decode_06(ir,fpregs)
1155 u_int ir;
1156 u_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  */
1293 static u_int
decode_26(ir,fpregs)1294 decode_26(ir,fpregs)
1295 u_int ir;
1296 u_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  */
1384 static u_int
decode_2e(ir,fpregs)1385 decode_2e(ir,fpregs)
1386 u_int ir;
1387 u_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  */
1450 static void
update_status_cbit(status,new_status,fpu_type,y_field)1451 update_status_cbit(status, new_status, fpu_type, y_field)
1452 u_int *status, new_status;
1453 u_int fpu_type;
1454 u_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 }
1481