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