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 exts(value
, bits
):
26 sign
= 1 << (bits
- 1)
27 return (value
& (sign
- 1)) - (value
& sign
)
31 """ extends sign bit out from current MSB to all 256 bits
33 log ("EXTS", value
, type(value
))
34 assert isinstance(value
, SelectableInt
)
35 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
39 """ extends sign bit out from current MSB to 64 bits
41 assert isinstance(value
, SelectableInt
)
42 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
46 """ extends sign bit out from current MSB to 128 bits
48 assert isinstance(value
, SelectableInt
)
49 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
52 # signed version of MUL
54 if isinstance(b
, int):
55 b
= SelectableInt(b
, self
.bits
)
56 b
= check_extsign(a
, b
)
57 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
58 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
59 result
= abs(a
) * abs(b
)
60 log("MULS", result
, a_s
, b_s
)
66 # XXX should this explicitly extend from 32 to 64?
68 if isinstance(value
, SelectableInt
):
70 return SelectableInt(value
& ((1 << 32)-1), 64)
73 def rotl(value
, bits
, wordlen
):
74 if isinstance(bits
, SelectableInt
):
76 mask
= (1 << wordlen
) - 1
77 bits
= bits
& (wordlen
- 1)
78 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
81 def SHL64(value
, bits
, wordlen
=64):
82 if isinstance(bits
, SelectableInt
):
84 mask
= (1 << wordlen
) - 1
85 bits
= bits
& (wordlen
- 1)
86 return SelectableInt((value
<< bits
) & mask
, 64)
89 def ROTL64(value
, bits
):
90 return rotl(value
, bits
, 64)
93 def ROTL32(value
, bits
):
94 if isinstance(bits
, SelectableInt
):
96 if isinstance(value
, SelectableInt
):
97 value
= SelectableInt(value
.value
, 64)
98 return rotl(value |
(value
<< 32), bits
, 64)
101 if isinstance(x
, SelectableInt
):
103 if isinstance(y
, SelectableInt
):
105 return MASK(x
+32, y
+32)
108 if isinstance(x
, SelectableInt
):
110 if isinstance(y
, SelectableInt
):
115 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
116 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
122 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
123 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
124 return mask_a ^ mask_b
128 return onebit(a
!= b
)
132 return onebit(a
== b
)
140 return onebit(a
>= b
)
148 return onebit(a
<= b
)
156 """ function that, for Power spec purposes, returns undefined bits of
157 the same shape as the input bits. however, for purposes of matching
158 POWER9's behavior returns the input bits unchanged. this effectively
159 "marks" (tags) locations in the v3.0B spec that need to be submitted
166 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
168 # result - WORD - start off all zeros
169 WORD
= SelectableInt(0, 32)
176 log ("s e m", s
.value
, e
.value
, m
.value
)
178 #No Denormalization Required (includes Zero / Infinity / NaN)
179 if e
.value
> 896 or FRS
[1:64].value
== 0:
180 log("nodenorm", FRS
[0:2].value
, hex(FRS
[5:35].value
))
182 WORD
[2:32] = FRS
[5:35]
184 #Denormalization Required
185 if e
.value
>= 874 and e
.value
<= 896:
188 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
189 log("exp, fract", exp
, hex(frac
.value
))
190 # denormalize operand
192 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
195 WORD
[1:9] = SelectableInt(0, 8)
196 WORD
[9:32] = frac
[1:24]
197 #else WORD = undefined # return zeros
203 # XXX NOTE: these are very quick hacked functions for utterly basic
206 def fp64toselectable(frt
):
207 """convert FP number to 64 bit SelectableInt
209 b
= struct
.pack(">d", frt
)
210 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
211 return SelectableInt(val
, 64)
215 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
216 #FRB = DOUBLE(SINGLE(FRB))
217 result
= math
.sin(float(FRB
))
218 cvt
= fp64toselectable(result
)
219 cvt
= DOUBLE2SINGLE(cvt
)
220 log ("FPSIN32", FRB
, float(FRB
), "=", result
, cvt
)
225 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
226 #FRB = DOUBLE(SINGLE(FRB))
227 result
= math
.cos(float(FRB
))
228 cvt
= fp64toselectable(result
)
229 cvt
= DOUBLE2SINGLE(cvt
)
230 log ("FPCOS32", FRB
, float(FRB
), "=", result
, cvt
)
234 def FPADD32(FRA
, FRB
):
235 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
236 #return FPADD64(FRA, FRB)
237 #FRA = DOUBLE(SINGLE(FRA))
238 #FRB = DOUBLE(SINGLE(FRB))
239 result
= float(FRA
) + float(FRB
)
240 cvt
= fp64toselectable(result
)
241 cvt
= DOUBLE2SINGLE(cvt
)
242 log ("FPADD32", FRA
, FRB
, float(FRA
), "+", float(FRB
), "=", result
, cvt
)
246 def FPSUB32(FRA
, FRB
):
247 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
248 #return FPSUB64(FRA, FRB)
249 #FRA = DOUBLE(SINGLE(FRA))
250 #FRB = DOUBLE(SINGLE(FRB))
251 result
= float(FRA
) - float(FRB
)
252 cvt
= fp64toselectable(result
)
253 cvt
= DOUBLE2SINGLE(cvt
)
254 log ("FPSUB32", FRA
, FRB
, float(FRA
), "-", float(FRB
), "=", result
, cvt
)
258 def signinv(res
, sign
):
267 def FPMUL32(FRA
, FRB
, sign
=1):
268 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
269 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE
270 #return FPMUL64(FRA, FRB)
271 FRA
= DOUBLE(SINGLE(FRA
))
272 FRB
= DOUBLE(SINGLE(FRB
))
273 result
= signinv(float(FRA
) * float(FRB
), sign
)
274 log ("FPMUL32", FRA
, FRB
, float(FRA
), float(FRB
), result
, sign
)
275 cvt
= fp64toselectable(result
)
276 cvt
= DOUBLE2SINGLE(cvt
)
281 def FPMULADD32(FRA
, FRC
, FRB
, mulsign
, addsign
):
282 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
283 #return FPMUL64(FRA, FRB)
284 #FRA = DOUBLE(SINGLE(FRA))
285 #FRB = DOUBLE(SINGLE(FRB))
288 result
= float(FRA
) * float(FRC
) + float(FRB
) # fmadds
290 result
= -(float(FRA
) * float(FRC
) - float(FRB
)) # fnmsubs
293 result
= float(FRA
) * float(FRC
) - float(FRB
) # fmsubs
295 result
= -(float(FRA
) * float(FRC
) + float(FRB
)) # fnmadds
298 log ("FPMULADD32 FRA FRC FRB", FRA
, FRC
, FRB
)
299 log (" FRA", float(FRA
))
300 log (" FRC", float(FRC
))
301 log (" FRB", float(FRB
))
302 log (" (FRA*FRC)+FRB=", mulsign
, addsign
, result
)
303 cvt
= fp64toselectable(result
)
304 cvt
= DOUBLE2SINGLE(cvt
)
309 def FPDIV32(FRA
, FRB
, sign
=1):
310 from openpower
.decoder
.isafunctions
.double2single
import DOUBLE2SINGLE
311 #return FPDIV64(FRA, FRB)
312 #FRA = DOUBLE(SINGLE(FRA))
313 #FRB = DOUBLE(SINGLE(FRB))
314 result
= signinv(float(FRA
) / float(FRB
), sign
)
315 cvt
= fp64toselectable(result
)
316 cvt
= DOUBLE2SINGLE(cvt
)
317 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
321 def FPADD64(FRA
, FRB
):
322 result
= float(FRA
) + float(FRB
)
323 cvt
= fp64toselectable(result
)
324 log ("FPADD64", FRA
, FRB
, result
, cvt
)
328 def FPSUB64(FRA
, FRB
):
329 result
= float(FRA
) - float(FRB
)
330 cvt
= fp64toselectable(result
)
331 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
335 def FPMUL64(FRA
, FRB
, sign
=1):
336 result
= signinv(float(FRA
) * float(FRB
), sign
)
337 cvt
= fp64toselectable(result
)
338 log ("FPMUL64", FRA
, FRB
, result
, cvt
, sign
)
342 def FPDIV64(FRA
, FRB
, sign
=1):
343 result
= signinv(float(FRA
) / float(FRB
), sign
)
344 cvt
= fp64toselectable(result
)
345 log ("FPDIV64", FRA
, FRB
, result
, cvt
, sign
)
351 """Returns the integer whose value is the reverse of the lowest
352 'width' bits of the integer 'val'
355 width
= VL
.bit_length()-1
356 for _
in range(width
):
357 result
= (result
<< 1) |
(val
& 1)
362 # For these tests I tried to find power instructions that would let me
363 # isolate each of these helper operations. So for instance, when I was
364 # testing the MASK() function, I chose rlwinm and rldicl because if I
365 # set the shift equal to 0 and passed in a value of all ones, the
366 # result I got would be exactly the same as the output of MASK()
369 class HelperTests(unittest
.TestCase
):
371 # Verified using rlwinm, rldicl, rldicr in qemu
373 # rlwinm reg, 1, 0, 5, 15
374 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
375 # rlwinm reg, 1, 0, 15, 5
376 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
377 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
378 # rldicl reg, 1, 0, 37
379 self
.assertHex(MASK(37, 63), 0x7ffffff)
380 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
381 self
.assertHex(MASK(58, 63), 0x3f)
382 # rldicr reg, 1, 0, 37
383 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
384 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
385 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
389 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
391 self
.assertHex(MASK(32, 33), 0xc0000000)
392 self
.assertHex(MASK(32, 32), 0x80000000)
393 self
.assertHex(MASK(33, 33), 0x40000000)
395 def test_ROTL64(self
):
396 # r1 = 0xdeadbeef12345678
397 value
= 0xdeadbeef12345678
399 # rldicl reg, 1, 10, 0
400 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
401 # rldicl reg, 1, 35, 0
402 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
403 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
404 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
406 def test_ROTL32(self
):
410 # rlwinm reg, 1, 10, 0, 31
411 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
412 # rlwinm reg, 1, 17, 0, 31
413 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
414 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
415 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
417 def test_EXTS64(self
):
418 value_a
= SelectableInt(0xdeadbeef, 32) # r1
419 value_b
= SelectableInt(0x73123456, 32) # r2
420 value_c
= SelectableInt(0x80000000, 32) # r3
423 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
425 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
427 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
429 def test_FPADD32(self
):
430 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
431 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
432 result
= FPADD32(value_a
, value_b
)
433 self
.assertHex(0x4040266666666666, result
)
435 def assertHex(self
, a
, b
):
437 if isinstance(a
, SelectableInt
):
440 if isinstance(b
, SelectableInt
):
442 msg
= "{:x} != {:x}".format(a_val
, b_val
)
443 return self
.assertEqual(a
, b
, msg
)
446 if __name__
== '__main__':
447 log(SelectableInt
.__bases
__)