* interp.c (fsca_s, fsrra_s): New functions.
authorJoern Rennecke <joern.rennecke@embecosm.com>
Mon, 3 Nov 2003 14:14:15 +0000 (14:14 +0000)
committerJoern Rennecke <joern.rennecke@embecosm.com>
Mon, 3 Nov 2003 14:14:15 +0000 (14:14 +0000)
* gencode.c (tab): Add entries for fsca and fsrra.
(expand_opcode): Allow variable length n / m fields.

sim/sh/ChangeLog
sim/sh/gencode.c
sim/sh/interp.c

index 2b6cf4353de7e55d5d6c2b2c11700d2650338c05..faa6ebc4f9a60d874e1cecf9243ad404953ff048 100644 (file)
@@ -1,3 +1,9 @@
+2003-11-03  J"orn Rennecke <joern.rennecke@superh.com>
+
+       * interp.c (fsca_s, fsrra_s): New functions.
+       * gencode.c (tab): Add entries for fsca and fsrra.
+       (expand_opcode): Allow variable length n / m fields.
+
 2003-10-15  J"orn Rennecke <joern.rennecke@superh.com>
 
        * syscall.h (SYS_truncate, SYS_ftruncate): Define.
index a4a1c2d34d70bd8f2ba324904d78146c3a33c6ad..07d62a98c5aa334d0da6df7d273fc0fd733b5705 100644 (file)
@@ -448,6 +448,17 @@ op tab[] =
     "  SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_FR);",
   },
 
+  /* sh4 */
+  { "", "", "fsca", "1111nnn011111101",
+    "if (FPSCR_PR)",
+    "  RAISE_EXCEPTION (SIGILL);",
+    "else",
+    "  {",
+    "    SET_FR (n, fsca_s (FPUL, &sin));",
+    "    SET_FR (n+1, fsca_s (FPUL, &cos));",
+    "  }",
+  },
+
   /* sh4 */
   { "", "", "fschg", "1111001111111101",
     "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_SZ);",
@@ -458,6 +469,14 @@ op tab[] =
     "FP_UNARY(n, sqrt);",
   },
 
+  /* sh4 */
+  { "", "", "fsrra", "1111nnnn01111101",
+    "if (FPSCR_PR)",
+    "  RAISE_EXCEPTION (SIGILL);",
+    "else",
+    "  SET_FR (n, fsrra_s (FR (n)));",
+  },
+
   /* sh2e */
   { "", "", "fsub <FREG_M>,<FREG_N>", "1111nnnnmmmm0001",
     "FP_OP(n, -, m);",
@@ -1979,6 +1998,8 @@ expand_opcode (shift, val, i, s)
          {
            int m, mv;
 
+           if (s[1] - '0' > 1U || !s[2] || ! s[3])
+             expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
            val |= bton (s) << shift;
            if (s[2] == '0' || s[2] == '1')
              expand_opcode (shift - 4, val, i, s + 4);
@@ -2003,12 +2024,17 @@ expand_opcode (shift, val, i, s)
          }
        case 'n':
        case 'm':
-         for (j = 0; j < 16; j++)
-           {
-             expand_opcode (shift - 4, val | (j << shift), i, s + 4);
-
-           }
-         break;
+         {
+           int digits = 1;
+           while (s[digits] == s[0])
+             digits++;
+           for (j = 0; j < (1 << digits); j++)
+             {
+               expand_opcode (shift - digits, val | (j << shift), i,
+                              s + digits);
+             }
+           break;
+         }
        case 'M':
          /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */
          for (j = 5; j < 16; j++)
index 711df1eb485fbc213174158f87b2e17133f1e3a7..5ca8e61a0a7591a596c1a36b3852f6dec36a2def 100644 (file)
@@ -1411,6 +1411,55 @@ macl (regs, memory, n, m)
   MACH = mach;
 }
 
+float
+fsca_s (int in, double (*f) (double))
+{
+  double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
+  double result = (*f) (rad);
+  double error, upper, lower, frac;
+  int exp;
+
+  /* Search the value with the maximum error that is still within the
+     architectural spec.  */
+  error = ldexp (1., -21);
+  /* compensate for calculation inaccuracy by reducing error.  */
+  error = error - ldexp (1., -50);
+  upper = result + error;
+  frac = frexp (upper, &exp);
+  upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
+  lower = result - error;
+  frac = frexp (lower, &exp);
+  lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
+  return abs (upper - result) >= abs (lower - result) ? upper : lower;
+}
+
+float
+fsrra_s (float in)
+{
+  double result = 1. / sqrt (in);
+  int exp;
+  double frac, upper, lower, error, eps;
+
+  /* refine result */
+  result = result - (result * result * in - 1) * 0.5 * result;
+  /* Search the value with the maximum error that is still within the
+     architectural spec.  */
+  frac = frexp (result, &exp);
+  frac = ldexp (frac, 24);
+  error = 4.; /* 1 << 24-1-21 */
+  /* use eps to compensate for possible 1 ulp error in our 'exact' result.  */
+  eps = ldexp (1., -29);
+  upper = floor (frac + error - eps);
+  if (upper > 16777216.)
+    upper = floor ((frac + error - eps) * 0.5) * 2.;
+  lower = ceil ((frac - error + eps) * 2) * .5;
+  if (lower > 8388608.)
+    lower = ceil (frac - error + eps);
+  upper = ldexp (upper, exp - 24);
+  lower = ldexp (lower, exp - 24);
+  return upper - result >= result - lower ? upper : lower;
+}
+
 static struct loop_bounds
 get_loop_bounds (rs, re, memory, mem_end, maskw, endianw)
      int rs, re;