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