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