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
21 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
25 def RANGE(start
, end
):
27 # auto-subtract-one (sigh) due to python range
30 # auto-add-one (sigh) due to python range
32 return range(start
, end
)
35 def exts(value
, bits
):
36 sign
= 1 << (bits
- 1)
37 return (value
& (sign
- 1)) - (value
& sign
)
41 """ extends sign bit out from current MSB to all 256 bits
43 log ("EXTS", value
, type(value
))
44 assert isinstance(value
, SelectableInt
)
45 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
49 """ extends sign bit out from current MSB to 64 bits
51 assert isinstance(value
, SelectableInt
)
52 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
56 """ extends sign bit out from current MSB to 128 bits
58 assert isinstance(value
, SelectableInt
)
59 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
62 # signed version of MUL
64 if isinstance(b
, int):
65 b
= SelectableInt(b
, self
.bits
)
66 b
= check_extsign(a
, b
)
67 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
68 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
69 result
= abs(a
) * abs(b
)
70 log("MULS", result
, a_s
, b_s
)
76 # XXX should this explicitly extend from 32 to 64?
78 if isinstance(value
, SelectableInt
):
80 return SelectableInt(value
& ((1 << 32)-1), 64)
83 def rotl(value
, bits
, wordlen
):
84 if isinstance(bits
, SelectableInt
):
86 mask
= (1 << wordlen
) - 1
87 bits
= bits
& (wordlen
- 1)
88 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
91 def SHL64(value
, bits
, wordlen
=64):
92 if isinstance(bits
, SelectableInt
):
94 mask
= (1 << wordlen
) - 1
95 bits
= bits
& (wordlen
- 1)
96 return SelectableInt((value
<< bits
) & mask
, 64)
99 def ROTL64(value
, bits
):
100 return rotl(value
, bits
, 64)
103 def ROTL32(value
, bits
):
104 if isinstance(bits
, SelectableInt
):
106 if isinstance(value
, SelectableInt
):
107 value
= SelectableInt(value
.value
, 64)
108 return rotl(value |
(value
<< 32), bits
, 64)
111 if isinstance(x
, SelectableInt
):
113 if isinstance(y
, SelectableInt
):
115 return MASK(x
+32, y
+32)
118 if isinstance(x
, SelectableInt
):
120 if isinstance(y
, SelectableInt
):
125 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
126 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
132 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
133 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
134 return mask_a ^ mask_b
138 return onebit(a
!= b
)
142 return onebit(a
== b
)
150 return onebit(a
>= b
)
158 return onebit(a
<= b
)
166 """ function that, for Power spec purposes, returns undefined bits of
167 the same shape as the input bits. however, for purposes of matching
168 POWER9's behavior returns the input bits unchanged. this effectively
169 "marks" (tags) locations in the v3.0B spec that need to be submitted
176 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
178 # result - WORD - start off all zeros
179 WORD
= SelectableInt(0, 32)
186 log ("s e m", s
.value
, e
.value
, m
.value
)
188 #No Denormalization Required (includes Zero / Infinity / NaN)
189 if e
.value
> 896 or FRS
[1:64].value
== 0:
190 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
192 WORD
[2:32] = FRS
[5:35]
194 #Denormalization Required
195 if e
.value
>= 874 and e
.value
<= 896:
198 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
199 log("exp, fract", exp
, hex(frac
.value
))
200 # denormalize operand
202 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
205 WORD
[1:9] = SelectableInt(0, 8)
206 WORD
[9:32] = frac
[1:24]
207 #else WORD = undefined # return zeros
213 # XXX NOTE: these are very quick hacked functions for utterly basic
216 def fp64toselectable(frt
):
217 """convert FP number to 64 bit SelectableInt
219 b
= struct
.pack(">d", frt
)
220 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
221 return SelectableInt(val
, 64)
225 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
226 #FRB = DOUBLE(SINGLE(FRB))
227 result
= math
.sin(float(FRB
))
228 cvt
= fp64toselectable(result
)
229 cvt
= DOUBLE2SINGLE(cvt
)
230 log ("FPSIN32", FRB
, float(FRB
), "=", result
, cvt
)
235 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
236 #FRB = DOUBLE(SINGLE(FRB))
237 result
= math
.cos(float(FRB
))
238 cvt
= fp64toselectable(result
)
239 cvt
= DOUBLE2SINGLE(cvt
)
240 log ("FPCOS32", FRB
, float(FRB
), "=", result
, cvt
)
244 def FPADD32(FRA
, FRB
):
245 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
246 #return FPADD64(FRA, FRB)
247 #FRA = DOUBLE(SINGLE(FRA))
248 #FRB = DOUBLE(SINGLE(FRB))
249 result
= float(FRA
) + float(FRB
)
250 cvt
= fp64toselectable(result
)
251 cvt
= DOUBLE2SINGLE(cvt
)
252 log ("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
256 def FPSUB32(FRA
, FRB
):
257 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
258 #return FPSUB64(FRA, FRB)
259 #FRA = DOUBLE(SINGLE(FRA))
260 #FRB = DOUBLE(SINGLE(FRB))
261 result
= float(FRA
) - float(FRB
)
262 cvt
= fp64toselectable(result
)
263 cvt
= DOUBLE2SINGLE(cvt
)
264 log ("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
268 def signinv(res
, sign
):
277 def FPMUL32(FRA
, FRB
, sign
=1):
278 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
279 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE
280 #return FPMUL64(FRA, FRB)
281 FRA
= DOUBLE(SINGLE(FRA
))
282 FRB
= DOUBLE(SINGLE(FRB
))
283 result
= signinv(float(FRA
) * float(FRB
), sign
)
284 log ("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
285 cvt
= fp64toselectable(result
)
286 cvt
= DOUBLE2SINGLE(cvt
)
291 def FPMULADD32(FRA
, FRC
, FRB
, mulsign
, addsign
):
292 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
293 #return FPMUL64(FRA, FRB)
294 #FRA = DOUBLE(SINGLE(FRA))
295 #FRB = DOUBLE(SINGLE(FRB))
298 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
300 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
303 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
305 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
308 log ("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
309 log (" FRA", float(FRA
))
310 log (" FRC", float(FRC
))
311 log (" FRB", float(FRB
))
312 log (" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
313 cvt
= fp64toselectable(result
)
314 cvt
= DOUBLE2SINGLE(cvt
)
319 def FPDIV32(FRA
, FRB
, sign
=1):
320 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
321 #return FPDIV64(FRA, FRB)
322 #FRA = DOUBLE(SINGLE(FRA))
323 #FRB = DOUBLE(SINGLE(FRB))
324 result
= signinv(float(FRA
) / float(FRB
), sign
)
325 cvt
= fp64toselectable(result
)
326 cvt
= DOUBLE2SINGLE(cvt
)
327 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
331 def FPADD64(FRA
, FRB
):
332 result
= float(FRA
) + float(FRB
)
333 cvt
= fp64toselectable(result
)
334 log ("FPADD64", FRA
, FRB
, result
, cvt
)
338 def FPSUB64(FRA
, FRB
):
339 result
= float(FRA
) - float(FRB
)
340 cvt
= fp64toselectable(result
)
341 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
345 def FPMUL64(FRA
, FRB
, sign
=1):
346 result
= signinv(float(FRA
) * float(FRB
), sign
)
347 cvt
= fp64toselectable(result
)
348 log ("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
352 def FPDIV64(FRA
, FRB
, sign
=1):
353 result
= signinv(float(FRA
) / float(FRB
), sign
)
354 cvt
= fp64toselectable(result
)
355 log ("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
361 """Returns the integer whose value is the reverse of the lowest
362 'width' bits of the integer 'val'
365 width
= VL
.bit_length()-1
366 for _
in range(width
):
367 result
= (result
<< 1) |
(val
& 1)
372 # For these tests I tried to find power instructions that would let me
373 # isolate each of these helper operations. So for instance, when I was
374 # testing the MASK() function, I chose rlwinm and rldicl because if I
375 # set the shift equal to 0 and passed in a value of all ones, the
376 # result I got would be exactly the same as the output of MASK()
379 class HelperTests(unittest
.TestCase
):
381 # Verified using rlwinm, rldicl, rldicr in qemu
383 # rlwinm reg, 1, 0, 5, 15
384 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
385 # rlwinm reg, 1, 0, 15, 5
386 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
387 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
388 # rldicl reg, 1, 0, 37
389 self
.assertHex(MASK(37, 63), 0x7ffffff)
390 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
391 self
.assertHex(MASK(58, 63), 0x3f)
392 # rldicr reg, 1, 0, 37
393 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
394 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
395 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
399 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
401 self
.assertHex(MASK(32, 33), 0xc0000000)
402 self
.assertHex(MASK(32, 32), 0x80000000)
403 self
.assertHex(MASK(33, 33), 0x40000000)
405 def test_ROTL64(self
):
406 # r1 = 0xdeadbeef12345678
407 value
= 0xdeadbeef12345678
409 # rldicl reg, 1, 10, 0
410 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
411 # rldicl reg, 1, 35, 0
412 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
413 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
414 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
416 def test_ROTL32(self
):
420 # rlwinm reg, 1, 10, 0, 31
421 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
422 # rlwinm reg, 1, 17, 0, 31
423 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
424 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
425 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
427 def test_EXTS64(self
):
428 value_a
= SelectableInt(0xdeadbeef, 32) # r1
429 value_b
= SelectableInt(0x73123456, 32) # r2
430 value_c
= SelectableInt(0x80000000, 32) # r3
433 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
435 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
437 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
439 def test_FPADD32(self
):
440 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
441 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
442 result
= FPADD32(value_a
, value_b
)
443 self
.assertHex(0x4040266666666666, result
)
445 def assertHex(self
, a
, b
):
447 if isinstance(a
, SelectableInt
):
450 if isinstance(b
, SelectableInt
):
452 msg
= "{:x} != {:x}".format(a_val
, b_val
)
453 return self
.assertEqual(a
, b
, msg
)
456 if __name__
== '__main__':
457 log(SelectableInt
.__bases
__)