fix div tests
[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 # For these tests I tried to find power instructions that would let me
133 # isolate each of these helper operations. So for instance, when I was
134 # testing the MASK() function, I chose rlwinm and rldicl because if I
135 # set the shift equal to 0 and passed in a value of all ones, the
136 # result I got would be exactly the same as the output of MASK()
137
138
139 class HelperTests(unittest.TestCase):
140 def test_MASK(self):
141 # Verified using rlwinm, rldicl, rldicr in qemu
142 # li 1, -1
143 # rlwinm reg, 1, 0, 5, 15
144 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
145 # rlwinm reg, 1, 0, 15, 5
146 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
147 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
148 # rldicl reg, 1, 0, 37
149 self.assertHex(MASK(37, 63), 0x7ffffff)
150 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
151 self.assertHex(MASK(58, 63), 0x3f)
152 # rldicr reg, 1, 0, 37
153 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
154 self.assertHex(MASK(0, 10), 0xffe0000000000000)
155 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
156
157 # li 2, 5
158 # slw 1, 1, 2
159 self.assertHex(MASK(32, 63-5), 0xffffffe0)
160
161 self.assertHex(MASK(32, 33), 0xc0000000)
162 self.assertHex(MASK(32, 32), 0x80000000)
163 self.assertHex(MASK(33, 33), 0x40000000)
164
165 def test_ROTL64(self):
166 # r1 = 0xdeadbeef12345678
167 value = 0xdeadbeef12345678
168
169 # rldicl reg, 1, 10, 0
170 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
171 # rldicl reg, 1, 35, 0
172 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
173 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
174 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
175
176 def test_ROTL32(self):
177 # r1 = 0xdeadbeef
178 value = 0xdeadbeef
179
180 # rlwinm reg, 1, 10, 0, 31
181 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
182 # rlwinm reg, 1, 17, 0, 31
183 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
184 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
185 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
186
187 def test_EXTS64(self):
188 value_a = SelectableInt(0xdeadbeef, 32) # r1
189 value_b = SelectableInt(0x73123456, 32) # r2
190 value_c = SelectableInt(0x80000000, 32) # r3
191
192 # extswsli reg, 1, 0
193 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
194 # extswsli reg, 2, 0
195 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
196 # extswsli reg, 3, 0
197 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
198
199 def assertHex(self, a, b):
200 a_val = a
201 if isinstance(a, SelectableInt):
202 a_val = a.value
203 b_val = b
204 if isinstance(b, SelectableInt):
205 b_val = b.value
206 msg = "{:x} != {:x}".format(a_val, b_val)
207 return self.assertEqual(a, b, msg)
208
209
210 if __name__ == '__main__':
211 print(SelectableInt.__bases__)
212 unittest.main()