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 # signed version of MUL
77 if isinstance(b
, int):
78 b
= SelectableInt(b
, self
.bits
)
79 b
= check_extsign(a
, b
)
80 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
81 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
82 result
= abs(a
) * abs(b
)
83 log("MULS", result
, a_s
, b_s
)
89 # XXX should this explicitly extend from 32 to 64?
91 if isinstance(value
, SelectableInt
):
93 return SelectableInt(value
& ((1 << 32)-1), 64)
96 def rotl(value
, bits
, wordlen
):
97 if isinstance(bits
, SelectableInt
):
99 mask
= (1 << wordlen
) - 1
100 bits
= bits
& (wordlen
- 1)
101 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
104 def SHL64(value
, bits
, wordlen
=64):
105 if isinstance(bits
, SelectableInt
):
107 mask
= (1 << wordlen
) - 1
108 bits
= bits
& (wordlen
- 1)
109 return SelectableInt((value
<< bits
) & mask
, 64)
113 return onebit(a
!= b
)
117 return onebit(a
== b
)
125 return onebit(a
>= b
)
133 return onebit(a
<= b
)
141 """ function that, for Power spec purposes, returns undefined bits of
142 the same shape as the input bits. however, for purposes of matching
143 POWER9's behavior returns the input bits unchanged. this effectively
144 "marks" (tags) locations in the v3.0B spec that need to be submitted
151 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
153 # result - WORD - start off all zeros
154 WORD
= SelectableInt(0, 32)
161 log("s e m", s
.value
, e
.value
, m
.value
)
163 # No Denormalization Required (includes Zero / Infinity / NaN)
164 if e
.value
> 896 or FRS
[1:64].value
== 0:
165 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
167 WORD
[2:32] = FRS
[5:35]
169 # Denormalization Required
170 if e
.value
>= 874 and e
.value
<= 896:
173 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
174 log("exp, fract", exp
, hex(frac
.value
))
175 # denormalize operand
177 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
180 WORD
[1:9] = SelectableInt(0, 8)
181 WORD
[9:32] = frac
[1:24]
182 # else WORD = undefined # return zeros
188 # XXX NOTE: these are very quick hacked functions for utterly basic
192 def signinv(res
, sign
):
201 def fp32toselectable(flt
):
202 """convert FP number to 32 bit SelectableInt
204 b
= struct
.pack("<f", flt
)
205 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
206 return SelectableInt(val
, 32)
209 def fp64toselectable(flt
):
210 """convert FP number to 64 bit SelectableInt
212 b
= struct
.pack("<d", flt
)
213 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
214 return SelectableInt(val
, 64)
234 # bfp32/64_OP naming mirrors that in the Power ISA spec.
236 def bfp64_ATAN2PI(self
, a
, b
):
237 # FIXME: use proper implementation
238 return fp64toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
240 def bfp32_ATAN2PI(self
, a
, b
):
241 # FIXME: use proper implementation
242 return fp32toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
244 def bfp64_ATAN2(self
, a
, b
):
245 # FIXME: use proper implementation
246 return fp64toselectable(math
.atan2(float(a
), float(b
)))
248 def bfp32_ATAN2(self
, a
, b
):
249 # FIXME: use proper implementation
250 return fp32toselectable(math
.atan2(float(a
), float(b
)))
252 def bfp64_HYPOT(self
, a
, b
):
253 # FIXME: use proper implementation
254 return fp64toselectable(math
.hypot(float(a
), float(b
)))
256 def bfp32_HYPOT(self
, a
, b
):
257 # FIXME: use proper implementation
258 return fp32toselectable(math
.hypot(float(a
), float(b
)))
260 def bfp64_MINNUM08(self
, a
, b
):
261 # FIXME: use proper implementation
262 return fp64toselectable(min(float(a
), float(b
)))
264 def bfp32_MINNUM08(self
, a
, b
):
265 # FIXME: use proper implementation
266 return fp32toselectable(min(float(a
), float(b
)))
268 def bfp64_MIN19(self
, a
, b
):
269 # FIXME: use proper implementation
270 return fp64toselectable(min(float(a
), float(b
)))
272 def bfp32_MIN19(self
, a
, b
):
273 # FIXME: use proper implementation
274 return fp32toselectable(min(float(a
), float(b
)))
276 def bfp64_MINNUM19(self
, a
, b
):
277 # FIXME: use proper implementation
278 return fp64toselectable(min(float(a
), float(b
)))
280 def bfp32_MINNUM19(self
, a
, b
):
281 # FIXME: use proper implementation
282 return fp32toselectable(min(float(a
), float(b
)))
284 def bfp64_MINC(self
, a
, b
):
285 # FIXME: use proper implementation
286 return fp64toselectable(min(float(a
), float(b
)))
288 def bfp32_MINC(self
, a
, b
):
289 # FIXME: use proper implementation
290 return fp32toselectable(min(float(a
), float(b
)))
292 def bfp64_MAXNUM08(self
, a
, b
):
293 # FIXME: use proper implementation
294 return fp64toselectable(max(float(a
), float(b
)))
296 def bfp32_MAXNUM08(self
, a
, b
):
297 # FIXME: use proper implementation
298 return fp32toselectable(max(float(a
), float(b
)))
300 def bfp64_MAX19(self
, a
, b
):
301 # FIXME: use proper implementation
302 return fp64toselectable(max(float(a
), float(b
)))
304 def bfp32_MAX19(self
, a
, b
):
305 # FIXME: use proper implementation
306 return fp32toselectable(max(float(a
), float(b
)))
308 def bfp64_MAXNUM19(self
, a
, b
):
309 # FIXME: use proper implementation
310 return fp64toselectable(max(float(a
), float(b
)))
312 def bfp32_MAXNUM19(self
, a
, b
):
313 # FIXME: use proper implementation
314 return fp32toselectable(max(float(a
), float(b
)))
316 def bfp64_MAXC(self
, a
, b
):
317 # FIXME: use proper implementation
318 return fp64toselectable(max(float(a
), float(b
)))
320 def bfp32_MAXC(self
, a
, b
):
321 # FIXME: use proper implementation
322 return fp32toselectable(max(float(a
), float(b
)))
324 def bfp64_MINMAGNUM08(self
, a
, b
):
325 # FIXME: use proper implementation
326 return fp64toselectable(_minmag(float(a
), float(b
)))
328 def bfp32_MINMAGNUM08(self
, a
, b
):
329 # FIXME: use proper implementation
330 return fp32toselectable(_minmag(float(a
), float(b
)))
332 def bfp64_MAXMAGNUM08(self
, a
, b
):
333 # FIXME: use proper implementation
334 return fp64toselectable(_maxmag(float(a
), float(b
)))
336 def bfp32_MAXMAGNUM08(self
, a
, b
):
337 # FIXME: use proper implementation
338 return fp32toselectable(_maxmag(float(a
), float(b
)))
340 def bfp64_MOD(self
, a
, b
):
341 # FIXME: use proper implementation
342 return fp64toselectable(math
.fmod(float(a
), float(b
)))
344 def bfp32_MOD(self
, a
, b
):
345 # FIXME: use proper implementation
346 return fp32toselectable(math
.fmod(float(a
), float(b
)))
348 def bfp64_MINMAG19(self
, a
, b
):
349 # FIXME: use proper implementation
350 return fp64toselectable(_minmag(float(a
), float(b
)))
352 def bfp32_MINMAG19(self
, a
, b
):
353 # FIXME: use proper implementation
354 return fp32toselectable(_minmag(float(a
), float(b
)))
356 def bfp64_MAXMAG19(self
, a
, b
):
357 # FIXME: use proper implementation
358 return fp64toselectable(_maxmag(float(a
), float(b
)))
360 def bfp32_MAXMAG19(self
, a
, b
):
361 # FIXME: use proper implementation
362 return fp32toselectable(_maxmag(float(a
), float(b
)))
364 def bfp64_MINMAGNUM19(self
, a
, b
):
365 # FIXME: use proper implementation
366 return fp64toselectable(_minmag(float(a
), float(b
)))
368 def bfp32_MINMAGNUM19(self
, a
, b
):
369 # FIXME: use proper implementation
370 return fp32toselectable(_minmag(float(a
), float(b
)))
372 def bfp64_MAXMAGNUM19(self
, a
, b
):
373 # FIXME: use proper implementation
374 return fp64toselectable(_maxmag(float(a
), float(b
)))
376 def bfp32_MAXMAGNUM19(self
, a
, b
):
377 # FIXME: use proper implementation
378 return fp32toselectable(_maxmag(float(a
), float(b
)))
380 def bfp64_REMAINDER(self
, a
, b
):
381 # FIXME: use proper implementation
382 return fp64toselectable(math
.remainder(float(a
), float(b
)))
384 def bfp32_REMAINDER(self
, a
, b
):
385 # FIXME: use proper implementation
386 return fp32toselectable(math
.remainder(float(a
), float(b
)))
388 def bfp64_POWR(self
, a
, b
):
389 # FIXME: use proper implementation
390 return fp64toselectable(pow(float(a
), float(b
)))
392 def bfp32_POWR(self
, a
, b
):
393 # FIXME: use proper implementation
394 return fp32toselectable(pow(float(a
), float(b
)))
396 def bfp64_POW(self
, a
, b
):
397 # FIXME: use proper implementation
398 return fp64toselectable(pow(float(a
), float(b
)))
400 def bfp32_POW(self
, a
, b
):
401 # FIXME: use proper implementation
402 return fp32toselectable(pow(float(a
), float(b
)))
404 def bfp64_MINMAGC(self
, a
, b
):
405 # FIXME: use proper implementation
406 return fp64toselectable(_minmag(float(a
), float(b
)))
408 def bfp32_MINMAGC(self
, a
, b
):
409 # FIXME: use proper implementation
410 return fp32toselectable(_minmag(float(a
), float(b
)))
412 def bfp64_MAXMAGC(self
, a
, b
):
413 # FIXME: use proper implementation
414 return fp64toselectable(_maxmag(float(a
), float(b
)))
416 def bfp32_MAXMAGC(self
, a
, b
):
417 # FIXME: use proper implementation
418 return fp32toselectable(_maxmag(float(a
), float(b
)))
420 def bfp64_POWN(self
, a
, b
):
421 # FIXME: use proper implementation
422 return fp64toselectable(pow(float(a
), int(b
)))
424 def bfp32_POWN(self
, a
, b
):
425 # FIXME: use proper implementation
426 return fp32toselectable(pow(float(a
), int(b
)))
428 def bfp64_ROOTN(self
, a
, b
):
429 # FIXME: use proper implementation
430 return fp64toselectable(pow(float(a
), 1 / int(b
)))
432 def bfp32_ROOTN(self
, a
, b
):
433 # FIXME: use proper implementation
434 return fp32toselectable(pow(float(a
), 1 / int(b
)))
436 def bfp64_CBRT(self
, v
):
437 # FIXME: use proper implementation
438 return fp64toselectable(pow(float(v
), 1 / 3))
440 def bfp32_CBRT(self
, v
):
441 # FIXME: use proper implementation
442 return fp32toselectable(pow(float(v
), 1 / 3))
444 def bfp64_SINPI(self
, v
):
445 # FIXME: use proper implementation
446 return fp64toselectable(math
.sin(float(v
) * math
.pi
))
448 def bfp32_SINPI(self
, v
):
449 # FIXME: use proper implementation
450 return fp32toselectable(math
.sin(float(v
) * math
.pi
))
452 def bfp64_ASINPI(self
, v
):
453 # FIXME: use proper implementation
454 return fp64toselectable(math
.asin(float(v
)) / math
.pi
)
456 def bfp32_ASINPI(self
, v
):
457 # FIXME: use proper implementation
458 return fp32toselectable(math
.asin(float(v
)) / math
.pi
)
460 def bfp64_COSPI(self
, v
):
461 # FIXME: use proper implementation
462 return fp64toselectable(math
.cos(float(v
) * math
.pi
))
464 def bfp32_COSPI(self
, v
):
465 # FIXME: use proper implementation
466 return fp32toselectable(math
.cos(float(v
) * math
.pi
))
468 def bfp64_TANPI(self
, v
):
469 # FIXME: use proper implementation
470 return fp64toselectable(math
.tan(float(v
) * math
.pi
))
472 def bfp32_TANPI(self
, v
):
473 # FIXME: use proper implementation
474 return fp32toselectable(math
.tan(float(v
) * math
.pi
))
476 def bfp64_ACOSPI(self
, v
):
477 # FIXME: use proper implementation
478 return fp64toselectable(math
.acos(float(v
)) / math
.pi
)
480 def bfp32_ACOSPI(self
, v
):
481 # FIXME: use proper implementation
482 return fp32toselectable(math
.acos(float(v
)) / math
.pi
)
484 def bfp64_ATANPI(self
, v
):
485 # FIXME: use proper implementation
486 return fp64toselectable(math
.atan(float(v
)) / math
.pi
)
488 def bfp32_ATANPI(self
, v
):
489 # FIXME: use proper implementation
490 return fp32toselectable(math
.atan(float(v
)) / math
.pi
)
492 def bfp64_RSQRT(self
, v
):
493 # FIXME: use proper implementation
494 return fp64toselectable(1 / math
.sqrt(float(v
)))
496 def bfp32_RSQRT(self
, v
):
497 # FIXME: use proper implementation
498 return fp32toselectable(1 / math
.sqrt(float(v
)))
500 def bfp64_SIN(self
, v
):
501 # FIXME: use proper implementation
502 return fp64toselectable(math
.sin(float(v
)))
504 def bfp32_SIN(self
, v
):
505 # FIXME: use proper implementation
506 return fp32toselectable(math
.sin(float(v
)))
508 def bfp64_ASIN(self
, v
):
509 # FIXME: use proper implementation
510 return fp64toselectable(math
.asin(float(v
)))
512 def bfp32_ASIN(self
, v
):
513 # FIXME: use proper implementation
514 return fp32toselectable(math
.asin(float(v
)))
516 def bfp64_COS(self
, v
):
517 # FIXME: use proper implementation
518 return fp64toselectable(math
.cos(float(v
)))
520 def bfp32_COS(self
, v
):
521 # FIXME: use proper implementation
522 return fp32toselectable(math
.cos(float(v
)))
524 def bfp64_TAN(self
, v
):
525 # FIXME: use proper implementation
526 return fp64toselectable(math
.tan(float(v
)))
528 def bfp32_TAN(self
, v
):
529 # FIXME: use proper implementation
530 return fp32toselectable(math
.tan(float(v
)))
532 def bfp64_ACOS(self
, v
):
533 # FIXME: use proper implementation
534 return fp64toselectable(math
.acos(float(v
)))
536 def bfp32_ACOS(self
, v
):
537 # FIXME: use proper implementation
538 return fp32toselectable(math
.acos(float(v
)))
540 def bfp64_ATAN(self
, v
):
541 # FIXME: use proper implementation
542 return fp64toselectable(math
.atan(float(v
)))
544 def bfp32_ATAN(self
, v
):
545 # FIXME: use proper implementation
546 return fp32toselectable(math
.atan(float(v
)))
548 def bfp64_RECIP(self
, v
):
549 # FIXME: use proper implementation
550 return fp64toselectable(1 / float(v
))
552 def bfp32_RECIP(self
, v
):
553 # FIXME: use proper implementation
554 return fp32toselectable(1 / float(v
))
556 def bfp64_SINH(self
, v
):
557 # FIXME: use proper implementation
558 return fp64toselectable(math
.sinh(float(v
)))
560 def bfp32_SINH(self
, v
):
561 # FIXME: use proper implementation
562 return fp32toselectable(math
.sinh(float(v
)))
564 def bfp64_ASINH(self
, v
):
565 # FIXME: use proper implementation
566 return fp64toselectable(math
.asinh(float(v
)))
568 def bfp32_ASINH(self
, v
):
569 # FIXME: use proper implementation
570 return fp32toselectable(math
.asinh(float(v
)))
572 def bfp64_COSH(self
, v
):
573 # FIXME: use proper implementation
574 return fp64toselectable(math
.cosh(float(v
)))
576 def bfp32_COSH(self
, v
):
577 # FIXME: use proper implementation
578 return fp32toselectable(math
.cosh(float(v
)))
580 def bfp64_TANH(self
, v
):
581 # FIXME: use proper implementation
582 return fp64toselectable(math
.tanh(float(v
)))
584 def bfp32_TANH(self
, v
):
585 # FIXME: use proper implementation
586 return fp32toselectable(math
.tanh(float(v
)))
588 def bfp64_ACOSH(self
, v
):
589 # FIXME: use proper implementation
590 return fp64toselectable(math
.acosh(float(v
)))
592 def bfp32_ACOSH(self
, v
):
593 # FIXME: use proper implementation
594 return fp32toselectable(math
.acosh(float(v
)))
596 def bfp64_ATANH(self
, v
):
597 # FIXME: use proper implementation
598 return fp64toselectable(math
.atanh(float(v
)))
600 def bfp32_ATANH(self
, v
):
601 # FIXME: use proper implementation
602 return fp32toselectable(math
.atanh(float(v
)))
604 def bfp64_EXP2M1(self
, v
):
605 # FIXME: use proper implementation
606 return fp64toselectable(pow(2, float(v
)) - 1)
608 def bfp32_EXP2M1(self
, v
):
609 # FIXME: use proper implementation
610 return fp32toselectable(pow(2, float(v
)) - 1)
612 def bfp64_LOG2P1(self
, v
):
613 # FIXME: use proper implementation
614 return fp64toselectable(math
.log2(float(v
) + 1))
616 def bfp32_LOG2P1(self
, v
):
617 # FIXME: use proper implementation
618 return fp32toselectable(math
.log2(float(v
) + 1))
620 def bfp64_EXPM1(self
, v
):
621 # FIXME: use proper implementation
622 return fp64toselectable(math
.expm1(float(v
)))
624 def bfp32_EXPM1(self
, v
):
625 # FIXME: use proper implementation
626 return fp32toselectable(math
.expm1(float(v
)))
628 def bfp64_LOGP1(self
, v
):
629 # FIXME: use proper implementation
630 return fp64toselectable(math
.log1p(float(v
)))
632 def bfp32_LOGP1(self
, v
):
633 # FIXME: use proper implementation
634 return fp32toselectable(math
.log1p(float(v
)))
636 def bfp64_EXP10M1(self
, v
):
637 # FIXME: use proper implementation
638 return fp64toselectable(pow(10, float(v
)) - 1)
640 def bfp32_EXP10M1(self
, v
):
641 # FIXME: use proper implementation
642 return fp32toselectable(pow(10, float(v
)) - 1)
644 def bfp64_LOG10P1(self
, v
):
645 # FIXME: use proper implementation
646 return fp64toselectable(math
.log10(float(v
) + 1))
648 def bfp32_LOG10P1(self
, v
):
649 # FIXME: use proper implementation
650 return fp32toselectable(math
.log10(float(v
) + 1))
652 def bfp64_EXP2(self
, v
):
653 # FIXME: use proper implementation
654 return fp64toselectable(pow(2, float(v
)))
656 def bfp32_EXP2(self
, v
):
657 # FIXME: use proper implementation
658 return fp32toselectable(pow(2, float(v
)))
660 def bfp64_LOG2(self
, v
):
661 # FIXME: use proper implementation
662 return fp64toselectable(math
.log2(float(v
)))
664 def bfp32_LOG2(self
, v
):
665 # FIXME: use proper implementation
666 return fp32toselectable(math
.log2(float(v
)))
668 def bfp64_EXP(self
, v
):
669 # FIXME: use proper implementation
670 return fp64toselectable(math
.exp(float(v
)))
672 def bfp32_EXP(self
, v
):
673 # FIXME: use proper implementation
674 return fp32toselectable(math
.exp(float(v
)))
676 def bfp64_LOG(self
, v
):
677 # FIXME: use proper implementation
678 return fp64toselectable(math
.log(float(v
)))
680 def bfp32_LOG(self
, v
):
681 # FIXME: use proper implementation
682 return fp32toselectable(math
.log(float(v
)))
684 def bfp64_EXP10(self
, v
):
685 # FIXME: use proper implementation
686 return fp64toselectable(pow(10, float(v
)))
688 def bfp32_EXP10(self
, v
):
689 # FIXME: use proper implementation
690 return fp32toselectable(pow(10, float(v
)))
692 def bfp64_LOG10(self
, v
):
693 # FIXME: use proper implementation
694 return fp64toselectable(math
.log10(float(v
)))
696 def bfp32_LOG10(self
, v
):
697 # FIXME: use proper implementation
698 return fp32toselectable(math
.log10(float(v
)))
700 def FPADD32(self
, FRA
, FRB
):
701 # return FPADD64(FRA, FRB)
702 #FRA = DOUBLE(SINGLE(FRA))
703 #FRB = DOUBLE(SINGLE(FRB))
704 result
= float(FRA
) + float(FRB
)
705 cvt
= fp64toselectable(result
)
706 cvt
= self
.DOUBLE2SINGLE(cvt
)
707 log("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
710 def FPSUB32(self
, FRA
, FRB
):
711 # return FPSUB64(FRA, FRB)
712 #FRA = DOUBLE(SINGLE(FRA))
713 #FRB = DOUBLE(SINGLE(FRB))
714 result
= float(FRA
) - float(FRB
)
715 cvt
= fp64toselectable(result
)
716 cvt
= self
.DOUBLE2SINGLE(cvt
)
717 log("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
720 def FPMUL32(self
, FRA
, FRB
, sign
=1):
721 # return FPMUL64(FRA, FRB)
722 FRA
= self
.DOUBLE(SINGLE(FRA
))
723 FRB
= self
.DOUBLE(SINGLE(FRB
))
724 result
= signinv(float(FRA
) * float(FRB
), sign
)
725 log("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
726 cvt
= fp64toselectable(result
)
727 cvt
= self
.DOUBLE2SINGLE(cvt
)
731 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
732 # return FPMUL64(FRA, FRB)
733 #FRA = DOUBLE(SINGLE(FRA))
734 #FRB = DOUBLE(SINGLE(FRB))
737 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
739 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
742 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
744 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
747 log("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
748 log(" FRA", float(FRA
))
749 log(" FRC", float(FRC
))
750 log(" FRB", float(FRB
))
751 log(" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
752 cvt
= fp64toselectable(result
)
753 cvt
= self
.DOUBLE2SINGLE(cvt
)
757 def FPDIV32(self
, FRA
, FRB
, sign
=1):
758 # return FPDIV64(FRA, FRB)
759 #FRA = DOUBLE(SINGLE(FRA))
760 #FRB = DOUBLE(SINGLE(FRB))
761 result
= signinv(float(FRA
) / float(FRB
), sign
)
762 cvt
= fp64toselectable(result
)
763 cvt
= self
.DOUBLE2SINGLE(cvt
)
764 log("FPDIV32", FRA
, FRB
, result
, cvt
)
768 def FPADD64(FRA
, FRB
):
769 result
= float(FRA
) + float(FRB
)
770 cvt
= fp64toselectable(result
)
771 log("FPADD64", FRA
, FRB
, result
, cvt
)
775 def FPSUB64(FRA
, FRB
):
776 result
= float(FRA
) - float(FRB
)
777 cvt
= fp64toselectable(result
)
778 log("FPSUB64", FRA
, FRB
, result
, cvt
)
782 def FPMUL64(FRA
, FRB
, sign
=1):
783 result
= signinv(float(FRA
) * float(FRB
), sign
)
784 cvt
= fp64toselectable(result
)
785 log("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
789 def FPDIV64(FRA
, FRB
, sign
=1):
790 result
= signinv(float(FRA
) / float(FRB
), sign
)
791 cvt
= fp64toselectable(result
)
792 log("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
797 """Returns the integer whose value is the reverse of the lowest
798 'width' bits of the integer 'val'
801 width
= VL
.bit_length()-1
802 for _
in range(width
):
803 result
= (result
<< 1) |
(val
& 1)
809 """return the base-2 logarithm of `val`. Only works for powers of 2."""
810 if isinstance(val
, SelectableInt
):
812 retval
= val
.bit_length() - 1
813 assert val
== 2 ** retval
, "value is not a power of 2"
817 # BFP classification predicates
818 # these need to be implemented in python because they work with multiple
821 if isinstance(v
, BFPState
):
822 return onebit(v
.class_
.Infinity
)
823 # TODO: implement for SelectableInt/int
824 raise NotImplementedError("not yet implemented for non-BFPState values")
828 if isinstance(v
, BFPState
):
829 return onebit(v
.class_
.SNaN
or v
.class_
.QNaN
)
830 # TODO: implement for SelectableInt/int
831 raise NotImplementedError("not yet implemented for non-BFPState values")
835 if isinstance(v
, BFPState
):
836 if v
.class_
.SNaN
or v
.class_
.QNaN
or v
.class_
.Zero
:
838 return onebit(v
.sign
)
839 # TODO: implement for SelectableInt/int
840 raise NotImplementedError("not yet implemented for non-BFPState values")
844 if isinstance(v
, BFPState
):
845 return onebit(v
.class_
.SNaN
)
846 # TODO: implement for SelectableInt/int
847 raise NotImplementedError("not yet implemented for non-BFPState values")
851 if isinstance(v
, BFPState
):
852 return onebit(v
.class_
.Zero
)
853 # TODO: implement for SelectableInt/int
854 raise NotImplementedError("not yet implemented for non-BFPState values")
857 def SetFX(fpscr
, field
):
858 assert isinstance(fpscr
, FPSCRState
), "SetFX only works on FPSCR fields"
859 if eq(getattr(fpscr
, field
), SelectableInt(0, 1)):
860 setattr(fpscr
, field
, SelectableInt(1, 1))
861 fpscr
.FX
= SelectableInt(1, 1)
864 class ISACallerHelper
:
865 def __init__(self
, XLEN
, FPSCR
):
879 def EXTZXL(self
, value
, bits
=None):
882 elif isinstance(bits
, SelectableInt
):
884 if isinstance(value
, SelectableInt
):
886 return SelectableInt(value
& ((1 << bits
) - 1), self
.XLEN
)
888 def EXTSXL(self
, value
, bits
=None):
889 if isinstance(value
, SelectableInt
):
893 elif isinstance(bits
, SelectableInt
):
895 return SelectableInt(exts(value
, bits
), self
.XLEN
)
897 def DOUBLE2SINGLE(self
, FRS
):
898 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
899 implementation of the frsp instruction.
900 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
902 return self
.FRSP(FRS
)
904 def ROTL32(self
, value
, bits
):
905 if isinstance(bits
, SelectableInt
):
907 if isinstance(value
, SelectableInt
):
908 value
= SelectableInt(value
.value
, self
.XLEN
)
909 value
= value |
(value
<< (self
.XLEN
//2))
910 value
= rotl(value
, bits
, self
.XLEN
)
913 def ROTL128(self
, value
, bits
):
914 return rotl(value
, bits
, self
.XLEN
*2)
916 def ROTL64(self
, value
, bits
):
917 return rotl(value
, bits
, self
.XLEN
)
919 def MASK32(self
, x
, y
):
920 if isinstance(x
, SelectableInt
):
922 if isinstance(y
, SelectableInt
):
924 return self
.MASK(x
+(self
.XLEN
//2), y
+(self
.XLEN
//2))
926 def MASK(self
, x
, y
, lim
=None):
929 if isinstance(x
, SelectableInt
):
931 if isinstance(y
, SelectableInt
):
936 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
937 mask_b
= ((1 << y
) - 1) & ((1 << lim
) - 1)
939 return 1 << ((lim
-1)-x
)
943 mask_a
= ((1 << x
) - 1) & ((1 << lim
) - 1)
944 mask_b
= (~
((1 << y
) - 1)) & ((1 << lim
) - 1)
945 return mask_a ^ mask_b
947 def __getattr__(self
, attr
):
948 """workaround for getting function out of the global namespace
949 within this module, as a way to get functions being transitioned
950 to Helper classes within ISACaller (and therefore pseudocode)
953 return globals()[attr
]
955 raise AttributeError(attr
)
958 # For these tests I tried to find power instructions that would let me
959 # isolate each of these helper operations. So for instance, when I was
960 # testing the MASK() function, I chose rlwinm and rldicl because if I
961 # set the shift equal to 0 and passed in a value of all ones, the
962 # result I got would be exactly the same as the output of MASK()
964 class HelperTests(unittest
.TestCase
, ISACallerHelper
):
965 def __init__(self
, *args
, **kwargs
):
966 # TODO: dynamic (64/32/16/8)
967 ISACallerHelper
.__init
__(self
, 64, FPSCR
=None)
968 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
971 # Verified using rlwinm, rldicl, rldicr in qemu
973 # rlwinm reg, 1, 0, 5, 15
974 self
.assertHex(self
.MASK(5+32, 15+32), 0x7ff0000)
975 # rlwinm reg, 1, 0, 15, 5
976 self
.assertHex(self
.MASK(15+32, 5+32), 0xfffffffffc01ffff)
977 self
.assertHex(self
.MASK(30+32, 2+32), 0xffffffffe0000003)
978 # rldicl reg, 1, 0, 37
979 self
.assertHex(self
.MASK(37, 63), 0x7ffffff)
980 self
.assertHex(self
.MASK(10, 63), 0x3fffffffffffff)
981 self
.assertHex(self
.MASK(58, 63), 0x3f)
982 # rldicr reg, 1, 0, 37
983 self
.assertHex(self
.MASK(0, 37), 0xfffffffffc000000)
984 self
.assertHex(self
.MASK(0, 10), 0xffe0000000000000)
985 self
.assertHex(self
.MASK(0, 58), 0xffffffffffffffe0)
989 self
.assertHex(self
.MASK(32, 63-5), 0xffffffe0)
991 self
.assertHex(self
.MASK(32, 33), 0xc0000000)
992 self
.assertHex(self
.MASK(32, 32), 0x80000000)
993 self
.assertHex(self
.MASK(33, 33), 0x40000000)
995 def test_ROTL64(self
):
996 # r1 = 0xdeadbeef12345678
997 value
= 0xdeadbeef12345678
999 # rldicl reg, 1, 10, 0
1000 self
.assertHex(self
.ROTL64(value
, 10), 0xb6fbbc48d159e37a)
1001 # rldicl reg, 1, 35, 0
1002 self
.assertHex(self
.ROTL64(value
, 35), 0x91a2b3c6f56df778)
1003 self
.assertHex(self
.ROTL64(value
, 58), 0xe37ab6fbbc48d159)
1004 self
.assertHex(self
.ROTL64(value
, 22), 0xbbc48d159e37ab6f)
1006 def test_ROTL32(self
):
1008 value
= SelectableInt(0xdeadbeef, self
.XLEN
)
1010 # rlwinm reg, 1, 10, 0, 31
1011 self
.assertHex(self
.ROTL32(value
, 10), 0xb6fbbf7a)
1012 # rlwinm reg, 1, 17, 0, 31
1013 self
.assertHex(self
.ROTL32(value
, 17), 0x7ddfbd5b)
1014 self
.assertHex(self
.ROTL32(value
, 25), 0xdfbd5b7d)
1015 self
.assertHex(self
.ROTL32(value
, 30), 0xf7ab6fbb)
1017 def test_EXTS64(self
):
1018 value_a
= SelectableInt(0xdeadbeef, 32) # r1
1019 value_b
= SelectableInt(0x73123456, 32) # r2
1020 value_c
= SelectableInt(0x80000000, 32) # r3
1022 # extswsli reg, 1, 0
1023 self
.assertHex(self
.EXTS64(value_a
), 0xffffffffdeadbeef)
1024 # extswsli reg, 2, 0
1025 self
.assertHex(self
.EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
1026 # extswsli reg, 3, 0
1027 self
.assertHex(self
.EXTS64(value_c
), 0xffffffff80000000)
1029 def test_FPADD32(self
):
1030 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
1031 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1032 result
= FPADD32(value_a
, value_b
)
1033 self
.assertHex(0x4040266666666666, result
)
1035 def assertHex(self
, a
, b
):
1037 if isinstance(a
, SelectableInt
):
1040 if isinstance(b
, SelectableInt
):
1042 msg
= "{:x} != {:x}".format(a_val
, b_val
)
1043 return self
.assertEqual(a
, b
, msg
)
1047 if __name__
== '__main__':
1048 log(SelectableInt
.__bases
__)