master
  1/*
  2 * The Hexagon user status register includes five status fields which work
  3 * as sticky flags for the five IEEE-defined exception conditions:
  4 * inexact, overflow, underflow, divide by zero, and invalid.
  5 * A sticky flag is set when the corresponding exception occurs,
  6 * and remains set until explicitly cleared.
  7 *
  8 *  usr:23:22 - Rounding Mode
  9 *  00: Round toward nearest
 10 *  01: Round toward zero
 11 *  10: Downward Round toward negative infinity
 12 *  11: Upward Round toward positive infinity
 13 *
 14 *  usr:5 - Floating-point IEEE Inexact Sticky Flag.
 15 *  usr:4 - Floating-point IEEE Underflow Sticky Flag.
 16 *  usr:3 - Floating-point IEEE Overflow Sticky Flag.
 17 *  usr:2 - Floating-point IEEE Divide-By-Zero Sticky Flag.
 18 *  usr:1 - Floating-point IEEE Invalid Sticky Flag.
 19 *  usr:0 - Sticky Saturation Overflow, when 1 saturation occurred.
 20 */
 21
 22#define FE_ALL_EXCEPT 0x3f
 23
 24#define USR_FE_MASK 0x3fc0003f
 25#define RND_MASK    (0x3 << 22)
 26#define RND_NEAR    (0x0 << 22)
 27#define RND_ZERO    (0x1 << 22)
 28#define RND_DOWN    (0x2 << 22)
 29#define RND_UP      (0x3 << 22)
 30
 31/*
 32 * int feclearexcept(int mask)
 33 */
 34.global feclearexcept
 35.type feclearexcept,@function
 36feclearexcept:
 37  {
 38    r0 = and(r0, #FE_ALL_EXCEPT) // Only touch the IEEE flag bits.
 39    r1 = usr
 40  }
 41  r1 = and(r1, ~r0)
 42  {
 43    usr = r1
 44    r0 = #0
 45    jumpr r31
 46  }
 47
 48/*
 49 * int feraiseexcept(int mask)
 50 */
 51.global feraiseexcept
 52.type feraiseexcept,@function
 53feraiseexcept:
 54  {
 55    r0 = and(r0, #FE_ALL_EXCEPT) // Only touch the IEEE flag bits.
 56    r1 = usr
 57  }
 58  r1 = or(r1, r0)
 59  {
 60    usr = r1
 61    r0 = #0
 62    jumpr r31
 63  }
 64
 65
 66/*
 67 * int fetestexcept(int mask)
 68 */
 69.global fetestexcept
 70.type fetestexcept,@function
 71fetestexcept:
 72  {
 73    r0 = and(r0, #FE_ALL_EXCEPT) // Only touch the IEEE flag bits.
 74    r1 = usr
 75  }
 76  {
 77    r0 = and(r1, r0)
 78    jumpr r31
 79  }
 80
 81/*
 82 *int fegetround(void)
 83 */
 84.global fegetround
 85.type fegetround,@function
 86fegetround:
 87  r0 = usr
 88  r0 = and(r0, ##RND_MASK)
 89  r0 = lsr(r0, #22);
 90  jumpr r31
 91
 92/*
 93 * int __fesetround(int r)
 94 */
 95.global __fesetround
 96.type __fesetround,@function
 97__fesetround:
 98  {
 99    r0 = and(r0, #0x3) // Can only be 0,1,2, or 3
100    r1 = usr
101    r2 = ##RND_MASK
102  }
103  {
104    r1 = and (r1, ~r2)  // Clear the current rounding bits.
105    r0 = asl (r0, #22)
106  }
107  r1 = or(r1, r0)
108  usr = r1
109  {
110    r0 = #0; jumpr r31
111  }
112
113/*
114 * int fegetenv(fenv_t *envp)
115 */
116.global fegetenv
117.type fegetenv,@function
118fegetenv:
119  r1 = usr
120  memw(r0) = r1
121  {
122    r0 = #0
123    jumpr r31
124  }
125
126/*
127 * int fesetenv(const fenv_t *envp)
128 */
129.global fesetenv
130.type fesetenv,@function
131fesetenv:
132  { p0 = cmp.eq(r0, #-1); if (p0.new) r1 = #0 }  /* The default mode */
133  if (!p0) r1 = memw(r0)                         /* stored in fenv_t */
134
135  r2 = ##USR_FE_MASK // USR:FE bit mask
136  r1 = and(r1, r2)   // MASK the input bits with the FE bits
137  r3 = usr
138  r3 = and(r3, ~r2)  // Clear any currently set FE bits
139  r3 = or(r3, r1)    // Set the newbits
140  usr = r3
141  {
142    r0 = #0
143    jumpr r31
144  }