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