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