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
157 FRT
= SelectableInt(0, 64)
158 z1
= SelectableInt(0, 1)
159 z29
= SelectableInt(0, 29)
161 if WORD
[1:9] > 0 and WORD
[1:9] < 255:
166 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
168 # Denormalized Operand
169 if WORD
[1:9] == 0 and WORD
[9:32] != 0:
172 frac
= selectconcat(z1
, WORD
[9:32], z29
)
173 # normalize the operand
175 frac
[0:53] = selectconcat(frac
[1:53], z1
)
178 FRT
[1:12] = exp
+ 1023
179 FRT
[12:64] = frac
[1:53]
181 # Zero / Infinity / NaN
182 if WORD
[1:9] == 255 or WORD
[1:32] == 0:
187 FRT
[5:64] = selectconcat(WORD
[2:32], z29
)
193 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
195 # result - WORD - start off all zeros
196 WORD
= SelectableInt(0, 32)
198 #No Denormalization Required (includes Zero / Infinity / NaN)
199 if FRS
[1:12] > 896 or FRS
[1:64] == 0:
201 WORD
[2:32] = FRS
[5:35]
203 #Denormalization Required
204 if FRS
[1:12] >= 874 and FRS
[1:12] <= 896:
206 exp
= FRS
[1:12] - 1023
207 frac
= selectconcat(SelectableInt(1, 1), FRS
[12:64])
208 # denormalize operand
210 frac
[0:53] = selectconcat(SelectableInt(0, 1), frac
[0:52])
213 WORD
[1:9] = SelectableInt(0, 8)
214 WORD
[9:32] = frac
[1:24]
215 #else WORD = undefined # return zeros
219 def fp64toselectable(frt
):
220 """convert FP number to 64 bit SelectableInt
222 b
= struct
.pack(">d", frt
)
223 val
= int.from_bytes(b
, byteorder
='big', signed
=False)
224 return SelectableInt(val
, 64)
228 result
= float(FRA
) + float(FRB
)
229 cvt
= fp64toselectable(result
)
230 print ("FPADD", FRA
, FRB
, result
, cvt
)
234 result
= float(FRA
) - float(FRB
)
235 cvt
= fp64toselectable(result
)
236 print ("FPSUB", FRA
, FRB
, result
, cvt
)
240 result
= float(FRA
) * float(FRB
)
241 cvt
= fp64toselectable(result
)
242 print ("FPMUL", FRA
, FRB
, result
, cvt
)
246 result
= float(FRA
) / float(FRB
)
247 cvt
= fp64toselectable(result
)
248 print ("FPMUL", FRA
, FRB
, result
, cvt
)
251 # For these tests I tried to find power instructions that would let me
252 # isolate each of these helper operations. So for instance, when I was
253 # testing the MASK() function, I chose rlwinm and rldicl because if I
254 # set the shift equal to 0 and passed in a value of all ones, the
255 # result I got would be exactly the same as the output of MASK()
258 class HelperTests(unittest
.TestCase
):
260 # Verified using rlwinm, rldicl, rldicr in qemu
262 # rlwinm reg, 1, 0, 5, 15
263 self
.assertHex(MASK(5+32, 15+32), 0x7ff0000)
264 # rlwinm reg, 1, 0, 15, 5
265 self
.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
266 self
.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
267 # rldicl reg, 1, 0, 37
268 self
.assertHex(MASK(37, 63), 0x7ffffff)
269 self
.assertHex(MASK(10, 63), 0x3fffffffffffff)
270 self
.assertHex(MASK(58, 63), 0x3f)
271 # rldicr reg, 1, 0, 37
272 self
.assertHex(MASK(0, 37), 0xfffffffffc000000)
273 self
.assertHex(MASK(0, 10), 0xffe0000000000000)
274 self
.assertHex(MASK(0, 58), 0xffffffffffffffe0)
278 self
.assertHex(MASK(32, 63-5), 0xffffffe0)
280 self
.assertHex(MASK(32, 33), 0xc0000000)
281 self
.assertHex(MASK(32, 32), 0x80000000)
282 self
.assertHex(MASK(33, 33), 0x40000000)
284 def test_ROTL64(self
):
285 # r1 = 0xdeadbeef12345678
286 value
= 0xdeadbeef12345678
288 # rldicl reg, 1, 10, 0
289 self
.assertHex(ROTL64(value
, 10), 0xb6fbbc48d159e37a)
290 # rldicl reg, 1, 35, 0
291 self
.assertHex(ROTL64(value
, 35), 0x91a2b3c6f56df778)
292 self
.assertHex(ROTL64(value
, 58), 0xe37ab6fbbc48d159)
293 self
.assertHex(ROTL64(value
, 22), 0xbbc48d159e37ab6f)
295 def test_ROTL32(self
):
299 # rlwinm reg, 1, 10, 0, 31
300 self
.assertHex(ROTL32(value
, 10), 0xb6fbbf7a)
301 # rlwinm reg, 1, 17, 0, 31
302 self
.assertHex(ROTL32(value
, 17), 0x7ddfbd5b)
303 self
.assertHex(ROTL32(value
, 25), 0xdfbd5b7d)
304 self
.assertHex(ROTL32(value
, 30), 0xf7ab6fbb)
306 def test_EXTS64(self
):
307 value_a
= SelectableInt(0xdeadbeef, 32) # r1
308 value_b
= SelectableInt(0x73123456, 32) # r2
309 value_c
= SelectableInt(0x80000000, 32) # r3
312 self
.assertHex(EXTS64(value_a
), 0xffffffffdeadbeef)
314 self
.assertHex(EXTS64(value_b
), SelectableInt(value_b
.value
, 64))
316 self
.assertHex(EXTS64(value_c
), 0xffffffff80000000)
318 def test_FPADD(self
):
319 value_a
= SelectableInt(0x4014000000000000, 64) # 5.0
320 value_b
= SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
321 result
= FPADD(value_a
, value_b
)
322 self
.assertHex(0x4040266666666666, result
)
324 def assertHex(self
, a
, b
):
326 if isinstance(a
, SelectableInt
):
329 if isinstance(b
, SelectableInt
):
331 msg
= "{:x} != {:x}".format(a_val
, b_val
)
332 return self
.assertEqual(a
, b
, msg
)
335 if __name__
== '__main__':
336 print(SelectableInt
.__bases
__)