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