Merge branch 'master' of git.libre-soc.org:soc
[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 # signed version of MUL
40 def MULS(a, b):
41 if isinstance(b, int):
42 b = SelectableInt(b, self.bits)
43 b = check_extsign(a, b)
44 a_s = a.value & (1 << (a.bits-1)) != 0
45 b_s = b.value & (1 << (b.bits-1)) != 0
46 result = abs(a) * abs(b)
47 print("MULS", result, a_s, b_s)
48 if a_s == b_s:
49 return result
50 return -result
51
52
53 # XXX should this explicitly extend from 32 to 64?
54 def EXTZ64(value):
55 if isinstance(value, SelectableInt):
56 value = value.value
57 return SelectableInt(value & ((1 << 32)-1), 64)
58
59
60 def rotl(value, bits, wordlen):
61 if isinstance(bits, SelectableInt):
62 bits = bits.value
63 mask = (1 << wordlen) - 1
64 bits = bits & (wordlen - 1)
65 return ((value << bits) | (value >> (wordlen-bits))) & mask
66
67
68 def ROTL64(value, bits):
69 return rotl(value, bits, 64)
70
71
72 def ROTL32(value, bits):
73 if isinstance(value, SelectableInt):
74 value = SelectableInt(value.value, 64)
75 return rotl(value | (value << 32), bits, 64)
76
77
78 def MASK(x, y):
79 if isinstance(x, SelectableInt):
80 x = x.value
81 if isinstance(y, SelectableInt):
82 y = y.value
83 if x < y:
84 x = 64-x
85 y = 63-y
86 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
87 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
88 elif x == y:
89 return 1 << (63-x)
90 else:
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 return mask_a ^ mask_b
96
97
98 def ne(a, b):
99 return onebit(a != b)
100
101
102 def eq(a, b):
103 return onebit(a == b)
104
105
106 def gt(a, b):
107 return onebit(a > b)
108
109
110 def ge(a, b):
111 return onebit(a >= b)
112
113
114 def lt(a, b):
115 return onebit(a < b)
116
117
118 def le(a, b):
119 return onebit(a <= b)
120
121
122 def length(a):
123 return len(a)
124
125 # For these tests I tried to find power instructions that would let me
126 # isolate each of these helper operations. So for instance, when I was
127 # testing the MASK() function, I chose rlwinm and rldicl because if I
128 # set the shift equal to 0 and passed in a value of all ones, the
129 # result I got would be exactly the same as the output of MASK()
130
131
132 class HelperTests(unittest.TestCase):
133 def test_MASK(self):
134 # Verified using rlwinm, rldicl, rldicr in qemu
135 # li 1, -1
136 # rlwinm reg, 1, 0, 5, 15
137 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
138 # rlwinm reg, 1, 0, 15, 5
139 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
140 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
141 # rldicl reg, 1, 0, 37
142 self.assertHex(MASK(37, 63), 0x7ffffff)
143 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
144 self.assertHex(MASK(58, 63), 0x3f)
145 # rldicr reg, 1, 0, 37
146 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
147 self.assertHex(MASK(0, 10), 0xffe0000000000000)
148 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
149
150 # li 2, 5
151 # slw 1, 1, 2
152 self.assertHex(MASK(32, 63-5), 0xffffffe0)
153
154 self.assertHex(MASK(32, 33), 0xc0000000)
155 self.assertHex(MASK(32, 32), 0x80000000)
156 self.assertHex(MASK(33, 33), 0x40000000)
157
158 def test_ROTL64(self):
159 # r1 = 0xdeadbeef12345678
160 value = 0xdeadbeef12345678
161
162 # rldicl reg, 1, 10, 0
163 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
164 # rldicl reg, 1, 35, 0
165 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
166 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
167 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
168
169 def test_ROTL32(self):
170 # r1 = 0xdeadbeef
171 value = 0xdeadbeef
172
173 # rlwinm reg, 1, 10, 0, 31
174 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
175 # rlwinm reg, 1, 17, 0, 31
176 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
177 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
178 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
179
180 def test_EXTS64(self):
181 value_a = SelectableInt(0xdeadbeef, 32) # r1
182 value_b = SelectableInt(0x73123456, 32) # r2
183 value_c = SelectableInt(0x80000000, 32) # r3
184
185 # extswsli reg, 1, 0
186 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
187 # extswsli reg, 2, 0
188 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
189 # extswsli reg, 3, 0
190 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
191
192 def assertHex(self, a, b):
193 a_val = a
194 if isinstance(a, SelectableInt):
195 a_val = a.value
196 b_val = b
197 if isinstance(b, SelectableInt):
198 b_val = b.value
199 msg = "{:x} != {:x}".format(a_val, b_val)
200 return self.assertEqual(a, b, msg)
201
202
203 if __name__ == '__main__':
204 print(SelectableInt.__bases__)
205 unittest.main()