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
.xer
import XERState
14 from openpower
.decoder
.isa
.svshape
import SVSHAPE
15 from openpower
.decoder
.isa
.svstate
import SVP64State
16 from openpower
.decoder
.fp_working_format
import (
17 BFPState
, SelectableMSB0Fraction
)
19 from openpower
.util
import log
29 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
30 * https://bugs.libre-soc.org/show_bug.cgi?id=671#c38 - RANGE (and bugfixes)
34 def RANGE(start
, end
):
37 # auto-subtract-one (sigh) due to python range
38 return range(start
, end
-1, -1)
39 # auto-add-one (sigh) due to python range
40 return range(start
, end
+1)
43 def exts(value
, bits
):
44 sign
= 1 << (bits
- 1)
45 return (value
& (sign
- 1)) - (value
& sign
)
49 """ extends sign bit out from current MSB to MAX limit bits
51 log("EXTS", value
, type(value
))
52 assert isinstance(value
, SelectableInt
)
53 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << EU
)-1), EU
)
57 """ zero extend to EFFECTIVELY_UNLIMITED bits
59 if isinstance(value
, SelectableInt
):
61 return SelectableInt(value
& ((1 << EU
) - 1), EU
)
65 """ extends sign bit out from current MSB to 64 bits
67 assert isinstance(value
, SelectableInt
)
68 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
72 """ extends sign bit out from current MSB to 128 bits
74 assert isinstance(value
, SelectableInt
)
75 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
78 def copy_assign_rhs(inp
):
79 """ implicitly added function call to all assignment RHSes.
80 This copies the passed-in value so later assignments to parts of the
81 LHS don't modify the RHS if it's a SelectableInt.
85 # this needs to copy the SelectableInt instance in RA
86 # not just assign a reference to it to A
88 A[0] <- 1 # if the copy wasn't performed, we just modified RA too!
91 if isinstance(inp
, (str, int)):
93 if isinstance(inp
, FPSCRState
):
94 return FPSCRState(inp
)
95 if isinstance(inp
, XERState
):
97 if isinstance(inp
, SVSHAPE
):
99 if isinstance(inp
, SVP64State
):
100 return SVP64State(inp
)
101 if isinstance(inp
, (SelectableInt
, FieldSelectableInt
)):
102 return SelectableInt(inp
)
103 if isinstance(inp
, BFPState
):
105 if isinstance(inp
, SelectableMSB0Fraction
):
106 return SelectableMSB0Fraction(inp
)
107 if isinstance(inp
, tuple):
108 return tuple(map(copy_assign_rhs
, inp
))
109 if isinstance(inp
, dict):
110 return {copy_assign_rhs(k
): copy_assign_rhs(v
) for k
, v
in inp
.items()}
111 raise TypeError("tried to assign an unsupported type in pseudo-code",
115 # signed version of MUL
117 if isinstance(b
, int):
118 b
= SelectableInt(b
, self
.bits
)
119 b
= check_extsign(a
, b
)
120 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
121 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
122 result
= abs(a
) * abs(b
)
123 log("MULS", result
, a_s
, b_s
)
129 # XXX should this explicitly extend from 32 to 64?
131 if isinstance(value
, SelectableInt
):
133 return SelectableInt(value
& ((1 << 32)-1), 64)
136 def rotl(value
, bits
, wordlen
):
137 if isinstance(bits
, SelectableInt
):
139 mask
= (1 << wordlen
) - 1
140 bits
= bits
& (wordlen
- 1)
141 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
144 def SHL64(value
, bits
, wordlen
=64):
145 if isinstance(bits
, SelectableInt
):
147 mask
= (1 << wordlen
) - 1
148 bits
= bits
& (wordlen
- 1)
149 return SelectableInt((value
<< bits
) & mask
, 64)
153 return onebit(a
!= b
)
157 return onebit(a
== b
)
165 return onebit(a
>= b
)
173 return onebit(a
<= b
)
181 """ function that, for Power spec purposes, returns undefined bits of
182 the same shape as the input bits. however, for purposes of matching
183 POWER9's behavior returns the input bits unchanged. this effectively
184 "marks" (tags) locations in the v3.0B spec that need to be submitted
191 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
193 # result - WORD - start off all zeros
194 WORD
= SelectableInt(0, 32)
201 log("s e m", s
.value
, e
.value
, m
.value
)
203 # No Denormalization Required (includes Zero / Infinity / NaN)
204 if e
.value
> 896 or FRS
[1:64].value
== 0:
205 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
207 WORD
[2:32] = FRS
[5:35]
209 # Denormalization Required
210 if e
.value
>= 874 and e
.value
<= 896:
213 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
214 log("exp, fract", exp
, hex(frac
.value
))
215 # denormalize operand
217 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
220 WORD
[1:9] = SelectableInt(0, 8)
221 WORD
[9:32] = frac
[1:24]
222 # else WORD = undefined # return zeros
228 # XXX NOTE: these are very quick hacked functions for utterly basic
232 def signinv(res
, sign
):
241 def fp32toselectable(flt
):
242 """convert FP number to 32 bit SelectableInt
244 b
= struct
.pack("<f", flt
)
245 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
246 return SelectableInt(val
, 32)
249 def fp64toselectable(flt
):
250 """convert FP number to 64 bit SelectableInt
252 b
= struct
.pack("<d", flt
)
253 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
254 return SelectableInt(val
, 64)
274 # bfp32/64_OP naming mirrors that in the Power ISA spec.
276 def bfp64_ATAN2PI(self
, a
, b
):
277 # FIXME: use proper implementation
278 return fp64toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
280 def bfp32_ATAN2PI(self
, a
, b
):
281 # FIXME: use proper implementation
282 return fp32toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
284 def bfp64_ATAN2(self
, a
, b
):
285 # FIXME: use proper implementation
286 return fp64toselectable(math
.atan2(float(a
), float(b
)))
288 def bfp32_ATAN2(self
, a
, b
):
289 # FIXME: use proper implementation
290 return fp32toselectable(math
.atan2(float(a
), float(b
)))
292 def bfp64_HYPOT(self
, a
, b
):
293 # FIXME: use proper implementation
294 return fp64toselectable(math
.hypot(float(a
), float(b
)))
296 def bfp32_HYPOT(self
, a
, b
):
297 # FIXME: use proper implementation
298 return fp32toselectable(math
.hypot(float(a
), float(b
)))
300 def bfp64_MINNUM08(self
, a
, b
):
301 # FIXME: use proper implementation
302 return fp64toselectable(min(float(a
), float(b
)))
304 def bfp32_MINNUM08(self
, a
, b
):
305 # FIXME: use proper implementation
306 return fp32toselectable(min(float(a
), float(b
)))
308 def bfp64_MIN19(self
, a
, b
):
309 # FIXME: use proper implementation
310 return fp64toselectable(min(float(a
), float(b
)))
312 def bfp32_MIN19(self
, a
, b
):
313 # FIXME: use proper implementation
314 return fp32toselectable(min(float(a
), float(b
)))
316 def bfp64_MINNUM19(self
, a
, b
):
317 # FIXME: use proper implementation
318 return fp64toselectable(min(float(a
), float(b
)))
320 def bfp32_MINNUM19(self
, a
, b
):
321 # FIXME: use proper implementation
322 return fp32toselectable(min(float(a
), float(b
)))
324 def bfp64_MINC(self
, a
, b
):
325 # FIXME: use proper implementation
326 return fp64toselectable(min(float(a
), float(b
)))
328 def bfp32_MINC(self
, a
, b
):
329 # FIXME: use proper implementation
330 return fp32toselectable(min(float(a
), float(b
)))
332 def bfp64_MAXNUM08(self
, a
, b
):
333 # FIXME: use proper implementation
334 return fp64toselectable(max(float(a
), float(b
)))
336 def bfp32_MAXNUM08(self
, a
, b
):
337 # FIXME: use proper implementation
338 return fp32toselectable(max(float(a
), float(b
)))
340 def bfp64_MAX19(self
, a
, b
):
341 # FIXME: use proper implementation
342 return fp64toselectable(max(float(a
), float(b
)))
344 def bfp32_MAX19(self
, a
, b
):
345 # FIXME: use proper implementation
346 return fp32toselectable(max(float(a
), float(b
)))
348 def bfp64_MAXNUM19(self
, a
, b
):
349 # FIXME: use proper implementation
350 return fp64toselectable(max(float(a
), float(b
)))
352 def bfp32_MAXNUM19(self
, a
, b
):
353 # FIXME: use proper implementation
354 return fp32toselectable(max(float(a
), float(b
)))
356 def bfp64_MAXC(self
, a
, b
):
357 # FIXME: use proper implementation
358 return fp64toselectable(max(float(a
), float(b
)))
360 def bfp32_MAXC(self
, a
, b
):
361 # FIXME: use proper implementation
362 return fp32toselectable(max(float(a
), float(b
)))
364 def bfp64_MINMAGNUM08(self
, a
, b
):
365 # FIXME: use proper implementation
366 return fp64toselectable(_minmag(float(a
), float(b
)))
368 def bfp32_MINMAGNUM08(self
, a
, b
):
369 # FIXME: use proper implementation
370 return fp32toselectable(_minmag(float(a
), float(b
)))
372 def bfp64_MAXMAGNUM08(self
, a
, b
):
373 # FIXME: use proper implementation
374 return fp64toselectable(_maxmag(float(a
), float(b
)))
376 def bfp32_MAXMAGNUM08(self
, a
, b
):
377 # FIXME: use proper implementation
378 return fp32toselectable(_maxmag(float(a
), float(b
)))
380 def bfp64_MOD(self
, a
, b
):
381 # FIXME: use proper implementation
382 return fp64toselectable(math
.fmod(float(a
), float(b
)))
384 def bfp32_MOD(self
, a
, b
):
385 # FIXME: use proper implementation
386 return fp32toselectable(math
.fmod(float(a
), float(b
)))
388 def bfp64_MINMAG19(self
, a
, b
):
389 # FIXME: use proper implementation
390 return fp64toselectable(_minmag(float(a
), float(b
)))
392 def bfp32_MINMAG19(self
, a
, b
):
393 # FIXME: use proper implementation
394 return fp32toselectable(_minmag(float(a
), float(b
)))
396 def bfp64_MAXMAG19(self
, a
, b
):
397 # FIXME: use proper implementation
398 return fp64toselectable(_maxmag(float(a
), float(b
)))
400 def bfp32_MAXMAG19(self
, a
, b
):
401 # FIXME: use proper implementation
402 return fp32toselectable(_maxmag(float(a
), float(b
)))
404 def bfp64_MINMAGNUM19(self
, a
, b
):
405 # FIXME: use proper implementation
406 return fp64toselectable(_minmag(float(a
), float(b
)))
408 def bfp32_MINMAGNUM19(self
, a
, b
):
409 # FIXME: use proper implementation
410 return fp32toselectable(_minmag(float(a
), float(b
)))
412 def bfp64_MAXMAGNUM19(self
, a
, b
):
413 # FIXME: use proper implementation
414 return fp64toselectable(_maxmag(float(a
), float(b
)))
416 def bfp32_MAXMAGNUM19(self
, a
, b
):
417 # FIXME: use proper implementation
418 return fp32toselectable(_maxmag(float(a
), float(b
)))
420 def bfp64_REMAINDER(self
, a
, b
):
421 # FIXME: use proper implementation
422 return fp64toselectable(math
.remainder(float(a
), float(b
)))
424 def bfp32_REMAINDER(self
, a
, b
):
425 # FIXME: use proper implementation
426 return fp32toselectable(math
.remainder(float(a
), float(b
)))
428 def bfp64_POWR(self
, a
, b
):
429 # FIXME: use proper implementation
430 return fp64toselectable(pow(float(a
), float(b
)))
432 def bfp32_POWR(self
, a
, b
):
433 # FIXME: use proper implementation
434 return fp32toselectable(pow(float(a
), float(b
)))
436 def bfp64_POW(self
, a
, b
):
437 # FIXME: use proper implementation
438 return fp64toselectable(pow(float(a
), float(b
)))
440 def bfp32_POW(self
, a
, b
):
441 # FIXME: use proper implementation
442 return fp32toselectable(pow(float(a
), float(b
)))
444 def bfp64_MINMAGC(self
, a
, b
):
445 # FIXME: use proper implementation
446 return fp64toselectable(_minmag(float(a
), float(b
)))
448 def bfp32_MINMAGC(self
, a
, b
):
449 # FIXME: use proper implementation
450 return fp32toselectable(_minmag(float(a
), float(b
)))
452 def bfp64_MAXMAGC(self
, a
, b
):
453 # FIXME: use proper implementation
454 return fp64toselectable(_maxmag(float(a
), float(b
)))
456 def bfp32_MAXMAGC(self
, a
, b
):
457 # FIXME: use proper implementation
458 return fp32toselectable(_maxmag(float(a
), float(b
)))
460 def bfp64_POWN(self
, a
, b
):
461 # FIXME: use proper implementation
462 return fp64toselectable(pow(float(a
), int(b
)))
464 def bfp32_POWN(self
, a
, b
):
465 # FIXME: use proper implementation
466 return fp32toselectable(pow(float(a
), int(b
)))
468 def bfp64_ROOTN(self
, a
, b
):
469 # FIXME: use proper implementation
470 return fp64toselectable(pow(float(a
), 1 / int(b
)))
472 def bfp32_ROOTN(self
, a
, b
):
473 # FIXME: use proper implementation
474 return fp32toselectable(pow(float(a
), 1 / int(b
)))
476 def bfp64_CBRT(self
, v
):
477 # FIXME: use proper implementation
478 return fp64toselectable(pow(float(v
), 1 / 3))
480 def bfp32_CBRT(self
, v
):
481 # FIXME: use proper implementation
482 return fp32toselectable(pow(float(v
), 1 / 3))
484 def bfp64_SINPI(self
, v
):
485 # FIXME: use proper implementation
486 return fp64toselectable(math
.sin(float(v
) * math
.pi
))
488 def bfp32_SINPI(self
, v
):
489 # FIXME: use proper implementation
490 return fp32toselectable(math
.sin(float(v
) * math
.pi
))
492 def bfp64_ASINPI(self
, v
):
493 # FIXME: use proper implementation
494 return fp64toselectable(math
.asin(float(v
)) / math
.pi
)
496 def bfp32_ASINPI(self
, v
):
497 # FIXME: use proper implementation
498 return fp32toselectable(math
.asin(float(v
)) / math
.pi
)
500 def bfp64_COSPI(self
, v
):
501 # FIXME: use proper implementation
502 return fp64toselectable(math
.cos(float(v
) * math
.pi
))
504 def bfp32_COSPI(self
, v
):
505 # FIXME: use proper implementation
506 return fp32toselectable(math
.cos(float(v
) * math
.pi
))
508 def bfp64_TANPI(self
, v
):
509 # FIXME: use proper implementation
510 return fp64toselectable(math
.tan(float(v
) * math
.pi
))
512 def bfp32_TANPI(self
, v
):
513 # FIXME: use proper implementation
514 return fp32toselectable(math
.tan(float(v
) * math
.pi
))
516 def bfp64_ACOSPI(self
, v
):
517 # FIXME: use proper implementation
518 return fp64toselectable(math
.acos(float(v
)) / math
.pi
)
520 def bfp32_ACOSPI(self
, v
):
521 # FIXME: use proper implementation
522 return fp32toselectable(math
.acos(float(v
)) / math
.pi
)
524 def bfp64_ATANPI(self
, v
):
525 # FIXME: use proper implementation
526 return fp64toselectable(math
.atan(float(v
)) / math
.pi
)
528 def bfp32_ATANPI(self
, v
):
529 # FIXME: use proper implementation
530 return fp32toselectable(math
.atan(float(v
)) / math
.pi
)
532 def bfp64_RSQRT(self
, v
):
533 # FIXME: use proper implementation
534 return fp64toselectable(1 / math
.sqrt(float(v
)))
536 def bfp32_RSQRT(self
, v
):
537 # FIXME: use proper implementation
538 return fp32toselectable(1 / math
.sqrt(float(v
)))
540 def bfp64_SIN(self
, v
):
541 # FIXME: use proper implementation
542 return fp64toselectable(math
.sin(float(v
)))
544 def bfp32_SIN(self
, v
):
545 # FIXME: use proper implementation
546 return fp32toselectable(math
.sin(float(v
)))
548 def bfp64_ASIN(self
, v
):
549 # FIXME: use proper implementation
550 return fp64toselectable(math
.asin(float(v
)))
552 def bfp32_ASIN(self
, v
):
553 # FIXME: use proper implementation
554 return fp32toselectable(math
.asin(float(v
)))
556 def bfp64_COS(self
, v
):
557 # FIXME: use proper implementation
558 return fp64toselectable(math
.cos(float(v
)))
560 def bfp32_COS(self
, v
):
561 # FIXME: use proper implementation
562 return fp32toselectable(math
.cos(float(v
)))
564 def bfp64_TAN(self
, v
):
565 # FIXME: use proper implementation
566 return fp64toselectable(math
.tan(float(v
)))
568 def bfp32_TAN(self
, v
):
569 # FIXME: use proper implementation
570 return fp32toselectable(math
.tan(float(v
)))
572 def bfp64_ACOS(self
, v
):
573 # FIXME: use proper implementation
574 return fp64toselectable(math
.acos(float(v
)))
576 def bfp32_ACOS(self
, v
):
577 # FIXME: use proper implementation
578 return fp32toselectable(math
.acos(float(v
)))
580 def bfp64_ATAN(self
, v
):
581 # FIXME: use proper implementation
582 return fp64toselectable(math
.atan(float(v
)))
584 def bfp32_ATAN(self
, v
):
585 # FIXME: use proper implementation
586 return fp32toselectable(math
.atan(float(v
)))
588 def bfp64_RECIP(self
, v
):
589 # FIXME: use proper implementation
590 return fp64toselectable(1 / float(v
))
592 def bfp32_RECIP(self
, v
):
593 # FIXME: use proper implementation
594 return fp32toselectable(1 / float(v
))
596 def bfp64_SINH(self
, v
):
597 # FIXME: use proper implementation
598 return fp64toselectable(math
.sinh(float(v
)))
600 def bfp32_SINH(self
, v
):
601 # FIXME: use proper implementation
602 return fp32toselectable(math
.sinh(float(v
)))
604 def bfp64_ASINH(self
, v
):
605 # FIXME: use proper implementation
606 return fp64toselectable(math
.asinh(float(v
)))
608 def bfp32_ASINH(self
, v
):
609 # FIXME: use proper implementation
610 return fp32toselectable(math
.asinh(float(v
)))
612 def bfp64_COSH(self
, v
):
613 # FIXME: use proper implementation
614 return fp64toselectable(math
.cosh(float(v
)))
616 def bfp32_COSH(self
, v
):
617 # FIXME: use proper implementation
618 return fp32toselectable(math
.cosh(float(v
)))
620 def bfp64_TANH(self
, v
):
621 # FIXME: use proper implementation
622 return fp64toselectable(math
.tanh(float(v
)))
624 def bfp32_TANH(self
, v
):
625 # FIXME: use proper implementation
626 return fp32toselectable(math
.tanh(float(v
)))
628 def bfp64_ACOSH(self
, v
):
629 # FIXME: use proper implementation
630 return fp64toselectable(math
.acosh(float(v
)))
632 def bfp32_ACOSH(self
, v
):
633 # FIXME: use proper implementation
634 return fp32toselectable(math
.acosh(float(v
)))
636 def bfp64_ATANH(self
, v
):
637 # FIXME: use proper implementation
638 return fp64toselectable(math
.atanh(float(v
)))
640 def bfp32_ATANH(self
, v
):
641 # FIXME: use proper implementation
642 return fp32toselectable(math
.atanh(float(v
)))
644 def bfp64_EXP2M1(self
, v
):
645 # FIXME: use proper implementation
646 return fp64toselectable(pow(2, float(v
)) - 1)
648 def bfp32_EXP2M1(self
, v
):
649 # FIXME: use proper implementation
650 return fp32toselectable(pow(2, float(v
)) - 1)
652 def bfp64_LOG2P1(self
, v
):
653 # FIXME: use proper implementation
654 return fp64toselectable(math
.log2(float(v
) + 1))
656 def bfp32_LOG2P1(self
, v
):
657 # FIXME: use proper implementation
658 return fp32toselectable(math
.log2(float(v
) + 1))
660 def bfp64_EXPM1(self
, v
):
661 # FIXME: use proper implementation
662 return fp64toselectable(math
.expm1(float(v
)))
664 def bfp32_EXPM1(self
, v
):
665 # FIXME: use proper implementation
666 return fp32toselectable(math
.expm1(float(v
)))
668 def bfp64_LOGP1(self
, v
):
669 # FIXME: use proper implementation
670 return fp64toselectable(math
.log1p(float(v
)))
672 def bfp32_LOGP1(self
, v
):
673 # FIXME: use proper implementation
674 return fp32toselectable(math
.log1p(float(v
)))
676 def bfp64_EXP10M1(self
, v
):
677 # FIXME: use proper implementation
678 return fp64toselectable(pow(10, float(v
)) - 1)
680 def bfp32_EXP10M1(self
, v
):
681 # FIXME: use proper implementation
682 return fp32toselectable(pow(10, float(v
)) - 1)
684 def bfp64_LOG10P1(self
, v
):
685 # FIXME: use proper implementation
686 return fp64toselectable(math
.log10(float(v
) + 1))
688 def bfp32_LOG10P1(self
, v
):
689 # FIXME: use proper implementation
690 return fp32toselectable(math
.log10(float(v
) + 1))
692 def bfp64_EXP2(self
, v
):
693 # FIXME: use proper implementation
694 return fp64toselectable(pow(2, float(v
)))
696 def bfp32_EXP2(self
, v
):
697 # FIXME: use proper implementation
698 return fp32toselectable(pow(2, float(v
)))
700 def bfp64_LOG2(self
, v
):
701 # FIXME: use proper implementation
702 return fp64toselectable(math
.log2(float(v
)))
704 def bfp32_LOG2(self
, v
):
705 # FIXME: use proper implementation
706 return fp32toselectable(math
.log2(float(v
)))
708 def bfp64_EXP(self
, v
):
709 # FIXME: use proper implementation
710 return fp64toselectable(math
.exp(float(v
)))
712 def bfp32_EXP(self
, v
):
713 # FIXME: use proper implementation
714 return fp32toselectable(math
.exp(float(v
)))
716 def bfp64_LOG(self
, v
):
717 # FIXME: use proper implementation
718 return fp64toselectable(math
.log(float(v
)))
720 def bfp32_LOG(self
, v
):
721 # FIXME: use proper implementation
722 return fp32toselectable(math
.log(float(v
)))
724 def bfp64_EXP10(self
, v
):
725 # FIXME: use proper implementation
726 return fp64toselectable(pow(10, float(v
)))
728 def bfp32_EXP10(self
, v
):
729 # FIXME: use proper implementation
730 return fp32toselectable(pow(10, float(v
)))
732 def bfp64_LOG10(self
, v
):
733 # FIXME: use proper implementation
734 return fp64toselectable(math
.log10(float(v
)))
736 def bfp32_LOG10(self
, v
):
737 # FIXME: use proper implementation
738 return fp32toselectable(math
.log10(float(v
)))
740 def FPADD32(self
, FRA
, FRB
):
741 # return FPADD64(FRA, FRB)
742 #FRA = DOUBLE(SINGLE(FRA))
743 #FRB = DOUBLE(SINGLE(FRB))
744 result
= float(FRA
) + float(FRB
)
745 cvt
= fp64toselectable(result
)
746 cvt
= self
.DOUBLE2SINGLE(cvt
)
747 log("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
750 def FPSUB32(self
, FRA
, FRB
):
751 # return FPSUB64(FRA, FRB)
752 #FRA = DOUBLE(SINGLE(FRA))
753 #FRB = DOUBLE(SINGLE(FRB))
754 result
= float(FRA
) - float(FRB
)
755 cvt
= fp64toselectable(result
)
756 cvt
= self
.DOUBLE2SINGLE(cvt
)
757 log("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
760 def FPMUL32(self
, FRA
, FRB
, sign
=1):
761 # return FPMUL64(FRA, FRB)
762 FRA
= self
.DOUBLE(SINGLE(FRA
))
763 FRB
= self
.DOUBLE(SINGLE(FRB
))
764 result
= signinv(float(FRA
) * float(FRB
), sign
)
765 log("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
766 cvt
= fp64toselectable(result
)
767 cvt
= self
.DOUBLE2SINGLE(cvt
)
771 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
772 # return FPMUL64(FRA, FRB)
773 #FRA = DOUBLE(SINGLE(FRA))
774 #FRB = DOUBLE(SINGLE(FRB))
777 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
779 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
782 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
784 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
787 log("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
788 log(" FRA", float(FRA
))
789 log(" FRC", float(FRC
))
790 log(" FRB", float(FRB
))
791 log(" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
792 cvt
= fp64toselectable(result
)
793 cvt
= self
.DOUBLE2SINGLE(cvt
)
797 def FPDIV32(self
, FRA
, FRB
, sign
=1):
798 # return FPDIV64(FRA, FRB)
799 #FRA = DOUBLE(SINGLE(FRA))
800 #FRB = DOUBLE(SINGLE(FRB))
801 result
= signinv(float(FRA
) / float(FRB
), sign
)
802 cvt
= fp64toselectable(result
)
803 cvt
= self
.DOUBLE2SINGLE(cvt
)
804 log("FPDIV32", FRA
, FRB
, result
, cvt
)
808 def FPADD64(FRA
, FRB
):
809 result
= float(FRA
) + float(FRB
)
810 cvt
= fp64toselectable(result
)
811 log("FPADD64", FRA
, FRB
, result
, cvt
)
815 def FPSUB64(FRA
, FRB
):
816 result
= float(FRA
) - float(FRB
)
817 cvt
= fp64toselectable(result
)
818 log("FPSUB64", FRA
, FRB
, result
, cvt
)
822 def FPMUL64(FRA
, FRB
, sign
=1):
823 result
= signinv(float(FRA
) * float(FRB
), sign
)
824 cvt
= fp64toselectable(result
)
825 log("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
829 def FPDIV64(FRA
, FRB
, sign
=1):
830 result
= signinv(float(FRA
) / float(FRB
), sign
)
831 cvt
= fp64toselectable(result
)
832 log("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
837 """Returns the integer whose value is the reverse of the lowest
838 'width' bits of the integer 'val'
841 width
= VL
.bit_length()-1
842 for _
in range(width
):
843 result
= (result
<< 1) |
(val
& 1)
849 """return the base-2 logarithm of `val`. Only works for powers of 2."""
850 if isinstance(val
, SelectableInt
):
852 retval
= val
.bit_length() - 1
853 assert val
== 2 ** retval
, "value is not a power of 2"
857 # BFP classification predicates
858 # these need to be implemented in python because they work with multiple
861 if isinstance(v
, BFPState
):
862 return onebit(v
.class_
.Infinity
)
863 # TODO: implement for SelectableInt/int
864 raise NotImplementedError("not yet implemented for non-BFPState values")
868 if isinstance(v
, BFPState
):
869 return onebit(v
.class_
.SNaN
or v
.class_
.QNaN
)
870 # TODO: implement for SelectableInt/int
871 raise NotImplementedError("not yet implemented for non-BFPState values")
875 if isinstance(v
, BFPState
):
876 if v
.class_
.SNaN
or v
.class_
.QNaN
or v
.class_
.Zero
:
878 return onebit(v
.sign
)
879 # TODO: implement for SelectableInt/int
880 raise NotImplementedError("not yet implemented for non-BFPState values")
884 if isinstance(v
, BFPState
):
885 return onebit(v
.class_
.SNaN
)
886 # TODO: implement for SelectableInt/int
887 raise NotImplementedError("not yet implemented for non-BFPState values")
891 if isinstance(v
, BFPState
):
892 return onebit(v
.class_
.Zero
)
893 # TODO: implement for SelectableInt/int
894 raise NotImplementedError("not yet implemented for non-BFPState values")
897 def SetFX(fpscr
, field
):
898 assert isinstance(fpscr
, FPSCRState
), "SetFX only works on FPSCR fields"
899 if eq(getattr(fpscr
, field
), SelectableInt(0, 1)):
900 setattr(fpscr
, field
, SelectableInt(1, 1))
901 fpscr
.FX
= SelectableInt(1, 1)
904 class ISACallerHelper
:
905 def __init__(self
, XLEN
, FPSCR
):
919 def EXTZXL(self
, value
, bits
=None):
922 elif isinstance(bits
, SelectableInt
):
924 if isinstance(value
, SelectableInt
):
926 return SelectableInt(value
& ((1 << bits
) - 1), self
.XLEN
)
928 def EXTSXL(self
, value
, bits
=None):
929 if isinstance(value
, SelectableInt
):
933 elif isinstance(bits
, SelectableInt
):
935 return SelectableInt(exts(value
, bits
), self
.XLEN
)
937 def DOUBLE2SINGLE(self
, FRS
):
938 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
939 implementation of the frsp instruction.
940 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
942 return self
.FRSP(FRS
)
944 def ROTL32(self
, value
, bits
):
945 if isinstance(bits
, SelectableInt
):
947 if isinstance(value
, SelectableInt
):
948 value
= SelectableInt(value
.value
, self
.XLEN
)
949 value
= value |
(value
<< (self
.XLEN
//2))
950 value
= rotl(value
, bits
, self
.XLEN
)
953 def ROTL128(self
, value
, bits
):
954 return rotl(value
, bits
, self
.XLEN
*2)
956 def ROTL64(self
, value
, bits
):
957 return rotl(value
, bits
, self
.XLEN
)
959 def MASK32(self
, x
, y
):
960 if isinstance(x
, SelectableInt
):
962 if isinstance(y
, SelectableInt
):
964 return self
.MASK(x
+(self
.XLEN
//2), y
+(self
.XLEN
//2))
966 def MASK(self
, x
, y
, lim
=None):
969 if isinstance(x
, SelectableInt
):
971 if isinstance(y
, SelectableInt
):
976 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
977 mask_b
= ((1 << y
) - 1) & ((1 << lim
) - 1)
979 return 1 << ((lim
-1)-x
)
983 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
984 mask_b
= (~
((1 << y
) - 1)) & ((1 << lim
) - 1)
985 return mask_a ^ mask_b
987 def __getattr__(self
, attr
):
988 """workaround for getting function out of the global namespace
989 within this module, as a way to get functions being transitioned
990 to Helper classes within ISACaller (and therefore pseudocode)
993 return globals()[attr
]
995 raise AttributeError(attr
)
998 # For these tests I tried to find power instructions that would let me
999 # isolate each of these helper operations. So for instance, when I was
1000 # testing the MASK() function, I chose rlwinm and rldicl because if I
1001 # set the shift equal to 0 and passed in a value of all ones, the
1002 # result I got would be exactly the same as the output of MASK()
1004 class HelperTests(unittest
.TestCase
, ISACallerHelper
):
1005 def __init__(self
, *args
, **kwargs
):
1006 # TODO: dynamic (64/32/16/8)
1007 ISACallerHelper
.__init
__(self
, 64, FPSCR
=None)
1008 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
1010 def test_MASK(self
):
1011 # Verified using rlwinm, rldicl, rldicr in qemu
1013 # rlwinm reg, 1, 0, 5, 15
1014 self
.assertHex(self
.MASK(5+32, 15+32), 0x7ff0000)
1015 # rlwinm reg, 1, 0, 15, 5
1016 self
.assertHex(self
.MASK(15+32, 5+32), 0xfffffffffc01ffff)
1017 self
.assertHex(self
.MASK(30+32, 2+32), 0xffffffffe0000003)
1018 # rldicl reg, 1, 0, 37
1019 self
.assertHex(self
.MASK(37, 63), 0x7ffffff)
1020 self
.assertHex(self
.MASK(10, 63), 0x3fffffffffffff)
1021 self
.assertHex(self
.MASK(58, 63), 0x3f)
1022 # rldicr reg, 1, 0, 37
1023 self
.assertHex(self
.MASK(0, 37), 0xfffffffffc000000)
1024 self
.assertHex(self
.MASK(0, 10), 0xffe0000000000000)
1025 self
.assertHex(self
.MASK(0, 58), 0xffffffffffffffe0)
1029 self
.assertHex(self
.MASK(32, 63-5), 0xffffffe0)
1031 self
.assertHex(self
.MASK(32, 33), 0xc0000000)
1032 self
.assertHex(self
.MASK(32, 32), 0x80000000)
1033 self
.assertHex(self
.MASK(33, 33), 0x40000000)
1035 def test_ROTL64(self
):
1036 # r1 = 0xdeadbeef12345678
1037 value
= 0xdeadbeef12345678
1039 # rldicl reg, 1, 10, 0
1040 self
.assertHex(self
.ROTL64(value
, 10), 0xb6fbbc48d159e37a)
1041 # rldicl reg, 1, 35, 0
1042 self
.assertHex(self
.ROTL64(value
, 35), 0x91a2b3c6f56df778)
1043 self
.assertHex(self
.ROTL64(value
, 58), 0xe37ab6fbbc48d159)
1044 self
.assertHex(self
.ROTL64(value
, 22), 0xbbc48d159e37ab6f)
1046 def test_ROTL32(self
):
1048 value
= SelectableInt(0xdeadbeef, self
.XLEN
)
1050 # rlwinm reg, 1, 10, 0, 31
1051 self
.assertHex(self
.ROTL32(value
, 10), 0xb6fbbf7a)
1052 # rlwinm reg, 1, 17, 0, 31
1053 self
.assertHex(self
.ROTL32(value
, 17), 0x7ddfbd5b)
1054 self
.assertHex(self
.ROTL32(value
, 25), 0xdfbd5b7d)
1055 self
.assertHex(self
.ROTL32(value
, 30), 0xf7ab6fbb)
1057 def test_EXTS64(self
):
1058 value_a
= SelectableInt(0xdeadbeef, 32) # r1
1059 value_b
= SelectableInt(0x73123456, 32) # r2
1060 value_c
= SelectableInt(0x80000000, 32) # r3
1062 # extswsli reg, 1, 0
1063 self
.assertHex(self
.EXTS64(value_a
), 0xffffffffdeadbeef)
1064 # extswsli reg, 2, 0
1065 self
.assertHex(self
.EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
1066 # extswsli reg, 3, 0
1067 self
.assertHex(self
.EXTS64(value_c
), 0xffffffff80000000)
1069 def test_FPADD32(self
):
1070 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
1071 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1072 result
= FPADD32(value_a
, value_b
)
1073 self
.assertHex(0x4040266666666666, result
)
1075 def assertHex(self
, a
, b
):
1077 if isinstance(a
, SelectableInt
):
1080 if isinstance(b
, SelectableInt
):
1082 msg
= "{:x} != {:x}".format(a_val
, b_val
)
1083 return self
.assertEqual(a
, b
, msg
)
1087 if __name__
== '__main__':
1088 log(SelectableInt
.__bases
__)