Home | History | Annotate | Line # | Download | only in mips
cp1.c revision 1.10
      1   1.1  christos /*> cp1.c <*/
      2   1.1  christos /* MIPS Simulator FPU (CoProcessor 1) support.
      3  1.10  christos    Copyright (C) 2002-2023 Free Software Foundation, Inc.
      4   1.1  christos    Originally created by Cygnus Solutions.  Extensive modifications,
      5   1.1  christos    including paired-single operation support and MIPS-3D support
      6   1.1  christos    contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
      7   1.1  christos    Corporation (SiByte).
      8   1.1  christos 
      9   1.1  christos This file is part of GDB, the GNU debugger.
     10   1.1  christos 
     11   1.1  christos This program is free software; you can redistribute it and/or modify
     12   1.1  christos it under the terms of the GNU General Public License as published by
     13   1.1  christos the Free Software Foundation; either version 3 of the License, or
     14   1.1  christos (at your option) any later version.
     15   1.1  christos 
     16   1.1  christos This program is distributed in the hope that it will be useful,
     17   1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     18   1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19   1.1  christos GNU General Public License for more details.
     20   1.1  christos 
     21   1.1  christos You should have received a copy of the GNU General Public License
     22   1.1  christos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     23   1.1  christos 
     24   1.1  christos /* XXX: The following notice should be removed as soon as is practical:  */
     25   1.1  christos /* Floating Point Support for gdb MIPS simulators
     26   1.1  christos 
     27   1.1  christos    This file is part of the MIPS sim
     28   1.1  christos 
     29   1.1  christos 		THIS SOFTWARE IS NOT COPYRIGHTED
     30   1.1  christos    (by Cygnus.)
     31   1.1  christos 
     32   1.1  christos    Cygnus offers the following for use in the public domain.  Cygnus
     33   1.1  christos    makes no warranty with regard to the software or it's performance
     34   1.1  christos    and the user accepts the software "AS IS" with all faults.
     35   1.1  christos 
     36   1.1  christos    CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
     37   1.1  christos    THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     38   1.1  christos    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     39   1.1  christos 
     40   1.1  christos    (Originally, this code was in interp.c)
     41   1.1  christos */
     42   1.1  christos 
     43  1.10  christos /* This must come before any other includes.  */
     44  1.10  christos #include "defs.h"
     45  1.10  christos 
     46   1.1  christos #include "sim-main.h"
     47   1.1  christos 
     48  1.10  christos #include <stdlib.h>
     49  1.10  christos 
     50   1.1  christos /* Within cp1.c we refer to sim_cpu directly.  */
     51   1.1  christos #define CPU cpu
     52   1.1  christos #define SD CPU_STATE(cpu)
     53   1.1  christos 
     54   1.1  christos /*-- FPU support routines ---------------------------------------------------*/
     55   1.1  christos 
     56   1.1  christos /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
     57   1.1  christos    formats conform to ANSI/IEEE Std 754-1985.
     58   1.1  christos 
     59   1.1  christos    SINGLE precision floating:
     60   1.1  christos       seeeeeeeefffffffffffffffffffffff
     61   1.1  christos         s =  1bit  = sign
     62   1.1  christos         e =  8bits = exponent
     63   1.1  christos         f = 23bits = fraction
     64   1.1  christos 
     65   1.1  christos    SINGLE precision fixed:
     66   1.1  christos       siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
     67   1.1  christos         s =  1bit  = sign
     68   1.1  christos         i = 31bits = integer
     69   1.1  christos 
     70   1.1  christos    DOUBLE precision floating:
     71   1.1  christos       seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
     72   1.1  christos         s =  1bit  = sign
     73   1.1  christos         e = 11bits = exponent
     74   1.1  christos         f = 52bits = fraction
     75   1.1  christos 
     76   1.1  christos    DOUBLE precision fixed:
     77   1.1  christos       siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
     78   1.1  christos         s =  1bit  = sign
     79   1.1  christos         i = 63bits = integer
     80   1.1  christos 
     81   1.1  christos    PAIRED SINGLE precision floating:
     82   1.1  christos       seeeeeeeefffffffffffffffffffffffseeeeeeeefffffffffffffffffffffff
     83   1.1  christos       |         upper                ||         lower                |
     84   1.1  christos         s =  1bit  = sign
     85   1.1  christos         e =  8bits = exponent
     86   1.1  christos         f = 23bits = fraction
     87   1.1  christos     Note: upper = [63..32], lower = [31..0]
     88   1.1  christos  */
     89   1.1  christos 
     90   1.1  christos /* Extract packed single values:  */
     91   1.1  christos #define FP_PS_upper(v) (((v) >> 32) & (unsigned)0xFFFFFFFF)
     92   1.1  christos #define FP_PS_lower(v) ((v) & (unsigned)0xFFFFFFFF)
     93  1.10  christos #define FP_PS_cat(u,l) (((uint64_t)((u) & (unsigned)0xFFFFFFFF) << 32) \
     94  1.10  christos                         | (uint64_t)((l) & 0xFFFFFFFF))
     95   1.1  christos 
     96   1.1  christos /* Explicit QNaN values.  */
     97   1.1  christos #define FPQNaN_SINGLE   (0x7FBFFFFF)
     98   1.1  christos #define FPQNaN_WORD     (0x7FFFFFFF)
     99   1.1  christos #define FPQNaN_DOUBLE   (UNSIGNED64 (0x7FF7FFFFFFFFFFFF))
    100   1.1  christos #define FPQNaN_LONG     (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
    101   1.1  christos #define FPQNaN_PS       (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
    102   1.1  christos 
    103  1.10  christos static void update_fcsr (sim_cpu *, address_word, sim_fpu_status);
    104  1.10  christos 
    105   1.1  christos static const char *fpu_format_name (FP_formats fmt);
    106   1.1  christos #ifdef DEBUG
    107   1.1  christos static const char *fpu_rounding_mode_name (int rm);
    108   1.1  christos #endif
    109   1.1  christos 
    110   1.1  christos uword64
    111   1.1  christos value_fpr (sim_cpu *cpu,
    112   1.1  christos 	   address_word cia,
    113   1.1  christos 	   int fpr,
    114   1.1  christos 	   FP_formats fmt)
    115   1.1  christos {
    116   1.1  christos   uword64 value = 0;
    117   1.1  christos   int err = 0;
    118   1.1  christos 
    119   1.1  christos   /* Treat unused register values, as fixed-point 64bit values.  */
    120   1.1  christos   if (fmt == fmt_unknown)
    121   1.1  christos     {
    122   1.1  christos #if 1
    123   1.1  christos       /* If request to read data as "unknown", then use the current
    124   1.1  christos 	 encoding:  */
    125   1.1  christos       fmt = FPR_STATE[fpr];
    126   1.1  christos #else
    127   1.1  christos       fmt = fmt_long;
    128   1.1  christos #endif
    129   1.1  christos     }
    130   1.1  christos 
    131   1.1  christos   /* For values not yet accessed, set to the desired format.  */
    132  1.10  christos   if (fmt < fmt_uninterpreted && fmt != fmt_dc32)
    133   1.1  christos     {
    134   1.1  christos       if (FPR_STATE[fpr] == fmt_uninterpreted)
    135   1.1  christos 	{
    136   1.1  christos 	  FPR_STATE[fpr] = fmt;
    137   1.1  christos #ifdef DEBUG
    138   1.1  christos 	  printf ("DBG: Register %d was fmt_uninterpreted. Now %s\n", fpr,
    139   1.1  christos 		  fpu_format_name (fmt));
    140   1.1  christos #endif /* DEBUG */
    141   1.1  christos 	}
    142  1.10  christos       else if (fmt != FPR_STATE[fpr]
    143  1.10  christos 	       && !(fmt == fmt_single
    144  1.10  christos 		    && FPR_STATE[fpr] == fmt_double
    145  1.10  christos 		    && (FGR[fpr] == 0 || FGR[fpr] == 0xFFFFFFFF)))
    146   1.1  christos 	{
    147   1.1  christos 	  sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
    148   1.1  christos 			  fpr, fpu_format_name (FPR_STATE[fpr]),
    149   1.1  christos 			  fpu_format_name (fmt), pr_addr (cia));
    150   1.1  christos 	  FPR_STATE[fpr] = fmt_unknown;
    151   1.1  christos 	}
    152   1.1  christos     }
    153   1.1  christos 
    154   1.1  christos   if (FPR_STATE[fpr] == fmt_unknown)
    155   1.1  christos     {
    156   1.1  christos       /* Set QNaN value:  */
    157   1.1  christos       switch (fmt)
    158   1.1  christos 	{
    159   1.1  christos 	case fmt_single:  value = FPQNaN_SINGLE;  break;
    160   1.1  christos 	case fmt_double:  value = FPQNaN_DOUBLE;  break;
    161   1.1  christos 	case fmt_word:    value = FPQNaN_WORD;    break;
    162   1.1  christos 	case fmt_long:    value = FPQNaN_LONG;    break;
    163   1.1  christos 	case fmt_ps:      value = FPQNaN_PS;      break;
    164   1.1  christos 	default:          err = -1;               break;
    165   1.1  christos 	}
    166   1.1  christos     }
    167   1.1  christos   else if (SizeFGR () == 64)
    168   1.1  christos     {
    169   1.1  christos       switch (fmt)
    170   1.1  christos 	{
    171   1.1  christos 	case fmt_uninterpreted_32:
    172   1.1  christos 	case fmt_single:
    173   1.1  christos 	case fmt_word:
    174  1.10  christos 	case fmt_dc32:
    175   1.1  christos 	  value = (FGR[fpr] & 0xFFFFFFFF);
    176   1.1  christos 	  break;
    177   1.1  christos 
    178   1.1  christos 	case fmt_uninterpreted_64:
    179   1.1  christos 	case fmt_uninterpreted:
    180   1.1  christos 	case fmt_double:
    181   1.1  christos 	case fmt_long:
    182   1.1  christos 	case fmt_ps:
    183   1.1  christos 	  value = FGR[fpr];
    184   1.1  christos 	  break;
    185   1.1  christos 
    186   1.1  christos 	default:
    187   1.1  christos 	  err = -1;
    188   1.1  christos 	  break;
    189   1.1  christos 	}
    190   1.1  christos     }
    191   1.1  christos   else
    192   1.1  christos     {
    193   1.1  christos       switch (fmt)
    194   1.1  christos 	{
    195   1.1  christos 	case fmt_uninterpreted_32:
    196   1.1  christos 	case fmt_single:
    197   1.1  christos 	case fmt_word:
    198   1.1  christos 	  value = (FGR[fpr] & 0xFFFFFFFF);
    199   1.1  christos 	  break;
    200   1.1  christos 
    201   1.1  christos 	case fmt_uninterpreted_64:
    202   1.1  christos 	case fmt_uninterpreted:
    203   1.1  christos 	case fmt_double:
    204   1.1  christos 	case fmt_long:
    205   1.1  christos 	  if ((fpr & 1) == 0)
    206   1.1  christos 	    {
    207   1.1  christos 	      /* Even register numbers only.  */
    208   1.1  christos #ifdef DEBUG
    209   1.1  christos 	      printf ("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
    210   1.1  christos 		      fpr + 1, pr_uword64 ((uword64) FGR[fpr+1]),
    211   1.1  christos 		      fpr, pr_uword64 ((uword64) FGR[fpr]));
    212   1.1  christos #endif
    213   1.1  christos 	      value = ((((uword64) FGR[fpr+1]) << 32)
    214   1.1  christos 		       | (FGR[fpr] & 0xFFFFFFFF));
    215   1.1  christos 	    }
    216   1.1  christos 	  else
    217   1.1  christos 	    {
    218   1.1  christos 	      SignalException (ReservedInstruction, 0);
    219   1.1  christos 	    }
    220   1.1  christos 	  break;
    221   1.1  christos 
    222   1.1  christos 	case fmt_ps:
    223   1.1  christos 	  SignalException (ReservedInstruction, 0);
    224   1.1  christos 	  break;
    225   1.1  christos 
    226   1.1  christos 	default:
    227   1.1  christos 	  err = -1;
    228   1.1  christos 	  break;
    229   1.1  christos 	}
    230   1.1  christos     }
    231   1.1  christos 
    232   1.1  christos   if (err)
    233   1.1  christos     SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR ()");
    234   1.1  christos 
    235   1.1  christos #ifdef DEBUG
    236   1.1  christos   printf ("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d\n",
    237   1.1  christos 	  fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
    238   1.1  christos 	  SizeFGR ());
    239   1.1  christos #endif /* DEBUG */
    240   1.1  christos 
    241   1.1  christos   return (value);
    242   1.1  christos }
    243   1.1  christos 
    244   1.1  christos void
    245   1.1  christos store_fpr (sim_cpu *cpu,
    246   1.1  christos 	   address_word cia,
    247   1.1  christos 	   int fpr,
    248   1.1  christos 	   FP_formats fmt,
    249   1.1  christos 	   uword64 value)
    250   1.1  christos {
    251   1.1  christos   int err = 0;
    252   1.1  christos 
    253   1.1  christos #ifdef DEBUG
    254   1.1  christos   printf ("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR () = %d, \n",
    255   1.1  christos 	  fpr, fpu_format_name (fmt), pr_uword64 (value), pr_addr (cia),
    256   1.1  christos 	  SizeFGR ());
    257   1.1  christos #endif /* DEBUG */
    258   1.1  christos 
    259   1.1  christos   if (SizeFGR () == 64)
    260   1.1  christos     {
    261   1.1  christos       switch (fmt)
    262   1.1  christos 	{
    263   1.1  christos 	case fmt_uninterpreted_32:
    264   1.1  christos 	  fmt = fmt_uninterpreted;
    265   1.1  christos 	case fmt_single:
    266   1.1  christos 	case fmt_word:
    267   1.1  christos 	  if (STATE_VERBOSE_P (SD))
    268   1.1  christos 	    sim_io_eprintf (SD,
    269   1.1  christos 			    "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
    270   1.1  christos 			    pr_addr (cia));
    271   1.1  christos 	  FGR[fpr] = (((uword64) 0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
    272   1.1  christos 	  FPR_STATE[fpr] = fmt;
    273   1.1  christos 	  break;
    274   1.1  christos 
    275   1.1  christos 	case fmt_uninterpreted_64:
    276   1.1  christos 	  fmt = fmt_uninterpreted;
    277   1.1  christos 	case fmt_uninterpreted:
    278   1.1  christos 	case fmt_double:
    279   1.1  christos 	case fmt_long:
    280   1.1  christos 	case fmt_ps:
    281   1.1  christos 	  FGR[fpr] = value;
    282   1.1  christos 	  FPR_STATE[fpr] = fmt;
    283   1.1  christos 	  break;
    284   1.1  christos 
    285   1.1  christos 	default:
    286   1.1  christos 	  FPR_STATE[fpr] = fmt_unknown;
    287   1.1  christos 	  err = -1;
    288   1.1  christos 	  break;
    289   1.1  christos 	}
    290   1.1  christos     }
    291   1.1  christos   else
    292   1.1  christos     {
    293   1.1  christos       switch (fmt)
    294   1.1  christos 	{
    295   1.1  christos 	case fmt_uninterpreted_32:
    296   1.1  christos 	  fmt = fmt_uninterpreted;
    297   1.1  christos 	case fmt_single:
    298   1.1  christos 	case fmt_word:
    299   1.1  christos 	  FGR[fpr] = (value & 0xFFFFFFFF);
    300   1.1  christos 	  FPR_STATE[fpr] = fmt;
    301   1.1  christos 	  break;
    302   1.1  christos 
    303   1.1  christos 	case fmt_uninterpreted_64:
    304   1.1  christos 	  fmt = fmt_uninterpreted;
    305   1.1  christos 	case fmt_uninterpreted:
    306   1.1  christos 	case fmt_double:
    307   1.1  christos 	case fmt_long:
    308   1.1  christos 	  if ((fpr & 1) == 0)
    309   1.1  christos 	    {
    310   1.1  christos 	      /* Even register numbers only.  */
    311   1.1  christos 	      FGR[fpr+1] = (value >> 32);
    312   1.1  christos 	      FGR[fpr] = (value & 0xFFFFFFFF);
    313   1.1  christos 	      FPR_STATE[fpr + 1] = fmt;
    314   1.1  christos 	      FPR_STATE[fpr] = fmt;
    315   1.1  christos 	    }
    316   1.1  christos 	  else
    317   1.1  christos 	    {
    318   1.1  christos 	      FPR_STATE[fpr] = fmt_unknown;
    319   1.1  christos 	      FPR_STATE[fpr ^ 1] = fmt_unknown;
    320   1.1  christos 	      SignalException (ReservedInstruction, 0);
    321   1.1  christos 	    }
    322   1.1  christos 	  break;
    323   1.1  christos 
    324   1.1  christos 	case fmt_ps:
    325   1.1  christos 	  FPR_STATE[fpr] = fmt_unknown;
    326   1.1  christos 	  SignalException (ReservedInstruction, 0);
    327   1.1  christos 	  break;
    328   1.1  christos 
    329   1.1  christos 	default:
    330   1.1  christos 	  FPR_STATE[fpr] = fmt_unknown;
    331   1.1  christos 	  err = -1;
    332   1.1  christos 	  break;
    333   1.1  christos 	}
    334   1.1  christos     }
    335   1.1  christos 
    336   1.1  christos   if (err)
    337   1.1  christos     SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
    338   1.1  christos 
    339   1.1  christos #ifdef DEBUG
    340   1.1  christos   printf ("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",
    341   1.1  christos 	  fpr, pr_uword64 (FGR[fpr]), fpu_format_name (fmt));
    342   1.1  christos #endif /* DEBUG */
    343   1.1  christos 
    344   1.1  christos   return;
    345   1.1  christos }
    346   1.1  christos 
    347   1.1  christos 
    348   1.1  christos /* CP1 control/status register access functions.  */
    349   1.1  christos 
    350   1.1  christos void
    351   1.1  christos test_fcsr (sim_cpu *cpu,
    352   1.1  christos 	   address_word cia)
    353   1.1  christos {
    354   1.1  christos   unsigned int cause;
    355   1.1  christos 
    356   1.1  christos   cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
    357   1.1  christos   if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
    358   1.1  christos       || (cause & (1 << UO)))
    359   1.1  christos     {
    360   1.1  christos       SignalExceptionFPE();
    361   1.1  christos     }
    362   1.1  christos }
    363   1.1  christos 
    364   1.1  christos unsigned_word
    365   1.1  christos value_fcr(sim_cpu *cpu,
    366   1.1  christos 	  address_word cia,
    367   1.1  christos 	  int fcr)
    368   1.1  christos {
    369  1.10  christos   uint32_t value = 0;
    370   1.1  christos 
    371   1.1  christos   switch (fcr)
    372   1.1  christos     {
    373   1.1  christos     case 0:  /* FP Implementation and Revision Register.  */
    374   1.1  christos       value = FCR0;
    375   1.1  christos       break;
    376   1.1  christos     case 25:  /* FP Condition Codes Register (derived from FCSR).  */
    377   1.1  christos       value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
    378   1.1  christos       value = (value & 0x1) | (value >> 1);   /* Close FCC gap.  */
    379   1.1  christos       break;
    380   1.1  christos     case 26:  /* FP Exceptions Register (derived from FCSR).  */
    381   1.1  christos       value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
    382   1.1  christos       break;
    383   1.1  christos     case 28:  /* FP Enables Register (derived from FCSR).  */
    384   1.1  christos       value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
    385   1.1  christos       if ((FCR31 & fcsr_FS) != 0)
    386   1.1  christos 	value |= fenr_FS;
    387   1.1  christos       break;
    388   1.1  christos     case 31:  /* FP Control/Status Register (FCSR).  */
    389   1.1  christos       value = FCR31 & ~fcsr_ZERO_mask;
    390   1.1  christos       break;
    391   1.1  christos     }
    392   1.1  christos 
    393   1.1  christos   return (EXTEND32 (value));
    394   1.1  christos }
    395   1.1  christos 
    396   1.1  christos void
    397   1.1  christos store_fcr(sim_cpu *cpu,
    398   1.1  christos 	  address_word cia,
    399   1.1  christos 	  int fcr,
    400   1.1  christos 	  unsigned_word value)
    401   1.1  christos {
    402  1.10  christos   uint32_t v;
    403   1.1  christos 
    404   1.1  christos   v = VL4_8(value);
    405   1.1  christos   switch (fcr)
    406   1.1  christos     {
    407   1.1  christos     case 25:  /* FP Condition Codes Register (stored into FCSR).  */
    408   1.1  christos       v = (v << 1) | (v & 0x1);             /* Adjust for FCC gap.  */
    409   1.1  christos       FCR31 &= ~fcsr_FCC_mask;
    410   1.1  christos       FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
    411   1.1  christos       break;
    412   1.1  christos     case 26:  /* FP Exceptions Register (stored into FCSR).  */
    413   1.1  christos       FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
    414   1.1  christos       FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
    415   1.1  christos       test_fcsr(cpu, cia);
    416   1.1  christos       break;
    417   1.1  christos     case 28:  /* FP Enables Register (stored into FCSR).  */
    418   1.1  christos       if ((v & fenr_FS) != 0)
    419   1.1  christos 	v |= fcsr_FS;
    420   1.1  christos       else
    421   1.1  christos 	v &= ~fcsr_FS;
    422   1.1  christos       FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
    423   1.1  christos       FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
    424   1.1  christos       test_fcsr(cpu, cia);
    425   1.1  christos       break;
    426   1.1  christos     case 31:  /* FP Control/Status Register (FCSR).  */
    427   1.1  christos       FCR31 = v & ~fcsr_ZERO_mask;
    428   1.1  christos       test_fcsr(cpu, cia);
    429   1.1  christos       break;
    430   1.1  christos     }
    431   1.1  christos }
    432   1.1  christos 
    433  1.10  christos static void
    434   1.1  christos update_fcsr (sim_cpu *cpu,
    435   1.1  christos 	     address_word cia,
    436   1.1  christos 	     sim_fpu_status status)
    437   1.1  christos {
    438   1.1  christos   FCSR &= ~fcsr_CAUSE_mask;
    439   1.1  christos 
    440   1.1  christos   if (status != 0)
    441   1.1  christos     {
    442   1.1  christos       unsigned int cause = 0;
    443   1.1  christos 
    444   1.1  christos       /* map between sim_fpu codes and MIPS FCSR */
    445   1.1  christos       if (status & (sim_fpu_status_invalid_snan
    446   1.1  christos 		    | sim_fpu_status_invalid_isi
    447   1.1  christos 		    | sim_fpu_status_invalid_idi
    448   1.1  christos 		    | sim_fpu_status_invalid_zdz
    449   1.1  christos 		    | sim_fpu_status_invalid_imz
    450   1.1  christos 		    | sim_fpu_status_invalid_cmp
    451   1.1  christos 		    | sim_fpu_status_invalid_sqrt
    452   1.1  christos 		    | sim_fpu_status_invalid_cvi))
    453   1.1  christos 	cause |= (1 << IO);
    454   1.1  christos       if (status & sim_fpu_status_invalid_div0)
    455   1.1  christos 	cause |= (1 << DZ);
    456   1.1  christos       if (status & sim_fpu_status_overflow)
    457   1.1  christos 	cause |= (1 << OF);
    458   1.1  christos       if (status & sim_fpu_status_underflow)
    459   1.1  christos 	cause |= (1 << UF);
    460   1.1  christos       if (status & sim_fpu_status_inexact)
    461   1.1  christos 	cause |= (1 << IR);
    462   1.1  christos #if 0 /* Not yet.  */
    463   1.1  christos       /* Implicit clearing of other bits by unimplemented done by callers.  */
    464   1.1  christos       if (status & sim_fpu_status_unimplemented)
    465   1.1  christos 	cause |= (1 << UO);
    466   1.1  christos #endif
    467   1.1  christos 
    468   1.1  christos       FCSR |= (cause << fcsr_CAUSE_shift);
    469   1.1  christos       test_fcsr (cpu, cia);
    470   1.1  christos       FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
    471   1.1  christos     }
    472   1.1  christos   return;
    473   1.1  christos }
    474   1.1  christos 
    475   1.1  christos static sim_fpu_round
    476   1.1  christos rounding_mode(int rm)
    477   1.1  christos {
    478   1.1  christos   sim_fpu_round round;
    479   1.1  christos 
    480   1.1  christos   switch (rm)
    481   1.1  christos     {
    482   1.1  christos     case FP_RM_NEAREST:
    483   1.1  christos       /* Round result to nearest representable value. When two
    484   1.1  christos 	 representable values are equally near, round to the value
    485   1.1  christos 	 that has a least significant bit of zero (i.e. is even).  */
    486   1.1  christos       round = sim_fpu_round_near;
    487   1.1  christos       break;
    488   1.1  christos     case FP_RM_TOZERO:
    489   1.1  christos       /* Round result to the value closest to, and not greater in
    490   1.1  christos 	 magnitude than, the result.  */
    491   1.1  christos       round = sim_fpu_round_zero;
    492   1.1  christos       break;
    493   1.1  christos     case FP_RM_TOPINF:
    494   1.1  christos       /* Round result to the value closest to, and not less than,
    495   1.1  christos 	 the result.  */
    496   1.1  christos       round = sim_fpu_round_up;
    497   1.1  christos       break;
    498   1.1  christos     case FP_RM_TOMINF:
    499   1.1  christos       /* Round result to the value closest to, and not greater than,
    500   1.1  christos 	 the result.  */
    501   1.1  christos       round = sim_fpu_round_down;
    502   1.1  christos       break;
    503   1.1  christos     default:
    504   1.1  christos       round = 0;
    505   1.1  christos       fprintf (stderr, "Bad switch\n");
    506   1.1  christos       abort ();
    507   1.1  christos     }
    508   1.1  christos   return round;
    509   1.1  christos }
    510   1.1  christos 
    511   1.1  christos /* When the FS bit is set, MIPS processors return zero for
    512   1.1  christos    denormalized results and optionally replace denormalized inputs
    513   1.1  christos    with zero.  When FS is clear, some implementation trap on input
    514   1.1  christos    and/or output, while other perform the operation in hardware.  */
    515   1.1  christos static sim_fpu_denorm
    516   1.1  christos denorm_mode(sim_cpu *cpu)
    517   1.1  christos {
    518   1.1  christos   sim_fpu_denorm denorm;
    519   1.1  christos 
    520   1.1  christos   /* XXX: FIXME: Eventually should be CPU model dependent.  */
    521   1.1  christos   if (GETFS())
    522   1.1  christos     denorm = sim_fpu_denorm_zero;
    523   1.1  christos   else
    524   1.1  christos     denorm = 0;
    525   1.1  christos   return denorm;
    526   1.1  christos }
    527   1.1  christos 
    528   1.1  christos 
    529   1.1  christos /* Comparison operations.  */
    530   1.1  christos 
    531   1.1  christos static sim_fpu_status
    532  1.10  christos fp_test(uint64_t op1,
    533  1.10  christos 	uint64_t op2,
    534   1.1  christos 	FP_formats fmt,
    535   1.1  christos 	int abs,
    536   1.1  christos 	int cond,
    537   1.1  christos 	int *condition)
    538   1.1  christos {
    539   1.1  christos   sim_fpu wop1;
    540   1.1  christos   sim_fpu wop2;
    541   1.1  christos   sim_fpu_status status = 0;
    542   1.1  christos   int  less, equal, unordered;
    543   1.1  christos 
    544   1.1  christos   /* The format type has already been checked:  */
    545   1.1  christos   switch (fmt)
    546   1.1  christos     {
    547   1.1  christos     case fmt_single:
    548   1.1  christos       {
    549   1.1  christos 	sim_fpu_32to (&wop1, op1);
    550   1.1  christos 	sim_fpu_32to (&wop2, op2);
    551   1.1  christos 	break;
    552   1.1  christos       }
    553   1.1  christos     case fmt_double:
    554   1.1  christos       {
    555   1.1  christos 	sim_fpu_64to (&wop1, op1);
    556   1.1  christos 	sim_fpu_64to (&wop2, op2);
    557   1.1  christos 	break;
    558   1.1  christos       }
    559   1.1  christos     default:
    560   1.1  christos       fprintf (stderr, "Bad switch\n");
    561   1.1  christos       abort ();
    562   1.1  christos     }
    563   1.1  christos 
    564   1.1  christos   if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
    565   1.1  christos     {
    566  1.10  christos       if ((cond & (1 << 3))
    567  1.10  christos 	  || sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
    568   1.1  christos 	status = sim_fpu_status_invalid_snan;
    569   1.1  christos       less = 0;
    570   1.1  christos       equal = 0;
    571   1.1  christos       unordered = 1;
    572   1.1  christos     }
    573   1.1  christos   else
    574   1.1  christos     {
    575   1.1  christos       if (abs)
    576   1.1  christos 	{
    577   1.1  christos 	  status |= sim_fpu_abs (&wop1, &wop1);
    578   1.1  christos 	  status |= sim_fpu_abs (&wop2, &wop2);
    579   1.1  christos 	}
    580   1.1  christos       equal = sim_fpu_is_eq (&wop1, &wop2);
    581   1.1  christos       less = !equal && sim_fpu_is_lt (&wop1, &wop2);
    582   1.1  christos       unordered = 0;
    583   1.1  christos     }
    584   1.1  christos   *condition = (((cond & (1 << 2)) && less)
    585   1.1  christos 		|| ((cond & (1 << 1)) && equal)
    586   1.1  christos 		|| ((cond & (1 << 0)) && unordered));
    587   1.1  christos   return status;
    588   1.1  christos }
    589   1.1  christos 
    590  1.10  christos static const int sim_fpu_class_mips_mapping[] = {
    591  1.10  christos   FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number  */
    592  1.10  christos   FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number  */
    593  1.10  christos   FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity  */
    594  1.10  christos   FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity  */
    595  1.10  christos   FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN]  */
    596  1.10  christos   FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX]  */
    597  1.10  christos   FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0)  */
    598  1.10  christos   FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN)  */
    599  1.10  christos   FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0  */
    600  1.10  christos   FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0  */
    601  1.10  christos };
    602  1.10  christos 
    603  1.10  christos uint64_t
    604  1.10  christos fp_classify (sim_cpu *cpu,
    605  1.10  christos 	     address_word cia,
    606  1.10  christos 	     uint64_t op,
    607  1.10  christos 	     FP_formats fmt)
    608  1.10  christos {
    609  1.10  christos   sim_fpu wop;
    610  1.10  christos 
    611  1.10  christos   switch (fmt)
    612  1.10  christos     {
    613  1.10  christos     case fmt_single:
    614  1.10  christos       sim_fpu_32to (&wop, op);
    615  1.10  christos       break;
    616  1.10  christos     case fmt_double:
    617  1.10  christos       sim_fpu_64to (&wop, op);
    618  1.10  christos       break;
    619  1.10  christos     default:
    620  1.10  christos       sim_io_error (SD, "Bad switch\n");
    621  1.10  christos     }
    622  1.10  christos   return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1];
    623  1.10  christos }
    624  1.10  christos 
    625  1.10  christos int
    626  1.10  christos fp_rint (sim_cpu *cpu,
    627  1.10  christos 	 address_word cia,
    628  1.10  christos 	 uint64_t op,
    629  1.10  christos 	 uint64_t *ans,
    630  1.10  christos 	 FP_formats fmt)
    631  1.10  christos {
    632  1.10  christos   sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0};
    633  1.10  christos   int64_t intermediate;
    634  1.10  christos   int status = 0;
    635  1.10  christos   sim_fpu_round round = rounding_mode (GETRM());
    636  1.10  christos 
    637  1.10  christos   switch (fmt)
    638  1.10  christos     {
    639  1.10  christos     case fmt_single:
    640  1.10  christos       sim_fpu_32to (&wop, op);
    641  1.10  christos       sim_fpu_32to (&wmagic, 0x4b000000);
    642  1.10  christos       break;
    643  1.10  christos     case fmt_double:
    644  1.10  christos       sim_fpu_64to (&wop, op);
    645  1.10  christos       sim_fpu_64to (&wmagic, 0x4330000000000000);
    646  1.10  christos       break;
    647  1.10  christos     default:
    648  1.10  christos       sim_io_error (SD, "Bad switch\n");
    649  1.10  christos     }
    650  1.10  christos 
    651  1.10  christos   if (sim_fpu_is_nan (&wop) || sim_fpu_is_infinity (&wop))
    652  1.10  christos     {
    653  1.10  christos       status = sim_fpu_status_invalid_cvi;
    654  1.10  christos       update_fcsr (cpu, cia, status);
    655  1.10  christos       return status;
    656  1.10  christos     }
    657  1.10  christos 
    658  1.10  christos   switch (fmt)
    659  1.10  christos     {
    660  1.10  christos     case fmt_single:
    661  1.10  christos       if (sim_fpu_is_ge (&wop, &wmagic))
    662  1.10  christos 	wans = wop;
    663  1.10  christos       else
    664  1.10  christos 	{
    665  1.10  christos 	  sim_fpu_add (&wtemp, &wop, &wmagic);
    666  1.10  christos 	  sim_fpu_round_32 (&wtemp, round, sim_fpu_denorm_default);
    667  1.10  christos 	  sim_fpu_sub (&wans, &wtemp, &wmagic);
    668  1.10  christos 	}
    669  1.10  christos       sim_fpu_to32 ((uint32_t *) ans, &wans);
    670  1.10  christos       break;
    671  1.10  christos     case fmt_double:
    672  1.10  christos       if (sim_fpu_is_ge (&wop, &wmagic))
    673  1.10  christos 	wans = wop;
    674  1.10  christos       else
    675  1.10  christos 	{
    676  1.10  christos 	  sim_fpu_add (&wtemp, &wop, &wmagic);
    677  1.10  christos 	  sim_fpu_round_64 (&wtemp, round, sim_fpu_denorm_default);
    678  1.10  christos 	  sim_fpu_sub (&wans, &wtemp, &wmagic);
    679  1.10  christos 	}
    680  1.10  christos       sim_fpu_to64 (ans, &wans);
    681  1.10  christos       break;
    682  1.10  christos     default:
    683  1.10  christos       sim_io_error (SD, "Bad switch\n");
    684  1.10  christos     }
    685  1.10  christos 
    686  1.10  christos   if (*ans != op && status == 0)
    687  1.10  christos     status = sim_fpu_status_inexact;
    688  1.10  christos 
    689  1.10  christos   update_fcsr (cpu, cia, status);
    690  1.10  christos   return status;
    691  1.10  christos }
    692  1.10  christos 
    693   1.1  christos void
    694   1.1  christos fp_cmp(sim_cpu *cpu,
    695   1.1  christos        address_word cia,
    696  1.10  christos        uint64_t op1,
    697  1.10  christos        uint64_t op2,
    698   1.1  christos        FP_formats fmt,
    699   1.1  christos        int abs,
    700   1.1  christos        int cond,
    701   1.1  christos        int cc)
    702   1.1  christos {
    703   1.1  christos   sim_fpu_status status = 0;
    704   1.1  christos 
    705   1.1  christos   /* The format type should already have been checked.  The FCSR is
    706   1.1  christos      updated before the condition codes so that any exceptions will
    707   1.1  christos      be signalled before the condition codes are changed.  */
    708   1.1  christos   switch (fmt)
    709   1.1  christos     {
    710   1.1  christos     case fmt_single:
    711   1.1  christos     case fmt_double:
    712   1.1  christos       {
    713   1.1  christos 	int result;
    714   1.1  christos 	status = fp_test(op1, op2, fmt, abs, cond, &result);
    715   1.1  christos 	update_fcsr (cpu, cia, status);
    716   1.1  christos 	SETFCC (cc, result);
    717   1.1  christos 	break;
    718   1.1  christos       }
    719   1.1  christos     case fmt_ps:
    720   1.1  christos       {
    721   1.1  christos 	int result0, result1;
    722   1.1  christos 	status  = fp_test(FP_PS_lower (op1), FP_PS_lower (op2), fmt_single,
    723   1.1  christos 			  abs, cond, &result0);
    724   1.1  christos 	status |= fp_test(FP_PS_upper (op1), FP_PS_upper (op2), fmt_single,
    725   1.1  christos 			  abs, cond, &result1);
    726   1.1  christos 	update_fcsr (cpu, cia, status);
    727   1.1  christos 	SETFCC (cc, result0);
    728   1.1  christos 	SETFCC (cc+1, result1);
    729   1.1  christos 	break;
    730   1.1  christos       }
    731   1.1  christos     default:
    732  1.10  christos       sim_io_error (SD, "Bad switch\n");
    733   1.1  christos     }
    734   1.1  christos }
    735   1.1  christos 
    736  1.10  christos uint64_t
    737  1.10  christos fp_r6_cmp (sim_cpu *cpu,
    738  1.10  christos 	   address_word cia,
    739  1.10  christos 	   uint64_t op1,
    740  1.10  christos 	   uint64_t op2,
    741  1.10  christos 	   FP_formats fmt,
    742  1.10  christos 	   int cond)
    743  1.10  christos {
    744  1.10  christos   sim_fpu wop1, wop2;
    745  1.10  christos   int result = 0;
    746  1.10  christos   int signalling = cond & 0x8;
    747  1.10  christos 
    748  1.10  christos   switch (fmt)
    749  1.10  christos     {
    750  1.10  christos     case fmt_single:
    751  1.10  christos       sim_fpu_32to (&wop1, op1);
    752  1.10  christos       sim_fpu_32to (&wop2, op2);
    753  1.10  christos       break;
    754  1.10  christos     case fmt_double:
    755  1.10  christos       sim_fpu_64to (&wop1, op1);
    756  1.10  christos       sim_fpu_64to (&wop2, op2);
    757  1.10  christos       break;
    758  1.10  christos     default:
    759  1.10  christos       sim_io_error (SD, "Bad switch\n");
    760  1.10  christos     }
    761  1.10  christos 
    762  1.10  christos   switch (cond)
    763  1.10  christos     {
    764  1.10  christos     case FP_R6CMP_AF:
    765  1.10  christos       result = 0;
    766  1.10  christos       break;
    767  1.10  christos     case FP_R6CMP_UN:
    768  1.10  christos       result = sim_fpu_is_un (&wop1, &wop2);
    769  1.10  christos       break;
    770  1.10  christos     case FP_R6CMP_OR:
    771  1.10  christos       result = sim_fpu_is_or (&wop1, &wop2);
    772  1.10  christos       break;
    773  1.10  christos     case FP_R6CMP_EQ:
    774  1.10  christos       result = sim_fpu_is_eq (&wop1, &wop2);
    775  1.10  christos       break;
    776  1.10  christos     case FP_R6CMP_NE:
    777  1.10  christos       result = sim_fpu_is_ne (&wop1, &wop2);
    778  1.10  christos       break;
    779  1.10  christos     case FP_R6CMP_LT:
    780  1.10  christos       result = sim_fpu_is_lt (&wop1, &wop2);
    781  1.10  christos       break;
    782  1.10  christos     case FP_R6CMP_LE:
    783  1.10  christos       result = sim_fpu_is_le (&wop1, &wop2);
    784  1.10  christos       break;
    785  1.10  christos     case FP_R6CMP_UEQ:
    786  1.10  christos       result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_eq (&wop1, &wop2);
    787  1.10  christos       break;
    788  1.10  christos     case FP_R6CMP_UNE:
    789  1.10  christos       result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_ne (&wop1, &wop2);
    790  1.10  christos       break;
    791  1.10  christos     case FP_R6CMP_ULT:
    792  1.10  christos       result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_lt (&wop1, &wop2);
    793  1.10  christos       break;
    794  1.10  christos     case FP_R6CMP_ULE:
    795  1.10  christos       result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_le (&wop1, &wop2);
    796  1.10  christos       break;
    797  1.10  christos     default:
    798  1.10  christos       update_fcsr (cpu, cia, sim_fpu_status_invalid_cmp);
    799  1.10  christos       break;
    800  1.10  christos     }
    801  1.10  christos 
    802  1.10  christos   if (result)
    803  1.10  christos     {
    804  1.10  christos       switch (fmt)
    805  1.10  christos 	{
    806  1.10  christos 	case fmt_single:
    807  1.10  christos 	  return 0xFFFFFFFF;
    808  1.10  christos 	case fmt_double:
    809  1.10  christos 	  return 0xFFFFFFFFFFFFFFFF;
    810  1.10  christos 	default:
    811  1.10  christos 	  sim_io_error (SD, "Bad switch\n");
    812  1.10  christos 	}
    813  1.10  christos      }
    814  1.10  christos    else
    815  1.10  christos      return 0;
    816  1.10  christos }
    817   1.1  christos 
    818   1.1  christos /* Basic arithmetic operations.  */
    819   1.1  christos 
    820  1.10  christos static uint64_t
    821   1.1  christos fp_unary(sim_cpu *cpu,
    822   1.1  christos 	 address_word cia,
    823   1.1  christos 	 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *),
    824  1.10  christos 	 uint64_t op,
    825   1.1  christos 	 FP_formats fmt)
    826   1.1  christos {
    827  1.10  christos   sim_fpu wop = {0};
    828   1.1  christos   sim_fpu ans;
    829   1.1  christos   sim_fpu_round round = rounding_mode (GETRM());
    830   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
    831   1.1  christos   sim_fpu_status status = 0;
    832  1.10  christos   uint64_t result = 0;
    833   1.1  christos 
    834   1.1  christos   /* The format type has already been checked: */
    835   1.1  christos   switch (fmt)
    836   1.1  christos     {
    837   1.1  christos     case fmt_single:
    838   1.1  christos       {
    839  1.10  christos 	uint32_t res;
    840   1.1  christos 	sim_fpu_32to (&wop, op);
    841   1.1  christos 	status |= (*sim_fpu_op) (&ans, &wop);
    842   1.1  christos 	status |= sim_fpu_round_32 (&ans, round, denorm);
    843   1.1  christos 	sim_fpu_to32 (&res, &ans);
    844   1.1  christos 	result = res;
    845   1.1  christos 	break;
    846   1.1  christos       }
    847   1.1  christos     case fmt_double:
    848   1.1  christos       {
    849  1.10  christos 	uint64_t res;
    850   1.1  christos 	sim_fpu_64to (&wop, op);
    851   1.1  christos 	status |= (*sim_fpu_op) (&ans, &wop);
    852   1.1  christos 	status |= sim_fpu_round_64 (&ans, round, denorm);
    853   1.1  christos 	sim_fpu_to64 (&res, &ans);
    854   1.1  christos 	result = res;
    855   1.1  christos 	break;
    856   1.1  christos       }
    857   1.1  christos     case fmt_ps:
    858   1.1  christos       {
    859   1.1  christos 	int status_u = 0, status_l = 0;
    860  1.10  christos 	uint32_t res_u, res_l;
    861   1.1  christos 	sim_fpu_32to (&wop, FP_PS_upper(op));
    862   1.1  christos 	status_u |= (*sim_fpu_op) (&ans, &wop);
    863   1.1  christos 	sim_fpu_to32 (&res_u, &ans);
    864   1.1  christos 	sim_fpu_32to (&wop, FP_PS_lower(op));
    865   1.1  christos 	status_l |= (*sim_fpu_op) (&ans, &wop);
    866   1.1  christos 	sim_fpu_to32 (&res_l, &ans);
    867   1.1  christos 	result = FP_PS_cat(res_u, res_l);
    868   1.1  christos 	status = status_u | status_l;
    869   1.1  christos 	break;
    870   1.1  christos       }
    871   1.1  christos     default:
    872  1.10  christos       sim_io_error (SD, "Bad switch\n");
    873   1.1  christos     }
    874   1.1  christos 
    875   1.1  christos   update_fcsr (cpu, cia, status);
    876   1.1  christos   return result;
    877   1.1  christos }
    878   1.1  christos 
    879  1.10  christos static uint64_t
    880   1.1  christos fp_binary(sim_cpu *cpu,
    881   1.1  christos 	  address_word cia,
    882   1.1  christos 	  int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
    883  1.10  christos 	  uint64_t op1,
    884  1.10  christos 	  uint64_t op2,
    885   1.1  christos 	  FP_formats fmt)
    886   1.1  christos {
    887  1.10  christos   sim_fpu wop1 = {0};
    888  1.10  christos   sim_fpu wop2 = {0};
    889  1.10  christos   sim_fpu ans  = {0};
    890   1.1  christos   sim_fpu_round round = rounding_mode (GETRM());
    891   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
    892   1.1  christos   sim_fpu_status status = 0;
    893  1.10  christos   uint64_t result = 0;
    894   1.1  christos 
    895   1.1  christos   /* The format type has already been checked: */
    896   1.1  christos   switch (fmt)
    897   1.1  christos     {
    898   1.1  christos     case fmt_single:
    899   1.1  christos       {
    900  1.10  christos 	uint32_t res;
    901   1.1  christos 	sim_fpu_32to (&wop1, op1);
    902   1.1  christos 	sim_fpu_32to (&wop2, op2);
    903   1.1  christos 	status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
    904   1.1  christos 	status |= sim_fpu_round_32 (&ans, round, denorm);
    905   1.1  christos 	sim_fpu_to32 (&res, &ans);
    906   1.1  christos 	result = res;
    907   1.1  christos 	break;
    908   1.1  christos       }
    909   1.1  christos     case fmt_double:
    910   1.1  christos       {
    911  1.10  christos 	uint64_t res;
    912   1.1  christos 	sim_fpu_64to (&wop1, op1);
    913   1.1  christos 	sim_fpu_64to (&wop2, op2);
    914   1.1  christos 	status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
    915   1.1  christos 	status |= sim_fpu_round_64 (&ans, round, denorm);
    916   1.1  christos 	sim_fpu_to64 (&res, &ans);
    917   1.1  christos 	result = res;
    918   1.1  christos 	break;
    919   1.1  christos       }
    920   1.1  christos     case fmt_ps:
    921   1.1  christos       {
    922   1.1  christos 	int status_u = 0, status_l = 0;
    923  1.10  christos 	uint32_t res_u, res_l;
    924   1.1  christos 	sim_fpu_32to (&wop1, FP_PS_upper(op1));
    925   1.1  christos 	sim_fpu_32to (&wop2, FP_PS_upper(op2));
    926   1.1  christos 	status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2);
    927   1.1  christos 	sim_fpu_to32 (&res_u, &ans);
    928   1.1  christos 	sim_fpu_32to (&wop1, FP_PS_lower(op1));
    929   1.1  christos 	sim_fpu_32to (&wop2, FP_PS_lower(op2));
    930   1.1  christos 	status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2);
    931   1.1  christos 	sim_fpu_to32 (&res_l, &ans);
    932   1.1  christos 	result = FP_PS_cat(res_u, res_l);
    933   1.1  christos 	status = status_u | status_l;
    934   1.1  christos 	break;
    935   1.1  christos       }
    936   1.1  christos     default:
    937  1.10  christos       sim_io_error (SD, "Bad switch\n");
    938   1.1  christos     }
    939   1.1  christos 
    940   1.1  christos   update_fcsr (cpu, cia, status);
    941   1.1  christos   return result;
    942   1.1  christos }
    943   1.1  christos 
    944   1.1  christos /* Common MAC code for single operands (.s or .d), defers setting FCSR.  */
    945   1.1  christos static sim_fpu_status
    946   1.1  christos inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
    947  1.10  christos 	  uint64_t op1,
    948  1.10  christos 	  uint64_t op2,
    949  1.10  christos 	  uint64_t op3,
    950   1.1  christos 	  int scale,
    951   1.1  christos 	  int negate,
    952   1.1  christos 	  FP_formats fmt,
    953   1.1  christos 	  sim_fpu_round round,
    954   1.1  christos 	  sim_fpu_denorm denorm,
    955  1.10  christos 	  uint64_t *result)
    956   1.1  christos {
    957   1.1  christos   sim_fpu wop1;
    958   1.1  christos   sim_fpu wop2;
    959   1.1  christos   sim_fpu ans;
    960   1.1  christos   sim_fpu_status status = 0;
    961   1.1  christos   sim_fpu_status op_status;
    962  1.10  christos   uint64_t temp = 0;
    963   1.1  christos 
    964   1.1  christos   switch (fmt)
    965   1.1  christos     {
    966   1.1  christos     case fmt_single:
    967   1.1  christos       {
    968  1.10  christos 	uint32_t res;
    969   1.1  christos 	sim_fpu_32to (&wop1, op1);
    970   1.1  christos 	sim_fpu_32to (&wop2, op2);
    971   1.1  christos 	status |= sim_fpu_mul (&ans, &wop1, &wop2);
    972   1.1  christos 	if (scale != 0 && sim_fpu_is_number (&ans))  /* number or denorm */
    973   1.1  christos 	  ans.normal_exp += scale;
    974   1.1  christos 	status |= sim_fpu_round_32 (&ans, round, denorm);
    975   1.1  christos 	wop1 = ans;
    976  1.10  christos 	op_status = 0;
    977   1.1  christos 	sim_fpu_32to (&wop2, op3);
    978   1.1  christos 	op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
    979   1.1  christos 	op_status |= sim_fpu_round_32 (&ans, round, denorm);
    980   1.1  christos 	status |= op_status;
    981   1.1  christos 	if (negate)
    982   1.1  christos 	  {
    983   1.1  christos 	    wop1 = ans;
    984   1.1  christos 	    op_status = sim_fpu_neg (&ans, &wop1);
    985   1.1  christos 	    op_status |= sim_fpu_round_32 (&ans, round, denorm);
    986   1.1  christos 	    status |= op_status;
    987   1.1  christos 	  }
    988   1.1  christos 	sim_fpu_to32 (&res, &ans);
    989   1.1  christos 	temp = res;
    990   1.1  christos 	break;
    991   1.1  christos       }
    992   1.1  christos     case fmt_double:
    993   1.1  christos       {
    994  1.10  christos 	uint64_t res;
    995   1.1  christos 	sim_fpu_64to (&wop1, op1);
    996   1.1  christos 	sim_fpu_64to (&wop2, op2);
    997   1.1  christos 	status |= sim_fpu_mul (&ans, &wop1, &wop2);
    998   1.1  christos 	if (scale != 0 && sim_fpu_is_number (&ans))  /* number or denorm */
    999   1.1  christos 	  ans.normal_exp += scale;
   1000   1.1  christos 	status |= sim_fpu_round_64 (&ans, round, denorm);
   1001   1.1  christos 	wop1 = ans;
   1002  1.10  christos 	op_status = 0;
   1003   1.1  christos 	sim_fpu_64to (&wop2, op3);
   1004   1.1  christos 	op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
   1005   1.1  christos 	op_status |= sim_fpu_round_64 (&ans, round, denorm);
   1006   1.1  christos 	status |= op_status;
   1007   1.1  christos 	if (negate)
   1008   1.1  christos 	  {
   1009   1.1  christos 	    wop1 = ans;
   1010   1.1  christos 	    op_status = sim_fpu_neg (&ans, &wop1);
   1011   1.1  christos 	    op_status |= sim_fpu_round_64 (&ans, round, denorm);
   1012   1.1  christos 	    status |= op_status;
   1013   1.1  christos 	  }
   1014   1.1  christos 	sim_fpu_to64 (&res, &ans);
   1015   1.1  christos 	temp = res;
   1016   1.1  christos 	break;
   1017   1.1  christos       }
   1018   1.1  christos     default:
   1019   1.1  christos       fprintf (stderr, "Bad switch\n");
   1020   1.1  christos       abort ();
   1021   1.1  christos     }
   1022   1.1  christos   *result = temp;
   1023   1.1  christos   return status;
   1024   1.1  christos }
   1025   1.1  christos 
   1026   1.1  christos /* Common implementation of madd, nmadd, msub, nmsub that does
   1027   1.1  christos    intermediate rounding per spec.  Also used for recip2 and rsqrt2,
   1028   1.1  christos    which are transformed into equivalent nmsub operations.  The scale
   1029   1.1  christos    argument is an adjustment to the exponent of the intermediate
   1030   1.1  christos    product op1*op2.  It is currently non-zero for rsqrt2 (-1), which
   1031   1.1  christos    requires an effective division by 2. */
   1032  1.10  christos static uint64_t
   1033   1.1  christos fp_mac(sim_cpu *cpu,
   1034   1.1  christos        address_word cia,
   1035   1.1  christos        int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
   1036  1.10  christos        uint64_t op1,
   1037  1.10  christos        uint64_t op2,
   1038  1.10  christos        uint64_t op3,
   1039   1.1  christos        int scale,
   1040   1.1  christos        int negate,
   1041   1.1  christos        FP_formats fmt)
   1042   1.1  christos {
   1043   1.1  christos   sim_fpu_round round = rounding_mode (GETRM());
   1044   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
   1045   1.1  christos   sim_fpu_status status = 0;
   1046  1.10  christos   uint64_t result = 0;
   1047   1.1  christos 
   1048   1.1  christos   /* The format type has already been checked: */
   1049   1.1  christos   switch (fmt)
   1050   1.1  christos     {
   1051   1.1  christos     case fmt_single:
   1052   1.1  christos     case fmt_double:
   1053   1.1  christos       status = inner_mac(sim_fpu_op, op1, op2, op3, scale,
   1054   1.1  christos 			 negate, fmt, round, denorm, &result);
   1055   1.1  christos       break;
   1056   1.1  christos     case fmt_ps:
   1057   1.1  christos       {
   1058   1.1  christos 	int status_u, status_l;
   1059  1.10  christos 	uint64_t result_u, result_l;
   1060   1.1  christos 	status_u = inner_mac(sim_fpu_op, FP_PS_upper(op1), FP_PS_upper(op2),
   1061   1.1  christos 			     FP_PS_upper(op3), scale, negate, fmt_single,
   1062   1.1  christos 			     round, denorm, &result_u);
   1063   1.1  christos 	status_l = inner_mac(sim_fpu_op, FP_PS_lower(op1), FP_PS_lower(op2),
   1064   1.1  christos 			     FP_PS_lower(op3), scale, negate, fmt_single,
   1065   1.1  christos 			     round, denorm, &result_l);
   1066   1.1  christos 	result = FP_PS_cat(result_u, result_l);
   1067   1.1  christos 	status = status_u | status_l;
   1068   1.1  christos 	break;
   1069   1.1  christos       }
   1070   1.1  christos     default:
   1071  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1072  1.10  christos     }
   1073  1.10  christos 
   1074  1.10  christos   update_fcsr (cpu, cia, status);
   1075  1.10  christos   return result;
   1076  1.10  christos }
   1077  1.10  christos 
   1078  1.10  christos /* Common FMAC code for .s, .d. Defers setting FCSR to caller.  */
   1079  1.10  christos static sim_fpu_status
   1080  1.10  christos inner_fmac (sim_cpu *cpu,
   1081  1.10  christos 	    int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
   1082  1.10  christos 	    uint64_t op1,
   1083  1.10  christos 	    uint64_t op2,
   1084  1.10  christos 	    uint64_t op3,
   1085  1.10  christos 	    sim_fpu_round round,
   1086  1.10  christos 	    sim_fpu_denorm denorm,
   1087  1.10  christos 	    FP_formats fmt,
   1088  1.10  christos 	    uint64_t *result)
   1089  1.10  christos {
   1090  1.10  christos   sim_fpu wop1, wop2, ans;
   1091  1.10  christos   sim_fpu_status status = 0;
   1092  1.10  christos   sim_fpu_status op_status;
   1093  1.10  christos   uint32_t t32 = 0;
   1094  1.10  christos   uint64_t t64 = 0;
   1095  1.10  christos 
   1096  1.10  christos   switch (fmt)
   1097  1.10  christos     {
   1098  1.10  christos     case fmt_single:
   1099  1.10  christos       sim_fpu_32to (&wop1, op1);
   1100  1.10  christos       sim_fpu_32to (&wop2, op2);
   1101  1.10  christos       status |= sim_fpu_mul (&ans, &wop1, &wop2);
   1102  1.10  christos       wop1 = ans;
   1103  1.10  christos       op_status = 0;
   1104  1.10  christos       sim_fpu_32to (&wop2, op3);
   1105  1.10  christos       op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
   1106  1.10  christos       op_status |= sim_fpu_round_32 (&ans, round, denorm);
   1107  1.10  christos       status |= op_status;
   1108  1.10  christos       sim_fpu_to32 (&t32, &ans);
   1109  1.10  christos       t64 = t32;
   1110  1.10  christos       break;
   1111  1.10  christos     case fmt_double:
   1112  1.10  christos       sim_fpu_64to (&wop1, op1);
   1113  1.10  christos       sim_fpu_64to (&wop2, op2);
   1114  1.10  christos       status |= sim_fpu_mul (&ans, &wop1, &wop2);
   1115  1.10  christos       wop1 = ans;
   1116  1.10  christos       op_status = 0;
   1117  1.10  christos       sim_fpu_64to (&wop2, op3);
   1118  1.10  christos       op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
   1119  1.10  christos       op_status |= sim_fpu_round_64 (&ans, round, denorm);
   1120  1.10  christos       status |= op_status;
   1121  1.10  christos       sim_fpu_to64 (&t64, &ans);
   1122  1.10  christos       break;
   1123  1.10  christos     default:
   1124  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1125  1.10  christos     }
   1126  1.10  christos 
   1127  1.10  christos   *result = t64;
   1128  1.10  christos   return status;
   1129  1.10  christos }
   1130  1.10  christos 
   1131  1.10  christos static uint64_t
   1132  1.10  christos fp_fmac (sim_cpu *cpu,
   1133  1.10  christos 	 address_word cia,
   1134  1.10  christos 	 int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
   1135  1.10  christos 	 uint64_t op1,
   1136  1.10  christos 	 uint64_t op2,
   1137  1.10  christos 	 uint64_t op3,
   1138  1.10  christos 	 FP_formats fmt)
   1139  1.10  christos {
   1140  1.10  christos   sim_fpu_round round = rounding_mode (GETRM());
   1141  1.10  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
   1142  1.10  christos   sim_fpu_status status = 0;
   1143  1.10  christos   uint64_t result = 0;
   1144  1.10  christos 
   1145  1.10  christos   switch (fmt)
   1146  1.10  christos     {
   1147  1.10  christos     case fmt_single:
   1148  1.10  christos     case fmt_double:
   1149  1.10  christos       status = inner_fmac (cpu, sim_fpu_op, op1, op2, op3,
   1150  1.10  christos 			   round, denorm, fmt, &result);
   1151  1.10  christos       break;
   1152  1.10  christos     default:
   1153  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1154   1.1  christos     }
   1155   1.1  christos 
   1156   1.1  christos   update_fcsr (cpu, cia, status);
   1157   1.1  christos   return result;
   1158   1.1  christos }
   1159   1.1  christos 
   1160   1.1  christos /* Common rsqrt code for single operands (.s or .d), intermediate rounding.  */
   1161   1.1  christos static sim_fpu_status
   1162  1.10  christos inner_rsqrt(uint64_t op1,
   1163   1.1  christos 	    FP_formats fmt,
   1164   1.1  christos 	    sim_fpu_round round,
   1165   1.1  christos 	    sim_fpu_denorm denorm,
   1166  1.10  christos 	    uint64_t *result)
   1167   1.1  christos {
   1168   1.1  christos   sim_fpu wop1;
   1169   1.1  christos   sim_fpu ans;
   1170   1.1  christos   sim_fpu_status status = 0;
   1171   1.1  christos   sim_fpu_status op_status;
   1172  1.10  christos   uint64_t temp = 0;
   1173   1.1  christos 
   1174   1.1  christos   switch (fmt)
   1175   1.1  christos     {
   1176   1.1  christos     case fmt_single:
   1177   1.1  christos       {
   1178  1.10  christos 	uint32_t res;
   1179   1.1  christos 	sim_fpu_32to (&wop1, op1);
   1180   1.1  christos 	status |= sim_fpu_sqrt (&ans, &wop1);
   1181   1.1  christos 	status |= sim_fpu_round_32 (&ans, status, round);
   1182   1.1  christos 	wop1 = ans;
   1183   1.1  christos 	op_status = sim_fpu_inv (&ans, &wop1);
   1184   1.1  christos 	op_status |= sim_fpu_round_32 (&ans, round, denorm);
   1185   1.1  christos 	sim_fpu_to32 (&res, &ans);
   1186   1.1  christos 	temp = res;
   1187   1.1  christos 	status |= op_status;
   1188   1.1  christos 	break;
   1189   1.1  christos       }
   1190   1.1  christos     case fmt_double:
   1191   1.1  christos       {
   1192  1.10  christos 	uint64_t res;
   1193   1.1  christos 	sim_fpu_64to (&wop1, op1);
   1194   1.1  christos 	status |= sim_fpu_sqrt (&ans, &wop1);
   1195   1.1  christos 	status |= sim_fpu_round_64 (&ans, round, denorm);
   1196   1.1  christos 	wop1 = ans;
   1197   1.1  christos 	op_status = sim_fpu_inv (&ans, &wop1);
   1198   1.1  christos 	op_status |= sim_fpu_round_64 (&ans, round, denorm);
   1199   1.1  christos 	sim_fpu_to64 (&res, &ans);
   1200   1.1  christos 	temp = res;
   1201   1.1  christos 	status |= op_status;
   1202   1.1  christos 	break;
   1203   1.1  christos       }
   1204   1.1  christos     default:
   1205   1.1  christos       fprintf (stderr, "Bad switch\n");
   1206   1.1  christos       abort ();
   1207   1.1  christos     }
   1208   1.1  christos   *result = temp;
   1209   1.1  christos   return status;
   1210   1.1  christos }
   1211   1.1  christos 
   1212  1.10  christos static uint64_t
   1213   1.1  christos fp_inv_sqrt(sim_cpu *cpu,
   1214   1.1  christos 	    address_word cia,
   1215  1.10  christos 	    uint64_t op1,
   1216   1.1  christos 	    FP_formats fmt)
   1217   1.1  christos {
   1218   1.1  christos   sim_fpu_round round = rounding_mode (GETRM());
   1219   1.1  christos   sim_fpu_round denorm = denorm_mode (cpu);
   1220   1.1  christos   sim_fpu_status status = 0;
   1221  1.10  christos   uint64_t result = 0;
   1222   1.1  christos 
   1223   1.1  christos   /* The format type has already been checked: */
   1224   1.1  christos   switch (fmt)
   1225   1.1  christos     {
   1226   1.1  christos     case fmt_single:
   1227   1.1  christos     case fmt_double:
   1228   1.1  christos       status = inner_rsqrt (op1, fmt, round, denorm, &result);
   1229   1.1  christos       break;
   1230   1.1  christos     case fmt_ps:
   1231   1.1  christos       {
   1232   1.1  christos 	int status_u, status_l;
   1233  1.10  christos 	uint64_t result_u, result_l;
   1234   1.1  christos 	status_u = inner_rsqrt (FP_PS_upper(op1), fmt_single, round, denorm,
   1235   1.1  christos 				&result_u);
   1236   1.1  christos 	status_l = inner_rsqrt (FP_PS_lower(op1), fmt_single, round, denorm,
   1237   1.1  christos 				&result_l);
   1238   1.1  christos 	result = FP_PS_cat(result_u, result_l);
   1239   1.1  christos 	status = status_u | status_l;
   1240   1.1  christos 	break;
   1241   1.1  christos       }
   1242   1.1  christos     default:
   1243  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1244   1.1  christos     }
   1245   1.1  christos 
   1246   1.1  christos   update_fcsr (cpu, cia, status);
   1247   1.1  christos   return result;
   1248   1.1  christos }
   1249   1.1  christos 
   1250   1.1  christos 
   1251  1.10  christos uint64_t
   1252   1.1  christos fp_abs(sim_cpu *cpu,
   1253   1.1  christos        address_word cia,
   1254  1.10  christos        uint64_t op,
   1255   1.1  christos        FP_formats fmt)
   1256   1.1  christos {
   1257   1.1  christos   return fp_unary(cpu, cia, &sim_fpu_abs, op, fmt);
   1258   1.1  christos }
   1259   1.1  christos 
   1260  1.10  christos uint64_t
   1261   1.1  christos fp_neg(sim_cpu *cpu,
   1262   1.1  christos        address_word cia,
   1263  1.10  christos        uint64_t op,
   1264   1.1  christos        FP_formats fmt)
   1265   1.1  christos {
   1266   1.1  christos   return fp_unary(cpu, cia, &sim_fpu_neg, op, fmt);
   1267   1.1  christos }
   1268   1.1  christos 
   1269  1.10  christos uint64_t
   1270   1.1  christos fp_add(sim_cpu *cpu,
   1271   1.1  christos        address_word cia,
   1272  1.10  christos        uint64_t op1,
   1273  1.10  christos        uint64_t op2,
   1274   1.1  christos        FP_formats fmt)
   1275   1.1  christos {
   1276   1.1  christos   return fp_binary(cpu, cia, &sim_fpu_add, op1, op2, fmt);
   1277   1.1  christos }
   1278   1.1  christos 
   1279  1.10  christos uint64_t
   1280   1.1  christos fp_sub(sim_cpu *cpu,
   1281   1.1  christos        address_word cia,
   1282  1.10  christos        uint64_t op1,
   1283  1.10  christos        uint64_t op2,
   1284   1.1  christos        FP_formats fmt)
   1285   1.1  christos {
   1286   1.1  christos   return fp_binary(cpu, cia, &sim_fpu_sub, op1, op2, fmt);
   1287   1.1  christos }
   1288   1.1  christos 
   1289  1.10  christos uint64_t
   1290   1.1  christos fp_mul(sim_cpu *cpu,
   1291   1.1  christos        address_word cia,
   1292  1.10  christos        uint64_t op1,
   1293  1.10  christos        uint64_t op2,
   1294   1.1  christos        FP_formats fmt)
   1295   1.1  christos {
   1296   1.1  christos   return fp_binary(cpu, cia, &sim_fpu_mul, op1, op2, fmt);
   1297   1.1  christos }
   1298   1.1  christos 
   1299  1.10  christos uint64_t
   1300   1.1  christos fp_div(sim_cpu *cpu,
   1301   1.1  christos        address_word cia,
   1302  1.10  christos        uint64_t op1,
   1303  1.10  christos        uint64_t op2,
   1304   1.1  christos        FP_formats fmt)
   1305   1.1  christos {
   1306   1.1  christos   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
   1307   1.1  christos }
   1308   1.1  christos 
   1309  1.10  christos uint64_t
   1310  1.10  christos fp_min (sim_cpu *cpu,
   1311  1.10  christos 	address_word cia,
   1312  1.10  christos 	uint64_t op1,
   1313  1.10  christos 	uint64_t op2,
   1314  1.10  christos 	FP_formats fmt)
   1315  1.10  christos {
   1316  1.10  christos   return fp_binary (cpu, cia, &sim_fpu_min, op1, op2, fmt);
   1317  1.10  christos }
   1318  1.10  christos 
   1319  1.10  christos uint64_t
   1320  1.10  christos fp_max (sim_cpu *cpu,
   1321  1.10  christos 	address_word cia,
   1322  1.10  christos 	uint64_t op1,
   1323  1.10  christos 	uint64_t op2,
   1324  1.10  christos 	FP_formats fmt)
   1325  1.10  christos {
   1326  1.10  christos   return fp_binary (cpu, cia, &sim_fpu_max, op1, op2, fmt);
   1327  1.10  christos }
   1328  1.10  christos 
   1329  1.10  christos uint64_t
   1330  1.10  christos fp_mina (sim_cpu *cpu,
   1331  1.10  christos 	 address_word cia,
   1332  1.10  christos 	 uint64_t op1,
   1333  1.10  christos 	 uint64_t op2,
   1334  1.10  christos 	 FP_formats fmt)
   1335  1.10  christos {
   1336  1.10  christos   uint64_t ret;
   1337  1.10  christos   sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
   1338  1.10  christos   sim_fpu_status status = 0;
   1339  1.10  christos 
   1340  1.10  christos   switch (fmt)
   1341  1.10  christos     {
   1342  1.10  christos     case fmt_single:
   1343  1.10  christos       sim_fpu_32to (&wop1, op1);
   1344  1.10  christos       sim_fpu_32to (&wop2, op2);
   1345  1.10  christos       break;
   1346  1.10  christos     case fmt_double:
   1347  1.10  christos       sim_fpu_64to (&wop1, op1);
   1348  1.10  christos       sim_fpu_64to (&wop2, op2);
   1349  1.10  christos       break;
   1350  1.10  christos     default:
   1351  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1352  1.10  christos     }
   1353  1.10  christos 
   1354  1.10  christos   status |= sim_fpu_abs (&waop1, &wop1);
   1355  1.10  christos   status |= sim_fpu_abs (&waop2, &wop2);
   1356  1.10  christos   status |= sim_fpu_min (&wans, &waop1, &waop2);
   1357  1.10  christos   ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
   1358  1.10  christos 
   1359  1.10  christos   update_fcsr (cpu, cia, status);
   1360  1.10  christos   return ret;
   1361  1.10  christos }
   1362  1.10  christos 
   1363  1.10  christos uint64_t
   1364  1.10  christos fp_maxa (sim_cpu *cpu,
   1365  1.10  christos 	 address_word cia,
   1366  1.10  christos 	 uint64_t op1,
   1367  1.10  christos 	 uint64_t op2,
   1368  1.10  christos 	 FP_formats fmt)
   1369  1.10  christos {
   1370  1.10  christos   uint64_t ret;
   1371  1.10  christos   sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
   1372  1.10  christos   sim_fpu_status status = 0;
   1373  1.10  christos 
   1374  1.10  christos   switch (fmt)
   1375  1.10  christos     {
   1376  1.10  christos     case fmt_single:
   1377  1.10  christos       sim_fpu_32to (&wop1, op1);
   1378  1.10  christos       sim_fpu_32to (&wop2, op2);
   1379  1.10  christos       break;
   1380  1.10  christos     case fmt_double:
   1381  1.10  christos       sim_fpu_64to (&wop1, op1);
   1382  1.10  christos       sim_fpu_64to (&wop2, op2);
   1383  1.10  christos       break;
   1384  1.10  christos     default:
   1385  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1386  1.10  christos     }
   1387  1.10  christos 
   1388  1.10  christos   status |= sim_fpu_abs (&waop1, &wop1);
   1389  1.10  christos   status |= sim_fpu_abs (&waop2, &wop2);
   1390  1.10  christos   status |= sim_fpu_max (&wans, &waop1, &waop2);
   1391  1.10  christos   ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
   1392  1.10  christos 
   1393  1.10  christos   update_fcsr (cpu, cia, status);
   1394  1.10  christos   return ret;
   1395  1.10  christos }
   1396  1.10  christos 
   1397  1.10  christos uint64_t
   1398   1.1  christos fp_recip(sim_cpu *cpu,
   1399   1.1  christos          address_word cia,
   1400  1.10  christos          uint64_t op,
   1401   1.1  christos          FP_formats fmt)
   1402   1.1  christos {
   1403   1.1  christos   return fp_unary(cpu, cia, &sim_fpu_inv, op, fmt);
   1404   1.1  christos }
   1405   1.1  christos 
   1406  1.10  christos uint64_t
   1407   1.1  christos fp_sqrt(sim_cpu *cpu,
   1408   1.1  christos         address_word cia,
   1409  1.10  christos         uint64_t op,
   1410   1.1  christos         FP_formats fmt)
   1411   1.1  christos {
   1412   1.1  christos   return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt);
   1413   1.1  christos }
   1414   1.1  christos 
   1415  1.10  christos uint64_t
   1416   1.1  christos fp_rsqrt(sim_cpu *cpu,
   1417   1.1  christos          address_word cia,
   1418  1.10  christos          uint64_t op,
   1419   1.1  christos          FP_formats fmt)
   1420   1.1  christos {
   1421   1.1  christos   return fp_inv_sqrt(cpu, cia, op, fmt);
   1422   1.1  christos }
   1423   1.1  christos 
   1424  1.10  christos uint64_t
   1425   1.1  christos fp_madd(sim_cpu *cpu,
   1426   1.1  christos         address_word cia,
   1427  1.10  christos         uint64_t op1,
   1428  1.10  christos         uint64_t op2,
   1429  1.10  christos         uint64_t op3,
   1430   1.1  christos         FP_formats fmt)
   1431   1.1  christos {
   1432   1.1  christos   return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
   1433   1.1  christos }
   1434   1.1  christos 
   1435  1.10  christos uint64_t
   1436   1.1  christos fp_msub(sim_cpu *cpu,
   1437   1.1  christos         address_word cia,
   1438  1.10  christos         uint64_t op1,
   1439  1.10  christos         uint64_t op2,
   1440  1.10  christos         uint64_t op3,
   1441   1.1  christos         FP_formats fmt)
   1442   1.1  christos {
   1443   1.1  christos   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
   1444   1.1  christos }
   1445   1.1  christos 
   1446  1.10  christos uint64_t
   1447  1.10  christos fp_fmadd (sim_cpu *cpu,
   1448  1.10  christos           address_word cia,
   1449  1.10  christos           uint64_t op1,
   1450  1.10  christos           uint64_t op2,
   1451  1.10  christos           uint64_t op3,
   1452  1.10  christos           FP_formats fmt)
   1453  1.10  christos {
   1454  1.10  christos   return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt);
   1455  1.10  christos }
   1456  1.10  christos 
   1457  1.10  christos uint64_t
   1458  1.10  christos fp_fmsub (sim_cpu *cpu,
   1459  1.10  christos           address_word cia,
   1460  1.10  christos           uint64_t op1,
   1461  1.10  christos           uint64_t op2,
   1462  1.10  christos           uint64_t op3,
   1463  1.10  christos           FP_formats fmt)
   1464  1.10  christos {
   1465  1.10  christos   return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt);
   1466  1.10  christos }
   1467  1.10  christos 
   1468  1.10  christos uint64_t
   1469   1.1  christos fp_nmadd(sim_cpu *cpu,
   1470   1.1  christos          address_word cia,
   1471  1.10  christos          uint64_t op1,
   1472  1.10  christos          uint64_t op2,
   1473  1.10  christos          uint64_t op3,
   1474   1.1  christos          FP_formats fmt)
   1475   1.1  christos {
   1476   1.1  christos   return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt);
   1477   1.1  christos }
   1478   1.1  christos 
   1479  1.10  christos uint64_t
   1480   1.1  christos fp_nmsub(sim_cpu *cpu,
   1481   1.1  christos          address_word cia,
   1482  1.10  christos          uint64_t op1,
   1483  1.10  christos          uint64_t op2,
   1484  1.10  christos          uint64_t op3,
   1485   1.1  christos          FP_formats fmt)
   1486   1.1  christos {
   1487   1.1  christos   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt);
   1488   1.1  christos }
   1489   1.1  christos 
   1490   1.1  christos 
   1491   1.1  christos /* MIPS-3D ASE operations.  */
   1492   1.1  christos 
   1493   1.1  christos /* Variant of fp_binary for *r.ps MIPS-3D operations. */
   1494  1.10  christos static uint64_t
   1495   1.1  christos fp_binary_r(sim_cpu *cpu,
   1496   1.1  christos 	    address_word cia,
   1497   1.1  christos 	    int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
   1498  1.10  christos 	    uint64_t op1,
   1499  1.10  christos 	    uint64_t op2)
   1500   1.1  christos {
   1501   1.1  christos   sim_fpu wop1;
   1502   1.1  christos   sim_fpu wop2;
   1503   1.1  christos   sim_fpu ans;
   1504   1.1  christos   sim_fpu_round round = rounding_mode (GETRM ());
   1505   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
   1506   1.1  christos   sim_fpu_status status_u, status_l;
   1507  1.10  christos   uint64_t result;
   1508  1.10  christos   uint32_t res_u, res_l;
   1509   1.1  christos 
   1510   1.1  christos   /* The format must be fmt_ps.  */
   1511   1.1  christos   status_u = 0;
   1512   1.1  christos   sim_fpu_32to (&wop1, FP_PS_upper (op1));
   1513   1.1  christos   sim_fpu_32to (&wop2, FP_PS_lower (op1));
   1514   1.1  christos   status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2);
   1515   1.1  christos   status_u |= sim_fpu_round_32 (&ans, round, denorm);
   1516   1.1  christos   sim_fpu_to32 (&res_u, &ans);
   1517   1.1  christos   status_l = 0;
   1518   1.1  christos   sim_fpu_32to (&wop1, FP_PS_upper (op2));
   1519   1.1  christos   sim_fpu_32to (&wop2, FP_PS_lower (op2));
   1520   1.1  christos   status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2);
   1521   1.1  christos   status_l |= sim_fpu_round_32 (&ans, round, denorm);
   1522   1.1  christos   sim_fpu_to32 (&res_l, &ans);
   1523   1.1  christos   result = FP_PS_cat (res_u, res_l);
   1524   1.1  christos 
   1525   1.1  christos   update_fcsr (cpu, cia, status_u | status_l);
   1526   1.1  christos   return result;
   1527   1.1  christos }
   1528   1.1  christos 
   1529  1.10  christos uint64_t
   1530   1.1  christos fp_add_r(sim_cpu *cpu,
   1531   1.1  christos          address_word cia,
   1532  1.10  christos          uint64_t op1,
   1533  1.10  christos          uint64_t op2,
   1534   1.1  christos          FP_formats fmt)
   1535   1.1  christos {
   1536   1.1  christos   return fp_binary_r (cpu, cia, &sim_fpu_add, op1, op2);
   1537   1.1  christos }
   1538   1.1  christos 
   1539  1.10  christos uint64_t
   1540   1.1  christos fp_mul_r(sim_cpu *cpu,
   1541   1.1  christos          address_word cia,
   1542  1.10  christos          uint64_t op1,
   1543  1.10  christos          uint64_t op2,
   1544   1.1  christos          FP_formats fmt)
   1545   1.1  christos {
   1546   1.1  christos   return fp_binary_r (cpu, cia, &sim_fpu_mul, op1, op2);
   1547   1.1  christos }
   1548   1.1  christos 
   1549   1.1  christos #define NR_FRAC_GUARD   (60)
   1550   1.1  christos #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD)
   1551   1.1  christos 
   1552   1.1  christos static int
   1553   1.1  christos fpu_inv1(sim_fpu *f, const sim_fpu *l)
   1554   1.1  christos {
   1555   1.1  christos   static const sim_fpu sim_fpu_one = {
   1556   1.1  christos     sim_fpu_class_number, 0, IMPLICIT_1, 0
   1557   1.1  christos   };
   1558   1.1  christos   int  status = 0;
   1559   1.1  christos   sim_fpu t;
   1560   1.1  christos 
   1561   1.1  christos   if (sim_fpu_is_zero (l))
   1562   1.1  christos     {
   1563   1.1  christos       *f = sim_fpu_maxfp;
   1564   1.1  christos       f->sign = l->sign;
   1565   1.1  christos       return sim_fpu_status_invalid_div0;
   1566   1.1  christos     }
   1567   1.1  christos   if (sim_fpu_is_infinity (l))
   1568   1.1  christos     {
   1569   1.1  christos       *f = sim_fpu_zero;
   1570   1.1  christos       f->sign = l->sign;
   1571   1.1  christos       return status;
   1572   1.1  christos     }
   1573   1.1  christos   status |= sim_fpu_div (f, &sim_fpu_one, l);
   1574   1.1  christos   return status;
   1575   1.1  christos }
   1576   1.1  christos 
   1577   1.1  christos static int
   1578   1.1  christos fpu_inv1_32(sim_fpu *f, const sim_fpu *l)
   1579   1.1  christos {
   1580   1.1  christos   if (sim_fpu_is_zero (l))
   1581   1.1  christos     {
   1582   1.1  christos       *f = sim_fpu_max32;
   1583   1.1  christos       f->sign = l->sign;
   1584   1.1  christos       return sim_fpu_status_invalid_div0;
   1585   1.1  christos     }
   1586   1.1  christos   return fpu_inv1 (f, l);
   1587   1.1  christos }
   1588   1.1  christos 
   1589   1.1  christos static int
   1590   1.1  christos fpu_inv1_64(sim_fpu *f, const sim_fpu *l)
   1591   1.1  christos {
   1592   1.1  christos   if (sim_fpu_is_zero (l))
   1593   1.1  christos     {
   1594   1.1  christos       *f = sim_fpu_max64;
   1595   1.1  christos       f->sign = l->sign;
   1596   1.1  christos       return sim_fpu_status_invalid_div0;
   1597   1.1  christos     }
   1598   1.1  christos   return fpu_inv1 (f, l);
   1599   1.1  christos }
   1600   1.1  christos 
   1601  1.10  christos uint64_t
   1602   1.1  christos fp_recip1(sim_cpu *cpu,
   1603   1.1  christos           address_word cia,
   1604  1.10  christos           uint64_t op,
   1605   1.1  christos           FP_formats fmt)
   1606   1.1  christos {
   1607   1.1  christos   switch (fmt)
   1608   1.1  christos     {
   1609   1.1  christos     case fmt_single:
   1610   1.1  christos     case fmt_ps:
   1611   1.1  christos       return fp_unary (cpu, cia, &fpu_inv1_32, op, fmt);
   1612   1.1  christos     case fmt_double:
   1613   1.1  christos       return fp_unary (cpu, cia, &fpu_inv1_64, op, fmt);
   1614   1.1  christos     }
   1615   1.1  christos   return 0;
   1616   1.1  christos }
   1617   1.1  christos 
   1618  1.10  christos uint64_t
   1619   1.1  christos fp_recip2(sim_cpu *cpu,
   1620   1.1  christos           address_word cia,
   1621  1.10  christos           uint64_t op1,
   1622  1.10  christos           uint64_t op2,
   1623   1.1  christos           FP_formats fmt)
   1624   1.1  christos {
   1625  1.10  christos   static const uint64_t one_single = UNSIGNED64 (0x3F800000);
   1626  1.10  christos   static const uint64_t one_double = UNSIGNED64 (0x3FF0000000000000);
   1627  1.10  christos   static const uint64_t one_ps = (UNSIGNED64 (0x3F800000) << 32 | UNSIGNED64 (0x3F800000));
   1628  1.10  christos   uint64_t one;
   1629   1.1  christos 
   1630   1.1  christos   /* Implemented as nmsub fd, 1, fs, ft.  */
   1631   1.1  christos   switch (fmt)
   1632   1.1  christos     {
   1633   1.1  christos     case fmt_single:  one = one_single;  break;
   1634   1.1  christos     case fmt_double:  one = one_double;  break;
   1635   1.1  christos     case fmt_ps:      one = one_ps;      break;
   1636   1.1  christos     default:          one = 0;           abort ();
   1637   1.1  christos     }
   1638   1.1  christos   return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, one, 0, 1, fmt);
   1639   1.1  christos }
   1640   1.1  christos 
   1641   1.1  christos static int
   1642   1.1  christos fpu_inv_sqrt1(sim_fpu *f, const sim_fpu *l)
   1643   1.1  christos {
   1644   1.1  christos   static const sim_fpu sim_fpu_one = {
   1645   1.1  christos     sim_fpu_class_number, 0, IMPLICIT_1, 0
   1646   1.1  christos   };
   1647   1.1  christos   int  status = 0;
   1648   1.1  christos   sim_fpu t;
   1649   1.1  christos 
   1650   1.1  christos   if (sim_fpu_is_zero (l))
   1651   1.1  christos     {
   1652   1.1  christos       *f = sim_fpu_maxfp;
   1653   1.1  christos       f->sign = l->sign;
   1654   1.1  christos       return sim_fpu_status_invalid_div0;
   1655   1.1  christos     }
   1656   1.1  christos   if (sim_fpu_is_infinity (l))
   1657   1.1  christos     {
   1658   1.1  christos       if (!l->sign)
   1659   1.1  christos 	{
   1660   1.1  christos 	  f->class = sim_fpu_class_zero;
   1661   1.1  christos 	  f->sign = 0;
   1662   1.1  christos 	}
   1663   1.1  christos       else
   1664   1.1  christos 	{
   1665   1.1  christos 	  *f = sim_fpu_qnan;
   1666   1.1  christos 	  status = sim_fpu_status_invalid_sqrt;
   1667   1.1  christos 	}
   1668   1.1  christos       return status;
   1669   1.1  christos     }
   1670   1.1  christos   status |= sim_fpu_sqrt (&t, l);
   1671   1.1  christos   status |= sim_fpu_div (f, &sim_fpu_one, &t);
   1672   1.1  christos   return status;
   1673   1.1  christos }
   1674   1.1  christos 
   1675   1.1  christos static int
   1676   1.1  christos fpu_inv_sqrt1_32(sim_fpu *f, const sim_fpu *l)
   1677   1.1  christos {
   1678   1.1  christos   if (sim_fpu_is_zero (l))
   1679   1.1  christos     {
   1680   1.1  christos       *f = sim_fpu_max32;
   1681   1.1  christos       f->sign = l->sign;
   1682   1.1  christos       return sim_fpu_status_invalid_div0;
   1683   1.1  christos     }
   1684   1.1  christos   return fpu_inv_sqrt1 (f, l);
   1685   1.1  christos }
   1686   1.1  christos 
   1687   1.1  christos static int
   1688   1.1  christos fpu_inv_sqrt1_64(sim_fpu *f, const sim_fpu *l)
   1689   1.1  christos {
   1690   1.1  christos   if (sim_fpu_is_zero (l))
   1691   1.1  christos     {
   1692   1.1  christos       *f = sim_fpu_max64;
   1693   1.1  christos       f->sign = l->sign;
   1694   1.1  christos       return sim_fpu_status_invalid_div0;
   1695   1.1  christos     }
   1696   1.1  christos   return fpu_inv_sqrt1 (f, l);
   1697   1.1  christos }
   1698   1.1  christos 
   1699  1.10  christos uint64_t
   1700   1.1  christos fp_rsqrt1(sim_cpu *cpu,
   1701   1.1  christos           address_word cia,
   1702  1.10  christos           uint64_t op,
   1703   1.1  christos           FP_formats fmt)
   1704   1.1  christos {
   1705   1.1  christos   switch (fmt)
   1706   1.1  christos     {
   1707   1.1  christos     case fmt_single:
   1708   1.1  christos     case fmt_ps:
   1709   1.1  christos       return fp_unary (cpu, cia, &fpu_inv_sqrt1_32, op, fmt);
   1710   1.1  christos     case fmt_double:
   1711   1.1  christos       return fp_unary (cpu, cia, &fpu_inv_sqrt1_64, op, fmt);
   1712   1.1  christos     }
   1713   1.1  christos   return 0;
   1714   1.1  christos }
   1715   1.1  christos 
   1716  1.10  christos uint64_t
   1717   1.1  christos fp_rsqrt2(sim_cpu *cpu,
   1718   1.1  christos           address_word cia,
   1719  1.10  christos           uint64_t op1,
   1720  1.10  christos           uint64_t op2,
   1721   1.1  christos           FP_formats fmt)
   1722   1.1  christos {
   1723  1.10  christos   static const uint64_t half_single = UNSIGNED64 (0x3F000000);
   1724  1.10  christos   static const uint64_t half_double = UNSIGNED64 (0x3FE0000000000000);
   1725  1.10  christos   static const uint64_t half_ps = (UNSIGNED64 (0x3F000000) << 32 | UNSIGNED64 (0x3F000000));
   1726  1.10  christos   uint64_t half;
   1727   1.1  christos 
   1728   1.1  christos   /* Implemented as (nmsub fd, 0.5, fs, ft)/2, where the divide is
   1729   1.1  christos      done by scaling the exponent during multiply.  */
   1730   1.1  christos   switch (fmt)
   1731   1.1  christos     {
   1732   1.1  christos     case fmt_single:  half = half_single;  break;
   1733   1.1  christos     case fmt_double:  half = half_double;  break;
   1734   1.1  christos     case fmt_ps:      half = half_ps;      break;
   1735   1.1  christos     default:          half = 0;            abort ();
   1736   1.1  christos     }
   1737   1.1  christos   return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, half, -1, 1, fmt);
   1738   1.1  christos }
   1739   1.1  christos 
   1740   1.1  christos 
   1741   1.1  christos /* Conversion operations.  */
   1742   1.1  christos 
   1743   1.1  christos uword64
   1744   1.1  christos convert (sim_cpu *cpu,
   1745   1.1  christos 	 address_word cia,
   1746   1.1  christos 	 int rm,
   1747   1.1  christos 	 uword64 op,
   1748   1.1  christos 	 FP_formats from,
   1749   1.1  christos 	 FP_formats to)
   1750   1.1  christos {
   1751   1.1  christos   sim_fpu wop;
   1752   1.1  christos   sim_fpu_round round = rounding_mode (rm);
   1753   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
   1754  1.10  christos   uint32_t result32;
   1755  1.10  christos   uint64_t result64;
   1756   1.1  christos   sim_fpu_status status = 0;
   1757   1.1  christos 
   1758   1.1  christos   /* Convert the input to sim_fpu internal format */
   1759   1.1  christos   switch (from)
   1760   1.1  christos     {
   1761   1.1  christos     case fmt_double:
   1762   1.1  christos       sim_fpu_64to (&wop, op);
   1763   1.1  christos       break;
   1764   1.1  christos     case fmt_single:
   1765   1.1  christos       sim_fpu_32to (&wop, op);
   1766   1.1  christos       break;
   1767   1.1  christos     case fmt_word:
   1768   1.1  christos       status = sim_fpu_i32to (&wop, op, round);
   1769   1.1  christos       break;
   1770   1.1  christos     case fmt_long:
   1771   1.1  christos       status = sim_fpu_i64to (&wop, op, round);
   1772   1.1  christos       break;
   1773   1.1  christos     default:
   1774  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1775   1.1  christos     }
   1776   1.1  christos 
   1777   1.1  christos   /* Convert sim_fpu format into the output */
   1778   1.1  christos   /* The value WOP is converted to the destination format, rounding
   1779   1.1  christos      using mode RM. When the destination is a fixed-point format, then
   1780   1.1  christos      a source value of Infinity, NaN or one which would round to an
   1781   1.1  christos      integer outside the fixed point range then an IEEE Invalid Operation
   1782   1.1  christos      condition is raised.  Not used if destination format is PS.  */
   1783   1.1  christos   switch (to)
   1784   1.1  christos     {
   1785   1.1  christos     case fmt_single:
   1786   1.1  christos       status |= sim_fpu_round_32 (&wop, round, denorm);
   1787   1.1  christos       /* For a NaN, normalize mantissa bits (cvt.s.d can't preserve them) */
   1788   1.1  christos       if (sim_fpu_is_qnan (&wop))
   1789   1.1  christos 	wop = sim_fpu_qnan;
   1790   1.1  christos       sim_fpu_to32 (&result32, &wop);
   1791   1.1  christos       result64 = result32;
   1792   1.1  christos       break;
   1793   1.1  christos     case fmt_double:
   1794   1.1  christos       status |= sim_fpu_round_64 (&wop, round, denorm);
   1795   1.1  christos       /* For a NaN, normalize mantissa bits (make cvt.d.s consistent) */
   1796   1.1  christos       if (sim_fpu_is_qnan (&wop))
   1797   1.1  christos 	wop = sim_fpu_qnan;
   1798   1.1  christos       sim_fpu_to64 (&result64, &wop);
   1799   1.1  christos       break;
   1800   1.1  christos     case fmt_word:
   1801  1.10  christos       status |= sim_fpu_to32u (&result32, &wop, round);
   1802   1.1  christos       result64 = result32;
   1803   1.1  christos       break;
   1804   1.1  christos     case fmt_long:
   1805  1.10  christos       status |= sim_fpu_to64u (&result64, &wop, round);
   1806   1.1  christos       break;
   1807   1.1  christos     default:
   1808   1.1  christos       result64 = 0;
   1809  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1810   1.1  christos     }
   1811   1.1  christos 
   1812   1.1  christos   update_fcsr (cpu, cia, status);
   1813   1.1  christos   return result64;
   1814   1.1  christos }
   1815   1.1  christos 
   1816  1.10  christos uint64_t
   1817   1.1  christos ps_lower(sim_cpu *cpu,
   1818   1.1  christos          address_word cia,
   1819  1.10  christos          uint64_t op)
   1820   1.1  christos {
   1821   1.1  christos   return FP_PS_lower (op);
   1822   1.1  christos }
   1823   1.1  christos 
   1824  1.10  christos uint64_t
   1825   1.1  christos ps_upper(sim_cpu *cpu,
   1826   1.1  christos          address_word cia,
   1827  1.10  christos          uint64_t op)
   1828   1.1  christos {
   1829   1.1  christos   return FP_PS_upper(op);
   1830   1.1  christos }
   1831   1.1  christos 
   1832  1.10  christos uint64_t
   1833   1.1  christos pack_ps(sim_cpu *cpu,
   1834   1.1  christos         address_word cia,
   1835  1.10  christos         uint64_t op1,
   1836  1.10  christos         uint64_t op2,
   1837   1.1  christos         FP_formats fmt)
   1838   1.1  christos {
   1839  1.10  christos   uint64_t result = 0;
   1840   1.1  christos 
   1841   1.1  christos   /* The registers must specify FPRs valid for operands of type
   1842   1.1  christos      "fmt". If they are not valid, the result is undefined. */
   1843   1.1  christos 
   1844   1.1  christos   /* The format type should already have been checked: */
   1845   1.1  christos   switch (fmt)
   1846   1.1  christos     {
   1847   1.1  christos     case fmt_single:
   1848   1.1  christos       {
   1849   1.1  christos 	sim_fpu wop;
   1850  1.10  christos 	uint32_t res_u, res_l;
   1851   1.1  christos 	sim_fpu_32to (&wop, op1);
   1852   1.1  christos 	sim_fpu_to32 (&res_u, &wop);
   1853   1.1  christos 	sim_fpu_32to (&wop, op2);
   1854   1.1  christos 	sim_fpu_to32 (&res_l, &wop);
   1855   1.1  christos 	result = FP_PS_cat(res_u, res_l);
   1856   1.1  christos 	break;
   1857   1.1  christos       }
   1858   1.1  christos     default:
   1859  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1860   1.1  christos     }
   1861   1.1  christos 
   1862   1.1  christos   return result;
   1863   1.1  christos }
   1864   1.1  christos 
   1865  1.10  christos uint64_t
   1866   1.1  christos convert_ps (sim_cpu *cpu,
   1867   1.1  christos             address_word cia,
   1868   1.1  christos             int rm,
   1869  1.10  christos             uint64_t op,
   1870   1.1  christos             FP_formats from,
   1871   1.1  christos             FP_formats to)
   1872   1.1  christos {
   1873   1.1  christos   sim_fpu wop_u, wop_l;
   1874   1.1  christos   sim_fpu_round round = rounding_mode (rm);
   1875   1.1  christos   sim_fpu_denorm denorm = denorm_mode (cpu);
   1876  1.10  christos   uint32_t res_u, res_l;
   1877  1.10  christos   uint64_t result;
   1878   1.1  christos   sim_fpu_status status_u = 0, status_l = 0;
   1879   1.1  christos 
   1880   1.1  christos   /* As convert, but used only for paired values (formats PS, PW) */
   1881   1.1  christos 
   1882   1.1  christos   /* Convert the input to sim_fpu internal format */
   1883   1.1  christos   switch (from)
   1884   1.1  christos     {
   1885   1.1  christos     case fmt_word:   /* fmt_pw */
   1886   1.1  christos       sim_fpu_i32to (&wop_u, (op >> 32) & (unsigned)0xFFFFFFFF, round);
   1887   1.1  christos       sim_fpu_i32to (&wop_l, op & (unsigned)0xFFFFFFFF, round);
   1888   1.1  christos       break;
   1889   1.1  christos     case fmt_ps:
   1890   1.1  christos       sim_fpu_32to (&wop_u, FP_PS_upper(op));
   1891   1.1  christos       sim_fpu_32to (&wop_l, FP_PS_lower(op));
   1892   1.1  christos       break;
   1893   1.1  christos     default:
   1894  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1895   1.1  christos     }
   1896   1.1  christos 
   1897   1.1  christos   /* Convert sim_fpu format into the output */
   1898   1.1  christos   switch (to)
   1899   1.1  christos     {
   1900   1.1  christos     case fmt_word:   /* fmt_pw */
   1901  1.10  christos       status_u |= sim_fpu_to32u (&res_u, &wop_u, round);
   1902  1.10  christos       status_l |= sim_fpu_to32u (&res_l, &wop_l, round);
   1903  1.10  christos       result = (((uint64_t)res_u) << 32) | (uint64_t)res_l;
   1904   1.1  christos       break;
   1905   1.1  christos     case fmt_ps:
   1906   1.1  christos       status_u |= sim_fpu_round_32 (&wop_u, 0, round);
   1907   1.1  christos       status_l |= sim_fpu_round_32 (&wop_l, 0, round);
   1908   1.1  christos       sim_fpu_to32 (&res_u, &wop_u);
   1909   1.1  christos       sim_fpu_to32 (&res_l, &wop_l);
   1910   1.1  christos       result = FP_PS_cat(res_u, res_l);
   1911   1.1  christos       break;
   1912   1.1  christos     default:
   1913   1.1  christos       result = 0;
   1914  1.10  christos       sim_io_error (SD, "Bad switch\n");
   1915   1.1  christos     }
   1916   1.1  christos 
   1917   1.1  christos   update_fcsr (cpu, cia, status_u | status_l);
   1918   1.1  christos   return result;
   1919   1.1  christos }
   1920   1.1  christos 
   1921   1.1  christos static const char *
   1922   1.1  christos fpu_format_name (FP_formats fmt)
   1923   1.1  christos {
   1924   1.1  christos   switch (fmt)
   1925   1.1  christos     {
   1926   1.1  christos     case fmt_single:
   1927   1.1  christos       return "single";
   1928   1.1  christos     case fmt_double:
   1929   1.1  christos       return "double";
   1930   1.1  christos     case fmt_word:
   1931   1.1  christos       return "word";
   1932   1.1  christos     case fmt_long:
   1933   1.1  christos       return "long";
   1934   1.1  christos     case fmt_ps:
   1935   1.1  christos       return "ps";
   1936   1.1  christos     case fmt_unknown:
   1937   1.1  christos       return "<unknown>";
   1938   1.1  christos     case fmt_uninterpreted:
   1939   1.1  christos       return "<uninterpreted>";
   1940   1.1  christos     case fmt_uninterpreted_32:
   1941   1.1  christos       return "<uninterpreted_32>";
   1942   1.1  christos     case fmt_uninterpreted_64:
   1943   1.1  christos       return "<uninterpreted_64>";
   1944   1.1  christos     default:
   1945   1.1  christos       return "<format error>";
   1946   1.1  christos     }
   1947   1.1  christos }
   1948   1.1  christos 
   1949   1.1  christos #ifdef DEBUG
   1950   1.1  christos static const char *
   1951   1.1  christos fpu_rounding_mode_name (int rm)
   1952   1.1  christos {
   1953   1.1  christos   switch (rm)
   1954   1.1  christos     {
   1955   1.1  christos     case FP_RM_NEAREST:
   1956   1.1  christos       return "Round";
   1957   1.1  christos     case FP_RM_TOZERO:
   1958   1.1  christos       return "Trunc";
   1959   1.1  christos     case FP_RM_TOPINF:
   1960   1.1  christos       return "Ceil";
   1961   1.1  christos     case FP_RM_TOMINF:
   1962   1.1  christos       return "Floor";
   1963   1.1  christos     default:
   1964   1.1  christos       return "<rounding mode error>";
   1965   1.1  christos     }
   1966   1.1  christos }
   1967   1.1  christos #endif /* DEBUG */
   1968