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 }