1 # binary-floating-point helper functions
3 `bfp_*` and related functions as needed by fcvt* from PowerISA v3.1B Book I
20 def bfp_CONVERT_FROM_BFP64(x):
21 # x is a binary floating-point value represented in
22 # double-precision format.
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
38 result.class.SNaN <- 1
40 result.significand[0] <- 0
41 result.significand[1:52] <- fraction
42 else if (exponent = 2047) & (fraction[0] != 0) & (fraction != 0) then
44 result.class.QNaN <- 1
46 result.significand[0] <- 0
47 result.significand[1:52] <- fraction
48 else if (exponent = 2047) & (fraction = 0) then
50 result.class.Infinity <- 1
52 else if (exponent = 0) & (fraction = 0) then
54 result.class.Zero <- 1
56 else if (exponent = 0) & (fraction != 0) then
58 result.class.Denormal <- 1
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
67 result.class.Normal <- 1
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
77 def bfp_CONVERT_FROM_SI32(x):
78 # x is an integer value represented in signed word integer format.
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
91 if x = 0x0000_0000 then
92 result.class.Zero <- 1
94 result.class.Normal <- 1
97 result.significand[0:32] <- EXTS(x)
99 if result.significand[0] = 1 then
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
107 def bfp_CONVERT_FROM_SI64(x):
108 # x is an integer value represented in signed double-word integer
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
122 if x = 0x0000_0000_0000_0000 then
123 result.class.Zero <- 1
125 result.class.Normal <- 1
127 result.exponent <- 64
128 result.significand[0:64] <- EXTS(x)
130 if result.significand[0] = 1 then
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
138 def bfp_CONVERT_FROM_SI128(x):
139 # x is a 128-bit signed integer value.
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
152 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
153 result.class.Zero <- 1
155 result.class.Normal <- 1
157 result.exponent <- 128
158 result.significand[0:128] <- EXTS(x)
160 if result.significand[0] = 1 then
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
168 def bfp_CONVERT_FROM_UI128(x):
169 # x is a 128-bit unsigned integer value.
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
182 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
183 result.class.Zero <- 1
185 result.class.Normal <- 1
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
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.
199 if IsSNaN(x) then vxsnan_flag <- 1
200 if IsNaN(x) & ¬IsSNaN(x) then return x
203 result.class.SNaN <- 0
204 result.class.QNaN <- 1
206 if IsInf(x) | IsZero(x) then return x
208 result.class.Denormal <- 0
209 result.class.Normal <- 0
212 more_than_halfway <- 0
214 if result.exponent < -1 then
215 # all values have magnitude < 0.5
216 result.significand <- 0
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
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
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
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?
265 def bfp_ROUND_TO_INTEGER_NEAR_EVEN(x):
266 return bfp_ROUND_TO_INTEGER(0b000, x)
268 def bfp_ROUND_TO_INTEGER_TRUNC(x):
269 return bfp_ROUND_TO_INTEGER(0b001, x)
271 def bfp_ROUND_TO_INTEGER_CEIL(x):
272 return bfp_ROUND_TO_INTEGER(0b010, x)
274 def bfp_ROUND_TO_INTEGER_FLOOR(x):
275 return bfp_ROUND_TO_INTEGER(0b011, x)
277 def bfp_ROUND_TO_INTEGER_NEAR_AWAY(x):
278 return bfp_ROUND_TO_INTEGER(0b100, x)
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.
286 if IsNaN(x) | IsNaN(y) then
288 if IsZero(x) & IsZero(y) then
290 if IsZero(x) | IsZero(y) then
292 if x.sign != y.sign then
294 if x.exponent != y.exponent then
296 return x.significand = y.significand
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.
304 if IsNaN(x) | IsNaN(y) then
306 if IsZero(x) & IsZero(y) then
312 if x.sign != y.sign then
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
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.
326 if IsNaN(x) | IsNaN(y) then
328 if IsZero(x) & IsZero(y) then
334 if x.sign != y.sign then
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
343 # x is a binary floating-point value represented in the
344 # binary floating-point working format.
349 def si128_CONVERT_FROM_BFP(x):
350 # x is an integer value represented in the
351 # binary floating-point working format.
355 if IsSNaN(x) then vxsnan_flag <- 1
356 return 0x8000_0000_0000_0000_0000_0000_0000_0000
360 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
361 # TODO: does the spec say these are preserved?
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
370 return 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
371 if bfp_COMPARE_LT(rnd, si128min) then
373 return 0x8000_0000_0000_0000_0000_0000_0000_0000
375 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
376 else xx_flag <- 0 # TODO: does the spec specify this?
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]