1 # binary-floating-point helper functions
3 `bfp_*` and related functions as needed by c[ft]fpr* 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_BFP32(x):
78 # x is a floating-point value represented in single-precision format.
85 result.significand <- 0
86 result.class.SNaN <- 0
87 result.class.QNaN <- 0
88 result.class.Infinity <- 0
89 result.class.Zero <- 0
90 result.class.Denormal <- 0
91 result.class.Normal <- 0
92 if (exponent = 255) & (fraction[0] = 0) & (fraction != 0) then
94 result.class.SNaN <- 1
96 result.significand[0] <- 0
97 result.significand[1:23] <- fraction
98 else if (exponent = 255) & (fraction[0] != 0) & (fraction != 0) then
100 result.class.QNaN <- 1
102 result.significand[0] <- 0
103 result.significand[1:23] <- fraction
104 else if (exponent = 255) & (fraction = 0) then
106 result.class.Infinity <- 1
108 else if (exponent = 0) & (fraction = 0) then
110 result.class.Zero <- 1
112 else if (exponent = 0) & (fraction != 0) then
114 result.class.Denormal <- 1
116 result.exponent <- -126
117 result.significand[0] <- 0
118 result.significand[1:23] <- fraction
119 do while result.significand[0] != 1
120 result.significand <- result.significand * 2
121 result.exponent <- result.exponent - 1
123 result.class.Normal <- 1
125 result.exponent <- exponent
126 # have to do the subtraction separately since SelectableInt won't
127 # give negative results
128 result.exponent <- result.exponent - 127
129 result.significand[0] <- 1
130 result.significand[1:23] <- fraction
133 def bfp_CONVERT_FROM_SI32(x):
134 # x is an integer value represented in signed word integer format.
139 result.significand <- 0
140 result.class.SNaN <- 0
141 result.class.QNaN <- 0
142 result.class.Infinity <- 0
143 result.class.Zero <- 0
144 result.class.Denormal <- 0
145 result.class.Normal <- 0
147 if x = 0x0000_0000 then
148 result.class.Zero <- 1
150 result.class.Normal <- 1
152 result.exponent <- 32
153 result.significand[0:32] <- EXTS(x)
155 if result.significand[0] = 1 then
157 result.significand[0:32] <- -result.significand[0:32]
158 do while result.significand[0] = 0
159 result.significand <- result.significand * 2
160 result.exponent <- result.exponent - 1
163 def bfp_CONVERT_FROM_SI64(x):
164 # x is an integer value represented in signed double-word integer
170 result.significand <- 0
171 result.class.SNaN <- 0
172 result.class.QNaN <- 0
173 result.class.Infinity <- 0
174 result.class.Zero <- 0
175 result.class.Denormal <- 0
176 result.class.Normal <- 0
178 if x = 0x0000_0000_0000_0000 then
179 result.class.Zero <- 1
181 result.class.Normal <- 1
183 result.exponent <- 64
184 result.significand[0:64] <- EXTS(x)
186 if result.significand[0] = 1 then
188 result.significand[0:64] <- -result.significand[0:64]
189 do while result.significand[0] = 0
190 result.significand <- result.significand * 2
191 result.exponent <- result.exponent - 1
194 def bfp_CONVERT_FROM_SI128(x):
195 # x is a 128-bit signed integer value.
200 result.significand <- 0
201 result.class.SNaN <- 0
202 result.class.QNaN <- 0
203 result.class.Infinity <- 0
204 result.class.Zero <- 0
205 result.class.Denormal <- 0
206 result.class.Normal <- 0
208 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
209 result.class.Zero <- 1
211 result.class.Normal <- 1
213 result.exponent <- 128
214 result.significand[0:128] <- EXTS(x)
216 if result.significand[0] = 1 then
218 result.significand[0:128] <- -result.significand[0:128]
219 do while result.significand[0] = 0
220 result.significand <- result.significand * 2
221 result.exponent <- result.exponent - 1
224 def bfp_CONVERT_FROM_UI32(x):
225 # x is an integer value represented in unsigned word integer
231 result.significand <- 0
232 result.class.SNaN <- 0
233 result.class.QNaN <- 0
234 result.class.Infinity <- 0
235 result.class.Zero <- 0
236 result.class.Denormal <- 0
237 result.class.Normal <- 0
239 if x = 0x0000_0000 then
240 result.class.Zero <- 1
242 result.class.Normal <- 1
244 result.exponent <- 32
245 result.significand[0:32] <- 0b0 || x
246 do while result.significand[0] = 0
247 result.significand <- result.significand * 2
248 result.exponent <- result.exponent - 1
251 def bfp_CONVERT_FROM_UI64(x):
252 # x is an integer value represented in unsigned double-word integer
258 result.significand <- 0
259 result.class.SNaN <- 0
260 result.class.QNaN <- 0
261 result.class.Infinity <- 0
262 result.class.Zero <- 0
263 result.class.Denormal <- 0
264 result.class.Normal <- 0
266 if x = 0x0000_0000_0000_0000 then
267 result.class.Zero <- 1
269 result.class.Normal <- 1
271 result.exponent <- 64
272 result.significand[0:64] <- 0b0 || x
273 do while result.significand[0] = 0
274 result.significand <- result.significand * 2
275 result.exponent <- result.exponent - 1
278 def bfp_CONVERT_FROM_UI128(x):
279 # x is a 128-bit unsigned integer value.
284 result.significand <- 0
285 result.class.SNaN <- 0
286 result.class.QNaN <- 0
287 result.class.Infinity <- 0
288 result.class.Zero <- 0
289 result.class.Denormal <- 0
290 result.class.Normal <- 0
292 if x = 0x0000_0000_0000_0000_0000_0000_0000_0000 then
293 result.class.Zero <- 1
295 result.class.Normal <- 1
297 result.exponent <- 128
298 result.significand[0:128] <- 0b0 || x
299 do while result.significand[0] = 0
300 result.significand <- result.significand * 2
301 result.exponent <- result.exponent - 1
304 def bfp_ROUND_TO_INTEGER(rmode, x):
305 # x is a binary floating-point value that is represented in the
306 # binary floating-point working format and has
307 # unbounded exponent range and significand precision.
309 if IsSNaN(x) then vxsnan_flag <- 1
310 if IsNaN(x) & ¬IsSNaN(x) then return x
313 result.class.SNaN <- 0
314 result.class.QNaN <- 1
316 if IsInf(x) | IsZero(x) then return x
318 result.class.Denormal <- 0
319 result.class.Normal <- 0
322 more_than_halfway <- 0b0
324 if result.exponent < -1 then
325 # all values have magnitude < 0.5
326 result.significand <- 0
329 else if result.exponent = -1 then
330 if result.significand[0] = 1 then
331 result.significand[0] <- 0
332 if result.significand = 0 then halfway <- 0b1
333 else more_than_halfway <- 0b1
334 result.significand <- 0
338 result.significand <- 0
339 int_part <- x.significand[0:x.exponent]
340 result.significand[0:x.exponent] <- int_part
341 even <- ¬int_part[x.exponent]
342 temp <- x.significand
343 temp[0:x.exponent] <- 0
344 if temp = 0 then exact <- 0b1
345 if temp[x.exponent + 1] = 1 then
346 temp[x.exponent + 1] <- 0
347 if temp = 0 then halfway <- 0b1
348 else more_than_halfway <- 0b1
349 if rmode = 0b000 then # Round to Nearest Even
350 round_up <- (¬even & halfway) | more_than_halfway
351 if rmode = 0b001 then # Round towards Zero
353 if rmode = 0b010 then # Round towards +Infinity
354 round_up <- (x.sign = 0) & ¬exact
355 if rmode = 0b011 then # Round towards -Infinity
356 round_up <- (x.sign = 1) & ¬exact
357 if rmode = 0b100 then # Round to Nearest Away
358 round_up <- halfway | more_than_halfway
362 temp.significand <- 0
363 temp.significand[result.exponent] <- 1
364 result.significand <- result.significand + temp.significand
365 if result.significand >= 2 then
366 result.significand <- truediv(result.significand, 2)
367 result.exponent <- result.exponent + 1
368 else inc_flag <- 0 # TODO: does the spec specify this?
369 if result.significand = 0 then result.class.Zero <- 1
370 else result.class.Normal <- 1
371 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
372 else xx_flag <- 0 # TODO: does the spec specify this?
375 def bfp_ROUND_TO_INTEGER_NEAR_EVEN(x):
376 return bfp_ROUND_TO_INTEGER(0b000, x)
378 def bfp_ROUND_TO_INTEGER_TRUNC(x):
379 return bfp_ROUND_TO_INTEGER(0b001, x)
381 def bfp_ROUND_TO_INTEGER_CEIL(x):
382 return bfp_ROUND_TO_INTEGER(0b010, x)
384 def bfp_ROUND_TO_INTEGER_FLOOR(x):
385 return bfp_ROUND_TO_INTEGER(0b011, x)
387 def bfp_ROUND_TO_INTEGER_NEAR_AWAY(x):
388 return bfp_ROUND_TO_INTEGER(0b100, x)
390 def bfp_COMPARE_EQ(x, y):
391 # x is a binary floating-point value represented in the
392 # binary floating-point working format.
393 # y is a binary floating-point value represented in the
394 # binary floating-point working format.
396 if IsNaN(x) | IsNaN(y) then
398 if IsZero(x) & IsZero(y) then
401 if IsInf(x) & IsInf(y) then
402 return x.sign = y.sign
403 if IsInf(x) | IsInf(y) then
405 if IsZero(x) | IsZero(y) then
407 if x.sign != y.sign then
409 if x.exponent > 0 then xs <- x.significand * pow(2, x.exponent)
410 else xs <- truediv(x.significand, pow(2, -x.exponent))
411 if y.exponent > 0 then ys <- y.significand * pow(2, y.exponent)
412 else ys <- truediv(y.significand, pow(2, -y.exponent))
415 def bfp_COMPARE_GT(x, y):
416 # x is a binary floating-point value represented in the
417 # binary floating-point working format.
418 # y is a binary floating-point value represented in the
419 # binary floating-point working format.
421 if IsNaN(x) | IsNaN(y) then
423 if IsZero(x) & IsZero(y) then
426 if IsInf(x) & IsInf(y) then
427 return ¬IsNeg(x) & IsNeg(y)
436 if x.sign != y.sign then
438 if x.exponent > 0 then xs <- x.significand * pow(2, x.exponent)
439 else xs <- truediv(x.significand, pow(2, -x.exponent))
440 if y.exponent > 0 then ys <- y.significand * pow(2, y.exponent)
441 else ys <- truediv(y.significand, pow(2, -y.exponent))
442 if x.sign = 1 then return xs < ys
445 def bfp_COMPARE_LT(x, y):
446 # x is a binary floating-point value represented in the
447 # binary floating-point working format.
448 # y is a binary floating-point value represented in the
449 # binary floating-point working format.
451 if IsNaN(x) | IsNaN(y) then
453 if IsZero(x) & IsZero(y) then
456 if IsInf(x) & IsInf(y) then
457 return IsNeg(x) & ¬IsNeg(y)
466 if x.sign != y.sign then
468 if x.exponent > 0 then xs <- x.significand * pow(2, x.exponent)
469 else xs <- truediv(x.significand, pow(2, -x.exponent))
470 if y.exponent > 0 then ys <- y.significand * pow(2, y.exponent)
471 else ys <- truediv(y.significand, pow(2, -y.exponent))
472 if x.sign = 1 then return xs > ys
476 # x is a binary floating-point value represented in the
477 # binary floating-point working format.
482 def si32_CONVERT_FROM_BFP(x):
483 # x is an integer value represented in the
484 # binary floating-point working format.
488 if IsSNaN(x) then vxsnan_flag <- 1
493 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
494 # TODO: does the spec say these are preserved?
497 exponent <- rnd.exponent
498 significand <- rnd.significand
499 si32max <- bfp_CONVERT_FROM_SI32(0b0 || [1] * 31)
500 si32min <- bfp_CONVERT_FROM_SI32(0b1 || [0] * 31)
501 if bfp_COMPARE_GT(rnd, si32max) then
504 if bfp_COMPARE_LT(rnd, si32min) then
508 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
509 else xx_flag <- 0 # TODO: does the spec specify this?
511 # TODO: spec says this is logical shift right:
512 significand <- significand[0:31] / pow(2, 31 - exponent)
513 if IsNeg(rnd) then significand <- -significand
514 return significand[0:31]
516 def si64_CONVERT_FROM_BFP(x):
517 # x is an integer value represented in the
518 # binary floating-point working format.
522 if IsSNaN(x) then vxsnan_flag <- 1
523 return 0x8000_0000_0000_0000
527 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
528 # TODO: does the spec say these are preserved?
531 exponent <- rnd.exponent
532 significand <- rnd.significand
533 si64max <- bfp_CONVERT_FROM_SI64(0b0 || [1] * 63)
534 si64min <- bfp_CONVERT_FROM_SI64(0b1 || [0] * 63)
535 if bfp_COMPARE_GT(rnd, si64max) then
537 return 0x7FFF_FFFF_FFFF_FFFF
538 if bfp_COMPARE_LT(rnd, si64min) then
540 return 0x8000_0000_0000_0000
542 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
543 else xx_flag <- 0 # TODO: does the spec specify this?
545 # TODO: spec says this is logical shift right:
546 significand <- significand[0:63] / pow(2, 63 - exponent)
547 if IsNeg(rnd) then significand <- -significand
548 return significand[0:63]
550 def si128_CONVERT_FROM_BFP(x):
551 # x is an integer value represented in the
552 # binary floating-point working format.
556 if IsSNaN(x) then vxsnan_flag <- 1
557 return 0x8000_0000_0000_0000_0000_0000_0000_0000
561 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
562 # TODO: does the spec say these are preserved?
565 exponent <- rnd.exponent
566 significand <- rnd.significand
567 si128max <- bfp_CONVERT_FROM_SI128(0b0 || [1] * 127)
568 si128min <- bfp_CONVERT_FROM_SI128(0b1 || [0] * 127)
569 if bfp_COMPARE_GT(rnd, si128max) then
571 return 0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
572 if bfp_COMPARE_LT(rnd, si128min) then
574 return 0x8000_0000_0000_0000_0000_0000_0000_0000
576 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
577 else xx_flag <- 0 # TODO: does the spec specify this?
579 # TODO: spec says this is logical shift right:
580 significand <- significand[0:127] / pow(2, 127 - exponent)
581 if IsNeg(rnd) then significand <- -significand
582 return significand[0:127]
584 def ui32_CONVERT_FROM_BFP(x):
585 # x is an integer value represented in the
586 # binary floating-point working format.
590 if IsSNaN(x) then vxsnan_flag <- 1
595 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
596 # TODO: does the spec say these are preserved?
599 exponent <- rnd.exponent
600 significand <- rnd.significand
601 ui32max <- bfp_CONVERT_FROM_UI32([1] * 32)
602 if bfp_COMPARE_GT(rnd, ui32max) then
609 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
610 else xx_flag <- 0 # TODO: does the spec specify this?
612 # TODO: spec says this is logical shift right:
613 significand <- significand[0:31] / pow(2, 31 - exponent)
614 return significand[0:31]
616 def ui64_CONVERT_FROM_BFP(x):
617 # x is an integer value represented in the
618 # binary floating-point working format.
622 if IsSNaN(x) then vxsnan_flag <- 1
623 return 0x0000_0000_0000_0000
627 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
628 # TODO: does the spec say these are preserved?
631 exponent <- rnd.exponent
632 significand <- rnd.significand
633 ui64max <- bfp_CONVERT_FROM_UI64([1] * 64)
634 if bfp_COMPARE_GT(rnd, ui64max) then
636 return 0xFFFF_FFFF_FFFF_FFFF
639 return 0x0000_0000_0000_0000
641 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
642 else xx_flag <- 0 # TODO: does the spec specify this?
644 # TODO: spec says this is logical shift right:
645 significand <- significand[0:63] / pow(2, 63 - exponent)
646 return significand[0:63]
648 def ui128_CONVERT_FROM_BFP(x):
649 # x is an integer value represented in the
650 # binary floating-point working format.
654 if IsSNaN(x) then vxsnan_flag <- 1
655 return 0x0000_0000_0000_0000_0000_0000_0000_0000
659 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(x)
660 # TODO: does the spec say these are preserved?
663 exponent <- rnd.exponent
664 significand <- rnd.significand
665 ui128max <- bfp_CONVERT_FROM_UI128([1] * 128)
666 if bfp_COMPARE_GT(rnd, ui128max) then
668 return 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF
671 return 0x0000_0000_0000_0000_0000_0000_0000_0000
673 if ¬bfp_COMPARE_EQ(rnd, x) then xx_flag <- 1
674 else xx_flag <- 0 # TODO: does the spec specify this?
676 # TODO: spec says this is logical shift right:
677 significand <- significand[0:127] / pow(2, 127 - exponent)
678 return significand[0:127]
680 def bfp64_CONVERT_FROM_BFP(x):
681 # x is a floating-point value represented in the binary floating-point
685 if x.class.QNaN = 1 then
687 result[1:11] <- 0b111_1111_1111
688 result[12:63] <- x.significand[1:52]
689 else if x.class.Infinity = 1 then
691 result[1:11] <- 0b111_1111_1111
693 else if x.class.Zero = 1 then
696 else if (x.exponent < -1022) & (FPSCR.UE = 0) then
698 sh_cnt <- -1022 - x.exponent
699 result[1:11] <- 0b000_0000_0000
700 # TODO: spec says this is shift right
701 result[12:63] <- x.significand[1:52] / pow(2, sh_cnt)
702 else if (x.exponent < -1022) & (FPSCR.UE = 1) then
703 result[0:63] <- undefined(0) # TODO: which undefined value to use?
704 else if (x.exponent > 1023) & (FPSCR.OE = 1) then
705 result[0:63] <- undefined(0) # TODO: which undefined value to use?
708 result[1:11] <- x.exponent + 1023
709 result[12:63] <- x.significand[1:52]
712 def bfp32_CONVERT_FROM_BFP(x):
713 # x is a floating-point value represented in the binary floating-point
717 if x.class.QNaN = 1 then
719 result[1:8] <- 0b1111_1111
720 result[9:31] <- x.significand[1:23]
721 else if x.class.Infinity = 1 then
723 result[1:9] <- 0b1111_1111
725 else if x.class.Zero = 1 then
728 else if (x.exponent < -126) & (FPSCR.UE = 0) then
730 sh_cnt <- -126 - x.exponent
731 result[1:8] <- 0b0000_0000
732 # TODO: spec says this is shift right
733 result[9:31] <- x.significand[1:23] / pow(2, sh_cnt)
734 else if (x.exponent < -126) & (FPSCR.UE = 1) then
735 result[0:31] <- undefined(0) # TODO: which undefined value to use?
736 else if (x.exponent > 127) & (FPSCR.OE = 1) then
737 result[0:31] <- undefined(0) # TODO: which undefined value to use?
740 result[1:8] <- x.exponent + 127
741 result[9:31] <- x.significand[1:23]
744 def bfp_ROUND_TO_BFP64(ro, rmode, x):
745 # x is a normalized binary floating-point value that is represented in
746 # the binary floating-point working format and has unbounded exponent
747 # range and significand precision.
748 # ro is a 1-bit unsigned integer and rmode is a 2-bit unsigned integer,
749 # together specifying one of five rounding modes to be used in
752 # ro=0 rmode=0b00 Round to Nearest Even
753 # ro=0 rmode=0b01 Round towards Zero
754 # ro=0 rmode=0b10 Round towards +Infinity
755 # ro=0 rmode=0b11 Round towards -Infinity
758 # Return the value x rounded to double-precision under control of the
759 # specified rounding mode.
761 if x.class.QNaN then return x
762 if x.class.Infinity then return x
763 if x.class.Zero then return x
764 if bfp_COMPARE_LT(bfp_ABSOLUTE(x), bfp_NMIN_BFP64()) then
766 x <- bfp_DENORM(-1022, x)
767 if (ro=0) & (rmode=0b00) then r <- bfp_ROUND_NEAR_EVEN(53, x)
768 if (ro=0) & (rmode=0b01) then r <- bfp_ROUND_TRUNC(53, x)
769 if (ro=0) & (rmode=0b10) then r <- bfp_ROUND_CEIL(53, x)
770 if (ro=0) & (rmode=0b11) then r <- bfp_ROUND_FLOOR(53, x)
771 if ro=1 then r <- bfp_ROUND_ODD(53, x)
775 x.exponent <- x.exponent + 1536
777 if (ro=0) & (rmode=0b00) then r <- bfp_ROUND_NEAR_EVEN(53, x)
778 if (ro=0) & (rmode=0b01) then r <- bfp_ROUND_TRUNC(53, x)
779 if (ro=0) & (rmode=0b10) then r <- bfp_ROUND_CEIL(53, x)
780 if (ro=0) & (rmode=0b11) then r <- bfp_ROUND_FLOOR(53, x)
781 if ro=1 then r <- bfp_ROUND_ODD(53, x)
782 if bfp_COMPARE_GT(bfp_ABSOLUTE(r), bfp_NMAX_BFP64()) then
784 if (ro=0) & (rmode=0b00) then r <- x.sign ? bfp_INFINITY() : bfp_INFINITY()
785 if (ro=0) & (rmode=0b01) then r <- x.sign ? bfp_NMAX_BFP64() : bfp_NMAX_BFP64()
786 if (ro=0) & (rmode=0b10) then r <- x.sign ? bfp_NMAX_BFP64() : bfp_INFINITY()
787 if (ro=0) & (rmode=0b11) then r <- x.sign ? bfp_INFINITY() : bfp_NMAX_BFP64()
788 if ro=1 then r <- x.sign ? bfp_NMAX_BFP64() : bfp_NMAX_BFP64()
792 inc_flag <- undefined(0) # TODO: which undefined value to use?
795 r.exponent <- r.exponent - 1536
799 def bfp_ROUND_TO_BFP32(rmode,x):
800 # x is a normalized binary floating-point value that is represented in
801 # the binary floating-point working format and has unbounded exponent
802 # range and significand precision.
804 # rmode is a 2-bit integer value specifying one of four rounding modes.
806 # rmode=0b00 Round to Nearest Even
807 # rmode=0b01 Round towards Zero
808 # rmode=0b10 Round towards +Infinity
809 # rmode=0b11 Round towards - Infinity
811 # If x is a QNaN, Infinity, or Zero, return x. Otherwise, if x is an
812 # SNaN, set vxsnan_flag to 1 and return the corresponding QNaN
813 # representation of x. Otherwise, return the value x rounded to
814 # single-precision format’s exponent range and significand precision
815 # represented in the floating-point working format using the rounding
816 # mode specified by rmode.
822 if x.class.QNaN then return x
823 if x.class.Infinity then return x
824 if x.class.Zero then return x
826 if bfp_COMPARE_LT(bfp_ABSOLUTE(x), bfp_NMIN_BFP32()) then
827 x <- bfp_DENORM(-126,x)
828 if rmode = 0b00 then r <- bfp_ROUND_NEAR_EVEN(24, x)
829 if rmode = 0b01 then r <- bfp_ROUND_TRUNC(24, x)
830 if rmode = 0b10 then r <- bfp_ROUND_CEIL(24, x)
831 if rmode = 0b11 then r <- bfp_ROUND_FLOOR(24, x)
836 x.exponent <- x.exponent + 192
839 if rmode = 0b00 then r <- bfp_ROUND_NEAR_EVEN(24, x)
840 if rmode = 0b01 then r <- bfp_ROUND_TRUNC(24, x)
841 if rmode = 0b10 then r <- bfp_ROUND_CEIL(24, x)
842 if rmode = 0b11 then r <- bfp_ROUND_FLOOR(24, x)
844 if bfp_COMPARE_GT(bfp_ABSOLUTE(r), bfp_NMAX_BFP32()) then
846 if rmode=0b00 then r <- x.sign ? bfp_INFINITY() : bfp_INFINITY()
847 if rmode=0b01 then r <- x.sign ? bfp_NMAX_BFP32() : bfp_NMAX_BFP32()
848 if rmode=0b10 then r <- x.sign ? bfp_NMAX_BFP32() : bfp_INFINITY()
849 if rmode=0b11 then r <- x.sign ? bfp_INFINITY() : bfp_NMAX_BFP32()
853 inc_flag <- undefined(0) # TODO: which undefined value to use?
856 r.exponent <- r.exponent - 192
861 # The value +Infinity represented in the binary floating-point working
864 r.class.Infinity <- 1
867 def bfp_NMAX_BFP32():
868 # Return the largest finite single-precision floating-point value
869 # (i.e., 2^128 - 2^(128-24)) in the binary floating-point working
871 return bfp_CONVERT_FROM_BFP32(0x7F7F_FFFF)
873 def bfp_NMAX_BFP64():
874 # Return the largest finite double-precision floating-point value
875 # (i.e., 2^1024 - 2^(1024-53)) in the binary floating-point working
877 return bfp_CONVERT_FROM_BFP64(0x7FEF_FFFF_FFFF_FFFF)
879 def bfp_NMIN_BFP32():
880 # Return the smallest positive normalized single-precision
881 # floating-point value, 2^-126, represented in the binary
882 # floating-point working format.
883 return bfp_CONVERT_FROM_BFP32(0x0080_0000)
885 def bfp_NMIN_BFP64():
886 # Return the smallest positive normalized double-precision
887 # floating-point value, 2^-1022, represented in the binary
888 # floating-point working format.
889 return bfp_CONVERT_FROM_BFP64(0x0010_0000_0000_0000)
891 def bfp_ROUND_HELPER(p, ro, rmode, x):
892 # not part of the PowerISA v3.1B specification.
893 # helper function for the bfp_ROUND_* functions.
894 # doesn't set inc_flag or xx_flag.
896 # x is a binary floating-point value that is represented in the binary
897 # floating-point working format and has unbounded exponent range and
898 # significand precision. x must be rounded as presented, without
901 # p is an integer value specifying the precision (i.e., number of bits)
902 # the significand is rounded to.
904 # ro is a 1-bit unsigned integer and rmode is a 3-bit unsigned integer,
905 # together specifying one of six rounding modes to be used in
908 # ro=0 rmode=0b000 Round to Nearest Even
909 # ro=0 rmode=0b001 Round towards Zero
910 # ro=0 rmode=0b010 Round towards +Infinity
911 # ro=0 rmode=0b011 Round towards -Infinity
912 # ro=0 rmode=0b100 Round to Nearest Away
915 if IsInf(x) | IsNaN(x) | IsZero(x) then
916 inc_flag <- 0 # TODO: does the spec specify this?
917 xx_flag <- 0 # TODO: does the spec specify this?
921 result.significand <- 0
922 result.significand[0:p - 1] <- x.significand[0:p - 1]
923 exact <- x.significand = result.significand
925 more_than_half <- 0b0
926 if x.significand[p] then
929 t.significand[0:p] <- x.significand[0:p]
930 if t.significand = x.significand then halfway <- 0b1
931 else more_than_half <- 0b1
932 even <- ¬result.significand[p - 1]
934 if (ro=0) & (rmode=0b000) then # Round to Nearest Even
935 round_up <- (halfway & ¬even) | more_than_half
936 if (ro=0) & (rmode=0b001) then # Round towards Zero
938 if (ro=0) & (rmode=0b010) then # Round towards +Infinity
939 round_up <- (x.sign = 0) & ¬exact
940 if (ro=0) & (rmode=0b011) then # Round towards -Infinity
941 round_up <- (x.sign = 1) & ¬exact
942 if (ro=0) & (rmode=0b100) then # Round to Nearest Away
943 round_up <- halfway | more_than_half
944 if ro=1 then # Round to Odd
945 round_up <- ¬exact & even
948 result.significand[0:p-1] <- result.significand[0:p-1] + 1
949 if result.significand[0:p-1] = 0 then
950 result.significand[0] <- 1
951 result.exponent <- result.exponent + 1
953 if result.significand != 0 then
954 do while result.significand[0] != 1
955 result.significand <- result.significand * 2
956 result.exponent <- result.exponent - 1
957 result.class.Normal <- 1
958 result.class.Denormal <- 0
959 result.class.Zero <- 0
961 result.class.Normal <- 0
962 result.class.Denormal <- 0
963 result.class.Zero <- 1
967 def bfp_ROUND_NEAR_EVEN(p, x):
968 # x is a binary floating-point value that is represented in the binary
969 # floating-point working format and has unbounded exponent range and
970 # significand precision. x must be rounded as presented, without
973 # p is an integer value specifying the precision (i.e., number of bits)
974 # the significand is rounded to.
976 result <- bfp_ROUND_HELPER(p, 0b0, 0b000, x)
978 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
980 else inc_flag <- 0 # TODO: does the spec specify this?
981 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
982 else xx_flag <- 0 # TODO: does the spec specify this?
986 def bfp_ROUND_TRUNC(p, x):
987 # x is a binary floating-point value that is represented in the binary
988 # floating-point working format and has unbounded exponent range and
989 # significand precision. x must be rounded as presented, without
992 # p is an integer value specifying the precision (i.e., number of bits)
993 # the significand is rounded to.
995 result <- bfp_ROUND_HELPER(p, 0b0, 0b001, x)
997 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
999 else inc_flag <- 0 # TODO: does the spec specify this?
1000 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
1001 else xx_flag <- 0 # TODO: does the spec specify this?
1005 def bfp_ROUND_CEIL(p, x):
1006 # x is a binary floating-point value that is represented in the binary
1007 # floating-point working format and has unbounded exponent range and
1008 # significand precision. x must be rounded as presented, without
1011 # p is an integer value specifying the precision (i.e., number of bits)
1012 # the significand is rounded to.
1014 result <- bfp_ROUND_HELPER(p, 0b0, 0b010, x)
1016 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
1018 else inc_flag <- 0 # TODO: does the spec specify this?
1019 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
1020 else xx_flag <- 0 # TODO: does the spec specify this?
1024 def bfp_ROUND_FLOOR(p, x):
1025 # x is a binary floating-point value that is represented in the binary
1026 # floating-point working format and has unbounded exponent range and
1027 # significand precision. x must be rounded as presented, without
1030 # p is an integer value specifying the precision (i.e., number of bits)
1031 # the significand is rounded to.
1033 result <- bfp_ROUND_HELPER(p, 0b0, 0b011, x)
1035 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
1037 else inc_flag <- 0 # TODO: does the spec specify this?
1038 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
1039 else xx_flag <- 0 # TODO: does the spec specify this?
1043 def bfp_ROUND_NEAR_AWAY(p, x):
1044 # not part of the PowerISA v3.1B specification.
1046 # x is a binary floating-point value that is represented in the binary
1047 # floating-point working format and has unbounded exponent range and
1048 # significand precision. x must be rounded as presented, without
1051 # p is an integer value specifying the precision (i.e., number of bits)
1052 # the significand is rounded to.
1054 result <- bfp_ROUND_HELPER(p, 0b0, 0b100, x)
1056 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
1058 else inc_flag <- 0 # TODO: does the spec specify this?
1059 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
1060 else xx_flag <- 0 # TODO: does the spec specify this?
1064 def bfp_ROUND_ODD(p, x):
1065 # x is a binary floating-point value that is represented in the binary
1066 # floating-point working format and has unbounded exponent range and
1067 # significand precision. x must be rounded as presented, without
1070 # p is an integer value specifying the precision (i.e., number of bits)
1071 # the significand is rounded to.
1073 result <- bfp_ROUND_HELPER(p, 0b1, 0b000, x)
1075 if bfp_COMPARE_GT(bfp_ABSOLUTE(result), bfp_ABSOLUTE(x)) then
1077 else inc_flag <- 0 # TODO: does the spec specify this?
1078 if ¬bfp_COMPARE_EQ(result, x) then xx_flag <- 1
1079 else xx_flag <- 0 # TODO: does the spec specify this?
1083 def fprf_CLASS_BFP64(x):
1084 # x is a floating-point value represented in double-precision format.
1086 # Return the 5-bit code that specifies the sign and class of x.
1088 v <- bfp_CONVERT_FROM_BFP64(x)
1089 if v.class.QNaN then return 0b10001
1090 if (v.sign = 1) & v.class.Infinity then return 0b01001
1091 if (v.sign = 0) & v.class.Infinity then return 0b00101
1092 if (v.sign = 1) & v.class.Zero then return 0b10010
1093 if (v.sign = 0) & v.class.Zero then return 0b00010
1094 if (v.sign = 1) & v.class.Denormal then return 0b11000
1095 if (v.sign = 0) & v.class.Denormal then return 0b10100
1096 if (v.sign = 1) & v.class.Normal then return 0b01000
1097 if (v.sign = 0) & v.class.Normal then return 0b00100
1099 def fprf_CLASS_BFP32(x):
1100 # x is a floating-point value represented in single-precision format.
1102 # Return the 5-bit code that specifies the sign and class of x.
1104 v <- bfp_CONVERT_FROM_BFP32(x)
1105 if v.class.QNaN then return 0b10001
1106 if (v.sign = 1) & v.class.Infinity then return 0b01001
1107 if (v.sign = 0) & v.class.Infinity then return 0b00101
1108 if (v.sign = 1) & v.class.Zero then return 0b10010
1109 if (v.sign = 0) & v.class.Zero then return 0b00010
1110 if (v.sign = 1) & v.class.Denormal then return 0b11000
1111 if (v.sign = 0) & v.class.Denormal then return 0b10100
1112 if (v.sign = 1) & v.class.Normal then return 0b01000
1113 if (v.sign = 0) & v.class.Normal then return 0b00100