add FP load test lfsx
[openpower-isa.git] / src / openpower / decoder / helpers.py
1 import unittest
2 import struct
3 from openpower.decoder.selectable_int import (SelectableInt, onebit,
4 selectconcat)
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
10
11 trunc_div = floordiv
12 trunc_rem = mod
13 DIVS = trunc_divs
14 MODS = trunc_rems
15
16 """
17 Links:
18 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
19 """
20
21
22 def exts(value, bits):
23 sign = 1 << (bits - 1)
24 return (value & (sign - 1)) - (value & sign)
25
26
27 def EXTS(value):
28 """ extends sign bit out from current MSB to all 256 bits
29 """
30 print ("EXTS", value, type(value))
31 assert isinstance(value, SelectableInt)
32 return SelectableInt(exts(value.value, value.bits) & ((1 << 256)-1), 256)
33
34
35 def EXTS64(value):
36 """ extends sign bit out from current MSB to 64 bits
37 """
38 assert isinstance(value, SelectableInt)
39 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
40
41
42 def EXTS128(value):
43 """ extends sign bit out from current MSB to 128 bits
44 """
45 assert isinstance(value, SelectableInt)
46 return SelectableInt(exts(value.value, value.bits) & ((1 << 128)-1), 128)
47
48
49 # signed version of MUL
50 def MULS(a, b):
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)
58 if a_s == b_s:
59 return result
60 return -result
61
62
63 # XXX should this explicitly extend from 32 to 64?
64 def EXTZ64(value):
65 if isinstance(value, SelectableInt):
66 value = value.value
67 return SelectableInt(value & ((1 << 32)-1), 64)
68
69
70 def rotl(value, bits, wordlen):
71 if isinstance(bits, SelectableInt):
72 bits = bits.value
73 mask = (1 << wordlen) - 1
74 bits = bits & (wordlen - 1)
75 return ((value << bits) | (value >> (wordlen-bits))) & mask
76
77
78 def ROTL64(value, bits):
79 return rotl(value, bits, 64)
80
81
82 def ROTL32(value, bits):
83 if isinstance(bits, SelectableInt):
84 bits = bits.value
85 if isinstance(value, SelectableInt):
86 value = SelectableInt(value.value, 64)
87 return rotl(value | (value << 32), bits, 64)
88
89 def MASK32(x, y):
90 if isinstance(x, SelectableInt):
91 x = x.value
92 if isinstance(y, SelectableInt):
93 y = y.value
94 return MASK(x+32, y+32)
95
96 def MASK(x, y):
97 if isinstance(x, SelectableInt):
98 x = x.value
99 if isinstance(y, SelectableInt):
100 y = y.value
101 if x < y:
102 x = 64-x
103 y = 63-y
104 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
105 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
106 elif x == y:
107 return 1 << (63-x)
108 else:
109 x = 64-x
110 y = 63-y
111 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
112 mask_b = (~((1 << y) - 1)) & ((1 << 64) - 1)
113 return mask_a ^ mask_b
114
115
116 def ne(a, b):
117 return onebit(a != b)
118
119
120 def eq(a, b):
121 return onebit(a == b)
122
123
124 def gt(a, b):
125 return onebit(a > b)
126
127
128 def ge(a, b):
129 return onebit(a >= b)
130
131
132 def lt(a, b):
133 return onebit(a < b)
134
135
136 def le(a, b):
137 return onebit(a <= b)
138
139
140 def length(a):
141 return len(a)
142
143
144 def undefined(v):
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
149 for clarification.
150 """
151 return v
152
153 def DOUBLE(WORD):
154 """convert incoming WORD to double. v3.0B p140 section 4.6.2
155 """
156 # result, FRT, start off all zeros
157 print ("WORD", WORD)
158 FRT = SelectableInt(0, 64)
159 z1 = SelectableInt(0, 1)
160 z29 = SelectableInt(0, 29)
161 e = WORD[1:9]
162 m = WORD[9:32]
163 s = WORD[0]
164 print ("word s e m", s, e, m)
165
166 # Normalized Operand
167 if e.value > 0 and e.value < 255:
168 print ("normalised")
169 FRT[0:2] = WORD[0:2]
170 FRT[2] = ~WORD[1]
171 FRT[3] = ~WORD[1]
172 FRT[4] = ~WORD[1]
173 FRT[5:64] = selectconcat(WORD[2:32], z29)
174
175 # Denormalized Operand
176 if e.value == 0 and m.value != 0:
177 print ("denormalised")
178 sign = WORD[0]
179 exp = -126
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)
184 exp = exp - 1
185 FRT[0] = sign
186 FRT[1:12] = exp + 1023
187 FRT[12:64] = frac[1:53]
188
189 # Zero / Infinity / NaN
190 if e.value == 255 or m.value == 0:
191 print ("z/inf/nan")
192 FRT[0:2] = WORD[0:2]
193 FRT[2] = WORD[1]
194 FRT[3] = WORD[1]
195 FRT[4] = WORD[1]
196 FRT[5:64] = selectconcat(WORD[2:32], z29)
197
198 print ("Double s e m", FRT[0].value, FRT[1:12].value-1023,
199 FRT[12:64].value)
200
201 return FRT
202
203
204 def SINGLE(FRS):
205 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
206 """
207 # result - WORD - start off all zeros
208 WORD = SelectableInt(0, 32)
209
210 #No Denormalization Required (includes Zero / Infinity / NaN)
211 if FRS[1:12].value > 896 or FRS[1:64].value == 0:
212 WORD[0:2] = FRS[0:2]
213 WORD[2:32] = FRS[5:35]
214
215 #Denormalization Required
216 if FRS[1:12].value >= 874 and FRS[1:12].value <= 896:
217 sign = FRS[0]
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])
223 exp = exp + 1
224 WORD[0] = sign
225 WORD[1:9] = SelectableInt(0, 8)
226 WORD[9:32] = frac[1:24]
227 #else WORD = undefined # return zeros
228
229 return WORD
230
231 # XXX NOTE: these are very quick hacked functions for utterly basic
232 # FP support
233
234 def fp64toselectable(frt):
235 """convert FP number to 64 bit SelectableInt
236 """
237 b = struct.pack(">d", frt)
238 val = int.from_bytes(b, byteorder='big', signed=False)
239 return SelectableInt(val, 64)
240
241
242 def FPADD(FRA, FRB):
243 result = float(FRA) + float(FRB)
244 cvt = fp64toselectable(result)
245 print ("FPADD", FRA, FRB, result, cvt)
246
247
248 def FPSUB(FRA, FRB):
249 result = float(FRA) - float(FRB)
250 cvt = fp64toselectable(result)
251 print ("FPSUB", FRA, FRB, result, cvt)
252
253
254 def FPMUL(FRA, FRB):
255 result = float(FRA) * float(FRB)
256 cvt = fp64toselectable(result)
257 print ("FPMUL", FRA, FRB, result, cvt)
258
259
260 def FPDIV(FRA, FRB):
261 result = float(FRA) / float(FRB)
262 cvt = fp64toselectable(result)
263 print ("FPDIV", FRA, FRB, result, cvt)
264
265
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()
271
272
273 class HelperTests(unittest.TestCase):
274 def test_MASK(self):
275 # Verified using rlwinm, rldicl, rldicr in qemu
276 # li 1, -1
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)
290
291 # li 2, 5
292 # slw 1, 1, 2
293 self.assertHex(MASK(32, 63-5), 0xffffffe0)
294
295 self.assertHex(MASK(32, 33), 0xc0000000)
296 self.assertHex(MASK(32, 32), 0x80000000)
297 self.assertHex(MASK(33, 33), 0x40000000)
298
299 def test_ROTL64(self):
300 # r1 = 0xdeadbeef12345678
301 value = 0xdeadbeef12345678
302
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)
309
310 def test_ROTL32(self):
311 # r1 = 0xdeadbeef
312 value = 0xdeadbeef
313
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)
320
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
325
326 # extswsli reg, 1, 0
327 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
328 # extswsli reg, 2, 0
329 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
330 # extswsli reg, 3, 0
331 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
332
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)
338
339 def assertHex(self, a, b):
340 a_val = a
341 if isinstance(a, SelectableInt):
342 a_val = a.value
343 b_val = b
344 if isinstance(b, SelectableInt):
345 b_val = b.value
346 msg = "{:x} != {:x}".format(a_val, b_val)
347 return self.assertEqual(a, b, msg)
348
349
350 if __name__ == '__main__':
351 print(SelectableInt.__bases__)
352 unittest.main()