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