Revert "skip broken test"
[openpower-isa.git] / src / openpower / decoder / helpers.py
1 import unittest
2 import struct
3 import sys
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)
15
16 from openpower.util import log
17 import math
18
19 trunc_div = floordiv
20 trunc_rem = mod
21 DIVS = trunc_divs
22 MODS = trunc_rems
23
24 """
25 Links:
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)
28 """
29
30
31 def RANGE(start, end):
32 if start > end:
33 # reverse direction
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)
38
39
40 def exts(value, bits):
41 sign = 1 << (bits - 1)
42 return (value & (sign - 1)) - (value & sign)
43
44
45 def EXTS(value):
46 """ extends sign bit out from current MSB to MAX limit bits
47 """
48 log("EXTS", value, type(value))
49 assert isinstance(value, SelectableInt)
50 return SelectableInt(exts(value.value, value.bits) & ((1 << EU)-1), EU)
51
52
53 def EXTZ(value):
54 """ zero extend to EFFECTIVELY_UNLIMITED bits
55 """
56 if isinstance(value, SelectableInt):
57 value = value.value
58 return SelectableInt(value & ((1 << EU) - 1), EU)
59
60
61 def EXTS64(value):
62 """ extends sign bit out from current MSB to 64 bits
63 """
64 assert isinstance(value, SelectableInt)
65 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
66
67
68 def EXTS128(value):
69 """ extends sign bit out from current MSB to 128 bits
70 """
71 assert isinstance(value, SelectableInt)
72 return SelectableInt(exts(value.value, value.bits) & ((1 << 128)-1), 128)
73
74
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.
79
80 Example:
81 ```
82 # this needs to copy the SelectableInt instance in RA
83 # not just assign a reference to it to A
84 A <- RA
85 A[0] <- 1 # if the copy wasn't performed, we just modified RA too!
86 ```
87 """
88 if isinstance(inp, (str, int)):
89 return inp
90 if isinstance(inp, (SelectableInt, FieldSelectableInt)):
91 return SelectableInt(inp)
92 if isinstance(inp, BFPState):
93 return BFPState(inp)
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",
101 repr(type(inp)))
102
103
104 # signed version of MUL
105 def MULS(a, b):
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)
113 if a_s == b_s:
114 return result
115 return -result
116
117
118 # XXX should this explicitly extend from 32 to 64?
119 def EXTZ64(value):
120 if isinstance(value, SelectableInt):
121 value = value.value
122 return SelectableInt(value & ((1 << 32)-1), 64)
123
124
125 def rotl(value, bits, wordlen):
126 if isinstance(bits, SelectableInt):
127 bits = bits.value
128 mask = (1 << wordlen) - 1
129 bits = bits & (wordlen - 1)
130 return ((value << bits) | (value >> (wordlen-bits))) & mask
131
132
133 def SHL64(value, bits, wordlen=64):
134 if isinstance(bits, SelectableInt):
135 bits = bits.value
136 mask = (1 << wordlen) - 1
137 bits = bits & (wordlen - 1)
138 return SelectableInt((value << bits) & mask, 64)
139
140
141 def ne(a, b):
142 return onebit(a != b)
143
144
145 def eq(a, b):
146 return onebit(a == b)
147
148
149 def gt(a, b):
150 return onebit(a > b)
151
152
153 def ge(a, b):
154 return onebit(a >= b)
155
156
157 def lt(a, b):
158 return onebit(a < b)
159
160
161 def le(a, b):
162 return onebit(a <= b)
163
164
165 def length(a):
166 return len(a)
167
168
169 def undefined(v):
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
174 for clarification.
175 """
176 return v
177
178
179 def SINGLE(FRS):
180 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
181 """
182 # result - WORD - start off all zeros
183 WORD = SelectableInt(0, 32)
184
185 e = FRS[1:12]
186 m = FRS[12:64]
187 s = FRS[0]
188
189 log("SINGLE", FRS)
190 log("s e m", s.value, e.value, m.value)
191
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))
195 WORD[0:2] = FRS[0:2]
196 WORD[2:32] = FRS[5:35]
197
198 # Denormalization Required
199 if e.value >= 874 and e.value <= 896:
200 sign = FRS[0]
201 exp = e.value - 1023
202 frac = selectconcat(SelectableInt(1, 1), FRS[12:64])
203 log("exp, fract", exp, hex(frac.value))
204 # denormalize operand
205 while exp < -126:
206 frac[0:53] = selectconcat(SelectableInt(0, 1), frac[0:52])
207 exp = exp + 1
208 WORD[0] = sign
209 WORD[1:9] = SelectableInt(0, 8)
210 WORD[9:32] = frac[1:24]
211 # else WORD = undefined # return zeros
212
213 log("WORD", WORD)
214
215 return WORD
216
217 # XXX NOTE: these are very quick hacked functions for utterly basic
218 # FP support
219
220
221 def signinv(res, sign):
222 if sign == 1:
223 return res
224 if sign == 0:
225 return 0.0
226 if sign == -1:
227 return -res
228
229
230 def fp32toselectable(flt):
231 """convert FP number to 32 bit SelectableInt
232 """
233 b = struct.pack("<f", flt)
234 val = int.from_bytes(b, byteorder='little', signed=False)
235 return SelectableInt(val, 32)
236
237
238 def fp64toselectable(flt):
239 """convert FP number to 64 bit SelectableInt
240 """
241 b = struct.pack("<d", flt)
242 val = int.from_bytes(b, byteorder='little', signed=False)
243 return SelectableInt(val, 64)
244
245
246 def _minmag(a, b):
247 if abs(a) < abs(b):
248 return a
249 if abs(a) > abs(b):
250 return b
251 return min(a, b)
252
253
254 def _maxmag(a, b):
255 if abs(a) < abs(b):
256 return b
257 if abs(a) > abs(b):
258 return a
259 return max(a, b)
260
261
262 class ISAFPHelpers:
263 # bfp32/64_OP naming mirrors that in the Power ISA spec.
264
265 def bfp64_ATAN2PI(self, a, b):
266 # FIXME: use proper implementation
267 return fp64toselectable(math.atan2(float(a), float(b)) / math.pi)
268
269 def bfp32_ATAN2PI(self, a, b):
270 # FIXME: use proper implementation
271 return fp32toselectable(math.atan2(float(a), float(b)) / math.pi)
272
273 def bfp64_ATAN2(self, a, b):
274 # FIXME: use proper implementation
275 return fp64toselectable(math.atan2(float(a), float(b)))
276
277 def bfp32_ATAN2(self, a, b):
278 # FIXME: use proper implementation
279 return fp32toselectable(math.atan2(float(a), float(b)))
280
281 def bfp64_HYPOT(self, a, b):
282 # FIXME: use proper implementation
283 return fp64toselectable(math.hypot(float(a), float(b)))
284
285 def bfp32_HYPOT(self, a, b):
286 # FIXME: use proper implementation
287 return fp32toselectable(math.hypot(float(a), float(b)))
288
289 def bfp64_MINNUM08(self, a, b):
290 # FIXME: use proper implementation
291 return fp64toselectable(min(float(a), float(b)))
292
293 def bfp32_MINNUM08(self, a, b):
294 # FIXME: use proper implementation
295 return fp32toselectable(min(float(a), float(b)))
296
297 def bfp64_MIN19(self, a, b):
298 # FIXME: use proper implementation
299 return fp64toselectable(min(float(a), float(b)))
300
301 def bfp32_MIN19(self, a, b):
302 # FIXME: use proper implementation
303 return fp32toselectable(min(float(a), float(b)))
304
305 def bfp64_MINNUM19(self, a, b):
306 # FIXME: use proper implementation
307 return fp64toselectable(min(float(a), float(b)))
308
309 def bfp32_MINNUM19(self, a, b):
310 # FIXME: use proper implementation
311 return fp32toselectable(min(float(a), float(b)))
312
313 def bfp64_MINC(self, a, b):
314 # FIXME: use proper implementation
315 return fp64toselectable(min(float(a), float(b)))
316
317 def bfp32_MINC(self, a, b):
318 # FIXME: use proper implementation
319 return fp32toselectable(min(float(a), float(b)))
320
321 def bfp64_MAXNUM08(self, a, b):
322 # FIXME: use proper implementation
323 return fp64toselectable(max(float(a), float(b)))
324
325 def bfp32_MAXNUM08(self, a, b):
326 # FIXME: use proper implementation
327 return fp32toselectable(max(float(a), float(b)))
328
329 def bfp64_MAX19(self, a, b):
330 # FIXME: use proper implementation
331 return fp64toselectable(max(float(a), float(b)))
332
333 def bfp32_MAX19(self, a, b):
334 # FIXME: use proper implementation
335 return fp32toselectable(max(float(a), float(b)))
336
337 def bfp64_MAXNUM19(self, a, b):
338 # FIXME: use proper implementation
339 return fp64toselectable(max(float(a), float(b)))
340
341 def bfp32_MAXNUM19(self, a, b):
342 # FIXME: use proper implementation
343 return fp32toselectable(max(float(a), float(b)))
344
345 def bfp64_MAXC(self, a, b):
346 # FIXME: use proper implementation
347 return fp64toselectable(max(float(a), float(b)))
348
349 def bfp32_MAXC(self, a, b):
350 # FIXME: use proper implementation
351 return fp32toselectable(max(float(a), float(b)))
352
353 def bfp64_MINMAGNUM08(self, a, b):
354 # FIXME: use proper implementation
355 return fp64toselectable(_minmag(float(a), float(b)))
356
357 def bfp32_MINMAGNUM08(self, a, b):
358 # FIXME: use proper implementation
359 return fp32toselectable(_minmag(float(a), float(b)))
360
361 def bfp64_MAXMAGNUM08(self, a, b):
362 # FIXME: use proper implementation
363 return fp64toselectable(_maxmag(float(a), float(b)))
364
365 def bfp32_MAXMAGNUM08(self, a, b):
366 # FIXME: use proper implementation
367 return fp32toselectable(_maxmag(float(a), float(b)))
368
369 def bfp64_MOD(self, a, b):
370 # FIXME: use proper implementation
371 return fp64toselectable(math.fmod(float(a), float(b)))
372
373 def bfp32_MOD(self, a, b):
374 # FIXME: use proper implementation
375 return fp32toselectable(math.fmod(float(a), float(b)))
376
377 def bfp64_MINMAG19(self, a, b):
378 # FIXME: use proper implementation
379 return fp64toselectable(_minmag(float(a), float(b)))
380
381 def bfp32_MINMAG19(self, a, b):
382 # FIXME: use proper implementation
383 return fp32toselectable(_minmag(float(a), float(b)))
384
385 def bfp64_MAXMAG19(self, a, b):
386 # FIXME: use proper implementation
387 return fp64toselectable(_maxmag(float(a), float(b)))
388
389 def bfp32_MAXMAG19(self, a, b):
390 # FIXME: use proper implementation
391 return fp32toselectable(_maxmag(float(a), float(b)))
392
393 def bfp64_MINMAGNUM19(self, a, b):
394 # FIXME: use proper implementation
395 return fp64toselectable(_minmag(float(a), float(b)))
396
397 def bfp32_MINMAGNUM19(self, a, b):
398 # FIXME: use proper implementation
399 return fp32toselectable(_minmag(float(a), float(b)))
400
401 def bfp64_MAXMAGNUM19(self, a, b):
402 # FIXME: use proper implementation
403 return fp64toselectable(_maxmag(float(a), float(b)))
404
405 def bfp32_MAXMAGNUM19(self, a, b):
406 # FIXME: use proper implementation
407 return fp32toselectable(_maxmag(float(a), float(b)))
408
409 def bfp64_REMAINDER(self, a, b):
410 # FIXME: use proper implementation
411 return fp64toselectable(math.remainder(float(a), float(b)))
412
413 def bfp32_REMAINDER(self, a, b):
414 # FIXME: use proper implementation
415 return fp32toselectable(math.remainder(float(a), float(b)))
416
417 def bfp64_POWR(self, a, b):
418 # FIXME: use proper implementation
419 return fp64toselectable(pow(float(a), float(b)))
420
421 def bfp32_POWR(self, a, b):
422 # FIXME: use proper implementation
423 return fp32toselectable(pow(float(a), float(b)))
424
425 def bfp64_POW(self, a, b):
426 # FIXME: use proper implementation
427 return fp64toselectable(pow(float(a), float(b)))
428
429 def bfp32_POW(self, a, b):
430 # FIXME: use proper implementation
431 return fp32toselectable(pow(float(a), float(b)))
432
433 def bfp64_MINMAGC(self, a, b):
434 # FIXME: use proper implementation
435 return fp64toselectable(_minmag(float(a), float(b)))
436
437 def bfp32_MINMAGC(self, a, b):
438 # FIXME: use proper implementation
439 return fp32toselectable(_minmag(float(a), float(b)))
440
441 def bfp64_MAXMAGC(self, a, b):
442 # FIXME: use proper implementation
443 return fp64toselectable(_maxmag(float(a), float(b)))
444
445 def bfp32_MAXMAGC(self, a, b):
446 # FIXME: use proper implementation
447 return fp32toselectable(_maxmag(float(a), float(b)))
448
449 def bfp64_POWN(self, a, b):
450 # FIXME: use proper implementation
451 return fp64toselectable(pow(float(a), int(b)))
452
453 def bfp32_POWN(self, a, b):
454 # FIXME: use proper implementation
455 return fp32toselectable(pow(float(a), int(b)))
456
457 def bfp64_ROOTN(self, a, b):
458 # FIXME: use proper implementation
459 return fp64toselectable(pow(float(a), 1 / int(b)))
460
461 def bfp32_ROOTN(self, a, b):
462 # FIXME: use proper implementation
463 return fp32toselectable(pow(float(a), 1 / int(b)))
464
465 def bfp64_CBRT(self, v):
466 # FIXME: use proper implementation
467 return fp64toselectable(pow(float(v), 1 / 3))
468
469 def bfp32_CBRT(self, v):
470 # FIXME: use proper implementation
471 return fp32toselectable(pow(float(v), 1 / 3))
472
473 def bfp64_SINPI(self, v):
474 # FIXME: use proper implementation
475 return fp64toselectable(math.sin(float(v) * math.pi))
476
477 def bfp32_SINPI(self, v):
478 # FIXME: use proper implementation
479 return fp32toselectable(math.sin(float(v) * math.pi))
480
481 def bfp64_ASINPI(self, v):
482 # FIXME: use proper implementation
483 return fp64toselectable(math.asin(float(v)) / math.pi)
484
485 def bfp32_ASINPI(self, v):
486 # FIXME: use proper implementation
487 return fp32toselectable(math.asin(float(v)) / math.pi)
488
489 def bfp64_COSPI(self, v):
490 # FIXME: use proper implementation
491 return fp64toselectable(math.cos(float(v) * math.pi))
492
493 def bfp32_COSPI(self, v):
494 # FIXME: use proper implementation
495 return fp32toselectable(math.cos(float(v) * math.pi))
496
497 def bfp64_TANPI(self, v):
498 # FIXME: use proper implementation
499 return fp64toselectable(math.tan(float(v) * math.pi))
500
501 def bfp32_TANPI(self, v):
502 # FIXME: use proper implementation
503 return fp32toselectable(math.tan(float(v) * math.pi))
504
505 def bfp64_ACOSPI(self, v):
506 # FIXME: use proper implementation
507 return fp64toselectable(math.acos(float(v)) / math.pi)
508
509 def bfp32_ACOSPI(self, v):
510 # FIXME: use proper implementation
511 return fp32toselectable(math.acos(float(v)) / math.pi)
512
513 def bfp64_ATANPI(self, v):
514 # FIXME: use proper implementation
515 return fp64toselectable(math.atan(float(v)) / math.pi)
516
517 def bfp32_ATANPI(self, v):
518 # FIXME: use proper implementation
519 return fp32toselectable(math.atan(float(v)) / math.pi)
520
521 def bfp64_RSQRT(self, v):
522 # FIXME: use proper implementation
523 return fp64toselectable(1 / math.sqrt(float(v)))
524
525 def bfp32_RSQRT(self, v):
526 # FIXME: use proper implementation
527 return fp32toselectable(1 / math.sqrt(float(v)))
528
529 def bfp64_SIN(self, v):
530 # FIXME: use proper implementation
531 return fp64toselectable(math.sin(float(v)))
532
533 def bfp32_SIN(self, v):
534 # FIXME: use proper implementation
535 return fp32toselectable(math.sin(float(v)))
536
537 def bfp64_ASIN(self, v):
538 # FIXME: use proper implementation
539 return fp64toselectable(math.asin(float(v)))
540
541 def bfp32_ASIN(self, v):
542 # FIXME: use proper implementation
543 return fp32toselectable(math.asin(float(v)))
544
545 def bfp64_COS(self, v):
546 # FIXME: use proper implementation
547 return fp64toselectable(math.cos(float(v)))
548
549 def bfp32_COS(self, v):
550 # FIXME: use proper implementation
551 return fp32toselectable(math.cos(float(v)))
552
553 def bfp64_TAN(self, v):
554 # FIXME: use proper implementation
555 return fp64toselectable(math.tan(float(v)))
556
557 def bfp32_TAN(self, v):
558 # FIXME: use proper implementation
559 return fp32toselectable(math.tan(float(v)))
560
561 def bfp64_ACOS(self, v):
562 # FIXME: use proper implementation
563 return fp64toselectable(math.acos(float(v)))
564
565 def bfp32_ACOS(self, v):
566 # FIXME: use proper implementation
567 return fp32toselectable(math.acos(float(v)))
568
569 def bfp64_ATAN(self, v):
570 # FIXME: use proper implementation
571 return fp64toselectable(math.atan(float(v)))
572
573 def bfp32_ATAN(self, v):
574 # FIXME: use proper implementation
575 return fp32toselectable(math.atan(float(v)))
576
577 def bfp64_RECIP(self, v):
578 # FIXME: use proper implementation
579 return fp64toselectable(1 / float(v))
580
581 def bfp32_RECIP(self, v):
582 # FIXME: use proper implementation
583 return fp32toselectable(1 / float(v))
584
585 def bfp64_SINH(self, v):
586 # FIXME: use proper implementation
587 return fp64toselectable(math.sinh(float(v)))
588
589 def bfp32_SINH(self, v):
590 # FIXME: use proper implementation
591 return fp32toselectable(math.sinh(float(v)))
592
593 def bfp64_ASINH(self, v):
594 # FIXME: use proper implementation
595 return fp64toselectable(math.asinh(float(v)))
596
597 def bfp32_ASINH(self, v):
598 # FIXME: use proper implementation
599 return fp32toselectable(math.asinh(float(v)))
600
601 def bfp64_COSH(self, v):
602 # FIXME: use proper implementation
603 return fp64toselectable(math.cosh(float(v)))
604
605 def bfp32_COSH(self, v):
606 # FIXME: use proper implementation
607 return fp32toselectable(math.cosh(float(v)))
608
609 def bfp64_TANH(self, v):
610 # FIXME: use proper implementation
611 return fp64toselectable(math.tanh(float(v)))
612
613 def bfp32_TANH(self, v):
614 # FIXME: use proper implementation
615 return fp32toselectable(math.tanh(float(v)))
616
617 def bfp64_ACOSH(self, v):
618 # FIXME: use proper implementation
619 return fp64toselectable(math.acosh(float(v)))
620
621 def bfp32_ACOSH(self, v):
622 # FIXME: use proper implementation
623 return fp32toselectable(math.acosh(float(v)))
624
625 def bfp64_ATANH(self, v):
626 # FIXME: use proper implementation
627 return fp64toselectable(math.atanh(float(v)))
628
629 def bfp32_ATANH(self, v):
630 # FIXME: use proper implementation
631 return fp32toselectable(math.atanh(float(v)))
632
633 def bfp64_EXP2M1(self, v):
634 # FIXME: use proper implementation
635 return fp64toselectable(pow(2, float(v)) - 1)
636
637 def bfp32_EXP2M1(self, v):
638 # FIXME: use proper implementation
639 return fp32toselectable(pow(2, float(v)) - 1)
640
641 def bfp64_LOG2P1(self, v):
642 # FIXME: use proper implementation
643 return fp64toselectable(math.log2(float(v) + 1))
644
645 def bfp32_LOG2P1(self, v):
646 # FIXME: use proper implementation
647 return fp32toselectable(math.log2(float(v) + 1))
648
649 def bfp64_EXPM1(self, v):
650 # FIXME: use proper implementation
651 return fp64toselectable(math.expm1(float(v)))
652
653 def bfp32_EXPM1(self, v):
654 # FIXME: use proper implementation
655 return fp32toselectable(math.expm1(float(v)))
656
657 def bfp64_LOGP1(self, v):
658 # FIXME: use proper implementation
659 return fp64toselectable(math.log1p(float(v)))
660
661 def bfp32_LOGP1(self, v):
662 # FIXME: use proper implementation
663 return fp32toselectable(math.log1p(float(v)))
664
665 def bfp64_EXP10M1(self, v):
666 # FIXME: use proper implementation
667 return fp64toselectable(pow(10, float(v)) - 1)
668
669 def bfp32_EXP10M1(self, v):
670 # FIXME: use proper implementation
671 return fp32toselectable(pow(10, float(v)) - 1)
672
673 def bfp64_LOG10P1(self, v):
674 # FIXME: use proper implementation
675 return fp64toselectable(math.log10(float(v) + 1))
676
677 def bfp32_LOG10P1(self, v):
678 # FIXME: use proper implementation
679 return fp32toselectable(math.log10(float(v) + 1))
680
681 def bfp64_EXP2(self, v):
682 # FIXME: use proper implementation
683 return fp64toselectable(pow(2, float(v)))
684
685 def bfp32_EXP2(self, v):
686 # FIXME: use proper implementation
687 return fp32toselectable(pow(2, float(v)))
688
689 def bfp64_LOG2(self, v):
690 # FIXME: use proper implementation
691 return fp64toselectable(math.log2(float(v)))
692
693 def bfp32_LOG2(self, v):
694 # FIXME: use proper implementation
695 return fp32toselectable(math.log2(float(v)))
696
697 def bfp64_EXP(self, v):
698 # FIXME: use proper implementation
699 return fp64toselectable(math.exp(float(v)))
700
701 def bfp32_EXP(self, v):
702 # FIXME: use proper implementation
703 return fp32toselectable(math.exp(float(v)))
704
705 def bfp64_LOG(self, v):
706 # FIXME: use proper implementation
707 return fp64toselectable(math.log(float(v)))
708
709 def bfp32_LOG(self, v):
710 # FIXME: use proper implementation
711 return fp32toselectable(math.log(float(v)))
712
713 def bfp64_EXP10(self, v):
714 # FIXME: use proper implementation
715 return fp64toselectable(pow(10, float(v)))
716
717 def bfp32_EXP10(self, v):
718 # FIXME: use proper implementation
719 return fp32toselectable(pow(10, float(v)))
720
721 def bfp64_LOG10(self, v):
722 # FIXME: use proper implementation
723 return fp64toselectable(math.log10(float(v)))
724
725 def bfp32_LOG10(self, v):
726 # FIXME: use proper implementation
727 return fp32toselectable(math.log10(float(v)))
728
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)
737 return cvt
738
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)
747 return cvt
748
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)
757 log(" cvt", cvt)
758 return cvt
759
760 def FPMULADD32(self, FRA, FRC, FRB, mulsign, addsign):
761 # return FPMUL64(FRA, FRB)
762 #FRA = DOUBLE(SINGLE(FRA))
763 #FRB = DOUBLE(SINGLE(FRB))
764 if addsign == 1:
765 if mulsign == 1:
766 result = float(FRA) * float(FRC) + float(FRB) # fmadds
767 elif mulsign == -1:
768 result = -(float(FRA) * float(FRC) - float(FRB)) # fnmsubs
769 elif addsign == -1:
770 if mulsign == 1:
771 result = float(FRA) * float(FRC) - float(FRB) # fmsubs
772 elif mulsign == -1:
773 result = -(float(FRA) * float(FRC) + float(FRB)) # fnmadds
774 elif addsign == 0:
775 result = 0.0
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)
783 log(" cvt", cvt)
784 return cvt
785
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)
794 return cvt
795
796
797 def FPADD64(FRA, FRB):
798 result = float(FRA) + float(FRB)
799 cvt = fp64toselectable(result)
800 log("FPADD64", FRA, FRB, result, cvt)
801 return cvt
802
803
804 def FPSUB64(FRA, FRB):
805 result = float(FRA) - float(FRB)
806 cvt = fp64toselectable(result)
807 log("FPSUB64", FRA, FRB, result, cvt)
808 return cvt
809
810
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)
815 return cvt
816
817
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)
822 return cvt
823
824
825 def bitrev(val, VL):
826 """Returns the integer whose value is the reverse of the lowest
827 'width' bits of the integer 'val'
828 """
829 result = 0
830 width = VL.bit_length()-1
831 for _ in range(width):
832 result = (result << 1) | (val & 1)
833 val >>= 1
834 return result
835
836
837 def log2(val):
838 """return the base-2 logarithm of `val`. Only works for powers of 2."""
839 if isinstance(val, SelectableInt):
840 val = val.value
841 retval = val.bit_length() - 1
842 assert val == 2 ** retval, "value is not a power of 2"
843 return retval
844
845
846 # BFP classification predicates
847 # these need to be implemented in python because they work with multiple
848 # input types
849 def IsInf(v):
850 if isinstance(v, BFPState):
851 return onebit(v.class_.Infinity)
852 # TODO: implement for SelectableInt/int
853 raise NotImplementedError("not yet implemented for non-BFPState values")
854
855
856 def IsNaN(v):
857 if isinstance(v, BFPState):
858 return onebit(v.class_.SNaN or v.class_.QNaN)
859 # TODO: implement for SelectableInt/int
860 raise NotImplementedError("not yet implemented for non-BFPState values")
861
862
863 def IsNeg(v):
864 if isinstance(v, BFPState):
865 if v.class_.SNaN or v.class_.QNaN or v.class_.Zero:
866 return onebit(0)
867 return onebit(v.sign)
868 # TODO: implement for SelectableInt/int
869 raise NotImplementedError("not yet implemented for non-BFPState values")
870
871
872 def IsSNaN(v):
873 if isinstance(v, BFPState):
874 return onebit(v.class_.SNaN)
875 # TODO: implement for SelectableInt/int
876 raise NotImplementedError("not yet implemented for non-BFPState values")
877
878
879 def IsZero(v):
880 if isinstance(v, BFPState):
881 return onebit(v.class_.Zero)
882 # TODO: implement for SelectableInt/int
883 raise NotImplementedError("not yet implemented for non-BFPState values")
884
885
886 def SetFX(fpscr, field):
887 assert isinstance(fpscr, FPSCRState), "SetFX only works on FPSCR fields"
888 if eq(getattr(fpscr, field), SelectableInt(0, 1)):
889 setattr(fpscr, field, SelectableInt(1, 1))
890 fpscr.FX = SelectableInt(1, 1)
891
892
893 class ISACallerHelper:
894 def __init__(self, XLEN, FPSCR):
895 self.__XLEN = XLEN
896 if FPSCR is None:
897 FPSCR = FPSCRState()
898 self.__FPSCR = FPSCR
899
900 @property
901 def XLEN(self):
902 return self.__XLEN
903
904 @property
905 def FPSCR(self):
906 return self.__FPSCR
907
908 def EXTZXL(self, value, bits=None):
909 if bits is None:
910 bits = self.XLEN
911 elif isinstance(bits, SelectableInt):
912 bits = bits.value
913 if isinstance(value, SelectableInt):
914 value = value.value
915 return SelectableInt(value & ((1 << bits) - 1), self.XLEN)
916
917 def EXTSXL(self, value, bits=None):
918 if isinstance(value, SelectableInt):
919 value = value.value
920 if bits is None:
921 bits = self.XLEN
922 elif isinstance(bits, SelectableInt):
923 bits = bits.value
924 return SelectableInt(exts(value, bits), self.XLEN)
925
926 def DOUBLE2SINGLE(self, FRS):
927 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
928 implementation of the frsp instruction.
929 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
930 """
931 return self.FRSP(FRS)
932
933 def ROTL32(self, value, bits):
934 if isinstance(bits, SelectableInt):
935 bits = bits.value
936 if isinstance(value, SelectableInt):
937 value = SelectableInt(value.value, self.XLEN)
938 value = value | (value << (self.XLEN//2))
939 value = rotl(value, bits, self.XLEN)
940 return value
941
942 def ROTL128(self, value, bits):
943 return rotl(value, bits, self.XLEN*2)
944
945 def ROTL64(self, value, bits):
946 return rotl(value, bits, self.XLEN)
947
948 def MASK32(self, x, y):
949 if isinstance(x, SelectableInt):
950 x = x.value
951 if isinstance(y, SelectableInt):
952 y = y.value
953 return self.MASK(x+(self.XLEN//2), y+(self.XLEN//2))
954
955 def MASK(self, x, y, lim=None):
956 if lim is None:
957 lim = self.XLEN
958 if isinstance(x, SelectableInt):
959 x = x.value
960 if isinstance(y, SelectableInt):
961 y = y.value
962 if x < y:
963 x = lim-x
964 y = (lim-1)-y
965 mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
966 mask_b = ((1 << y) - 1) & ((1 << lim) - 1)
967 elif x == y:
968 return 1 << ((lim-1)-x)
969 else:
970 x = lim-x
971 y = (lim-1)-y
972 mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
973 mask_b = (~((1 << y) - 1)) & ((1 << lim) - 1)
974 return mask_a ^ mask_b
975
976 def __getattr__(self, attr):
977 """workaround for getting function out of the global namespace
978 within this module, as a way to get functions being transitioned
979 to Helper classes within ISACaller (and therefore pseudocode)
980 """
981 try:
982 return globals()[attr]
983 except KeyError:
984 raise AttributeError(attr)
985
986
987 # For these tests I tried to find power instructions that would let me
988 # isolate each of these helper operations. So for instance, when I was
989 # testing the MASK() function, I chose rlwinm and rldicl because if I
990 # set the shift equal to 0 and passed in a value of all ones, the
991 # result I got would be exactly the same as the output of MASK()
992
993 class HelperTests(unittest.TestCase, ISACallerHelper):
994 def __init__(self, *args, **kwargs):
995 # TODO: dynamic (64/32/16/8)
996 ISACallerHelper.__init__(self, 64, FPSCR=None)
997 unittest.TestCase.__init__(self, *args, **kwargs)
998
999 def test_MASK(self):
1000 # Verified using rlwinm, rldicl, rldicr in qemu
1001 # li 1, -1
1002 # rlwinm reg, 1, 0, 5, 15
1003 self.assertHex(self.MASK(5+32, 15+32), 0x7ff0000)
1004 # rlwinm reg, 1, 0, 15, 5
1005 self.assertHex(self.MASK(15+32, 5+32), 0xfffffffffc01ffff)
1006 self.assertHex(self.MASK(30+32, 2+32), 0xffffffffe0000003)
1007 # rldicl reg, 1, 0, 37
1008 self.assertHex(self.MASK(37, 63), 0x7ffffff)
1009 self.assertHex(self.MASK(10, 63), 0x3fffffffffffff)
1010 self.assertHex(self.MASK(58, 63), 0x3f)
1011 # rldicr reg, 1, 0, 37
1012 self.assertHex(self.MASK(0, 37), 0xfffffffffc000000)
1013 self.assertHex(self.MASK(0, 10), 0xffe0000000000000)
1014 self.assertHex(self.MASK(0, 58), 0xffffffffffffffe0)
1015
1016 # li 2, 5
1017 # slw 1, 1, 2
1018 self.assertHex(self.MASK(32, 63-5), 0xffffffe0)
1019
1020 self.assertHex(self.MASK(32, 33), 0xc0000000)
1021 self.assertHex(self.MASK(32, 32), 0x80000000)
1022 self.assertHex(self.MASK(33, 33), 0x40000000)
1023
1024 def test_ROTL64(self):
1025 # r1 = 0xdeadbeef12345678
1026 value = 0xdeadbeef12345678
1027
1028 # rldicl reg, 1, 10, 0
1029 self.assertHex(self.ROTL64(value, 10), 0xb6fbbc48d159e37a)
1030 # rldicl reg, 1, 35, 0
1031 self.assertHex(self.ROTL64(value, 35), 0x91a2b3c6f56df778)
1032 self.assertHex(self.ROTL64(value, 58), 0xe37ab6fbbc48d159)
1033 self.assertHex(self.ROTL64(value, 22), 0xbbc48d159e37ab6f)
1034
1035 def test_ROTL32(self):
1036 # r1 = 0xdeadbeef
1037 value = SelectableInt(0xdeadbeef, self.XLEN)
1038
1039 # rlwinm reg, 1, 10, 0, 31
1040 self.assertHex(self.ROTL32(value, 10), 0xb6fbbf7a)
1041 # rlwinm reg, 1, 17, 0, 31
1042 self.assertHex(self.ROTL32(value, 17), 0x7ddfbd5b)
1043 self.assertHex(self.ROTL32(value, 25), 0xdfbd5b7d)
1044 self.assertHex(self.ROTL32(value, 30), 0xf7ab6fbb)
1045
1046 def test_EXTS64(self):
1047 value_a = SelectableInt(0xdeadbeef, 32) # r1
1048 value_b = SelectableInt(0x73123456, 32) # r2
1049 value_c = SelectableInt(0x80000000, 32) # r3
1050
1051 # extswsli reg, 1, 0
1052 self.assertHex(self.EXTS64(value_a), 0xffffffffdeadbeef)
1053 # extswsli reg, 2, 0
1054 self.assertHex(self.EXTS64(value_b), SelectableInt(value_b.value, 64))
1055 # extswsli reg, 3, 0
1056 self.assertHex(self.EXTS64(value_c), 0xffffffff80000000)
1057
1058 def test_FPADD32(self):
1059 value_a = SelectableInt(0x4014000000000000, 64) # 5.0
1060 value_b = SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1061 result = FPADD32(value_a, value_b)
1062 self.assertHex(0x4040266666666666, result)
1063
1064 def assertHex(self, a, b):
1065 a_val = a
1066 if isinstance(a, SelectableInt):
1067 a_val = a.value
1068 b_val = b
1069 if isinstance(b, SelectableInt):
1070 b_val = b.value
1071 msg = "{:x} != {:x}".format(a_val, b_val)
1072 return self.assertEqual(a, b, msg)
1073
1074
1075
1076 if __name__ == '__main__':
1077 log(SelectableInt.__bases__)
1078 unittest.main()