b219767cebe0726237a5e5fee422049b1593d2ec
3 from openpower
.decoder
.selectable_int
import (SelectableInt
, onebit
,
5 from nmutil
.divmod import trunc_divs
, trunc_rems
6 from operator
import floordiv
, mod
7 from openpower
.decoder
.selectable_int
import selectltu
as ltu
8 from openpower
.decoder
.selectable_int
import selectgtu
as gtu
9 from openpower
.decoder
.selectable_int
import check_extsign
11 from openpower
.util
import log
20 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
24 def exts(value
, bits
):
25 sign
= 1 << (bits
- 1)
26 return (value
& (sign
- 1)) - (value
& sign
)
30 """ extends sign bit out from current MSB to all 256 bits
32 log ("EXTS", value
, type(value
))
33 assert isinstance(value
, SelectableInt
)
34 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
38 """ extends sign bit out from current MSB to 64 bits
40 assert isinstance(value
, SelectableInt
)
41 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
45 """ extends sign bit out from current MSB to 128 bits
47 assert isinstance(value
, SelectableInt
)
48 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
51 # signed version of MUL
53 if isinstance(b
, int):
54 b
= SelectableInt(b
, self
.bits
)
55 b
= check_extsign(a
, b
)
56 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
57 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
58 result
= abs(a
) * abs(b
)
59 log("MULS", result
, a_s
, b_s
)
65 # XXX should this explicitly extend from 32 to 64?
67 if isinstance(value
, SelectableInt
):
69 return SelectableInt(value
& ((1 << 32)-1), 64)
72 def rotl(value
, bits
, wordlen
):
73 if isinstance(bits
, SelectableInt
):
75 mask
= (1 << wordlen
) - 1
76 bits
= bits
& (wordlen
- 1)
77 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
80 def SHL64(value
, bits
, wordlen
=64):
81 if isinstance(bits
, SelectableInt
):
83 mask
= (1 << wordlen
) - 1
84 bits
= bits
& (wordlen
- 1)
85 return SelectableInt((value
<< bits
) & mask
, 64)
88 def ROTL64(value
, bits
):
89 return rotl(value
, bits
, 64)
92 def ROTL32(value
, bits
):
93 if isinstance(bits
, SelectableInt
):
95 if isinstance(value
, SelectableInt
):
96 value
= SelectableInt(value
.value
, 64)
97 return rotl(value |
(value
<< 32), bits
, 64)
100 if isinstance(x
, SelectableInt
):
102 if isinstance(y
, SelectableInt
):
104 return MASK(x
+32, y
+32)
107 if isinstance(x
, SelectableInt
):
109 if isinstance(y
, SelectableInt
):
114 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
115 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
121 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
122 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
123 return mask_a ^ mask_b
127 return onebit(a
!= b
)
131 return onebit(a
== b
)
139 return onebit(a
>= b
)
147 return onebit(a
<= b
)
155 """ function that, for Power spec purposes, returns undefined bits of
156 the same shape as the input bits. however, for purposes of matching
157 POWER9's behavior returns the input bits unchanged. this effectively
158 "marks" (tags) locations in the v3.0B spec that need to be submitted
164 """convert incoming WORD to double. v3.0B p140 section 4.6.2
166 # result, FRT, start off all zeros
168 FRT
= SelectableInt(0, 64)
169 z1
= SelectableInt(0, 1)
170 z29
= SelectableInt(0, 29)
174 log ("word s e m", s
, e
, m
)
177 if e
.value
> 0 and e
.value
< 255:
183 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
185 # Denormalized Operand
186 if e
.value
== 0 and m
.value
!= 0:
190 frac
= selectconcat(z1
, WORD
[9:32], z29
)
191 # normalize the operand
192 while frac
[0].value
== 0:
193 frac
[0:53] = selectconcat(frac
[1:53], z1
)
196 FRT
[1:12] = exp
+ 1023
197 FRT
[12:64] = frac
[1:53]
199 # Zero / Infinity / NaN
200 if e
.value
== 255 or WORD
[1:32].value
== 0:
206 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
208 log ("Double s e m", FRT
[0].value
, FRT
[1:12].value
-1023,
215 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
217 # result - WORD - start off all zeros
218 WORD
= SelectableInt(0, 32)
225 log ("s e m", s
.value
, e
.value
, m
.value
)
227 #No Denormalization Required (includes Zero / Infinity / NaN)
228 if e
.value
> 896 or FRS
[1:64].value
== 0:
229 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
231 WORD
[2:32] = FRS
[5:35]
233 #Denormalization Required
234 if e
.value
>= 874 and e
.value
<= 896:
237 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
238 log("exp, fract", exp
, hex(frac
.value
))
239 # denormalize operand
241 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
244 WORD
[1:9] = SelectableInt(0, 8)
245 WORD
[9:32] = frac
[1:24]
246 #else WORD = undefined # return zeros
252 # XXX NOTE: these are very quick hacked functions for utterly basic
255 def fp64toselectable(frt
):
256 """convert FP number to 64 bit SelectableInt
258 b
= struct
.pack(">d", frt
)
259 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
260 return SelectableInt(val
, 64)
263 def FPADD32(FRA
, FRB
):
264 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
265 #return FPADD64(FRA, FRB)
266 #FRA = DOUBLE(SINGLE(FRA))
267 #FRB = DOUBLE(SINGLE(FRB))
268 result
= float(FRA
) + float(FRB
)
269 cvt
= fp64toselectable(result
)
270 cvt
= DOUBLE2SINGLE(cvt
)
271 log ("FPADD32", FRA
, FRB
, result
, cvt
)
275 def FPSUB32(FRA
, FRB
):
276 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
277 #return FPSUB64(FRA, FRB)
278 #FRA = DOUBLE(SINGLE(FRA))
279 #FRB = DOUBLE(SINGLE(FRB))
280 result
= float(FRA
) - float(FRB
)
281 cvt
= fp64toselectable(result
)
282 cvt
= DOUBLE2SINGLE(cvt
)
283 log ("FPSUB32", FRA
, FRB
, result
, cvt
)
287 def signinv(res
, sign
):
296 def FPMUL32(FRA
, FRB
, sign
=1):
297 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
298 #return FPMUL64(FRA, FRB)
299 FRA
= DOUBLE(SINGLE(FRA
))
300 FRB
= DOUBLE(SINGLE(FRB
))
301 result
= signinv(float(FRA
) * float(FRB
), sign
)
302 log ("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
303 cvt
= fp64toselectable(result
)
304 cvt
= DOUBLE2SINGLE(cvt
)
309 def FPMULADD32(FRA
, FRC
, FRB
, mulsign
, addsign
):
310 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
311 #return FPMUL64(FRA, FRB)
312 #FRA = DOUBLE(SINGLE(FRA))
313 #FRB = DOUBLE(SINGLE(FRB))
316 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
318 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
321 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
323 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
326 log ("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
327 log (" FRA", float(FRA
))
328 log (" FRC", float(FRC
))
329 log (" FRB", float(FRB
))
330 log (" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
331 cvt
= fp64toselectable(result
)
332 cvt
= DOUBLE2SINGLE(cvt
)
337 def FPDIV32(FRA
, FRB
, sign
=1):
338 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
339 #return FPDIV64(FRA, FRB)
340 #FRA = DOUBLE(SINGLE(FRA))
341 #FRB = DOUBLE(SINGLE(FRB))
342 result
= signinv(float(FRA
) / float(FRB
), sign
)
343 cvt
= fp64toselectable(result
)
344 cvt
= DOUBLE2SINGLE(cvt
)
345 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
349 def FPADD64(FRA
, FRB
):
350 result
= float(FRA
) + float(FRB
)
351 cvt
= fp64toselectable(result
)
352 log ("FPADD64", FRA
, FRB
, result
, cvt
)
356 def FPSUB64(FRA
, FRB
):
357 result
= float(FRA
) - float(FRB
)
358 cvt
= fp64toselectable(result
)
359 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
363 def FPMUL64(FRA
, FRB
, sign
=1):
364 result
= signinv(float(FRA
) * float(FRB
), sign
)
365 cvt
= fp64toselectable(result
)
366 log ("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
370 def FPDIV64(FRA
, FRB
, sign
=1):
371 result
= signinv(float(FRA
) / float(FRB
), sign
)
372 cvt
= fp64toselectable(result
)
373 log ("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
379 """Returns the integer whose value is the reverse of the lowest
380 'width' bits of the integer 'val'
383 width
= VL
.bit_length()-1
384 for _
in range(width
):
385 result
= (result
<< 1) |
(val
& 1)
390 # For these tests I tried to find power instructions that would let me
391 # isolate each of these helper operations. So for instance, when I was
392 # testing the MASK() function, I chose rlwinm and rldicl because if I
393 # set the shift equal to 0 and passed in a value of all ones, the
394 # result I got would be exactly the same as the output of MASK()
397 class HelperTests(unittest
.TestCase
):
399 # Verified using rlwinm, rldicl, rldicr in qemu
401 # rlwinm reg, 1, 0, 5, 15
402 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
403 # rlwinm reg, 1, 0, 15, 5
404 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
405 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
406 # rldicl reg, 1, 0, 37
407 self
.assertHex(MASK(37, 63), 0x7ffffff)
408 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
409 self
.assertHex(MASK(58, 63), 0x3f)
410 # rldicr reg, 1, 0, 37
411 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
412 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
413 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
417 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
419 self
.assertHex(MASK(32, 33), 0xc0000000)
420 self
.assertHex(MASK(32, 32), 0x80000000)
421 self
.assertHex(MASK(33, 33), 0x40000000)
423 def test_ROTL64(self
):
424 # r1 = 0xdeadbeef12345678
425 value
= 0xdeadbeef12345678
427 # rldicl reg, 1, 10, 0
428 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
429 # rldicl reg, 1, 35, 0
430 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
431 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
432 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
434 def test_ROTL32(self
):
438 # rlwinm reg, 1, 10, 0, 31
439 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
440 # rlwinm reg, 1, 17, 0, 31
441 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
442 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
443 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
445 def test_EXTS64(self
):
446 value_a
= SelectableInt(0xdeadbeef, 32) # r1
447 value_b
= SelectableInt(0x73123456, 32) # r2
448 value_c
= SelectableInt(0x80000000, 32) # r3
451 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
453 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
455 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
457 def test_FPADD32(self
):
458 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
459 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
460 result
= FPADD32(value_a
, value_b
)
461 self
.assertHex(0x4040266666666666, result
)
463 def assertHex(self
, a
, b
):
465 if isinstance(a
, SelectableInt
):
468 if isinstance(b
, SelectableInt
):
470 msg
= "{:x} != {:x}".format(a_val
, b_val
)
471 return self
.assertEqual(a
, b
, msg
)
474 if __name__
== '__main__':
475 log(SelectableInt
.__bases
__)