4e0a1c16c487b3ec8208b13c615f5fcf57dc88f6
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 ROTL64(value
, bits
):
81 return rotl(value
, bits
, 64)
84 def ROTL32(value
, bits
):
85 if isinstance(bits
, SelectableInt
):
87 if isinstance(value
, SelectableInt
):
88 value
= SelectableInt(value
.value
, 64)
89 return rotl(value |
(value
<< 32), bits
, 64)
92 if isinstance(x
, SelectableInt
):
94 if isinstance(y
, SelectableInt
):
96 return MASK(x
+32, y
+32)
99 if isinstance(x
, SelectableInt
):
101 if isinstance(y
, SelectableInt
):
106 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
107 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
113 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
114 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
115 return mask_a ^ mask_b
119 return onebit(a
!= b
)
123 return onebit(a
== b
)
131 return onebit(a
>= b
)
139 return onebit(a
<= b
)
147 """ function that, for Power spec purposes, returns undefined bits of
148 the same shape as the input bits. however, for purposes of matching
149 POWER9's behavior returns the input bits unchanged. this effectively
150 "marks" (tags) locations in the v3.0B spec that need to be submitted
156 """convert incoming WORD to double. v3.0B p140 section 4.6.2
158 # result, FRT, start off all zeros
160 FRT
= SelectableInt(0, 64)
161 z1
= SelectableInt(0, 1)
162 z29
= SelectableInt(0, 29)
166 log ("word s e m", s
, e
, m
)
169 if e
.value
> 0 and e
.value
< 255:
175 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
177 # Denormalized Operand
178 if e
.value
== 0 and m
.value
!= 0:
182 frac
= selectconcat(z1
, WORD
[9:32], z29
)
183 # normalize the operand
184 while frac
[0].value
== 0:
185 frac
[0:53] = selectconcat(frac
[1:53], z1
)
188 FRT
[1:12] = exp
+ 1023
189 FRT
[12:64] = frac
[1:53]
191 # Zero / Infinity / NaN
192 if e
.value
== 255 or WORD
[1:32].value
== 0:
198 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
200 log ("Double s e m", FRT
[0].value
, FRT
[1:12].value
-1023,
207 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
209 # result - WORD - start off all zeros
210 WORD
= SelectableInt(0, 32)
217 log ("s e m", s
.value
, e
.value
, m
.value
)
219 #No Denormalization Required (includes Zero / Infinity / NaN)
220 if e
.value
> 896 or FRS
[1:64].value
== 0:
221 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
223 WORD
[2:32] = FRS
[5:35]
225 #Denormalization Required
226 if e
.value
>= 874 and e
.value
<= 896:
229 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
230 log("exp, fract", exp
, hex(frac
.value
))
231 # denormalize operand
233 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
236 WORD
[1:9] = SelectableInt(0, 8)
237 WORD
[9:32] = frac
[1:24]
238 #else WORD = undefined # return zeros
244 # XXX NOTE: these are very quick hacked functions for utterly basic
247 def fp64toselectable(frt
):
248 """convert FP number to 64 bit SelectableInt
250 b
= struct
.pack(">d", frt
)
251 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
252 return SelectableInt(val
, 64)
255 def FPADD32(FRA
, FRB
):
256 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
257 #return FPADD64(FRA, FRB)
258 #FRA = DOUBLE(SINGLE(FRA))
259 #FRB = DOUBLE(SINGLE(FRB))
260 result
= float(FRA
) + float(FRB
)
261 cvt
= fp64toselectable(result
)
262 cvt
= DOUBLE2SINGLE(cvt
)
263 log ("FPADD32", FRA
, FRB
, result
, cvt
)
267 def FPSUB32(FRA
, FRB
):
268 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
269 #return FPSUB64(FRA, FRB)
270 #FRA = DOUBLE(SINGLE(FRA))
271 #FRB = DOUBLE(SINGLE(FRB))
272 result
= float(FRA
) - float(FRB
)
273 cvt
= fp64toselectable(result
)
274 cvt
= DOUBLE2SINGLE(cvt
)
275 log ("FPSUB32", FRA
, FRB
, result
, cvt
)
279 def signinv(res
, sign
):
288 def FPMUL32(FRA
, FRB
, sign
=1):
289 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
290 #return FPMUL64(FRA, FRB)
291 FRA
= DOUBLE(SINGLE(FRA
))
292 FRB
= DOUBLE(SINGLE(FRB
))
293 result
= signinv(float(FRA
) * float(FRB
), sign
)
294 log ("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
295 cvt
= fp64toselectable(result
)
296 cvt
= DOUBLE2SINGLE(cvt
)
301 def FPMULADD32(FRA
, FRC
, FRB
, mulsign
, addsign
):
302 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
303 #return FPMUL64(FRA, FRB)
304 #FRA = DOUBLE(SINGLE(FRA))
305 #FRB = DOUBLE(SINGLE(FRB))
308 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
310 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
313 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
315 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
318 log ("FPMULADD32", FRA
, FRB
, FRC
,
319 float(FRA
), float(FRB
), float(FRC
),
321 cvt
= fp64toselectable(result
)
322 cvt
= DOUBLE2SINGLE(cvt
)
327 def FPDIV32(FRA
, FRB
, sign
=1):
328 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
329 #return FPDIV64(FRA, FRB)
330 #FRA = DOUBLE(SINGLE(FRA))
331 #FRB = DOUBLE(SINGLE(FRB))
332 result
= signinv(float(FRA
) / float(FRB
), sign
)
333 cvt
= fp64toselectable(result
)
334 cvt
= DOUBLE2SINGLE(cvt
)
335 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
339 def FPADD64(FRA
, FRB
):
340 result
= float(FRA
) + float(FRB
)
341 cvt
= fp64toselectable(result
)
342 log ("FPADD64", FRA
, FRB
, result
, cvt
)
346 def FPSUB64(FRA
, FRB
):
347 result
= float(FRA
) - float(FRB
)
348 cvt
= fp64toselectable(result
)
349 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
353 def FPMUL64(FRA
, FRB
, sign
=1):
354 result
= signinv(float(FRA
) * float(FRB
), sign
)
355 cvt
= fp64toselectable(result
)
356 log ("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
360 def FPDIV64(FRA
, FRB
, sign
=1):
361 result
= signinv(float(FRA
) / float(FRB
), sign
)
362 cvt
= fp64toselectable(result
)
363 log ("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
369 """Returns the integer whose value is the reverse of the lowest
370 'width' bits of the integer 'val'
373 width
= VL
.bit_length()
374 for _
in range(width
):
375 result
= (result
<< 1) |
(val
& 1)
380 # For these tests I tried to find power instructions that would let me
381 # isolate each of these helper operations. So for instance, when I was
382 # testing the MASK() function, I chose rlwinm and rldicl because if I
383 # set the shift equal to 0 and passed in a value of all ones, the
384 # result I got would be exactly the same as the output of MASK()
387 class HelperTests(unittest
.TestCase
):
389 # Verified using rlwinm, rldicl, rldicr in qemu
391 # rlwinm reg, 1, 0, 5, 15
392 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
393 # rlwinm reg, 1, 0, 15, 5
394 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
395 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
396 # rldicl reg, 1, 0, 37
397 self
.assertHex(MASK(37, 63), 0x7ffffff)
398 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
399 self
.assertHex(MASK(58, 63), 0x3f)
400 # rldicr reg, 1, 0, 37
401 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
402 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
403 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
407 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
409 self
.assertHex(MASK(32, 33), 0xc0000000)
410 self
.assertHex(MASK(32, 32), 0x80000000)
411 self
.assertHex(MASK(33, 33), 0x40000000)
413 def test_ROTL64(self
):
414 # r1 = 0xdeadbeef12345678
415 value
= 0xdeadbeef12345678
417 # rldicl reg, 1, 10, 0
418 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
419 # rldicl reg, 1, 35, 0
420 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
421 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
422 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
424 def test_ROTL32(self
):
428 # rlwinm reg, 1, 10, 0, 31
429 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
430 # rlwinm reg, 1, 17, 0, 31
431 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
432 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
433 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
435 def test_EXTS64(self
):
436 value_a
= SelectableInt(0xdeadbeef, 32) # r1
437 value_b
= SelectableInt(0x73123456, 32) # r2
438 value_c
= SelectableInt(0x80000000, 32) # r3
441 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
443 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
445 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
447 def test_FPADD32(self
):
448 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
449 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
450 result
= FPADD32(value_a
, value_b
)
451 self
.assertHex(0x4040266666666666, result
)
453 def assertHex(self
, a
, b
):
455 if isinstance(a
, SelectableInt
):
458 if isinstance(b
, SelectableInt
):
460 msg
= "{:x} != {:x}".format(a_val
, b_val
)
461 return self
.assertEqual(a
, b
, msg
)
464 if __name__
== '__main__':
465 log(SelectableInt
.__bases
__)