fix `even` polarity in bfp_ROUND_TO_INTEGER
[openpower-isa.git] / openpower / isafunctions / bfp.mdwn
1 # binary-floating-point helper functions
2
3 `bfp_*` and related functions as needed by fcvt* from PowerISA v3.1B Book I
4 section 7.6.2.2
5
6 def reset_xflags():
7 vxsnan_flag <- 0
8 vximz_flag <- 0
9 vxidi_flag <- 0
10 vxisi_flag <- 0
11 vxzdz_flag <- 0
12 vxsqrt_flag <- 0
13 vxcvi_flag <- 0
14 vxvc_flag <- 0
15 ox_flag <- 0
16 ux_flag <- 0
17 xx_flag <- 0
18 zx_flag <- 0
19
20 def bfp_CONVERT_FROM_BFP64(x):
21 # x is a binary floating-point value represented in
22 # double-precision format.
23 exponent <- x[1:11]
24 fraction <- x[12:63]
25
26 result <- BFPState()
27 result.sign <- 0
28 result.exponent <- 0
29 result.significand <- 0
30 result.class.SNaN <- 0
31 result.class.QNaN <- 0
32 result.class.Infinity <- 0
33 result.class.Zero <- 0
34 result.class.Denormal <- 0
35 result.class.Normal <- 0
36 if (exponent = 2047) & (fraction[0] = 0) & (fraction != 0) then
37 # x is a SNaN
38 result.class.SNaN <- 1
39 result.sign <- x[0]
40 result.significand[0] <- 0
41 result.significand[1:52] <- fraction
42 else if (exponent = 2047) & (fraction[0] != 0) & (fraction != 0) then
43 # x is a QNaN
44 result.class.QNaN <- 1
45 result.sign <- x[0]
46 result.significand[0] <- 0
47 result.significand[1:52] <- fraction
48 else if (exponent = 2047) & (fraction = 0) then
49 # is an Infinity
50 result.class.Infinity <- 1
51 result.sign <- x[0]
52 else if (exponent = 0) & (fraction = 0) then
53 # x is a Zero
54 result.class.Zero <- 1
55 result.sign <- x[0]
56 else if (exponent = 0) & (fraction != 0) then
57 # x is a Denormal
58 result.class.Denormal <- 1
59 result.sign <- x[0]
60 result.exp <- -1022
61 result.significand[0] <- 0
62 result.significand[1:52] <- fraction
63 do while result.significand[0] != 1
64 result.significand <- result.significand * 2
65 result.exponent <- result.exponent - 1
66 else
67 result.class.Normal <- 1
68 result.sign <- x[0]
69 result.exponent <- exponent - 1023
70 result.significand[0] <- 1
71 result.significand[1:52] <- fraction
72 return result
73
74 def bfp_CONVERT_FROM_SI32(x):
75 # x is an integer value represented in signed word integer format.
76
77 result <- BFPState()
78 result.sign <- 0
79 result.exponent <- 0
80 result.significand <- 0
81 result.class.SNaN <- 0
82 result.class.QNaN <- 0
83 result.class.Infinity <- 0
84 result.class.Zero <- 0
85 result.class.Denormal <- 0
86 result.class.Normal <- 0
87
88 if x = 0x0000_0000 then
89 result.class.Zero <- 1
90 else
91 result.class.Normal <- 1
92 result.sign <- x[0]
93 result.exponent <- 32
94 result.significand[0:32] <- EXTS(x)
95
96 if result.significand[0] = 1 then
97 result.sign <- 1
98 result.significand[0:32] <- -result.significand[0:32]
99 do while result.significand[0] = 0
100 result.significand <- result.significand * 2
101 result.exponent <- result.exponent - 1
102 return result
103
104 def bfp_CONVERT_FROM_SI64(x):
105 # x is an integer value represented in signed double-word integer
106 # format.
107
108 result <- BFPState()
109 result.sign <- 0
110 result.exponent <- 0
111 result.significand <- 0
112 result.class.SNaN <- 0
113 result.class.QNaN <- 0
114 result.class.Infinity <- 0
115 result.class.Zero <- 0
116 result.class.Denormal <- 0
117 result.class.Normal <- 0
118
119 if x = 0x0000_0000_0000_0000 then
120 result.class.Zero <- 1
121 else
122 result.class.Normal <- 1
123 result.sign <- x[0]
124 result.exponent <- 64
125 result.significand[0:64] <- EXTS(x)
126
127 if result.significand[0] = 1 then
128 result.sign <- 1
129 result.significand[0:64] <- -result.significand[0:64]
130 do while result.significand[0] = 0
131 result.significand <- result.significand * 2
132 result.exponent <- result.exponent - 1
133 return result
134
135 def bfp_CONVERT_FROM_UI128(x):
136 # x is a 128-bit unsigned integer value.
137
138 result <- BFPState()
139 result.sign <- 0
140 result.exponent <- 0
141 result.significand <- 0
142 result.class.SNaN <- 0
143 result.class.QNaN <- 0
144 result.class.Infinity <- 0
145 result.class.Zero <- 0
146 result.class.Denormal <- 0
147 result.class.Normal <- 0
148
149 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
150 result.class.Zero <- 1
151 else
152 result.class.Normal <- 1
153 result.sign <- 0
154 result.exponent <- 128
155 result.significand[0:128] <- 0b0 || x
156 do while result.significand[0] = 0
157 result.significand <- result.significand * 2
158 result.exponent <- result.exponent - 1
159 return result
160
161 def bfp_ROUND_TO_INTEGER(rmode, x):
162 # x is a binary floating-point value that is represented in the
163 # binary floating-point working format and has
164 # unbounded exponent range and significand precision.
165
166 if IsSNaN(x) then vxsnan_flag <- 1
167 if IsNaN(x) & ¬IsSNaN(x) then return x
168 if IsSNaN(x) then
169 result <- x
170 result.class.SNaN <- 0
171 result.class.QNaN <- 1
172 return result
173 if IsInf(x) | IsZero(x) then return x
174 result <- x
175 result.class.Denormal <- 0
176 result.class.Normal <- 0
177 exact <- 0
178 halfway <- 0
179 more_than_halfway <- 0
180 even <- 0
181 if result.exponent < -1 then
182 # all values have magnitude < 0.5
183 result.significand <- 0
184 result.exponent <- 0
185 even <- 1
186 else if result.exponent = -1 then
187 if result.significand[0] = 1 then
188 result.significand[0] <- 0
189 if result.significand = 0 then halfway <- 1
190 else more_than_halfway <- 1
191 result.significand <- 0
192 result.exponent <- 0
193 even <- 1
194 else
195 result.significand <- 0
196 int_part <- x.significand[0:x.exponent]
197 result.significand[0:x.exponent] <- int_part
198 even <- ¬int_part[x.exponent]
199 temp <- x.significand
200 temp[0:x.exponent] <- 0
201 if temp = 0 then exact <- 1
202 if temp[x.exponent + 1] = 1 then
203 temp[x.exponent + 1] <- 0
204 if temp = 0 then halfway <- 1
205 else more_than_halfway <- 1
206 if rmode = 0b000 then # Round to Nearest Even
207 round_up <- (even & halfway) | more_than_halfway
208 if rmode = 0b001 then # Round towards Zero
209 round_up <- 0
210 if rmode = 0b010 then # Round towards +Infinity
211 round_up <- (x.sign = 0) & ¬exact
212 if rmode = 0b011 then # Round towards -Infinity
213 round_up <- (x.sign = 1) & ¬exact
214 if rmode = 0b100 then # Round to Nearest Away
215 round_up <- halfway | more_than_halfway
216 if round_up then
217 inc_flag <- 1
218 temp <- BFPState()
219 temp.significand <- 0
220 temp.significand[result.exponent] <- 1
221 result.significand <- result.significand + temp.significand
222 if result.significand >= 2 then
223 result.significand <- truediv(result.significand, 2)
224 result.exponent <- result.exponent + 1
225 else inc_flag <- 0 # TODO: does the spec specify this?
226 if result.significand = 0 then result.class.Zero <- 1
227 else result.class.Normal <- 1
228 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
229 else xx_flag <- 0 # TODO: does the spec specify this?
230 return result
231
232 def bfp_ROUND_TO_INTEGER_NEAR_EVEN(x):
233 return bfp_ROUND_TO_INTEGER(0b000, x)
234
235 def bfp_ROUND_TO_INTEGER_TRUNC(x):
236 return bfp_ROUND_TO_INTEGER(0b001, x)
237
238 def bfp_ROUND_TO_INTEGER_CEIL(x):
239 return bfp_ROUND_TO_INTEGER(0b010, x)
240
241 def bfp_ROUND_TO_INTEGER_FLOOR(x):
242 return bfp_ROUND_TO_INTEGER(0b011, x)
243
244 def bfp_ROUND_TO_INTEGER_NEAR_AWAY(x):
245 return bfp_ROUND_TO_INTEGER(0b100, x)
246
247 def bfp_COMPARE_EQ(x, y):
248 # x is a binary floating-point value represented in the
249 # binary floating-point working format.
250 # y is a binary floating-point value represented in the
251 # binary floating-point working format.
252
253 if IsNaN(x) | IsNaN(y) then
254 return 0b0
255 if IsZero(x) & IsZero(y) then
256 return 0b1
257 if IsZero(x) | IsZero(y) then
258 return 0b0
259 if x.sign != y.sign then
260 return 0b0
261 if x.exponent != y.exponent then
262 return 0b0
263 return x.significand = y.significand
264
265 def bfp_COMPARE_GT(x, y):
266 # x is a binary floating-point value represented in the
267 # binary floating-point working format.
268 # y is a binary floating-point value represented in the
269 # binary floating-point working format.
270
271 if IsNaN(x) | IsNaN(y) then
272 return 0b0
273 if IsZero(x) & IsZero(y) then
274 return 0b0
275 if IsZero(x) then
276 return IsNeg(y)
277 if IsZero(y) then
278 return ¬IsNeg(x)
279 if x.sign != y.sign then
280 return IsNeg(y)
281 if x.exponent != y.exponent then
282 if x.sign = 1 then return x.exponent < y.exponent
283 return x.exponent > y.exponent
284 if x.sign = 1 then return x.significand < y.significand
285 return x.significand > y.significand
286
287 def bfp_COMPARE_LT(x, y):
288 # x is a binary floating-point value represented in the
289 # binary floating-point working format.
290 # y is a binary floating-point value represented in the
291 # binary floating-point working format.
292
293 if IsNaN(x) | IsNaN(y) then
294 return 0b0
295 if IsZero(x) & IsZero(y) then
296 return 0b0
297 if IsZero(x) then
298 return ¬IsNeg(y)
299 if IsZero(y) then
300 return IsNeg(x)
301 if x.sign != y.sign then
302 return IsNeg(x)
303 if x.exponent != y.exponent then
304 if x.sign = 1 then return x.exponent > y.exponent
305 return x.exponent < y.exponent
306 if x.sign = 1 then return x.significand > y.significand
307 return x.significand < y.significand
308
309 def bfp_ABSOLUTE(x):
310 # x is a binary floating-point value represented in the
311 # binary floating-point working format.
312 result <- x
313 result.sign <- 0
314 return result