4 from openpower
.decoder
.selectable_int
import (SelectableInt
, onebit
,
5 selectconcat
, FieldSelectableInt
)
6 from openpower
.decoder
.selectable_int
import EFFECTIVELY_UNLIMITED
as EU
7 from nmutil
.divmod import trunc_divs
, trunc_rems
8 from operator
import floordiv
, mod
, truediv
# truediv used by bfp_* functions
9 from openpower
.decoder
.selectable_int
import selectltu
as ltu
10 from openpower
.decoder
.selectable_int
import selectgtu
as gtu
11 from openpower
.decoder
.selectable_int
import check_extsign
12 from openpower
.fpscr
import FPSCRState
13 from openpower
.decoder
.fp_working_format
import (
14 BFPState
, SelectableMSB0Fraction
)
16 from openpower
.util
import log
26 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
27 * https://bugs.libre-soc.org/show_bug.cgi?id=671#c38 - RANGE (and bugfixes)
31 def RANGE(start
, end
):
34 # auto-subtract-one (sigh) due to python range
35 return range(start
, end
-1, -1)
36 # auto-add-one (sigh) due to python range
37 return range(start
, end
+1)
40 def exts(value
, bits
):
41 sign
= 1 << (bits
- 1)
42 return (value
& (sign
- 1)) - (value
& sign
)
46 """ extends sign bit out from current MSB to MAX limit bits
48 log("EXTS", value
, type(value
))
49 assert isinstance(value
, SelectableInt
)
50 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << EU
)-1), EU
)
54 """ zero extend to EFFECTIVELY_UNLIMITED bits
56 if isinstance(value
, SelectableInt
):
58 return SelectableInt(value
& ((1 << EU
) - 1), EU
)
62 """ extends sign bit out from current MSB to 64 bits
64 assert isinstance(value
, SelectableInt
)
65 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
69 """ extends sign bit out from current MSB to 128 bits
71 assert isinstance(value
, SelectableInt
)
72 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
75 def copy_assign_rhs(inp
):
76 """ implicitly added function call to all assignment RHSes.
77 This copies the passed-in value so later assignments to parts of the
78 LHS don't modify the RHS if it's a SelectableInt.
82 # this needs to copy the SelectableInt instance in RA
83 # not just assign a reference to it to A
85 A[0] <- 1 # if the copy wasn't performed, we just modified RA too!
88 if isinstance(inp
, (str, int)):
90 if isinstance(inp
, (SelectableInt
, FieldSelectableInt
)):
91 return SelectableInt(inp
)
92 if isinstance(inp
, BFPState
):
94 if isinstance(inp
, SelectableMSB0Fraction
):
95 return SelectableMSB0Fraction(inp
)
96 if isinstance(inp
, tuple):
97 return tuple(map(copy_assign_rhs
, inp
))
98 if isinstance(inp
, dict):
99 return {copy_assign_rhs(k
): copy_assign_rhs(v
) for k
, v
in inp
.items()}
100 raise TypeError("tried to assign an unsupported type in pseudo-code",
104 # signed version of MUL
106 if isinstance(b
, int):
107 b
= SelectableInt(b
, self
.bits
)
108 b
= check_extsign(a
, b
)
109 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
110 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
111 result
= abs(a
) * abs(b
)
112 log("MULS", result
, a_s
, b_s
)
118 # XXX should this explicitly extend from 32 to 64?
120 if isinstance(value
, SelectableInt
):
122 return SelectableInt(value
& ((1 << 32)-1), 64)
125 def rotl(value
, bits
, wordlen
):
126 if isinstance(bits
, SelectableInt
):
128 mask
= (1 << wordlen
) - 1
129 bits
= bits
& (wordlen
- 1)
130 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
133 def SHL64(value
, bits
, wordlen
=64):
134 if isinstance(bits
, SelectableInt
):
136 mask
= (1 << wordlen
) - 1
137 bits
= bits
& (wordlen
- 1)
138 return SelectableInt((value
<< bits
) & mask
, 64)
142 return onebit(a
!= b
)
146 return onebit(a
== b
)
154 return onebit(a
>= b
)
162 return onebit(a
<= b
)
170 """ function that, for Power spec purposes, returns undefined bits of
171 the same shape as the input bits. however, for purposes of matching
172 POWER9's behavior returns the input bits unchanged. this effectively
173 "marks" (tags) locations in the v3.0B spec that need to be submitted
180 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
182 # result - WORD - start off all zeros
183 WORD
= SelectableInt(0, 32)
190 log("s e m", s
.value
, e
.value
, m
.value
)
192 # No Denormalization Required (includes Zero / Infinity / NaN)
193 if e
.value
> 896 or FRS
[1:64].value
== 0:
194 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
196 WORD
[2:32] = FRS
[5:35]
198 # Denormalization Required
199 if e
.value
>= 874 and e
.value
<= 896:
202 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
203 log("exp, fract", exp
, hex(frac
.value
))
204 # denormalize operand
206 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
209 WORD
[1:9] = SelectableInt(0, 8)
210 WORD
[9:32] = frac
[1:24]
211 # else WORD = undefined # return zeros
217 # XXX NOTE: these are very quick hacked functions for utterly basic
221 def signinv(res
, sign
):
230 def fp32toselectable(flt
):
231 """convert FP number to 32 bit SelectableInt
233 b
= struct
.pack("<f", flt
)
234 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
235 return SelectableInt(val
, 32)
238 def fp64toselectable(flt
):
239 """convert FP number to 64 bit SelectableInt
241 b
= struct
.pack("<d", flt
)
242 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
243 return SelectableInt(val
, 64)
263 # bfp32/64_OP naming mirrors that in the Power ISA spec.
265 def bfp64_ATAN2PI(self
, a
, b
):
266 # FIXME: use proper implementation
267 return fp64toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
269 def bfp32_ATAN2PI(self
, a
, b
):
270 # FIXME: use proper implementation
271 return fp32toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
273 def bfp64_ATAN2(self
, a
, b
):
274 # FIXME: use proper implementation
275 return fp64toselectable(math
.atan2(float(a
), float(b
)))
277 def bfp32_ATAN2(self
, a
, b
):
278 # FIXME: use proper implementation
279 return fp32toselectable(math
.atan2(float(a
), float(b
)))
281 def bfp64_HYPOT(self
, a
, b
):
282 # FIXME: use proper implementation
283 return fp64toselectable(math
.hypot(float(a
), float(b
)))
285 def bfp32_HYPOT(self
, a
, b
):
286 # FIXME: use proper implementation
287 return fp32toselectable(math
.hypot(float(a
), float(b
)))
289 def bfp64_MINNUM08(self
, a
, b
):
290 # FIXME: use proper implementation
291 return fp64toselectable(min(float(a
), float(b
)))
293 def bfp32_MINNUM08(self
, a
, b
):
294 # FIXME: use proper implementation
295 return fp32toselectable(min(float(a
), float(b
)))
297 def bfp64_MIN19(self
, a
, b
):
298 # FIXME: use proper implementation
299 return fp64toselectable(min(float(a
), float(b
)))
301 def bfp32_MIN19(self
, a
, b
):
302 # FIXME: use proper implementation
303 return fp32toselectable(min(float(a
), float(b
)))
305 def bfp64_MINNUM19(self
, a
, b
):
306 # FIXME: use proper implementation
307 return fp64toselectable(min(float(a
), float(b
)))
309 def bfp32_MINNUM19(self
, a
, b
):
310 # FIXME: use proper implementation
311 return fp32toselectable(min(float(a
), float(b
)))
313 def bfp64_MINC(self
, a
, b
):
314 # FIXME: use proper implementation
315 return fp64toselectable(min(float(a
), float(b
)))
317 def bfp32_MINC(self
, a
, b
):
318 # FIXME: use proper implementation
319 return fp32toselectable(min(float(a
), float(b
)))
321 def bfp64_MAXNUM08(self
, a
, b
):
322 # FIXME: use proper implementation
323 return fp64toselectable(max(float(a
), float(b
)))
325 def bfp32_MAXNUM08(self
, a
, b
):
326 # FIXME: use proper implementation
327 return fp32toselectable(max(float(a
), float(b
)))
329 def bfp64_MAX19(self
, a
, b
):
330 # FIXME: use proper implementation
331 return fp64toselectable(max(float(a
), float(b
)))
333 def bfp32_MAX19(self
, a
, b
):
334 # FIXME: use proper implementation
335 return fp32toselectable(max(float(a
), float(b
)))
337 def bfp64_MAXNUM19(self
, a
, b
):
338 # FIXME: use proper implementation
339 return fp64toselectable(max(float(a
), float(b
)))
341 def bfp32_MAXNUM19(self
, a
, b
):
342 # FIXME: use proper implementation
343 return fp32toselectable(max(float(a
), float(b
)))
345 def bfp64_MAXC(self
, a
, b
):
346 # FIXME: use proper implementation
347 return fp64toselectable(max(float(a
), float(b
)))
349 def bfp32_MAXC(self
, a
, b
):
350 # FIXME: use proper implementation
351 return fp32toselectable(max(float(a
), float(b
)))
353 def bfp64_MINMAGNUM08(self
, a
, b
):
354 # FIXME: use proper implementation
355 return fp64toselectable(_minmag(float(a
), float(b
)))
357 def bfp32_MINMAGNUM08(self
, a
, b
):
358 # FIXME: use proper implementation
359 return fp32toselectable(_minmag(float(a
), float(b
)))
361 def bfp64_MAXMAGNUM08(self
, a
, b
):
362 # FIXME: use proper implementation
363 return fp64toselectable(_maxmag(float(a
), float(b
)))
365 def bfp32_MAXMAGNUM08(self
, a
, b
):
366 # FIXME: use proper implementation
367 return fp32toselectable(_maxmag(float(a
), float(b
)))
369 def bfp64_MOD(self
, a
, b
):
370 # FIXME: use proper implementation
371 return fp64toselectable(math
.fmod(float(a
), float(b
)))
373 def bfp32_MOD(self
, a
, b
):
374 # FIXME: use proper implementation
375 return fp32toselectable(math
.fmod(float(a
), float(b
)))
377 def bfp64_MINMAG19(self
, a
, b
):
378 # FIXME: use proper implementation
379 return fp64toselectable(_minmag(float(a
), float(b
)))
381 def bfp32_MINMAG19(self
, a
, b
):
382 # FIXME: use proper implementation
383 return fp32toselectable(_minmag(float(a
), float(b
)))
385 def bfp64_MAXMAG19(self
, a
, b
):
386 # FIXME: use proper implementation
387 return fp64toselectable(_maxmag(float(a
), float(b
)))
389 def bfp32_MAXMAG19(self
, a
, b
):
390 # FIXME: use proper implementation
391 return fp32toselectable(_maxmag(float(a
), float(b
)))
393 def bfp64_MINMAGNUM19(self
, a
, b
):
394 # FIXME: use proper implementation
395 return fp64toselectable(_minmag(float(a
), float(b
)))
397 def bfp32_MINMAGNUM19(self
, a
, b
):
398 # FIXME: use proper implementation
399 return fp32toselectable(_minmag(float(a
), float(b
)))
401 def bfp64_MAXMAGNUM19(self
, a
, b
):
402 # FIXME: use proper implementation
403 return fp64toselectable(_maxmag(float(a
), float(b
)))
405 def bfp32_MAXMAGNUM19(self
, a
, b
):
406 # FIXME: use proper implementation
407 return fp32toselectable(_maxmag(float(a
), float(b
)))
409 def bfp64_REMAINDER(self
, a
, b
):
410 # FIXME: use proper implementation
411 return fp64toselectable(math
.remainder(float(a
), float(b
)))
413 def bfp32_REMAINDER(self
, a
, b
):
414 # FIXME: use proper implementation
415 return fp32toselectable(math
.remainder(float(a
), float(b
)))
417 def bfp64_POWR(self
, a
, b
):
418 # FIXME: use proper implementation
419 return fp64toselectable(pow(float(a
), float(b
)))
421 def bfp32_POWR(self
, a
, b
):
422 # FIXME: use proper implementation
423 return fp32toselectable(pow(float(a
), float(b
)))
425 def bfp64_POW(self
, a
, b
):
426 # FIXME: use proper implementation
427 return fp64toselectable(pow(float(a
), float(b
)))
429 def bfp32_POW(self
, a
, b
):
430 # FIXME: use proper implementation
431 return fp32toselectable(pow(float(a
), float(b
)))
433 def bfp64_MINMAGC(self
, a
, b
):
434 # FIXME: use proper implementation
435 return fp64toselectable(_minmag(float(a
), float(b
)))
437 def bfp32_MINMAGC(self
, a
, b
):
438 # FIXME: use proper implementation
439 return fp32toselectable(_minmag(float(a
), float(b
)))
441 def bfp64_MAXMAGC(self
, a
, b
):
442 # FIXME: use proper implementation
443 return fp64toselectable(_maxmag(float(a
), float(b
)))
445 def bfp32_MAXMAGC(self
, a
, b
):
446 # FIXME: use proper implementation
447 return fp32toselectable(_maxmag(float(a
), float(b
)))
449 def bfp64_POWN(self
, a
, b
):
450 # FIXME: use proper implementation
451 return fp64toselectable(pow(float(a
), int(b
)))
453 def bfp32_POWN(self
, a
, b
):
454 # FIXME: use proper implementation
455 return fp32toselectable(pow(float(a
), int(b
)))
457 def bfp64_ROOTN(self
, a
, b
):
458 # FIXME: use proper implementation
459 return fp64toselectable(pow(float(a
), 1 / int(b
)))
461 def bfp32_ROOTN(self
, a
, b
):
462 # FIXME: use proper implementation
463 return fp32toselectable(pow(float(a
), 1 / int(b
)))
465 def bfp64_CBRT(self
, v
):
466 # FIXME: use proper implementation
467 return fp64toselectable(pow(float(v
), 1 / 3))
469 def bfp32_CBRT(self
, v
):
470 # FIXME: use proper implementation
471 return fp32toselectable(pow(float(v
), 1 / 3))
473 def bfp64_SINPI(self
, v
):
474 # FIXME: use proper implementation
475 return fp64toselectable(math
.sin(float(v
) * math
.pi
))
477 def bfp32_SINPI(self
, v
):
478 # FIXME: use proper implementation
479 return fp32toselectable(math
.sin(float(v
) * math
.pi
))
481 def bfp64_ASINPI(self
, v
):
482 # FIXME: use proper implementation
483 return fp64toselectable(math
.asin(float(v
)) / math
.pi
)
485 def bfp32_ASINPI(self
, v
):
486 # FIXME: use proper implementation
487 return fp32toselectable(math
.asin(float(v
)) / math
.pi
)
489 def bfp64_COSPI(self
, v
):
490 # FIXME: use proper implementation
491 return fp64toselectable(math
.cos(float(v
) * math
.pi
))
493 def bfp32_COSPI(self
, v
):
494 # FIXME: use proper implementation
495 return fp32toselectable(math
.cos(float(v
) * math
.pi
))
497 def bfp64_TANPI(self
, v
):
498 # FIXME: use proper implementation
499 return fp64toselectable(math
.tan(float(v
) * math
.pi
))
501 def bfp32_TANPI(self
, v
):
502 # FIXME: use proper implementation
503 return fp32toselectable(math
.tan(float(v
) * math
.pi
))
505 def bfp64_ACOSPI(self
, v
):
506 # FIXME: use proper implementation
507 return fp64toselectable(math
.acos(float(v
)) / math
.pi
)
509 def bfp32_ACOSPI(self
, v
):
510 # FIXME: use proper implementation
511 return fp32toselectable(math
.acos(float(v
)) / math
.pi
)
513 def bfp64_ATANPI(self
, v
):
514 # FIXME: use proper implementation
515 return fp64toselectable(math
.atan(float(v
)) / math
.pi
)
517 def bfp32_ATANPI(self
, v
):
518 # FIXME: use proper implementation
519 return fp32toselectable(math
.atan(float(v
)) / math
.pi
)
521 def bfp64_RSQRT(self
, v
):
522 # FIXME: use proper implementation
523 return fp64toselectable(1 / math
.sqrt(float(v
)))
525 def bfp32_RSQRT(self
, v
):
526 # FIXME: use proper implementation
527 return fp32toselectable(1 / math
.sqrt(float(v
)))
529 def bfp64_SIN(self
, v
):
530 # FIXME: use proper implementation
531 return fp64toselectable(math
.sin(float(v
)))
533 def bfp32_SIN(self
, v
):
534 # FIXME: use proper implementation
535 return fp32toselectable(math
.sin(float(v
)))
537 def bfp64_ASIN(self
, v
):
538 # FIXME: use proper implementation
539 return fp64toselectable(math
.asin(float(v
)))
541 def bfp32_ASIN(self
, v
):
542 # FIXME: use proper implementation
543 return fp32toselectable(math
.asin(float(v
)))
545 def bfp64_COS(self
, v
):
546 # FIXME: use proper implementation
547 return fp64toselectable(math
.cos(float(v
)))
549 def bfp32_COS(self
, v
):
550 # FIXME: use proper implementation
551 return fp32toselectable(math
.cos(float(v
)))
553 def bfp64_TAN(self
, v
):
554 # FIXME: use proper implementation
555 return fp64toselectable(math
.tan(float(v
)))
557 def bfp32_TAN(self
, v
):
558 # FIXME: use proper implementation
559 return fp32toselectable(math
.tan(float(v
)))
561 def bfp64_ACOS(self
, v
):
562 # FIXME: use proper implementation
563 return fp64toselectable(math
.acos(float(v
)))
565 def bfp32_ACOS(self
, v
):
566 # FIXME: use proper implementation
567 return fp32toselectable(math
.acos(float(v
)))
569 def bfp64_ATAN(self
, v
):
570 # FIXME: use proper implementation
571 return fp64toselectable(math
.atan(float(v
)))
573 def bfp32_ATAN(self
, v
):
574 # FIXME: use proper implementation
575 return fp32toselectable(math
.atan(float(v
)))
577 def bfp64_RECIP(self
, v
):
578 # FIXME: use proper implementation
579 return fp64toselectable(1 / float(v
))
581 def bfp32_RECIP(self
, v
):
582 # FIXME: use proper implementation
583 return fp32toselectable(1 / float(v
))
585 def bfp64_SINH(self
, v
):
586 # FIXME: use proper implementation
587 return fp64toselectable(math
.sinh(float(v
)))
589 def bfp32_SINH(self
, v
):
590 # FIXME: use proper implementation
591 return fp32toselectable(math
.sinh(float(v
)))
593 def bfp64_ASINH(self
, v
):
594 # FIXME: use proper implementation
595 return fp64toselectable(math
.asinh(float(v
)))
597 def bfp32_ASINH(self
, v
):
598 # FIXME: use proper implementation
599 return fp32toselectable(math
.asinh(float(v
)))
601 def bfp64_COSH(self
, v
):
602 # FIXME: use proper implementation
603 return fp64toselectable(math
.cosh(float(v
)))
605 def bfp32_COSH(self
, v
):
606 # FIXME: use proper implementation
607 return fp32toselectable(math
.cosh(float(v
)))
609 def bfp64_TANH(self
, v
):
610 # FIXME: use proper implementation
611 return fp64toselectable(math
.tanh(float(v
)))
613 def bfp32_TANH(self
, v
):
614 # FIXME: use proper implementation
615 return fp32toselectable(math
.tanh(float(v
)))
617 def bfp64_ACOSH(self
, v
):
618 # FIXME: use proper implementation
619 return fp64toselectable(math
.acosh(float(v
)))
621 def bfp32_ACOSH(self
, v
):
622 # FIXME: use proper implementation
623 return fp32toselectable(math
.acosh(float(v
)))
625 def bfp64_ATANH(self
, v
):
626 # FIXME: use proper implementation
627 return fp64toselectable(math
.atanh(float(v
)))
629 def bfp32_ATANH(self
, v
):
630 # FIXME: use proper implementation
631 return fp32toselectable(math
.atanh(float(v
)))
633 def bfp64_EXP2M1(self
, v
):
634 # FIXME: use proper implementation
635 return fp64toselectable(pow(2, float(v
)) - 1)
637 def bfp32_EXP2M1(self
, v
):
638 # FIXME: use proper implementation
639 return fp32toselectable(pow(2, float(v
)) - 1)
641 def bfp64_LOG2P1(self
, v
):
642 # FIXME: use proper implementation
643 return fp64toselectable(math
.log2(float(v
) + 1))
645 def bfp32_LOG2P1(self
, v
):
646 # FIXME: use proper implementation
647 return fp32toselectable(math
.log2(float(v
) + 1))
649 def bfp64_EXPM1(self
, v
):
650 # FIXME: use proper implementation
651 return fp64toselectable(math
.expm1(float(v
)))
653 def bfp32_EXPM1(self
, v
):
654 # FIXME: use proper implementation
655 return fp32toselectable(math
.expm1(float(v
)))
657 def bfp64_LOGP1(self
, v
):
658 # FIXME: use proper implementation
659 return fp64toselectable(math
.log1p(float(v
)))
661 def bfp32_LOGP1(self
, v
):
662 # FIXME: use proper implementation
663 return fp32toselectable(math
.log1p(float(v
)))
665 def bfp64_EXP10M1(self
, v
):
666 # FIXME: use proper implementation
667 return fp64toselectable(pow(10, float(v
)) - 1)
669 def bfp32_EXP10M1(self
, v
):
670 # FIXME: use proper implementation
671 return fp32toselectable(pow(10, float(v
)) - 1)
673 def bfp64_LOG10P1(self
, v
):
674 # FIXME: use proper implementation
675 return fp64toselectable(math
.log10(float(v
) + 1))
677 def bfp32_LOG10P1(self
, v
):
678 # FIXME: use proper implementation
679 return fp32toselectable(math
.log10(float(v
) + 1))
681 def bfp64_EXP2(self
, v
):
682 # FIXME: use proper implementation
683 return fp64toselectable(pow(2, float(v
)))
685 def bfp32_EXP2(self
, v
):
686 # FIXME: use proper implementation
687 return fp32toselectable(pow(2, float(v
)))
689 def bfp64_LOG2(self
, v
):
690 # FIXME: use proper implementation
691 return fp64toselectable(math
.log2(float(v
)))
693 def bfp32_LOG2(self
, v
):
694 # FIXME: use proper implementation
695 return fp32toselectable(math
.log2(float(v
)))
697 def bfp64_EXP(self
, v
):
698 # FIXME: use proper implementation
699 return fp64toselectable(math
.exp(float(v
)))
701 def bfp32_EXP(self
, v
):
702 # FIXME: use proper implementation
703 return fp32toselectable(math
.exp(float(v
)))
705 def bfp64_LOG(self
, v
):
706 # FIXME: use proper implementation
707 return fp64toselectable(math
.log(float(v
)))
709 def bfp32_LOG(self
, v
):
710 # FIXME: use proper implementation
711 return fp32toselectable(math
.log(float(v
)))
713 def bfp64_EXP10(self
, v
):
714 # FIXME: use proper implementation
715 return fp64toselectable(pow(10, float(v
)))
717 def bfp32_EXP10(self
, v
):
718 # FIXME: use proper implementation
719 return fp32toselectable(pow(10, float(v
)))
721 def bfp64_LOG10(self
, v
):
722 # FIXME: use proper implementation
723 return fp64toselectable(math
.log10(float(v
)))
725 def bfp32_LOG10(self
, v
):
726 # FIXME: use proper implementation
727 return fp32toselectable(math
.log10(float(v
)))
729 def FPADD32(self
, FRA
, FRB
):
730 # return FPADD64(FRA, FRB)
731 #FRA = DOUBLE(SINGLE(FRA))
732 #FRB = DOUBLE(SINGLE(FRB))
733 result
= float(FRA
) + float(FRB
)
734 cvt
= fp64toselectable(result
)
735 cvt
= self
.DOUBLE2SINGLE(cvt
)
736 log("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
739 def FPSUB32(self
, FRA
, FRB
):
740 # return FPSUB64(FRA, FRB)
741 #FRA = DOUBLE(SINGLE(FRA))
742 #FRB = DOUBLE(SINGLE(FRB))
743 result
= float(FRA
) - float(FRB
)
744 cvt
= fp64toselectable(result
)
745 cvt
= self
.DOUBLE2SINGLE(cvt
)
746 log("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
749 def FPMUL32(self
, FRA
, FRB
, sign
=1):
750 # return FPMUL64(FRA, FRB)
751 FRA
= self
.DOUBLE(SINGLE(FRA
))
752 FRB
= self
.DOUBLE(SINGLE(FRB
))
753 result
= signinv(float(FRA
) * float(FRB
), sign
)
754 log("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
755 cvt
= fp64toselectable(result
)
756 cvt
= self
.DOUBLE2SINGLE(cvt
)
760 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
761 # return FPMUL64(FRA, FRB)
762 #FRA = DOUBLE(SINGLE(FRA))
763 #FRB = DOUBLE(SINGLE(FRB))
766 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
768 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
771 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
773 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
776 log("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
777 log(" FRA", float(FRA
))
778 log(" FRC", float(FRC
))
779 log(" FRB", float(FRB
))
780 log(" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
781 cvt
= fp64toselectable(result
)
782 cvt
= self
.DOUBLE2SINGLE(cvt
)
786 def FPDIV32(self
, FRA
, FRB
, sign
=1):
787 # return FPDIV64(FRA, FRB)
788 #FRA = DOUBLE(SINGLE(FRA))
789 #FRB = DOUBLE(SINGLE(FRB))
790 result
= signinv(float(FRA
) / float(FRB
), sign
)
791 cvt
= fp64toselectable(result
)
792 cvt
= self
.DOUBLE2SINGLE(cvt
)
793 log("FPDIV32", FRA
, FRB
, result
, cvt
)
797 def FPADD64(FRA
, FRB
):
798 result
= float(FRA
) + float(FRB
)
799 cvt
= fp64toselectable(result
)
800 log("FPADD64", FRA
, FRB
, result
, cvt
)
804 def FPSUB64(FRA
, FRB
):
805 result
= float(FRA
) - float(FRB
)
806 cvt
= fp64toselectable(result
)
807 log("FPSUB64", FRA
, FRB
, result
, cvt
)
811 def FPMUL64(FRA
, FRB
, sign
=1):
812 result
= signinv(float(FRA
) * float(FRB
), sign
)
813 cvt
= fp64toselectable(result
)
814 log("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
818 def FPDIV64(FRA
, FRB
, sign
=1):
819 result
= signinv(float(FRA
) / float(FRB
), sign
)
820 cvt
= fp64toselectable(result
)
821 log("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
826 """Returns the integer whose value is the reverse of the lowest
827 'width' bits of the integer 'val'
830 width
= VL
.bit_length()-1
831 for _
in range(width
):
832 result
= (result
<< 1) |
(val
& 1)
838 """return the base-2 logarithm of `val`. Only works for powers of 2."""
839 if isinstance(val
, SelectableInt
):
841 retval
= val
.bit_length() - 1
842 assert val
== 2 ** retval
, "value is not a power of 2"
846 # BFP classification predicates
847 # these need to be implemented in python because they work with multiple
850 if isinstance(v
, BFPState
):
851 return onebit(v
.class_
.Infinity
)
852 # TODO: implement for SelectableInt/int
853 raise NotImplementedError("not yet implemented for non-BFPState values")
857 if isinstance(v
, BFPState
):
858 return onebit(v
.class_
.SNaN
or v
.class_
.QNaN
)
859 # TODO: implement for SelectableInt/int
860 raise NotImplementedError("not yet implemented for non-BFPState values")
864 if isinstance(v
, BFPState
):
865 if v
.class_
.SNaN
or v
.class_
.QNaN
or v
.class_
.Zero
:
867 return onebit(v
.sign
)
868 # TODO: implement for SelectableInt/int
869 raise NotImplementedError("not yet implemented for non-BFPState values")
873 if isinstance(v
, BFPState
):
874 return onebit(v
.class_
.SNaN
)
875 # TODO: implement for SelectableInt/int
876 raise NotImplementedError("not yet implemented for non-BFPState values")
880 if isinstance(v
, BFPState
):
881 return onebit(v
.class_
.Zero
)
882 # TODO: implement for SelectableInt/int
883 raise NotImplementedError("not yet implemented for non-BFPState values")
886 def SetFX(fpscr
, field
):
887 assert isinstance(fpscr
, FPSCRState
), "SetFX only works on FPSCR fields"
888 if eq(getattr(fpscr
, field
), SelectableInt(0, 1)):
889 setattr(fpscr
, field
, SelectableInt(1, 1))
890 fpscr
.FX
= SelectableInt(1, 1)
893 class ISACallerHelper
:
894 def __init__(self
, XLEN
, FPSCR
):
908 def EXTZXL(self
, value
, bits
=None):
911 elif isinstance(bits
, SelectableInt
):
913 if isinstance(value
, SelectableInt
):
915 return SelectableInt(value
& ((1 << bits
) - 1), self
.XLEN
)
917 def EXTSXL(self
, value
, bits
=None):
918 if isinstance(value
, SelectableInt
):
922 elif isinstance(bits
, SelectableInt
):
924 return SelectableInt(exts(value
, bits
), self
.XLEN
)
926 def DOUBLE2SINGLE(self
, FRS
):
927 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
928 implementation of the frsp instruction.
929 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
931 return self
.FRSP(FRS
)
933 def ROTL32(self
, value
, bits
):
934 if isinstance(bits
, SelectableInt
):
936 if isinstance(value
, SelectableInt
):
937 value
= SelectableInt(value
.value
, self
.XLEN
)
938 value
= value |
(value
<< (self
.XLEN
//2))
939 value
= rotl(value
, bits
, self
.XLEN
)
942 def ROTL128(self
, value
, bits
):
943 return rotl(value
, bits
, self
.XLEN
*2)
945 def ROTL64(self
, value
, bits
):
946 return rotl(value
, bits
, self
.XLEN
)
948 def MASK32(self
, x
, y
):
949 if isinstance(x
, SelectableInt
):
951 if isinstance(y
, SelectableInt
):
953 return self
.MASK(x
+(self
.XLEN
//2), y
+(self
.XLEN
//2))
955 def MASK(self
, x
, y
, lim
=None):
958 if isinstance(x
, SelectableInt
):
960 if isinstance(y
, SelectableInt
):
965 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
966 mask_b
= ((1 << y
) - 1) & ((1 << lim
) - 1)
968 return 1 << ((lim
-1)-x
)
972 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
973 mask_b
= (~
((1 << y
) - 1)) & ((1 << lim
) - 1)
974 return mask_a ^ mask_b
976 def __getattr__(self
, attr
):
977 """workaround for getting function out of the global namespace
978 within this module, as a way to get functions being transitioned
979 to Helper classes within ISACaller (and therefore pseudocode)
982 return globals()[attr
]
984 raise AttributeError(attr
)
987 # For these tests I tried to find power instructions that would let me
988 # isolate each of these helper operations. So for instance, when I was
989 # testing the MASK() function, I chose rlwinm and rldicl because if I
990 # set the shift equal to 0 and passed in a value of all ones, the
991 # result I got would be exactly the same as the output of MASK()
993 class HelperTests(unittest
.TestCase
, ISACallerHelper
):
994 def __init__(self
, *args
, **kwargs
):
995 # TODO: dynamic (64/32/16/8)
996 ISACallerHelper
.__init
__(self
, 64, FPSCR
=None)
997 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
1000 # Verified using rlwinm, rldicl, rldicr in qemu
1002 # rlwinm reg, 1, 0, 5, 15
1003 self
.assertHex(self
.MASK(5+32, 15+32), 0x7ff0000)
1004 # rlwinm reg, 1, 0, 15, 5
1005 self
.assertHex(self
.MASK(15+32, 5+32), 0xfffffffffc01ffff)
1006 self
.assertHex(self
.MASK(30+32, 2+32), 0xffffffffe0000003)
1007 # rldicl reg, 1, 0, 37
1008 self
.assertHex(self
.MASK(37, 63), 0x7ffffff)
1009 self
.assertHex(self
.MASK(10, 63), 0x3fffffffffffff)
1010 self
.assertHex(self
.MASK(58, 63), 0x3f)
1011 # rldicr reg, 1, 0, 37
1012 self
.assertHex(self
.MASK(0, 37), 0xfffffffffc000000)
1013 self
.assertHex(self
.MASK(0, 10), 0xffe0000000000000)
1014 self
.assertHex(self
.MASK(0, 58), 0xffffffffffffffe0)
1018 self
.assertHex(self
.MASK(32, 63-5), 0xffffffe0)
1020 self
.assertHex(self
.MASK(32, 33), 0xc0000000)
1021 self
.assertHex(self
.MASK(32, 32), 0x80000000)
1022 self
.assertHex(self
.MASK(33, 33), 0x40000000)
1024 def test_ROTL64(self
):
1025 # r1 = 0xdeadbeef12345678
1026 value
= 0xdeadbeef12345678
1028 # rldicl reg, 1, 10, 0
1029 self
.assertHex(self
.ROTL64(value
, 10), 0xb6fbbc48d159e37a)
1030 # rldicl reg, 1, 35, 0
1031 self
.assertHex(self
.ROTL64(value
, 35), 0x91a2b3c6f56df778)
1032 self
.assertHex(self
.ROTL64(value
, 58), 0xe37ab6fbbc48d159)
1033 self
.assertHex(self
.ROTL64(value
, 22), 0xbbc48d159e37ab6f)
1035 def test_ROTL32(self
):
1037 value
= SelectableInt(0xdeadbeef, self
.XLEN
)
1039 # rlwinm reg, 1, 10, 0, 31
1040 self
.assertHex(self
.ROTL32(value
, 10), 0xb6fbbf7a)
1041 # rlwinm reg, 1, 17, 0, 31
1042 self
.assertHex(self
.ROTL32(value
, 17), 0x7ddfbd5b)
1043 self
.assertHex(self
.ROTL32(value
, 25), 0xdfbd5b7d)
1044 self
.assertHex(self
.ROTL32(value
, 30), 0xf7ab6fbb)
1046 def test_EXTS64(self
):
1047 value_a
= SelectableInt(0xdeadbeef, 32) # r1
1048 value_b
= SelectableInt(0x73123456, 32) # r2
1049 value_c
= SelectableInt(0x80000000, 32) # r3
1051 # extswsli reg, 1, 0
1052 self
.assertHex(self
.EXTS64(value_a
), 0xffffffffdeadbeef)
1053 # extswsli reg, 2, 0
1054 self
.assertHex(self
.EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
1055 # extswsli reg, 3, 0
1056 self
.assertHex(self
.EXTS64(value_c
), 0xffffffff80000000)
1058 def test_FPADD32(self
):
1059 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
1060 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1061 result
= FPADD32(value_a
, value_b
)
1062 self
.assertHex(0x4040266666666666, result
)
1064 def assertHex(self
, a
, b
):
1066 if isinstance(a
, SelectableInt
):
1069 if isinstance(b
, SelectableInt
):
1071 msg
= "{:x} != {:x}".format(a_val
, b_val
)
1072 return self
.assertEqual(a
, b
, msg
)
1076 if __name__
== '__main__':
1077 log(SelectableInt
.__bases
__)