4 from openpower
.decoder
.selectable_int
import (SelectableInt
, onebit
,
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
12 from openpower
.util
import log
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)
27 def RANGE(start
, end
):
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)
36 def exts(value
, bits
):
37 sign
= 1 << (bits
- 1)
38 return (value
& (sign
- 1)) - (value
& sign
)
42 """ extends sign bit out from current MSB to all 256 bits
44 log("EXTS", value
, type(value
))
45 assert isinstance(value
, SelectableInt
)
46 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
50 """ extends sign bit out from current MSB to 64 bits
52 assert isinstance(value
, SelectableInt
)
53 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
57 """ extends sign bit out from current MSB to 128 bits
59 assert isinstance(value
, SelectableInt
)
60 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
63 # signed version of MUL
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
)
77 # XXX should this explicitly extend from 32 to 64?
79 if isinstance(value
, SelectableInt
):
81 return SelectableInt(value
& ((1 << 32)-1), 64)
84 def rotl(value
, bits
, wordlen
):
85 if isinstance(bits
, SelectableInt
):
87 mask
= (1 << wordlen
) - 1
88 bits
= bits
& (wordlen
- 1)
89 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
92 def SHL64(value
, bits
, wordlen
=64):
93 if isinstance(bits
, SelectableInt
):
95 mask
= (1 << wordlen
) - 1
96 bits
= bits
& (wordlen
- 1)
97 return SelectableInt((value
<< bits
) & mask
, 64)
100 def ROTL64(value
, bits
):
101 return rotl(value
, bits
, 64)
104 def ROTL32(value
, bits
):
105 if isinstance(bits
, SelectableInt
):
107 if isinstance(value
, SelectableInt
):
108 value
= SelectableInt(value
.value
, 64)
109 return rotl(value |
(value
<< 32), bits
, 64)
113 if isinstance(x
, SelectableInt
):
115 if isinstance(y
, SelectableInt
):
117 return MASK(x
+32, y
+32)
121 if isinstance(x
, SelectableInt
):
123 if isinstance(y
, SelectableInt
):
128 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
129 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
135 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
136 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
137 return mask_a ^ mask_b
141 return onebit(a
!= b
)
145 return onebit(a
== b
)
153 return onebit(a
>= b
)
161 return onebit(a
<= b
)
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
179 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
181 # result - WORD - start off all zeros
182 WORD
= SelectableInt(0, 32)
189 log("s e m", s
.value
, e
.value
, m
.value
)
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
))
195 WORD
[2:32] = FRS
[5:35]
197 # Denormalization Required
198 if e
.value
>= 874 and e
.value
<= 896:
201 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
202 log("exp, fract", exp
, hex(frac
.value
))
203 # denormalize operand
205 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
208 WORD
[1:9] = SelectableInt(0, 8)
209 WORD
[9:32] = frac
[1:24]
210 # else WORD = undefined # return zeros
216 # XXX NOTE: these are very quick hacked functions for utterly basic
220 def signinv(res
, sign
):
229 def fp64toselectable(frt
):
230 """convert FP number to 64 bit SelectableInt
232 b
= struct
.pack(">d", frt
)
233 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
234 return SelectableInt(val
, 64)
239 def FPSIN32(self
, FRB
):
240 #FRB = DOUBLE(SINGLE(FRB))
241 result
= math
.sin(float(FRB
))
242 cvt
= fp64toselectable(result
)
243 cvt
= self
.DOUBLE2SINGLE(cvt
)
244 log("FPSIN32", FRB
, float(FRB
), "=", result
, cvt
)
247 def FPCOS32(self
, FRB
):
248 #FRB = DOUBLE(SINGLE(FRB))
249 result
= math
.cos(float(FRB
))
250 cvt
= fp64toselectable(result
)
251 cvt
= self
.DOUBLE2SINGLE(cvt
)
252 log("FPCOS32", FRB
, float(FRB
), "=", result
, cvt
)
255 def FPADD32(self
, FRA
, FRB
):
256 # return FPADD64(FRA, FRB)
257 #FRA = DOUBLE(SINGLE(FRA))
258 #FRB = DOUBLE(SINGLE(FRB))
259 result
= float(FRA
) + float(FRB
)
260 cvt
= fp64toselectable(result
)
261 cvt
= self
.DOUBLE2SINGLE(cvt
)
262 log("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
265 def FPSUB32(self
, FRA
, FRB
):
266 # return FPSUB64(FRA, FRB)
267 #FRA = DOUBLE(SINGLE(FRA))
268 #FRB = DOUBLE(SINGLE(FRB))
269 result
= float(FRA
) - float(FRB
)
270 cvt
= fp64toselectable(result
)
271 cvt
= self
.DOUBLE2SINGLE(cvt
)
272 log("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
275 def FPMUL32(self
, FRA
, FRB
, sign
=1):
276 # return FPMUL64(FRA, FRB)
277 FRA
= self
.DOUBLE(SINGLE(FRA
))
278 FRB
= self
.DOUBLE(SINGLE(FRB
))
279 result
= signinv(float(FRA
) * float(FRB
), sign
)
280 log("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
281 cvt
= fp64toselectable(result
)
282 cvt
= self
.DOUBLE2SINGLE(cvt
)
286 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
287 # return FPMUL64(FRA, FRB)
288 #FRA = DOUBLE(SINGLE(FRA))
289 #FRB = DOUBLE(SINGLE(FRB))
292 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
294 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
297 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
299 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
302 log("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
303 log(" FRA", float(FRA
))
304 log(" FRC", float(FRC
))
305 log(" FRB", float(FRB
))
306 log(" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
307 cvt
= fp64toselectable(result
)
308 cvt
= self
.DOUBLE2SINGLE(cvt
)
312 def FPDIV32(self
, FRA
, FRB
, sign
=1):
313 # return FPDIV64(FRA, FRB)
314 #FRA = DOUBLE(SINGLE(FRA))
315 #FRB = DOUBLE(SINGLE(FRB))
316 result
= signinv(float(FRA
) / float(FRB
), sign
)
317 cvt
= fp64toselectable(result
)
318 cvt
= self
.DOUBLE2SINGLE(cvt
)
319 log("FPDIV32", FRA
, FRB
, result
, cvt
)
323 def FPADD64(FRA
, FRB
):
324 result
= float(FRA
) + float(FRB
)
325 cvt
= fp64toselectable(result
)
326 log("FPADD64", FRA
, FRB
, result
, cvt
)
330 def FPSUB64(FRA
, FRB
):
331 result
= float(FRA
) - float(FRB
)
332 cvt
= fp64toselectable(result
)
333 log("FPSUB64", FRA
, FRB
, result
, cvt
)
337 def FPMUL64(FRA
, FRB
, sign
=1):
338 result
= signinv(float(FRA
) * float(FRB
), sign
)
339 cvt
= fp64toselectable(result
)
340 log("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
344 def FPDIV64(FRA
, FRB
, sign
=1):
345 result
= signinv(float(FRA
) / float(FRB
), sign
)
346 cvt
= fp64toselectable(result
)
347 log("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
352 """Returns the integer whose value is the reverse of the lowest
353 'width' bits of the integer 'val'
356 width
= VL
.bit_length()-1
357 for _
in range(width
):
358 result
= (result
<< 1) |
(val
& 1)
363 # For these tests I tried to find power instructions that would let me
364 # isolate each of these helper operations. So for instance, when I was
365 # testing the MASK() function, I chose rlwinm and rldicl because if I
366 # set the shift equal to 0 and passed in a value of all ones, the
367 # result I got would be exactly the same as the output of MASK()
370 class HelperTests(unittest
.TestCase
):
372 # Verified using rlwinm, rldicl, rldicr in qemu
374 # rlwinm reg, 1, 0, 5, 15
375 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
376 # rlwinm reg, 1, 0, 15, 5
377 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
378 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
379 # rldicl reg, 1, 0, 37
380 self
.assertHex(MASK(37, 63), 0x7ffffff)
381 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
382 self
.assertHex(MASK(58, 63), 0x3f)
383 # rldicr reg, 1, 0, 37
384 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
385 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
386 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
390 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
392 self
.assertHex(MASK(32, 33), 0xc0000000)
393 self
.assertHex(MASK(32, 32), 0x80000000)
394 self
.assertHex(MASK(33, 33), 0x40000000)
396 def test_ROTL64(self
):
397 # r1 = 0xdeadbeef12345678
398 value
= 0xdeadbeef12345678
400 # rldicl reg, 1, 10, 0
401 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
402 # rldicl reg, 1, 35, 0
403 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
404 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
405 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
407 def test_ROTL32(self
):
411 # rlwinm reg, 1, 10, 0, 31
412 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
413 # rlwinm reg, 1, 17, 0, 31
414 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
415 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
416 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
418 def test_EXTS64(self
):
419 value_a
= SelectableInt(0xdeadbeef, 32) # r1
420 value_b
= SelectableInt(0x73123456, 32) # r2
421 value_c
= SelectableInt(0x80000000, 32) # r3
424 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
426 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
428 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
430 def test_FPADD32(self
):
431 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
432 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
433 result
= FPADD32(value_a
, value_b
)
434 self
.assertHex(0x4040266666666666, result
)
436 def assertHex(self
, a
, b
):
438 if isinstance(a
, SelectableInt
):
441 if isinstance(b
, SelectableInt
):
443 msg
= "{:x} != {:x}".format(a_val
, b_val
)
444 return self
.assertEqual(a
, b
, msg
)
447 class ISACallerHelper
:
448 def __init__(self
, XLEN
):
455 def XLCASTS(self
, value
):
456 return SelectableInt(exts(value
.value
, self
.XLEN
), self
.XLEN
)
458 def XLCASTU(self
, value
):
459 # SelectableInt already takes care of masking out the bits
460 return SelectableInt(value
.value
, self
.XLEN
)
462 def EXTSXL(self
, value
, bits
):
463 return SelectableInt(exts(value
.value
, bits
), self
.XLEN
)
465 def __getattr__(self
, attr
):
467 return globals()[attr
]
469 raise AttributeError(attr
)
472 if __name__
== '__main__':
473 log(SelectableInt
.__bases
__)