Fix bug with ROTL32 helper
[soc.git] / src / soc / decoder / helpers.py
1 import unittest
2 from soc.decoder.selectable_int import SelectableInt
3
4
5 def exts(value, bits):
6 sign = 1 << (bits - 1)
7 return (value & (sign - 1)) - (value & sign)
8
9
10 def EXTS(value):
11 """ extends sign bit out from current MSB to all 256 bits
12 """
13 assert isinstance(value, SelectableInt)
14 return SelectableInt(exts(value.value, value.bits) & ((1 << 256)-1), 256)
15
16 def EXTS64(value):
17 """ extends sign bit out from current MSB to 64 bits
18 """
19 assert isinstance(value, SelectableInt)
20 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
21
22
23 # XXX should this explicitly extend from 32 to 64?
24 def EXTZ64(value):
25 if isinstance(value, SelectableInt):
26 value = value.value
27 return SelectableInt(value & ((1<<32)-1), 64)
28
29
30 def rotl(value, bits, wordlen):
31 if isinstance(bits, SelectableInt):
32 bits = bits.value
33 mask = (1 << wordlen) - 1
34 bits = bits & (wordlen - 1)
35 return ((value << bits) | (value >> (wordlen-bits))) & mask
36
37
38 def ROTL64(value, bits):
39 return rotl(value, bits, 64)
40
41
42 def ROTL32(value, bits):
43 if isinstance(value, SelectableInt):
44 value = SelectableInt(value.value, 64)
45 return rotl(value | (value << 32), bits, 64)
46
47
48 def MASK(x, y):
49 if isinstance(x, SelectableInt):
50 x = x.value
51 if isinstance(y, SelectableInt):
52 y = y.value
53 if x < y:
54 x = 64-x
55 y = 63-y
56 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
57 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
58 elif x == y:
59 return 1 << (63-x)
60 else:
61 x = 64-x
62 y = 63-y
63 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
64 mask_b = (~((1 << y) - 1)) & ((1 << 64) - 1)
65 return mask_a ^ mask_b
66
67 def ne(a, b):
68 return SelectableInt((a != b), bits=1)
69
70 def eq(a, b):
71 return SelectableInt((a == b), bits=1)
72
73 def gt(a, b):
74 return SelectableInt((a > b), bits=1)
75
76 def ge(a, b):
77 return SelectableInt((a >= b), bits=1)
78
79 def lt(a, b):
80 return SelectableInt((a < b), bits=1)
81
82 def le(a, b):
83 return SelectableInt((a <= b), bits=1)
84
85 def length(a):
86 return len(a)
87
88 # For these tests I tried to find power instructions that would let me
89 # isolate each of these helper operations. So for instance, when I was
90 # testing the MASK() function, I chose rlwinm and rldicl because if I
91 # set the shift equal to 0 and passed in a value of all ones, the
92 # result I got would be exactly the same as the output of MASK()
93
94 class HelperTests(unittest.TestCase):
95 def test_MASK(self):
96 # Verified using rlwinm, rldicl, rldicr in qemu
97 # li 1, -1
98 # rlwinm reg, 1, 0, 5, 15
99 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
100 # rlwinm reg, 1, 0, 15, 5
101 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
102 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
103 # rldicl reg, 1, 0, 37
104 self.assertHex(MASK(37, 63), 0x7ffffff)
105 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
106 self.assertHex(MASK(58, 63), 0x3f)
107 # rldicr reg, 1, 0, 37
108 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
109 self.assertHex(MASK(0, 10), 0xffe0000000000000)
110 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
111
112 # li 2, 5
113 # slw 1, 1, 2
114 self.assertHex(MASK(32, 63-5), 0xffffffe0)
115
116 self.assertHex(MASK(32, 33), 0xc0000000)
117 self.assertHex(MASK(32, 32), 0x80000000)
118 self.assertHex(MASK(33, 33), 0x40000000)
119
120 def test_ROTL64(self):
121 # r1 = 0xdeadbeef12345678
122 value = 0xdeadbeef12345678
123
124 # rldicl reg, 1, 10, 0
125 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
126 # rldicl reg, 1, 35, 0
127 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
128 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
129 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
130
131 def test_ROTL32(self):
132 # r1 = 0xdeadbeef
133 value = 0xdeadbeef
134
135 # rlwinm reg, 1, 10, 0, 31
136 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
137 # rlwinm reg, 1, 17, 0, 31
138 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
139 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
140 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
141
142 def test_EXTS64(self):
143 value_a = SelectableInt(0xdeadbeef, 32) # r1
144 value_b = SelectableInt(0x73123456, 32) # r2
145 value_c = SelectableInt(0x80000000, 32) # r3
146
147 # extswsli reg, 1, 0
148 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
149 # extswsli reg, 2, 0
150 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
151 # extswsli reg, 3, 0
152 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
153
154 def assertHex(self, a, b):
155 a_val = a
156 if isinstance(a, SelectableInt):
157 a_val = a.value
158 b_val = b
159 if isinstance(b, SelectableInt):
160 b_val = b.value
161 msg = "{:x} != {:x}".format(a_val, b_val)
162 return self.assertEqual(a, b, msg)
163
164
165 if __name__ == '__main__':
166 print (SelectableInt.__bases__)
167 unittest.main()