70e05d9716fc503cc5a2e9a20d9c046d9ac85990
[openpower-isa.git] / src / openpower / decoder / helpers.py
1 import unittest
2 from openpower.decoder.selectable_int import SelectableInt, onebit
3 from nmutil.divmod import trunc_divs, trunc_rems
4 from operator import floordiv, mod
5 from openpower.decoder.selectable_int import selectltu as ltu
6 from openpower.decoder.selectable_int import selectgtu as gtu
7 from openpower.decoder.selectable_int import check_extsign
8
9 trunc_div = floordiv
10 trunc_rem = mod
11 DIVS = trunc_divs
12 MODS = trunc_rems
13
14 """
15 Links:
16 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
17 """
18
19
20 def exts(value, bits):
21 sign = 1 << (bits - 1)
22 return (value & (sign - 1)) - (value & sign)
23
24
25 def EXTS(value):
26 """ extends sign bit out from current MSB to all 256 bits
27 """
28 print ("EXTS", value, type(value))
29 assert isinstance(value, SelectableInt)
30 return SelectableInt(exts(value.value, value.bits) & ((1 << 256)-1), 256)
31
32
33 def EXTS64(value):
34 """ extends sign bit out from current MSB to 64 bits
35 """
36 assert isinstance(value, SelectableInt)
37 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
38
39
40 def EXTS128(value):
41 """ extends sign bit out from current MSB to 128 bits
42 """
43 assert isinstance(value, SelectableInt)
44 return SelectableInt(exts(value.value, value.bits) & ((1 << 128)-1), 128)
45
46
47 # signed version of MUL
48 def MULS(a, b):
49 if isinstance(b, int):
50 b = SelectableInt(b, self.bits)
51 b = check_extsign(a, b)
52 a_s = a.value & (1 << (a.bits-1)) != 0
53 b_s = b.value & (1 << (b.bits-1)) != 0
54 result = abs(a) * abs(b)
55 print("MULS", result, a_s, b_s)
56 if a_s == b_s:
57 return result
58 return -result
59
60
61 # XXX should this explicitly extend from 32 to 64?
62 def EXTZ64(value):
63 if isinstance(value, SelectableInt):
64 value = value.value
65 return SelectableInt(value & ((1 << 32)-1), 64)
66
67
68 def rotl(value, bits, wordlen):
69 if isinstance(bits, SelectableInt):
70 bits = bits.value
71 mask = (1 << wordlen) - 1
72 bits = bits & (wordlen - 1)
73 return ((value << bits) | (value >> (wordlen-bits))) & mask
74
75
76 def ROTL64(value, bits):
77 return rotl(value, bits, 64)
78
79
80 def ROTL32(value, bits):
81 if isinstance(bits, SelectableInt):
82 bits = bits.value
83 if isinstance(value, SelectableInt):
84 value = SelectableInt(value.value, 64)
85 return rotl(value | (value << 32), bits, 64)
86
87 def MASK32(x, y):
88 if isinstance(x, SelectableInt):
89 x = x.value
90 if isinstance(y, SelectableInt):
91 y = y.value
92 return MASK(x+32, y+32)
93
94 def MASK(x, y):
95 if isinstance(x, SelectableInt):
96 x = x.value
97 if isinstance(y, SelectableInt):
98 y = y.value
99 if x < y:
100 x = 64-x
101 y = 63-y
102 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
103 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
104 elif x == y:
105 return 1 << (63-x)
106 else:
107 x = 64-x
108 y = 63-y
109 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
110 mask_b = (~((1 << y) - 1)) & ((1 << 64) - 1)
111 return mask_a ^ mask_b
112
113
114 def ne(a, b):
115 return onebit(a != b)
116
117
118 def eq(a, b):
119 return onebit(a == b)
120
121
122 def gt(a, b):
123 return onebit(a > b)
124
125
126 def ge(a, b):
127 return onebit(a >= b)
128
129
130 def lt(a, b):
131 return onebit(a < b)
132
133
134 def le(a, b):
135 return onebit(a <= b)
136
137
138 def length(a):
139 return len(a)
140
141
142 def undefined(v):
143 """ function that, for Power spec purposes, returns undefined bits of
144 the same shape as the input bits. however, for purposes of matching
145 POWER9's behavior returns the input bits unchanged. this effectively
146 "marks" (tags) locations in the v3.0B spec that need to be submitted
147 for clarification.
148 """
149 return v
150
151 # For these tests I tried to find power instructions that would let me
152 # isolate each of these helper operations. So for instance, when I was
153 # testing the MASK() function, I chose rlwinm and rldicl because if I
154 # set the shift equal to 0 and passed in a value of all ones, the
155 # result I got would be exactly the same as the output of MASK()
156
157
158 class HelperTests(unittest.TestCase):
159 def test_MASK(self):
160 # Verified using rlwinm, rldicl, rldicr in qemu
161 # li 1, -1
162 # rlwinm reg, 1, 0, 5, 15
163 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
164 # rlwinm reg, 1, 0, 15, 5
165 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
166 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
167 # rldicl reg, 1, 0, 37
168 self.assertHex(MASK(37, 63), 0x7ffffff)
169 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
170 self.assertHex(MASK(58, 63), 0x3f)
171 # rldicr reg, 1, 0, 37
172 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
173 self.assertHex(MASK(0, 10), 0xffe0000000000000)
174 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
175
176 # li 2, 5
177 # slw 1, 1, 2
178 self.assertHex(MASK(32, 63-5), 0xffffffe0)
179
180 self.assertHex(MASK(32, 33), 0xc0000000)
181 self.assertHex(MASK(32, 32), 0x80000000)
182 self.assertHex(MASK(33, 33), 0x40000000)
183
184 def test_ROTL64(self):
185 # r1 = 0xdeadbeef12345678
186 value = 0xdeadbeef12345678
187
188 # rldicl reg, 1, 10, 0
189 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
190 # rldicl reg, 1, 35, 0
191 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
192 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
193 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
194
195 def test_ROTL32(self):
196 # r1 = 0xdeadbeef
197 value = 0xdeadbeef
198
199 # rlwinm reg, 1, 10, 0, 31
200 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
201 # rlwinm reg, 1, 17, 0, 31
202 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
203 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
204 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
205
206 def test_EXTS64(self):
207 value_a = SelectableInt(0xdeadbeef, 32) # r1
208 value_b = SelectableInt(0x73123456, 32) # r2
209 value_c = SelectableInt(0x80000000, 32) # r3
210
211 # extswsli reg, 1, 0
212 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
213 # extswsli reg, 2, 0
214 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
215 # extswsli reg, 3, 0
216 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
217
218 def assertHex(self, a, b):
219 a_val = a
220 if isinstance(a, SelectableInt):
221 a_val = a.value
222 b_val = b
223 if isinstance(b, SelectableInt):
224 b_val = b.value
225 msg = "{:x} != {:x}".format(a_val, b_val)
226 return self.assertEqual(a, b, msg)
227
228
229 if __name__ == '__main__':
230 print(SelectableInt.__bases__)
231 unittest.main()