08409e8f0016f2be3ede7a7e3f09ca8a0f9973d6
[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.exponent <- -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
70 # have to do the subtraction separately since SelectableInt won't
71 # give negative results
72 result.exponent <- result.exponent - 1023
73 result.significand[0] <- 1
74 result.significand[1:52] <- fraction
75 return result
76
77 def bfp_CONVERT_FROM_SI32(x):
78 # x is an integer value represented in signed word integer format.
79
80 result <- BFPState()
81 result.sign <- 0
82 result.exponent <- 0
83 result.significand <- 0
84 result.class.SNaN <- 0
85 result.class.QNaN <- 0
86 result.class.Infinity <- 0
87 result.class.Zero <- 0
88 result.class.Denormal <- 0
89 result.class.Normal <- 0
90
91 if x = 0x0000_0000 then
92 result.class.Zero <- 1
93 else
94 result.class.Normal <- 1
95 result.sign <- x[0]
96 result.exponent <- 32
97 result.significand[0:32] <- EXTS(x)
98
99 if result.significand[0] = 1 then
100 result.sign <- 1
101 result.significand[0:32] <- -result.significand[0:32]
102 do while result.significand[0] = 0
103 result.significand <- result.significand * 2
104 result.exponent <- result.exponent - 1
105 return result
106
107 def bfp_CONVERT_FROM_SI64(x):
108 # x is an integer value represented in signed double-word integer
109 # format.
110
111 result <- BFPState()
112 result.sign <- 0
113 result.exponent <- 0
114 result.significand <- 0
115 result.class.SNaN <- 0
116 result.class.QNaN <- 0
117 result.class.Infinity <- 0
118 result.class.Zero <- 0
119 result.class.Denormal <- 0
120 result.class.Normal <- 0
121
122 if x = 0x0000_0000_0000_0000 then
123 result.class.Zero <- 1
124 else
125 result.class.Normal <- 1
126 result.sign <- x[0]
127 result.exponent <- 64
128 result.significand[0:64] <- EXTS(x)
129
130 if result.significand[0] = 1 then
131 result.sign <- 1
132 result.significand[0:64] <- -result.significand[0:64]
133 do while result.significand[0] = 0
134 result.significand <- result.significand * 2
135 result.exponent <- result.exponent - 1
136 return result
137
138 def bfp_CONVERT_FROM_SI128(x):
139 # x is a 128-bit signed integer value.
140
141 result <- BFPState()
142 result.sign <- 0
143 result.exponent <- 0
144 result.significand <- 0
145 result.class.SNaN <- 0
146 result.class.QNaN <- 0
147 result.class.Infinity <- 0
148 result.class.Zero <- 0
149 result.class.Denormal <- 0
150 result.class.Normal <- 0
151
152 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
153 result.class.Zero <- 1
154 else
155 result.class.Normal <- 1
156 result.sign <- x[0]
157 result.exponent <- 128
158 result.significand[0:128] <- EXTS(x)
159
160 if result.significand[0] = 1 then
161 result.sign <- 1
162 result.significand[0:128] <- -result.significand[0:128]
163 do while result.significand[0] = 0
164 result.significand <- result.significand * 2
165 result.exponent <- result.exponent - 1
166 return result
167
168 def bfp_CONVERT_FROM_UI128(x):
169 # x is a 128-bit unsigned integer value.
170
171 result <- BFPState()
172 result.sign <- 0
173 result.exponent <- 0
174 result.significand <- 0
175 result.class.SNaN <- 0
176 result.class.QNaN <- 0
177 result.class.Infinity <- 0
178 result.class.Zero <- 0
179 result.class.Denormal <- 0
180 result.class.Normal <- 0
181
182 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
183 result.class.Zero <- 1
184 else
185 result.class.Normal <- 1
186 result.sign <- 0
187 result.exponent <- 128
188 result.significand[0:128] <- 0b0 || x
189 do while result.significand[0] = 0
190 result.significand <- result.significand * 2
191 result.exponent <- result.exponent - 1
192 return result
193
194 def bfp_ROUND_TO_INTEGER(rmode, x):
195 # x is a binary floating-point value that is represented in the
196 # binary floating-point working format and has
197 # unbounded exponent range and significand precision.
198
199 if IsSNaN(x) then vxsnan_flag <- 1
200 if IsNaN(x) & ¬IsSNaN(x) then return x
201 if IsSNaN(x) then
202 result <- x
203 result.class.SNaN <- 0
204 result.class.QNaN <- 1
205 return result
206 if IsInf(x) | IsZero(x) then return x
207 result <- x
208 result.class.Denormal <- 0
209 result.class.Normal <- 0
210 exact <- 0
211 halfway <- 0
212 more_than_halfway <- 0
213 even <- 0
214 if result.exponent < -1 then
215 # all values have magnitude < 0.5
216 result.significand <- 0
217 result.exponent <- 0
218 even <- 1
219 else if result.exponent = -1 then
220 if result.significand[0] = 1 then
221 result.significand[0] <- 0
222 if result.significand = 0 then halfway <- 1
223 else more_than_halfway <- 1
224 result.significand <- 0
225 result.exponent <- 0
226 even <- 1
227 else
228 result.significand <- 0
229 int_part <- x.significand[0:x.exponent]
230 result.significand[0:x.exponent] <- int_part
231 even <- ¬int_part[x.exponent]
232 temp <- x.significand
233 temp[0:x.exponent] <- 0
234 if temp = 0 then exact <- 1
235 if temp[x.exponent + 1] = 1 then
236 temp[x.exponent + 1] <- 0
237 if temp = 0 then halfway <- 1
238 else more_than_halfway <- 1
239 if rmode = 0b000 then # Round to Nearest Even
240 round_up <- (even & halfway) | more_than_halfway
241 if rmode = 0b001 then # Round towards Zero
242 round_up <- 0
243 if rmode = 0b010 then # Round towards +Infinity
244 round_up <- (x.sign = 0) & ¬exact
245 if rmode = 0b011 then # Round towards -Infinity
246 round_up <- (x.sign = 1) & ¬exact
247 if rmode = 0b100 then # Round to Nearest Away
248 round_up <- halfway | more_than_halfway
249 if round_up then
250 inc_flag <- 1
251 temp <- BFPState()
252 temp.significand <- 0
253 temp.significand[result.exponent] <- 1
254 result.significand <- result.significand + temp.significand
255 if result.significand >= 2 then
256 result.significand <- truediv(result.significand, 2)
257 result.exponent <- result.exponent + 1
258 else inc_flag <- 0 # TODO: does the spec specify this?
259 if result.significand = 0 then result.class.Zero <- 1
260 else result.class.Normal <- 1
261 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
262 else xx_flag <- 0 # TODO: does the spec specify this?
263 return result
264
265 def bfp_ROUND_TO_INTEGER_NEAR_EVEN(x):
266 return bfp_ROUND_TO_INTEGER(0b000, x)
267
268 def bfp_ROUND_TO_INTEGER_TRUNC(x):
269 return bfp_ROUND_TO_INTEGER(0b001, x)
270
271 def bfp_ROUND_TO_INTEGER_CEIL(x):
272 return bfp_ROUND_TO_INTEGER(0b010, x)
273
274 def bfp_ROUND_TO_INTEGER_FLOOR(x):
275 return bfp_ROUND_TO_INTEGER(0b011, x)
276
277 def bfp_ROUND_TO_INTEGER_NEAR_AWAY(x):
278 return bfp_ROUND_TO_INTEGER(0b100, x)
279
280 def bfp_COMPARE_EQ(x, y):
281 # x is a binary floating-point value represented in the
282 # binary floating-point working format.
283 # y is a binary floating-point value represented in the
284 # binary floating-point working format.
285
286 if IsNaN(x) | IsNaN(y) then
287 return 0b0
288 if IsZero(x) & IsZero(y) then
289 return 0b1
290 if IsZero(x) | IsZero(y) then
291 return 0b0
292 if x.sign != y.sign then
293 return 0b0
294 if x.exponent != y.exponent then
295 return 0b0
296 return x.significand = y.significand
297
298 def bfp_COMPARE_GT(x, y):
299 # x is a binary floating-point value represented in the
300 # binary floating-point working format.
301 # y is a binary floating-point value represented in the
302 # binary floating-point working format.
303
304 if IsNaN(x) | IsNaN(y) then
305 return 0b0
306 if IsZero(x) & IsZero(y) then
307 return 0b0
308 if IsZero(x) then
309 return IsNeg(y)
310 if IsZero(y) then
311 return ¬IsNeg(x)
312 if x.sign != y.sign then
313 return IsNeg(y)
314 if x.exponent != y.exponent then
315 if x.sign = 1 then return x.exponent < y.exponent
316 return x.exponent > y.exponent
317 if x.sign = 1 then return x.significand < y.significand
318 return x.significand > y.significand
319
320 def bfp_COMPARE_LT(x, y):
321 # x is a binary floating-point value represented in the
322 # binary floating-point working format.
323 # y is a binary floating-point value represented in the
324 # binary floating-point working format.
325
326 if IsNaN(x) | IsNaN(y) then
327 return 0b0
328 if IsZero(x) & IsZero(y) then
329 return 0b0
330 if IsZero(x) then
331 return ¬IsNeg(y)
332 if IsZero(y) then
333 return IsNeg(x)
334 if x.sign != y.sign then
335 return IsNeg(x)
336 if x.exponent != y.exponent then
337 if x.sign = 1 then return x.exponent > y.exponent
338 return x.exponent < y.exponent
339 if x.sign = 1 then return x.significand > y.significand
340 return x.significand < y.significand
341
342 def bfp_ABSOLUTE(x):
343 # x is a binary floating-point value represented in the
344 # binary floating-point working format.
345 result <- x
346 result.sign <- 0
347 return result
348
349 def si128_CONVERT_FROM_BFP(x):
350 # x is an integer value represented in the
351 # binary floating-point working format.
352
353 if IsNaN(x) then
354 vxcvi_flag <- 1
355 if IsSNaN(x) then vxsnan_flag <- 1
356 return 0x8000_0000_0000_0000_0000_0000_0000_0000
357 else
358 temp_xx <- xx_flag
359 temp_inc <- inc_flag
360 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
361 # TODO: does the spec say these are preserved?
362 xx_flag <- temp_xx
363 inc_flag <- temp_inc
364 exponent <- rnd.exponent
365 significand <- rnd.significand
366 si128max <- bfp_CONVERT_FROM_SI128(0b0 || [1] * 127)
367 si128min <- bfp_CONVERT_FROM_SI128(0b1 || [0] * 127)
368 if bfp_COMPARE_GT(rnd, si128max) then
369 vxcvi_flag <- 1
370 return 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
371 if bfp_COMPARE_LT(rnd, si128min) then
372 vxcvi_flag <- 1
373 return 0x8000_0000_0000_0000_0000_0000_0000_0000
374 else
375 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
376 else xx_flag <- 0 # TODO: does the spec specify this?
377 inc_flag <- 0
378 # TODO: spec says this is logical shift right:
379 significand <- significand[0:127] / pow(2, 127 - exponent)
380 if IsNeg(rnd) then significand <- -significand
381 return significand[0:127]