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)
112 if isinstance(x
, SelectableInt
):
114 if isinstance(y
, SelectableInt
):
116 return MASK(x
+32, y
+32)
119 if isinstance(x
, SelectableInt
):
121 if isinstance(y
, SelectableInt
):
126 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
127 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
133 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
134 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
135 return mask_a ^ mask_b
139 return onebit(a
!= b
)
143 return onebit(a
== b
)
151 return onebit(a
>= b
)
159 return onebit(a
<= b
)
167 """ function that, for Power spec purposes, returns undefined bits of
168 the same shape as the input bits. however, for purposes of matching
169 POWER9's behavior returns the input bits unchanged. this effectively
170 "marks" (tags) locations in the v3.0B spec that need to be submitted
177 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
179 # result - WORD - start off all zeros
180 WORD
= SelectableInt(0, 32)
187 log ("s e m", s
.value
, e
.value
, m
.value
)
189 #No Denormalization Required (includes Zero / Infinity / NaN)
190 if e
.value
> 896 or FRS
[1:64].value
== 0:
191 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
193 WORD
[2:32] = FRS
[5:35]
195 #Denormalization Required
196 if e
.value
>= 874 and e
.value
<= 896:
199 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
200 log("exp, fract", exp
, hex(frac
.value
))
201 # denormalize operand
203 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
206 WORD
[1:9] = SelectableInt(0, 8)
207 WORD
[9:32] = frac
[1:24]
208 #else WORD = undefined # return zeros
214 # XXX NOTE: these are very quick hacked functions for utterly basic
217 def signinv(res
, sign
):
226 def fp64toselectable(frt
):
227 """convert FP number to 64 bit SelectableInt
229 b
= struct
.pack(">d", frt
)
230 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
231 return SelectableInt(val
, 64)
236 def FPSIN32(self
, FRB
):
237 #FRB = DOUBLE(SINGLE(FRB))
238 result
= math
.sin(float(FRB
))
239 cvt
= fp64toselectable(result
)
240 cvt
= self
.DOUBLE2SINGLE(cvt
)
241 log ("FPSIN32", FRB
, float(FRB
), "=", result
, cvt
)
244 def FPCOS32(self
, FRB
):
245 #FRB = DOUBLE(SINGLE(FRB))
246 result
= math
.cos(float(FRB
))
247 cvt
= fp64toselectable(result
)
248 cvt
= self
.DOUBLE2SINGLE(cvt
)
249 log ("FPCOS32", FRB
, float(FRB
), "=", result
, cvt
)
252 def FPADD32(self
, FRA
, FRB
):
253 #return FPADD64(FRA, FRB)
254 #FRA = DOUBLE(SINGLE(FRA))
255 #FRB = DOUBLE(SINGLE(FRB))
256 result
= float(FRA
) + float(FRB
)
257 cvt
= fp64toselectable(result
)
258 cvt
= self
.DOUBLE2SINGLE(cvt
)
259 log ("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
262 def FPSUB32(self
, FRA
, FRB
):
263 #return FPSUB64(FRA, FRB)
264 #FRA = DOUBLE(SINGLE(FRA))
265 #FRB = DOUBLE(SINGLE(FRB))
266 result
= float(FRA
) - float(FRB
)
267 cvt
= fp64toselectable(result
)
268 cvt
= self
.DOUBLE2SINGLE(cvt
)
269 log ("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
272 def FPMUL32(self
, FRA
, FRB
, sign
=1):
273 #return FPMUL64(FRA, FRB)
274 FRA
= self
.DOUBLE(SINGLE(FRA
))
275 FRB
= self
.DOUBLE(SINGLE(FRB
))
276 result
= signinv(float(FRA
) * float(FRB
), sign
)
277 log ("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
278 cvt
= fp64toselectable(result
)
279 cvt
= self
.DOUBLE2SINGLE(cvt
)
283 def FPMULADD32(self
, FRA
, FRC
, FRB
, mulsign
, addsign
):
284 #return FPMUL64(FRA, FRB)
285 #FRA = DOUBLE(SINGLE(FRA))
286 #FRB = DOUBLE(SINGLE(FRB))
289 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
291 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
294 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
296 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
299 log ("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
300 log (" FRA", float(FRA
))
301 log (" FRC", float(FRC
))
302 log (" FRB", float(FRB
))
303 log (" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
304 cvt
= fp64toselectable(result
)
305 cvt
= self
.DOUBLE2SINGLE(cvt
)
309 def FPDIV32(self
, FRA
, FRB
, sign
=1):
310 #return FPDIV64(FRA, FRB)
311 #FRA = DOUBLE(SINGLE(FRA))
312 #FRB = DOUBLE(SINGLE(FRB))
313 result
= signinv(float(FRA
) / float(FRB
), sign
)
314 cvt
= fp64toselectable(result
)
315 cvt
= self
.DOUBLE2SINGLE(cvt
)
316 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
320 def FPADD64(FRA
, FRB
):
321 result
= float(FRA
) + float(FRB
)
322 cvt
= fp64toselectable(result
)
323 log ("FPADD64", FRA
, FRB
, result
, cvt
)
327 def FPSUB64(FRA
, FRB
):
328 result
= float(FRA
) - float(FRB
)
329 cvt
= fp64toselectable(result
)
330 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
334 def FPMUL64(FRA
, FRB
, sign
=1):
335 result
= signinv(float(FRA
) * float(FRB
), sign
)
336 cvt
= fp64toselectable(result
)
337 log ("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
341 def FPDIV64(FRA
, FRB
, sign
=1):
342 result
= signinv(float(FRA
) / float(FRB
), sign
)
343 cvt
= fp64toselectable(result
)
344 log ("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
350 """Returns the integer whose value is the reverse of the lowest
351 'width' bits of the integer 'val'
354 width
= VL
.bit_length()-1
355 for _
in range(width
):
356 result
= (result
<< 1) |
(val
& 1)
361 # For these tests I tried to find power instructions that would let me
362 # isolate each of these helper operations. So for instance, when I was
363 # testing the MASK() function, I chose rlwinm and rldicl because if I
364 # set the shift equal to 0 and passed in a value of all ones, the
365 # result I got would be exactly the same as the output of MASK()
368 class HelperTests(unittest
.TestCase
):
370 # Verified using rlwinm, rldicl, rldicr in qemu
372 # rlwinm reg, 1, 0, 5, 15
373 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
374 # rlwinm reg, 1, 0, 15, 5
375 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
376 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
377 # rldicl reg, 1, 0, 37
378 self
.assertHex(MASK(37, 63), 0x7ffffff)
379 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
380 self
.assertHex(MASK(58, 63), 0x3f)
381 # rldicr reg, 1, 0, 37
382 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
383 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
384 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
388 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
390 self
.assertHex(MASK(32, 33), 0xc0000000)
391 self
.assertHex(MASK(32, 32), 0x80000000)
392 self
.assertHex(MASK(33, 33), 0x40000000)
394 def test_ROTL64(self
):
395 # r1 = 0xdeadbeef12345678
396 value
= 0xdeadbeef12345678
398 # rldicl reg, 1, 10, 0
399 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
400 # rldicl reg, 1, 35, 0
401 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
402 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
403 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
405 def test_ROTL32(self
):
409 # rlwinm reg, 1, 10, 0, 31
410 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
411 # rlwinm reg, 1, 17, 0, 31
412 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
413 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
414 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
416 def test_EXTS64(self
):
417 value_a
= SelectableInt(0xdeadbeef, 32) # r1
418 value_b
= SelectableInt(0x73123456, 32) # r2
419 value_c
= SelectableInt(0x80000000, 32) # r3
422 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
424 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
426 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
428 def test_FPADD32(self
):
429 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
430 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
431 result
= FPADD32(value_a
, value_b
)
432 self
.assertHex(0x4040266666666666, result
)
434 def assertHex(self
, a
, b
):
436 if isinstance(a
, SelectableInt
):
439 if isinstance(b
, SelectableInt
):
441 msg
= "{:x} != {:x}".format(a_val
, b_val
)
442 return self
.assertEqual(a
, b
, msg
)
445 class ISACallerHelper
:
446 def __init__(self
, XLEN
):
453 def __getattr__(self
, attr
):
454 return getattr(sys
.modules
[ISACallerHelper
.__module
__], attr
)
457 if __name__
== '__main__':
458 log(SelectableInt
.__bases
__)