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