db7ef6da7f44f4c43c479e9cb14976d8aa59f58a
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 #return FPADD64(FRA, FRB)
257 #FRA = DOUBLE(SINGLE(FRA))
258 #FRB = DOUBLE(SINGLE(FRB))
259 result
= float(FRA
) + float(FRB
)
260 cvt
= fp64toselectable(result
)
261 cvt
= DOUBLE(SINGLE(cvt
))
262 log ("FPADD32", FRA
, FRB
, result
, cvt
)
266 def FPSUB32(FRA
, FRB
):
267 #return FPSUB64(FRA, FRB)
268 #FRA = DOUBLE(SINGLE(FRA))
269 #FRB = DOUBLE(SINGLE(FRB))
270 result
= float(FRA
) - float(FRB
)
271 cvt
= fp64toselectable(result
)
272 cvt
= DOUBLE(SINGLE(cvt
))
273 log ("FPSUB32", FRA
, FRB
, result
, cvt
)
277 def FPMUL32(FRA
, FRB
):
278 #return FPMUL64(FRA, FRB)
279 #FRA = DOUBLE(SINGLE(FRA))
280 #FRB = DOUBLE(SINGLE(FRB))
281 result
= float(FRA
) * float(FRB
)
282 cvt
= fp64toselectable(result
)
283 cvt
= DOUBLE(SINGLE(cvt
))
284 log ("FPMUL32", FRA
, FRB
, result
, cvt
)
288 def FPDIV32(FRA
, FRB
):
289 #return FPDIV64(FRA, FRB)
290 #FRA = DOUBLE(SINGLE(FRA))
291 #FRB = DOUBLE(SINGLE(FRB))
292 result
= float(FRA
) / float(FRB
)
293 cvt
= fp64toselectable(result
)
294 cvt
= DOUBLE(SINGLE(cvt
))
295 log ("FPDIV32", FRA
, FRB
, result
, cvt
)
299 def FPADD64(FRA
, FRB
):
300 result
= float(FRA
) + float(FRB
)
301 cvt
= fp64toselectable(result
)
302 log ("FPADD64", FRA
, FRB
, result
, cvt
)
306 def FPSUB64(FRA
, FRB
):
307 result
= float(FRA
) - float(FRB
)
308 cvt
= fp64toselectable(result
)
309 log ("FPSUB64", FRA
, FRB
, result
, cvt
)
313 def FPMUL64(FRA
, FRB
):
314 result
= float(FRA
) * float(FRB
)
315 cvt
= fp64toselectable(result
)
316 log ("FPMUL64", FRA
, FRB
, result
, cvt
)
320 def FPDIV64(FRA
, FRB
):
321 result
= float(FRA
) / float(FRB
)
322 cvt
= fp64toselectable(result
)
323 log ("FPDIV64", FRA
, FRB
, result
, cvt
)
327 # For these tests I tried to find power instructions that would let me
328 # isolate each of these helper operations. So for instance, when I was
329 # testing the MASK() function, I chose rlwinm and rldicl because if I
330 # set the shift equal to 0 and passed in a value of all ones, the
331 # result I got would be exactly the same as the output of MASK()
334 class HelperTests(unittest
.TestCase
):
336 # Verified using rlwinm, rldicl, rldicr in qemu
338 # rlwinm reg, 1, 0, 5, 15
339 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
340 # rlwinm reg, 1, 0, 15, 5
341 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
342 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
343 # rldicl reg, 1, 0, 37
344 self
.assertHex(MASK(37, 63), 0x7ffffff)
345 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
346 self
.assertHex(MASK(58, 63), 0x3f)
347 # rldicr reg, 1, 0, 37
348 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
349 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
350 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
354 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
356 self
.assertHex(MASK(32, 33), 0xc0000000)
357 self
.assertHex(MASK(32, 32), 0x80000000)
358 self
.assertHex(MASK(33, 33), 0x40000000)
360 def test_ROTL64(self
):
361 # r1 = 0xdeadbeef12345678
362 value
= 0xdeadbeef12345678
364 # rldicl reg, 1, 10, 0
365 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
366 # rldicl reg, 1, 35, 0
367 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
368 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
369 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
371 def test_ROTL32(self
):
375 # rlwinm reg, 1, 10, 0, 31
376 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
377 # rlwinm reg, 1, 17, 0, 31
378 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
379 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
380 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
382 def test_EXTS64(self
):
383 value_a
= SelectableInt(0xdeadbeef, 32) # r1
384 value_b
= SelectableInt(0x73123456, 32) # r2
385 value_c
= SelectableInt(0x80000000, 32) # r3
388 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
390 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
392 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
394 def test_FPADD32(self
):
395 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
396 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
397 result
= FPADD32(value_a
, value_b
)
398 self
.assertHex(0x4040266666666666, result
)
400 def assertHex(self
, a
, b
):
402 if isinstance(a
, SelectableInt
):
405 if isinstance(b
, SelectableInt
):
407 msg
= "{:x} != {:x}".format(a_val
, b_val
)
408 return self
.assertEqual(a
, b
, msg
)
411 if __name__
== '__main__':
412 log(SelectableInt
.__bases
__)