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