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