f0dc1da32053da43c0836bb05961016b750b1ff4
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
18 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
22 def exts(value
, bits
):
23 sign
= 1 << (bits
- 1)
24 return (value
& (sign
- 1)) - (value
& sign
)
28 """ extends sign bit out from current MSB to all 256 bits
30 print ("EXTS", value
, type(value
))
31 assert isinstance(value
, SelectableInt
)
32 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 256)-1), 256)
36 """ extends sign bit out from current MSB to 64 bits
38 assert isinstance(value
, SelectableInt
)
39 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 64)-1), 64)
43 """ extends sign bit out from current MSB to 128 bits
45 assert isinstance(value
, SelectableInt
)
46 return SelectableInt(exts(value
.value
, value
.bits
) & ((1 << 128)-1), 128)
49 # signed version of MUL
51 if isinstance(b
, int):
52 b
= SelectableInt(b
, self
.bits
)
53 b
= check_extsign(a
, b
)
54 a_s
= a
.value
& (1 << (a
.bits
-1)) != 0
55 b_s
= b
.value
& (1 << (b
.bits
-1)) != 0
56 result
= abs(a
) * abs(b
)
57 print("MULS", result
, a_s
, b_s
)
63 # XXX should this explicitly extend from 32 to 64?
65 if isinstance(value
, SelectableInt
):
67 return SelectableInt(value
& ((1 << 32)-1), 64)
70 def rotl(value
, bits
, wordlen
):
71 if isinstance(bits
, SelectableInt
):
73 mask
= (1 << wordlen
) - 1
74 bits
= bits
& (wordlen
- 1)
75 return ((value
<< bits
) |
(value
>> (wordlen
-bits
))) & mask
78 def ROTL64(value
, bits
):
79 return rotl(value
, bits
, 64)
82 def ROTL32(value
, bits
):
83 if isinstance(bits
, SelectableInt
):
85 if isinstance(value
, SelectableInt
):
86 value
= SelectableInt(value
.value
, 64)
87 return rotl(value |
(value
<< 32), bits
, 64)
90 if isinstance(x
, SelectableInt
):
92 if isinstance(y
, SelectableInt
):
94 return MASK(x
+32, y
+32)
97 if isinstance(x
, SelectableInt
):
99 if isinstance(y
, SelectableInt
):
104 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
105 mask_b
= ((1 << y
) - 1) & ((1 << 64) - 1)
111 mask_a
= ((1 << x
) - 1) & ((1 << 64) - 1)
112 mask_b
= (~
((1 << y
) - 1)) & ((1 << 64) - 1)
113 return mask_a ^ mask_b
117 return onebit(a
!= b
)
121 return onebit(a
== b
)
129 return onebit(a
>= b
)
137 return onebit(a
<= b
)
145 """ function that, for Power spec purposes, returns undefined bits of
146 the same shape as the input bits. however, for purposes of matching
147 POWER9's behavior returns the input bits unchanged. this effectively
148 "marks" (tags) locations in the v3.0B spec that need to be submitted
154 """convert incoming WORD to double. v3.0B p140 section 4.6.2
156 # result, FRT, start off all zeros
158 FRT
= SelectableInt(0, 64)
159 z1
= SelectableInt(0, 1)
160 z29
= SelectableInt(0, 29)
164 print ("word s e m", s
, e
, m
)
167 if e
.value
> 0 and e
.value
< 255:
173 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
175 # Denormalized Operand
176 if e
.value
== 0 and m
.value
!= 0:
177 print ("denormalised")
180 frac
= selectconcat(z1
, WORD
[9:32], z29
)
181 # normalize the operand
182 while frac
[0].value
== 0:
183 frac
[0:53] = selectconcat(frac
[1:53], z1
)
186 FRT
[1:12] = exp
+ 1023
187 FRT
[12:64] = frac
[1:53]
189 # Zero / Infinity / NaN
190 if e
.value
== 255 or m
.value
== 0:
196 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
198 print ("Double s e m", FRT
[0].value
, FRT
[1:12].value
-1023,
205 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
207 # result - WORD - start off all zeros
208 WORD
= SelectableInt(0, 32)
214 print ("SINGLE", FRS
)
215 print ("s e m", s
.value
, e
.value
, m
.value
)
217 #No Denormalization Required (includes Zero / Infinity / NaN)
218 if e
.value
> 896 or FRS
[1:64].value
== 0:
220 WORD
[2:32] = FRS
[5:35]
222 #Denormalization Required
223 if e
.value
>= 874 and e
.value
<= 896:
226 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
227 # denormalize operand
228 while exp
.value
< -126:
229 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
232 WORD
[1:9] = SelectableInt(0, 8)
233 WORD
[9:32] = frac
[1:24]
234 #else WORD = undefined # return zeros
240 # XXX NOTE: these are very quick hacked functions for utterly basic
243 def fp64toselectable(frt
):
244 """convert FP number to 64 bit SelectableInt
246 b
= struct
.pack(">d", frt
)
247 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
248 return SelectableInt(val
, 64)
251 def FPADD32(FRA
, FRB
):
252 FRA
= DOUBLE(SINGLE(FRA
))
253 FRB
= DOUBLE(SINGLE(FRB
))
254 result
= float(FRA
) + float(FRB
)
255 cvt
= fp64toselectable(result
)
256 cvt
= DOUBLE(SINGLE(cvt
))
257 print ("FPADD32", FRA
, FRB
, result
, cvt
)
261 def FPSUB32(FRA
, FRB
):
262 FRA
= DOUBLE(SINGLE(FRA
))
263 FRB
= DOUBLE(SINGLE(FRB
))
264 result
= float(FRA
) - float(FRB
)
265 cvt
= fp64toselectable(result
)
266 cvt
= DOUBLE(SINGLE(cvt
))
267 print ("FPSUB32", FRA
, FRB
, result
, cvt
)
271 def FPMUL32(FRA
, FRB
):
272 FRA
= DOUBLE(SINGLE(FRA
))
273 FRB
= DOUBLE(SINGLE(FRB
))
274 result
= float(FRA
) * float(FRB
)
275 cvt
= fp64toselectable(result
)
276 cvt
= DOUBLE(SINGLE(cvt
))
277 print ("FPMUL32", FRA
, FRB
, result
, cvt
)
281 def FPDIV32(FRA
, FRB
):
282 FRA
= DOUBLE(SINGLE(FRA
))
283 FRB
= DOUBLE(SINGLE(FRB
))
284 result
= float(FRA
) / float(FRB
)
285 cvt
= fp64toselectable(result
)
286 cvt
= DOUBLE(SINGLE(cvt
))
287 print ("FPDIV32", FRA
, FRB
, result
, cvt
)
291 def FPADD64(FRA
, FRB
):
292 result
= float(FRA
) + float(FRB
)
293 cvt
= fp64toselectable(result
)
294 print ("FPADD64", FRA
, FRB
, result
, cvt
)
297 def FPSUB64(FRA
, FRB
):
298 result
= float(FRA
) - float(FRB
)
299 cvt
= fp64toselectable(result
)
300 print ("FPSUB64", FRA
, FRB
, result
, cvt
)
303 def FPMUL64(FRA
, FRB
):
304 result
= float(FRA
) * float(FRB
)
305 cvt
= fp64toselectable(result
)
306 print ("FPMUL64", FRA
, FRB
, result
, cvt
)
309 def FPDIV64(FRA
, FRB
):
310 result
= float(FRA
) / float(FRB
)
311 cvt
= fp64toselectable(result
)
312 print ("FPDIV64", FRA
, FRB
, result
, cvt
)
315 # For these tests I tried to find power instructions that would let me
316 # isolate each of these helper operations. So for instance, when I was
317 # testing the MASK() function, I chose rlwinm and rldicl because if I
318 # set the shift equal to 0 and passed in a value of all ones, the
319 # result I got would be exactly the same as the output of MASK()
322 class HelperTests(unittest
.TestCase
):
324 # Verified using rlwinm, rldicl, rldicr in qemu
326 # rlwinm reg, 1, 0, 5, 15
327 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
328 # rlwinm reg, 1, 0, 15, 5
329 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
330 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
331 # rldicl reg, 1, 0, 37
332 self
.assertHex(MASK(37, 63), 0x7ffffff)
333 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
334 self
.assertHex(MASK(58, 63), 0x3f)
335 # rldicr reg, 1, 0, 37
336 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
337 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
338 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
342 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
344 self
.assertHex(MASK(32, 33), 0xc0000000)
345 self
.assertHex(MASK(32, 32), 0x80000000)
346 self
.assertHex(MASK(33, 33), 0x40000000)
348 def test_ROTL64(self
):
349 # r1 = 0xdeadbeef12345678
350 value
= 0xdeadbeef12345678
352 # rldicl reg, 1, 10, 0
353 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
354 # rldicl reg, 1, 35, 0
355 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
356 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
357 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
359 def test_ROTL32(self
):
363 # rlwinm reg, 1, 10, 0, 31
364 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
365 # rlwinm reg, 1, 17, 0, 31
366 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
367 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
368 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
370 def test_EXTS64(self
):
371 value_a
= SelectableInt(0xdeadbeef, 32) # r1
372 value_b
= SelectableInt(0x73123456, 32) # r2
373 value_c
= SelectableInt(0x80000000, 32) # r3
376 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
378 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
380 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
382 def test_FPADD32(self
):
383 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
384 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
385 result
= FPADD32(value_a
, value_b
)
386 self
.assertHex(0x4040266666666666, result
)
388 def assertHex(self
, a
, b
):
390 if isinstance(a
, SelectableInt
):
393 if isinstance(b
, SelectableInt
):
395 msg
= "{:x} != {:x}".format(a_val
, b_val
)
396 return self
.assertEqual(a
, b
, msg
)
399 if __name__
== '__main__':
400 print(SelectableInt
.__bases
__)