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)
210 #No Denormalization Required (includes Zero / Infinity / NaN)
211 if FRS
[1:12].value
> 896 or FRS
[1:64].value
== 0:
213 WORD
[2:32] = FRS
[5:35]
215 #Denormalization Required
216 if FRS
[1:12].value
>= 874 and FRS
[1:12].value
<= 896:
218 exp
= FRS
[1:12] - 1023
219 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
220 # denormalize operand
221 while exp
.value
< -126:
222 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
225 WORD
[1:9] = SelectableInt(0, 8)
226 WORD
[9:32] = frac
[1:24]
227 #else WORD = undefined # return zeros
231 # XXX NOTE: these are very quick hacked functions for utterly basic
234 def fp64toselectable(frt
):
235 """convert FP number to 64 bit SelectableInt
237 b
= struct
.pack(">d", frt
)
238 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
239 return SelectableInt(val
, 64)
243 result
= float(FRA
) + float(FRB
)
244 cvt
= fp64toselectable(result
)
245 print ("FPADD", FRA
, FRB
, result
, cvt
)
249 result
= float(FRA
) - float(FRB
)
250 cvt
= fp64toselectable(result
)
251 print ("FPSUB", FRA
, FRB
, result
, cvt
)
255 result
= float(FRA
) * float(FRB
)
256 cvt
= fp64toselectable(result
)
257 print ("FPMUL", FRA
, FRB
, result
, cvt
)
261 result
= float(FRA
) / float(FRB
)
262 cvt
= fp64toselectable(result
)
263 print ("FPDIV", FRA
, FRB
, result
, cvt
)
266 # For these tests I tried to find power instructions that would let me
267 # isolate each of these helper operations. So for instance, when I was
268 # testing the MASK() function, I chose rlwinm and rldicl because if I
269 # set the shift equal to 0 and passed in a value of all ones, the
270 # result I got would be exactly the same as the output of MASK()
273 class HelperTests(unittest
.TestCase
):
275 # Verified using rlwinm, rldicl, rldicr in qemu
277 # rlwinm reg, 1, 0, 5, 15
278 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
279 # rlwinm reg, 1, 0, 15, 5
280 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
281 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
282 # rldicl reg, 1, 0, 37
283 self
.assertHex(MASK(37, 63), 0x7ffffff)
284 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
285 self
.assertHex(MASK(58, 63), 0x3f)
286 # rldicr reg, 1, 0, 37
287 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
288 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
289 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
293 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
295 self
.assertHex(MASK(32, 33), 0xc0000000)
296 self
.assertHex(MASK(32, 32), 0x80000000)
297 self
.assertHex(MASK(33, 33), 0x40000000)
299 def test_ROTL64(self
):
300 # r1 = 0xdeadbeef12345678
301 value
= 0xdeadbeef12345678
303 # rldicl reg, 1, 10, 0
304 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
305 # rldicl reg, 1, 35, 0
306 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
307 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
308 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
310 def test_ROTL32(self
):
314 # rlwinm reg, 1, 10, 0, 31
315 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
316 # rlwinm reg, 1, 17, 0, 31
317 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
318 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
319 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
321 def test_EXTS64(self
):
322 value_a
= SelectableInt(0xdeadbeef, 32) # r1
323 value_b
= SelectableInt(0x73123456, 32) # r2
324 value_c
= SelectableInt(0x80000000, 32) # r3
327 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
329 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
331 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
333 def test_FPADD(self
):
334 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
335 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
336 result
= FPADD(value_a
, value_b
)
337 self
.assertHex(0x4040266666666666, result
)
339 def assertHex(self
, a
, b
):
341 if isinstance(a
, SelectableInt
):
344 if isinstance(b
, SelectableInt
):
346 msg
= "{:x} != {:x}".format(a_val
, b_val
)
347 return self
.assertEqual(a
, b
, msg
)
350 if __name__
== '__main__':
351 print(SelectableInt
.__bases
__)