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