Minor cleanup
[soc.git] / src / soc / decoder / helpers.py
1 import unittest
2
3
4 def exts(value, bits):
5 sign = 1 << (bits - 1)
6 return (value & (sign - 1)) - (value & sign)
7
8
9 def EXTS64(value):
10 return exts(value, 32) & ((1 << 64)-1)
11
12
13 def EXTZ64(value):
14 return value & ((1<<32)-1)
15
16 def rotl(value, bits, wordlen):
17 mask = (1 << wordlen) - 1
18 bits = bits & (wordlen - 1)
19 return ((value << bits) | (value >> (wordlen-bits))) & mask
20
21
22 def ROTL64(value, bits):
23 return rotl(value, bits, 64)
24
25
26 def ROTL32(value, bits):
27 return rotl(value, bits, 32)
28
29
30 def MASK(x, y):
31 if x < y:
32 x = 64-x
33 y = 63-y
34 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
35 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
36 else:
37 x = 64-x
38 y = 63-y
39 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
40 mask_b = (~((1 << y) - 1)) & ((1 << 64) - 1)
41 return mask_a ^ mask_b
42
43
44 # For these tests I tried to find power instructions that would let me
45 # isolate each of these helper operations. So for instance, when I was
46 # testing the MASK() function, I chose rlwinm and rldicl because if I
47 # set the shift equal to 0 and passed in a value of all ones, the
48 # result I got would be exactly the same as the output of MASK()
49
50 class HelperTests(unittest.TestCase):
51 def test_MASK(self):
52 # Verified using rlwinm, rldicl, rldicr in qemu
53 # li 1, -1
54 # rlwinm reg, 1, 0, 5, 15
55 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
56 # rlwinm reg, 1, 0, 15, 5
57 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
58 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
59 # rldicl reg, 1, 0, 37
60 self.assertHex(MASK(37, 63), 0x7ffffff)
61 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
62 self.assertHex(MASK(58, 63), 0x3f)
63 # rldicr reg, 1, 0, 37
64 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
65 self.assertHex(MASK(0, 10), 0xffe0000000000000)
66 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
67
68 def test_ROTL64(self):
69 # r1 = 0xdeadbeef12345678
70 value = 0xdeadbeef12345678
71
72 # rldicl reg, 1, 10, 0
73 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
74 # rldicl reg, 1, 35, 0
75 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
76 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
77 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
78
79 def test_ROTL32(self):
80 # r1 = 0xdeadbeef
81 value = 0xdeadbeef
82
83 # rlwinm reg, 1, 10, 0, 31
84 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
85 # rlwinm reg, 1, 17, 0, 31
86 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
87 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
88 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
89
90 def test_EXTS64(self):
91 value_a = 0xdeadbeef # r1
92 value_b = 0x73123456 # r2
93 value_c = 0x80000000 # r3
94
95 # extswsli reg, 1, 0
96 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
97 # extswsli reg, 2, 0
98 self.assertHex(EXTS64(value_b), value_b)
99 # extswsli reg, 3, 0
100 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
101
102 def assertHex(self, a, b):
103 msg = "{:x} != {:x}".format(a, b)
104 return self.assertEqual(a, b, msg)
105
106
107 if __name__ == '__main__':
108 unittest.main()