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
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 class ISACallerHelper
:
847 def __init__(self
, XLEN
, FPSCR
):
861 def EXTZXL(self
, value
, bits
=None):
864 elif isinstance(bits
, SelectableInt
):
866 if isinstance(value
, SelectableInt
):
868 return SelectableInt(value
& ((1 << bits
) - 1), self
.XLEN
)
870 def EXTSXL(self
, value
, bits
=None):
871 if isinstance(value
, SelectableInt
):
875 elif isinstance(bits
, SelectableInt
):
877 return SelectableInt(exts(value
, bits
), self
.XLEN
)
879 def DOUBLE2SINGLE(self
, FRS
):
880 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
881 implementation of the frsp instruction.
882 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
884 return self
.FRSP(FRS
)
886 def ROTL32(self
, value
, bits
):
887 if isinstance(bits
, SelectableInt
):
889 if isinstance(value
, SelectableInt
):
890 value
= SelectableInt(value
.value
, self
.XLEN
)
891 value
= value |
(value
<< (self
.XLEN
//2))
892 value
= rotl(value
, bits
, self
.XLEN
)
895 def ROTL128(self
, value
, bits
):
896 return rotl(value
, bits
, self
.XLEN
*2)
898 def ROTL64(self
, value
, bits
):
899 return rotl(value
, bits
, self
.XLEN
)
901 def MASK32(self
, x
, y
):
902 if isinstance(x
, SelectableInt
):
904 if isinstance(y
, SelectableInt
):
906 return self
.MASK(x
+(self
.XLEN
//2), y
+(self
.XLEN
//2))
908 def MASK(self
, x
, y
, lim
=None):
911 if isinstance(x
, SelectableInt
):
913 if isinstance(y
, SelectableInt
):
918 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
919 mask_b
= ((1 << y
) - 1) & ((1 << lim
) - 1)
921 return 1 << ((lim
-1)-x
)
925 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
926 mask_b
= (~
((1 << y
) - 1)) & ((1 << lim
) - 1)
927 return mask_a ^ mask_b
929 def __getattr__(self
, attr
):
930 """workaround for getting function out of the global namespace
931 within this module, as a way to get functions being transitioned
932 to Helper classes within ISACaller (and therefore pseudocode)
935 return globals()[attr
]
937 raise AttributeError(attr
)
940 # For these tests I tried to find power instructions that would let me
941 # isolate each of these helper operations. So for instance, when I was
942 # testing the MASK() function, I chose rlwinm and rldicl because if I
943 # set the shift equal to 0 and passed in a value of all ones, the
944 # result I got would be exactly the same as the output of MASK()
946 class HelperTests(unittest
.TestCase
, ISACallerHelper
):
947 def __init__(self
, *args
, **kwargs
):
948 # TODO: dynamic (64/32/16/8)
949 ISACallerHelper
.__init
__(self
, 64, FPSCR
=None)
950 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
953 # Verified using rlwinm, rldicl, rldicr in qemu
955 # rlwinm reg, 1, 0, 5, 15
956 self
.assertHex(self
.MASK(5+32, 15+32), 0x7ff0000)
957 # rlwinm reg, 1, 0, 15, 5
958 self
.assertHex(self
.MASK(15+32, 5+32), 0xfffffffffc01ffff)
959 self
.assertHex(self
.MASK(30+32, 2+32), 0xffffffffe0000003)
960 # rldicl reg, 1, 0, 37
961 self
.assertHex(self
.MASK(37, 63), 0x7ffffff)
962 self
.assertHex(self
.MASK(10, 63), 0x3fffffffffffff)
963 self
.assertHex(self
.MASK(58, 63), 0x3f)
964 # rldicr reg, 1, 0, 37
965 self
.assertHex(self
.MASK(0, 37), 0xfffffffffc000000)
966 self
.assertHex(self
.MASK(0, 10), 0xffe0000000000000)
967 self
.assertHex(self
.MASK(0, 58), 0xffffffffffffffe0)
971 self
.assertHex(self
.MASK(32, 63-5), 0xffffffe0)
973 self
.assertHex(self
.MASK(32, 33), 0xc0000000)
974 self
.assertHex(self
.MASK(32, 32), 0x80000000)
975 self
.assertHex(self
.MASK(33, 33), 0x40000000)
977 def test_ROTL64(self
):
978 # r1 = 0xdeadbeef12345678
979 value
= 0xdeadbeef12345678
981 # rldicl reg, 1, 10, 0
982 self
.assertHex(self
.ROTL64(value
, 10), 0xb6fbbc48d159e37a)
983 # rldicl reg, 1, 35, 0
984 self
.assertHex(self
.ROTL64(value
, 35), 0x91a2b3c6f56df778)
985 self
.assertHex(self
.ROTL64(value
, 58), 0xe37ab6fbbc48d159)
986 self
.assertHex(self
.ROTL64(value
, 22), 0xbbc48d159e37ab6f)
988 def test_ROTL32(self
):
990 value
= SelectableInt(0xdeadbeef, self
.XLEN
)
992 # rlwinm reg, 1, 10, 0, 31
993 self
.assertHex(self
.ROTL32(value
, 10), 0xb6fbbf7a)
994 # rlwinm reg, 1, 17, 0, 31
995 self
.assertHex(self
.ROTL32(value
, 17), 0x7ddfbd5b)
996 self
.assertHex(self
.ROTL32(value
, 25), 0xdfbd5b7d)
997 self
.assertHex(self
.ROTL32(value
, 30), 0xf7ab6fbb)
999 def test_EXTS64(self
):
1000 value_a
= SelectableInt(0xdeadbeef, 32) # r1
1001 value_b
= SelectableInt(0x73123456, 32) # r2
1002 value_c
= SelectableInt(0x80000000, 32) # r3
1004 # extswsli reg, 1, 0
1005 self
.assertHex(self
.EXTS64(value_a
), 0xffffffffdeadbeef)
1006 # extswsli reg, 2, 0
1007 self
.assertHex(self
.EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
1008 # extswsli reg, 3, 0
1009 self
.assertHex(self
.EXTS64(value_c
), 0xffffffff80000000)
1011 def test_FPADD32(self
):
1012 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
1013 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1014 result
= FPADD32(value_a
, value_b
)
1015 self
.assertHex(0x4040266666666666, result
)
1017 def assertHex(self
, a
, b
):
1019 if isinstance(a
, SelectableInt
):
1022 if isinstance(b
, SelectableInt
):
1024 msg
= "{:x} != {:x}".format(a_val
, b_val
)
1025 return self
.assertEqual(a
, b
, msg
)
1029 if __name__
== '__main__':
1030 log(SelectableInt
.__bases
__)