4 from openpower
.decoder
.selectable_int
import (SelectableInt
, onebit
,
6 from nmutil
.divmod import trunc_divs
, trunc_rems
7 from operator
import floordiv
, mod
8 from openpower
.decoder
.selectable_int
import selectltu
as ltu
9 from openpower
.decoder
.selectable_int
import selectgtu
as gtu
10 from openpower
.decoder
.selectable_int
import check_extsign
12 from openpower
.util
import log
22 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
23 * https://bugs.libre-soc.org/show_bug.cgi?id=671#c38 - RANGE (and bugfixes)
27 def RANGE(start
, end
):
30 # auto-subtract-one (sigh) due to python range
31 return range(start
, end
-1, -1)
32 # auto-add-one (sigh) due to python range
33 return range(start
, end
+1)
36 def exts(value
, bits
):
37 sign
= 1 << (bits
- 1)
38 return (value
& (sign
- 1)) - (value
& sign
)
42 """ extends sign bit out from current MSB to all 256 bits
44 log("EXTS", value
, type(value
))
45 assert isinstance(value
, SelectableInt
)
46 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
50 """ extends sign bit out from current MSB to 64 bits
52 assert isinstance(value
, SelectableInt
)
53 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
57 """ extends sign bit out from current MSB to 128 bits
59 assert isinstance(value
, SelectableInt
)
60 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
63 # signed version of MUL
65 if isinstance(b
, int):
66 b
= SelectableInt(b
, self
.bits
)
67 b
= check_extsign(a
, b
)
68 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
69 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
70 result
= abs(a
) * abs(b
)
71 log("MULS", result
, a_s
, b_s
)
77 # XXX should this explicitly extend from 32 to 64?
79 if isinstance(value
, SelectableInt
):
81 return SelectableInt(value
& ((1 << 32)-1), 64)
84 def rotl(value
, bits
, wordlen
):
85 if isinstance(bits
, SelectableInt
):
87 mask
= (1 << wordlen
) - 1
88 bits
= bits
& (wordlen
- 1)
89 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
92 def SHL64(value
, bits
, wordlen
=64):
93 if isinstance(bits
, SelectableInt
):
95 mask
= (1 << wordlen
) - 1
96 bits
= bits
& (wordlen
- 1)
97 return SelectableInt((value
<< bits
) & mask
, 64)
100 def ROTL64(value
, bits
):
101 return rotl(value
, bits
, 64)
104 def ROTL32(value
, bits
):
105 if isinstance(bits
, SelectableInt
):
107 if isinstance(value
, SelectableInt
):
108 value
= SelectableInt(value
.value
, 64)
109 return rotl(value |
(value
<< 32), bits
, 64)
113 if isinstance(x
, SelectableInt
):
115 if isinstance(y
, SelectableInt
):
117 return MASK(x
+32, y
+32)
121 if isinstance(x
, SelectableInt
):
123 if isinstance(y
, SelectableInt
):
128 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
129 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
135 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
136 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
137 return mask_a ^ mask_b
141 return onebit(a
!= b
)
145 return onebit(a
== b
)
153 return onebit(a
>= b
)
161 return onebit(a
<= b
)
169 """ function that, for Power spec purposes, returns undefined bits of
170 the same shape as the input bits. however, for purposes of matching
171 POWER9's behavior returns the input bits unchanged. this effectively
172 "marks" (tags) locations in the v3.0B spec that need to be submitted
179 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
181 # result - WORD - start off all zeros
182 WORD
= SelectableInt(0, 32)
189 log("s e m", s
.value
, e
.value
, m
.value
)
191 # No Denormalization Required (includes Zero / Infinity / NaN)
192 if e
.value
> 896 or FRS
[1:64].value
== 0:
193 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
195 WORD
[2:32] = FRS
[5:35]
197 # Denormalization Required
198 if e
.value
>= 874 and e
.value
<= 896:
201 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
202 log("exp, fract", exp
, hex(frac
.value
))
203 # denormalize operand
205 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
208 WORD
[1:9] = SelectableInt(0, 8)
209 WORD
[9:32] = frac
[1:24]
210 # else WORD = undefined # return zeros
216 # XXX NOTE: these are very quick hacked functions for utterly basic
220 def signinv(res
, sign
):
229 def fp32toselectable(flt
):
230 """convert FP number to 32 bit SelectableInt
232 b
= struct
.pack("<f", flt
)
233 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
234 return SelectableInt(val
, 32)
237 def fp64toselectable(flt
):
238 """convert FP number to 64 bit SelectableInt
240 b
= struct
.pack("<d", flt
)
241 val
= int.from_bytes(b
, byteorder
='little', signed
=False)
242 return SelectableInt(val
, 64)
262 # bfp32/64_OP naming mirrors that in the Power ISA spec.
264 def bfp64_ATAN2PI(self
, a
, b
):
265 # FIXME: use proper implementation
266 return fp64toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
268 def bfp32_ATAN2PI(self
, a
, b
):
269 # FIXME: use proper implementation
270 return fp32toselectable(math
.atan2(float(a
), float(b
)) / math
.pi
)
272 def bfp64_ATAN2(self
, a
, b
):
273 # FIXME: use proper implementation
274 return fp64toselectable(math
.atan2(float(a
), float(b
)))
276 def bfp32_ATAN2(self
, a
, b
):
277 # FIXME: use proper implementation
278 return fp32toselectable(math
.atan2(float(a
), float(b
)))
280 def bfp64_HYPOT(self
, a
, b
):
281 # FIXME: use proper implementation
282 return fp64toselectable(math
.hypot(float(a
), float(b
)))
284 def bfp32_HYPOT(self
, a
, b
):
285 # FIXME: use proper implementation
286 return fp32toselectable(math
.hypot(float(a
), float(b
)))
288 def bfp64_MINNUM08(self
, a
, b
):
289 # FIXME: use proper implementation
290 return fp64toselectable(min(float(a
), float(b
)))
292 def bfp32_MINNUM08(self
, a
, b
):
293 # FIXME: use proper implementation
294 return fp32toselectable(min(float(a
), float(b
)))
296 def bfp64_MIN19(self
, a
, b
):
297 # FIXME: use proper implementation
298 return fp64toselectable(min(float(a
), float(b
)))
300 def bfp32_MIN19(self
, a
, b
):
301 # FIXME: use proper implementation
302 return fp32toselectable(min(float(a
), float(b
)))
304 def bfp64_MINNUM19(self
, a
, b
):
305 # FIXME: use proper implementation
306 return fp64toselectable(min(float(a
), float(b
)))
308 def bfp32_MINNUM19(self
, a
, b
):
309 # FIXME: use proper implementation
310 return fp32toselectable(min(float(a
), float(b
)))
312 def bfp64_MINC(self
, a
, b
):
313 # FIXME: use proper implementation
314 return fp64toselectable(min(float(a
), float(b
)))
316 def bfp32_MINC(self
, a
, b
):
317 # FIXME: use proper implementation
318 return fp32toselectable(min(float(a
), float(b
)))
320 def bfp64_MAXNUM08(self
, a
, b
):
321 # FIXME: use proper implementation
322 return fp64toselectable(max(float(a
), float(b
)))
324 def bfp32_MAXNUM08(self
, a
, b
):
325 # FIXME: use proper implementation
326 return fp32toselectable(max(float(a
), float(b
)))
328 def bfp64_MAX19(self
, a
, b
):
329 # FIXME: use proper implementation
330 return fp64toselectable(max(float(a
), float(b
)))
332 def bfp32_MAX19(self
, a
, b
):
333 # FIXME: use proper implementation
334 return fp32toselectable(max(float(a
), float(b
)))
336 def bfp64_MAXNUM19(self
, a
, b
):
337 # FIXME: use proper implementation
338 return fp64toselectable(max(float(a
), float(b
)))
340 def bfp32_MAXNUM19(self
, a
, b
):
341 # FIXME: use proper implementation
342 return fp32toselectable(max(float(a
), float(b
)))
344 def bfp64_MAXC(self
, a
, b
):
345 # FIXME: use proper implementation
346 return fp64toselectable(max(float(a
), float(b
)))
348 def bfp32_MAXC(self
, a
, b
):
349 # FIXME: use proper implementation
350 return fp32toselectable(max(float(a
), float(b
)))
352 def bfp64_MINMAGNUM08(self
, a
, b
):
353 # FIXME: use proper implementation
354 return fp64toselectable(_minmag(float(a
), float(b
)))
356 def bfp32_MINMAGNUM08(self
, a
, b
):
357 # FIXME: use proper implementation
358 return fp32toselectable(_minmag(float(a
), float(b
)))
360 def bfp64_MAXMAGNUM08(self
, a
, b
):
361 # FIXME: use proper implementation
362 return fp64toselectable(_maxmag(float(a
), float(b
)))
364 def bfp32_MAXMAGNUM08(self
, a
, b
):
365 # FIXME: use proper implementation
366 return fp32toselectable(_maxmag(float(a
), float(b
)))
368 def bfp64_MOD(self
, a
, b
):
369 # FIXME: use proper implementation
370 return fp64toselectable(math
.fmod(float(a
), float(b
)))
372 def bfp32_MOD(self
, a
, b
):
373 # FIXME: use proper implementation
374 return fp32toselectable(math
.fmod(float(a
), float(b
)))
376 def bfp64_MINMAG19(self
, a
, b
):
377 # FIXME: use proper implementation
378 return fp64toselectable(_minmag(float(a
), float(b
)))
380 def bfp32_MINMAG19(self
, a
, b
):
381 # FIXME: use proper implementation
382 return fp32toselectable(_minmag(float(a
), float(b
)))
384 def bfp64_MAXMAG19(self
, a
, b
):
385 # FIXME: use proper implementation
386 return fp64toselectable(_maxmag(float(a
), float(b
)))
388 def bfp32_MAXMAG19(self
, a
, b
):
389 # FIXME: use proper implementation
390 return fp32toselectable(_maxmag(float(a
), float(b
)))
392 def bfp64_MINMAGNUM19(self
, a
, b
):
393 # FIXME: use proper implementation
394 return fp64toselectable(_minmag(float(a
), float(b
)))
396 def bfp32_MINMAGNUM19(self
, a
, b
):
397 # FIXME: use proper implementation
398 return fp32toselectable(_minmag(float(a
), float(b
)))
400 def bfp64_MAXMAGNUM19(self
, a
, b
):
401 # FIXME: use proper implementation
402 return fp64toselectable(_maxmag(float(a
), float(b
)))
404 def bfp32_MAXMAGNUM19(self
, a
, b
):
405 # FIXME: use proper implementation
406 return fp32toselectable(_maxmag(float(a
), float(b
)))
408 def bfp64_REMAINDER(self
, a
, b
):
409 # FIXME: use proper implementation
410 return fp64toselectable(math
.remainder(float(a
), float(b
)))
412 def bfp32_REMAINDER(self
, a
, b
):
413 # FIXME: use proper implementation
414 return fp32toselectable(math
.remainder(float(a
), float(b
)))
416 def bfp64_POWR(self
, a
, b
):
417 # FIXME: use proper implementation
418 return fp64toselectable(pow(float(a
), float(b
)))
420 def bfp32_POWR(self
, a
, b
):
421 # FIXME: use proper implementation
422 return fp32toselectable(pow(float(a
), float(b
)))
424 def bfp64_POW(self
, a
, b
):
425 # FIXME: use proper implementation
426 return fp64toselectable(pow(float(a
), float(b
)))
428 def bfp32_POW(self
, a
, b
):
429 # FIXME: use proper implementation
430 return fp32toselectable(pow(float(a
), float(b
)))
432 def bfp64_MINMAGC(self
, a
, b
):
433 # FIXME: use proper implementation
434 return fp64toselectable(_minmag(float(a
), float(b
)))
436 def bfp32_MINMAGC(self
, a
, b
):
437 # FIXME: use proper implementation
438 return fp32toselectable(_minmag(float(a
), float(b
)))
440 def bfp64_MAXMAGC(self
, a
, b
):
441 # FIXME: use proper implementation
442 return fp64toselectable(_maxmag(float(a
), float(b
)))
444 def bfp32_MAXMAGC(self
, a
, b
):
445 # FIXME: use proper implementation
446 return fp32toselectable(_maxmag(float(a
), float(b
)))
448 def bfp64_POWN(self
, a
, b
):
449 # FIXME: use proper implementation
450 return fp64toselectable(pow(float(a
), int(b
)))
452 def bfp32_POWN(self
, a
, b
):
453 # FIXME: use proper implementation
454 return fp32toselectable(pow(float(a
), int(b
)))
456 def bfp64_ROOTN(self
, a
, b
):
457 # FIXME: use proper implementation
458 return fp64toselectable(pow(float(a
), 1 / int(b
)))
460 def bfp32_ROOTN(self
, a
, b
):
461 # FIXME: use proper implementation
462 return fp32toselectable(pow(float(a
), 1 / int(b
)))
464 def bfp64_CBRT(self
, v
):
465 # FIXME: use proper implementation
466 return fp64toselectable(pow(float(v
), 1 / 3))
468 def bfp32_CBRT(self
, v
):
469 # FIXME: use proper implementation
470 return fp32toselectable(pow(float(v
), 1 / 3))
472 def bfp64_SINPI(self
, v
):
473 # FIXME: use proper implementation
474 return fp64toselectable(math
.sin(float(v
) * math
.pi
))
476 def bfp32_SINPI(self
, v
):
477 # FIXME: use proper implementation
478 return fp32toselectable(math
.sin(float(v
) * math
.pi
))
480 def bfp64_ASINPI(self
, v
):
481 # FIXME: use proper implementation
482 return fp64toselectable(math
.asin(float(v
)) / math
.pi
)
484 def bfp32_ASINPI(self
, v
):
485 # FIXME: use proper implementation
486 return fp32toselectable(math
.asin(float(v
)) / math
.pi
)
488 def bfp64_COSPI(self
, v
):
489 # FIXME: use proper implementation
490 return fp64toselectable(math
.cos(float(v
) * math
.pi
))
492 def bfp32_COSPI(self
, v
):
493 # FIXME: use proper implementation
494 return fp32toselectable(math
.cos(float(v
) * math
.pi
))
496 def bfp64_TANPI(self
, v
):
497 # FIXME: use proper implementation
498 return fp64toselectable(math
.tan(float(v
) * math
.pi
))
500 def bfp32_TANPI(self
, v
):
501 # FIXME: use proper implementation
502 return fp32toselectable(math
.tan(float(v
) * math
.pi
))
504 def bfp64_ACOSPI(self
, v
):
505 # FIXME: use proper implementation
506 return fp64toselectable(math
.acos(float(v
)) / math
.pi
)
508 def bfp32_ACOSPI(self
, v
):
509 # FIXME: use proper implementation
510 return fp32toselectable(math
.acos(float(v
)) / math
.pi
)
512 def bfp64_ATANPI(self
, v
):
513 # FIXME: use proper implementation
514 return fp64toselectable(math
.atan(float(v
)) / math
.pi
)
516 def bfp32_ATANPI(self
, v
):
517 # FIXME: use proper implementation
518 return fp32toselectable(math
.atan(float(v
)) / math
.pi
)
520 def bfp64_RSQRT(self
, v
):
521 # FIXME: use proper implementation
522 return fp64toselectable(1 / math
.sqrt(float(v
)))
524 def bfp32_RSQRT(self
, v
):
525 # FIXME: use proper implementation
526 return fp32toselectable(1 / math
.sqrt(float(v
)))
528 def bfp64_SIN(self
, v
):
529 # FIXME: use proper implementation
530 return fp64toselectable(math
.sin(float(v
)))
532 def bfp32_SIN(self
, v
):
533 # FIXME: use proper implementation
534 return fp32toselectable(math
.sin(float(v
)))
536 def bfp64_ASIN(self
, v
):
537 # FIXME: use proper implementation
538 return fp64toselectable(math
.asin(float(v
)))
540 def bfp32_ASIN(self
, v
):
541 # FIXME: use proper implementation
542 return fp32toselectable(math
.asin(float(v
)))
544 def bfp64_COS(self
, v
):
545 # FIXME: use proper implementation
546 return fp64toselectable(math
.cos(float(v
)))
548 def bfp32_COS(self
, v
):
549 # FIXME: use proper implementation
550 return fp32toselectable(math
.cos(float(v
)))
552 def bfp64_TAN(self
, v
):
553 # FIXME: use proper implementation
554 return fp64toselectable(math
.tan(float(v
)))
556 def bfp32_TAN(self
, v
):
557 # FIXME: use proper implementation
558 return fp32toselectable(math
.tan(float(v
)))
560 def bfp64_ACOS(self
, v
):
561 # FIXME: use proper implementation
562 return fp64toselectable(math
.acos(float(v
)))
564 def bfp32_ACOS(self
, v
):
565 # FIXME: use proper implementation
566 return fp32toselectable(math
.acos(float(v
)))
568 def bfp64_ATAN(self
, v
):
569 # FIXME: use proper implementation
570 return fp64toselectable(math
.atan(float(v
)))
572 def bfp32_ATAN(self
, v
):
573 # FIXME: use proper implementation
574 return fp32toselectable(math
.atan(float(v
)))
576 def bfp64_RECIP(self
, v
):
577 # FIXME: use proper implementation
578 return fp64toselectable(1 / float(v
))
580 def bfp32_RECIP(self
, v
):
581 # FIXME: use proper implementation
582 return fp32toselectable(1 / float(v
))
584 def bfp64_SINH(self
, v
):
585 # FIXME: use proper implementation
586 return fp64toselectable(math
.sinh(float(v
)))
588 def bfp32_SINH(self
, v
):
589 # FIXME: use proper implementation
590 return fp32toselectable(math
.sinh(float(v
)))
592 def bfp64_ASINH(self
, v
):
593 # FIXME: use proper implementation
594 return fp64toselectable(math
.asinh(float(v
)))
596 def bfp32_ASINH(self
, v
):
597 # FIXME: use proper implementation
598 return fp32toselectable(math
.asinh(float(v
)))
600 def bfp64_COSH(self
, v
):
601 # FIXME: use proper implementation
602 return fp64toselectable(math
.cosh(float(v
)))
604 def bfp32_COSH(self
, v
):
605 # FIXME: use proper implementation
606 return fp32toselectable(math
.cosh(float(v
)))
608 def bfp64_TANH(self
, v
):
609 # FIXME: use proper implementation
610 return fp64toselectable(math
.tanh(float(v
)))
612 def bfp32_TANH(self
, v
):
613 # FIXME: use proper implementation
614 return fp32toselectable(math
.tanh(float(v
)))
616 def bfp64_ACOSH(self
, v
):
617 # FIXME: use proper implementation
618 return fp64toselectable(math
.acosh(float(v
)))
620 def bfp32_ACOSH(self
, v
):
621 # FIXME: use proper implementation
622 return fp32toselectable(math
.acosh(float(v
)))
624 def bfp64_ATANH(self
, v
):
625 # FIXME: use proper implementation
626 return fp64toselectable(math
.atanh(float(v
)))
628 def bfp32_ATANH(self
, v
):
629 # FIXME: use proper implementation
630 return fp32toselectable(math
.atanh(float(v
)))
632 def bfp64_EXP2M1(self
, v
):
633 # FIXME: use proper implementation
634 return fp64toselectable(pow(2, float(v
)) - 1)
636 def bfp32_EXP2M1(self
, v
):
637 # FIXME: use proper implementation
638 return fp32toselectable(pow(2, float(v
)) - 1)
640 def bfp64_LOG2P1(self
, v
):
641 # FIXME: use proper implementation
642 return fp64toselectable(math
.log2(float(v
) + 1))
644 def bfp32_LOG2P1(self
, v
):
645 # FIXME: use proper implementation
646 return fp32toselectable(math
.log2(float(v
) + 1))
648 def bfp64_EXPM1(self
, v
):
649 # FIXME: use proper implementation
650 return fp64toselectable(math
.expm1(float(v
)))
652 def bfp32_EXPM1(self
, v
):
653 # FIXME: use proper implementation
654 return fp32toselectable(math
.expm1(float(v
)))
656 def bfp64_LOGP1(self
, v
):
657 # FIXME: use proper implementation
658 return fp64toselectable(math
.log1p(float(v
)))
660 def bfp32_LOGP1(self
, v
):
661 # FIXME: use proper implementation
662 return fp32toselectable(math
.log1p(float(v
)))
664 def bfp64_EXP10M1(self
, v
):
665 # FIXME: use proper implementation
666 return fp64toselectable(pow(10, float(v
)) - 1)
668 def bfp32_EXP10M1(self
, v
):
669 # FIXME: use proper implementation
670 return fp32toselectable(pow(10, float(v
)) - 1)
672 def bfp64_LOG10P1(self
, v
):
673 # FIXME: use proper implementation
674 return fp64toselectable(math
.log10(float(v
) + 1))
676 def bfp32_LOG10P1(self
, v
):
677 # FIXME: use proper implementation
678 return fp32toselectable(math
.log10(float(v
) + 1))
680 def bfp64_EXP2(self
, v
):
681 # FIXME: use proper implementation
682 return fp64toselectable(pow(2, float(v
)))
684 def bfp32_EXP2(self
, v
):
685 # FIXME: use proper implementation
686 return fp32toselectable(pow(2, float(v
)))
688 def bfp64_LOG2(self
, v
):
689 # FIXME: use proper implementation
690 return fp64toselectable(math
.log2(float(v
)))
692 def bfp32_LOG2(self
, v
):
693 # FIXME: use proper implementation
694 return fp32toselectable(math
.log2(float(v
)))
696 def bfp64_EXP(self
, v
):
697 # FIXME: use proper implementation
698 return fp64toselectable(math
.exp(float(v
)))
700 def bfp32_EXP(self
, v
):
701 # FIXME: use proper implementation
702 return fp32toselectable(math
.exp(float(v
)))
704 def bfp64_LOG(self
, v
):
705 # FIXME: use proper implementation
706 return fp64toselectable(math
.log(float(v
)))
708 def bfp32_LOG(self
, v
):
709 # FIXME: use proper implementation
710 return fp32toselectable(math
.log(float(v
)))
712 def bfp64_EXP10(self
, v
):
713 # FIXME: use proper implementation
714 return fp64toselectable(pow(10, float(v
)))
716 def bfp32_EXP10(self
, v
):
717 # FIXME: use proper implementation
718 return fp32toselectable(pow(10, float(v
)))
720 def bfp64_LOG10(self
, v
):
721 # FIXME: use proper implementation
722 return fp64toselectable(math
.log10(float(v
)))
724 def bfp32_LOG10(self
, v
):
725 # FIXME: use proper implementation
726 return fp32toselectable(math
.log10(float(v
)))
728 def FPADD32(self
, FRA
, FRB
):
729 # return FPADD64(FRA, FRB)
730 #FRA = DOUBLE(SINGLE(FRA))
731 #FRB = DOUBLE(SINGLE(FRB))
732 result
= float(FRA
) + float(FRB
)
733 cvt
= fp64toselectable(result
)
734 cvt
= self
.DOUBLE2SINGLE(cvt
)
735 log("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
738 def FPSUB32(self
, FRA
, FRB
):
739 # return FPSUB64(FRA, FRB)
740 #FRA = DOUBLE(SINGLE(FRA))
741 #FRB = DOUBLE(SINGLE(FRB))
742 result
= float(FRA
) - float(FRB
)
743 cvt
= fp64toselectable(result
)
744 cvt
= self
.DOUBLE2SINGLE(cvt
)
745 log("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
748 def FPMUL32(self
, FRA
, FRB
, sign
=1):
749 # return FPMUL64(FRA, FRB)
750 FRA
= self
.DOUBLE(SINGLE(FRA
))
751 FRB
= self
.DOUBLE(SINGLE(FRB
))
752 result
= signinv(float(FRA
) * float(FRB
), sign
)
753 log("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
754 cvt
= fp64toselectable(result
)
755 cvt
= self
.DOUBLE2SINGLE(cvt
)
759 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
760 # return FPMUL64(FRA, FRB)
761 #FRA = DOUBLE(SINGLE(FRA))
762 #FRB = DOUBLE(SINGLE(FRB))
765 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
767 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
770 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
772 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
775 log("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
776 log(" FRA", float(FRA
))
777 log(" FRC", float(FRC
))
778 log(" FRB", float(FRB
))
779 log(" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
780 cvt
= fp64toselectable(result
)
781 cvt
= self
.DOUBLE2SINGLE(cvt
)
785 def FPDIV32(self
, FRA
, FRB
, sign
=1):
786 # return FPDIV64(FRA, FRB)
787 #FRA = DOUBLE(SINGLE(FRA))
788 #FRB = DOUBLE(SINGLE(FRB))
789 result
= signinv(float(FRA
) / float(FRB
), sign
)
790 cvt
= fp64toselectable(result
)
791 cvt
= self
.DOUBLE2SINGLE(cvt
)
792 log("FPDIV32", FRA
, FRB
, result
, cvt
)
796 def FPADD64(FRA
, FRB
):
797 result
= float(FRA
) + float(FRB
)
798 cvt
= fp64toselectable(result
)
799 log("FPADD64", FRA
, FRB
, result
, cvt
)
803 def FPSUB64(FRA
, FRB
):
804 result
= float(FRA
) - float(FRB
)
805 cvt
= fp64toselectable(result
)
806 log("FPSUB64", FRA
, FRB
, result
, cvt
)
810 def FPMUL64(FRA
, FRB
, sign
=1):
811 result
= signinv(float(FRA
) * float(FRB
), sign
)
812 cvt
= fp64toselectable(result
)
813 log("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
817 def FPDIV64(FRA
, FRB
, sign
=1):
818 result
= signinv(float(FRA
) / float(FRB
), sign
)
819 cvt
= fp64toselectable(result
)
820 log("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
825 """Returns the integer whose value is the reverse of the lowest
826 'width' bits of the integer 'val'
829 width
= VL
.bit_length()-1
830 for _
in range(width
):
831 result
= (result
<< 1) |
(val
& 1)
837 """return the base-2 logarithm of `val`. Only works for powers of 2."""
838 if isinstance(val
, SelectableInt
):
840 retval
= val
.bit_length() - 1
841 assert val
== 2 ** retval
, "value is not a power of 2"
845 # For these tests I tried to find power instructions that would let me
846 # isolate each of these helper operations. So for instance, when I was
847 # testing the MASK() function, I chose rlwinm and rldicl because if I
848 # set the shift equal to 0 and passed in a value of all ones, the
849 # result I got would be exactly the same as the output of MASK()
852 class HelperTests(unittest
.TestCase
):
854 # Verified using rlwinm, rldicl, rldicr in qemu
856 # rlwinm reg, 1, 0, 5, 15
857 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
858 # rlwinm reg, 1, 0, 15, 5
859 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
860 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
861 # rldicl reg, 1, 0, 37
862 self
.assertHex(MASK(37, 63), 0x7ffffff)
863 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
864 self
.assertHex(MASK(58, 63), 0x3f)
865 # rldicr reg, 1, 0, 37
866 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
867 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
868 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
872 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
874 self
.assertHex(MASK(32, 33), 0xc0000000)
875 self
.assertHex(MASK(32, 32), 0x80000000)
876 self
.assertHex(MASK(33, 33), 0x40000000)
878 def test_ROTL64(self
):
879 # r1 = 0xdeadbeef12345678
880 value
= 0xdeadbeef12345678
882 # rldicl reg, 1, 10, 0
883 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
884 # rldicl reg, 1, 35, 0
885 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
886 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
887 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
889 def test_ROTL32(self
):
893 # rlwinm reg, 1, 10, 0, 31
894 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
895 # rlwinm reg, 1, 17, 0, 31
896 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
897 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
898 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
900 def test_EXTS64(self
):
901 value_a
= SelectableInt(0xdeadbeef, 32) # r1
902 value_b
= SelectableInt(0x73123456, 32) # r2
903 value_c
= SelectableInt(0x80000000, 32) # r3
906 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
908 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
910 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
912 def test_FPADD32(self
):
913 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
914 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
915 result
= FPADD32(value_a
, value_b
)
916 self
.assertHex(0x4040266666666666, result
)
918 def assertHex(self
, a
, b
):
920 if isinstance(a
, SelectableInt
):
923 if isinstance(b
, SelectableInt
):
925 msg
= "{:x} != {:x}".format(a_val
, b_val
)
926 return self
.assertEqual(a
, b
, msg
)
929 class ISACallerHelper
:
930 def __init__(self
, XLEN
):
937 def XLCASTS(self
, value
):
938 return SelectableInt(exts(value
.value
, self
.XLEN
), self
.XLEN
)
940 def XLCASTU(self
, value
):
941 # SelectableInt already takes care of masking out the bits
942 return SelectableInt(value
.value
, self
.XLEN
)
944 def EXTSXL(self
, value
, bits
):
945 return SelectableInt(exts(value
.value
, bits
), self
.XLEN
)
947 def DOUBLE2SINGLE(self
, FRS
):
948 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
949 implementation of the frsp instruction.
950 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
953 'UE': SelectableInt(0, 1),
954 'OE': SelectableInt(0, 1),
955 'RN': SelectableInt(0, 2), # round to nearest, ties to even
956 'XX': SelectableInt(0, 1),
958 FRT
, FPSCR
= self
.FRSP(FRS
, FPSCR
)
961 def __getattr__(self
, attr
):
963 return globals()[attr
]
965 raise AttributeError(attr
)
968 if __name__
== '__main__':
969 log(SelectableInt
.__bases
__)