Skip to contentSkip to conversation

Missing rounding modes.

PATCH New Paul Brook 1 participant 1 message Mar 10, 2005

lore
Share & tools
lore

Paul Brook

author
#0 lore raw

PATCH 1/1 Missing rounding modes.

Some hosts (eg. arm-linux) don't support all the IEEE/C99 floating point rounding modes.

The attached patch adds appropriate ifdefs to the arm, ppc and sparc targets. Emulation obviously won't be perfect on these systems, but it will at least work to a first approximation.

Paul

Index: target-arm/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/op_helper.c,v retrieving revision 1.1
diff -c -p -r1.1 op_helper.c
*** target-arm/op_helper.c 22 Feb 2005 19:27:29 -0000 1.1
--- target-arm/op_helper.c 10 Mar 2005 01:27:20 -0000
*************** int vfp_host_exceptbits_to_host(int targ *** 177,183 ****

void do_vfp_set_fpscr(void)
{

-     int i;
      uint32_t changed;
  
      changed = env->vfp.fpscr;

--- 177,182 ----
*************** void do_vfp_set_fpscr(void)
*** 187,208 ****

      changed ^= T0;
      if (changed & (3 << 22)) {
!         i = (T0 >> 22) & 3;
!         switch (i) {
          case 0:
!             i = FE_TONEAREST;
              break;
          case 1:
!             i = FE_UPWARD;
              break;
          case 2:
!             i = FE_DOWNWARD;
              break;
          case 3:
!             i = FE_TOWARDZERO;
              break;
          }
-         fesetround (i);
      }
  
      /* Clear host exception flags.  */

--- 186,217 ----

      changed ^= T0;
      if (changed & (3 << 22)) {
!         switch ((T0 >> 22) & 3) {
          case 0:

! /* Best approximation (round to nearest) */
! #ifdef FE_TONEAREST
! fesetround(FE_TONEAREST);
! #endif

              break;
          case 1:

! /* Smaller magnitude (round toward zero) */
! #ifdef FE_TOWARDZERO
! fesetround(FE_TOWARDZERO);
! #endif

              break;
          case 2:

! /* Round toward +infinite */
! #ifdef FE_UPWARD
! fesetround(FE_UPWARD);
! #endif

              break;
          case 3:

! /* Round toward -infinite */
! #ifdef FE_DOWNWARD
! fesetround(FE_DOWNWARD);
! #endif

              break;
          }
      }
  
      /* Clear host exception flags.  */

*************** void do_vfp_set_fpscr(void)
*** 210,215 ****
--- 219,225 ----

  #ifdef feenableexcept
      if (changed & 0x1f00) {
+         int i;
          i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
          feenableexcept (i);
          fedisableexcept (FE_ALL_EXCEPT & ~i);

Index: target-ppc/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/op_helper.c,v retrieving revision 1.11
diff -c -p -r1.11 op_helper.c
*** target-ppc/op_helper.c 15 Feb 2005 23:06:19 -0000 1.11
--- target-ppc/op_helper.c 10 Mar 2005 01:27:22 -0000
*************** void do_store_fpscr (uint32_t mask) *** 227,245 ****
--- 227,253 ----

      switch (env->fpscr[0] & 0x3) {
      case 0:
          /* Best approximation (round to nearest) */
+ #ifdef FE_TONEAREST
          fesetround(FE_TONEAREST);
+ #endif
          break;
      case 1:
          /* Smaller magnitude (round toward zero) */
+ #ifdef FE_TOWARDZERO
          fesetround(FE_TOWARDZERO);
+ #endif
          break;
      case 2:
          /* Round toward +infinite */
+ #ifdef FE_UPWARD
          fesetround(FE_UPWARD);
+ #endif
          break;
      case 3:
          /* Round toward -infinite */
+ #ifdef FE_DOWNWARD
          fesetround(FE_DOWNWARD);
+ #endif
          break;
      }

}
*************** void do_fctiwz (void)
*** 269,275 ****
--- 277,285 ----

      } *p = (void *)&FT1;
      int cround = fegetround();

+ #ifdef FE_TOWARDZERO

      fesetround(FE_TOWARDZERO);
+ #endif
      if (FT0 > (double)0x7FFFFFFF)
          p->i = 0x7FFFFFFFULL << 32;
      else if (FT0 < -(double)0x80000000)

Index: target-sparc/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.9
diff -c -p -r1.9 op_helper.c
*** target-sparc/op_helper.c 22 Feb 2005 19:14:33 -0000 1.9
--- target-sparc/op_helper.c 10 Mar 2005 01:27:23 -0000
*************** void helper_ldfsr(void)
*** 252,267 ****
--- 252,275 ----

  {
      switch (env->fsr & FSR_RD_MASK) {
      case FSR_RD_NEAREST:

+ #ifdef FE_TONEAREST
fesetround(FE_TONEAREST);
+ #endif
break;
case FSR_RD_ZERO:
+ #ifdef FE_TOWARDZERO
fesetround(FE_TOWARDZERO);
+ #endif
break;
case FSR_RD_POS:
+ #ifdef FE_UPWARD
fesetround(FE_UPWARD);
+ #endif
break;
case FSR_RD_NEG:
+ #ifdef FE_DOWNWARD
fesetround(FE_DOWNWARD);
+ #endif

  	break;
      }

}