1# This file is part of PeachPy package and is licensed under the Simplified BSD license.
2#    See license.rst for the full text of the license.
3
4
5class Extension:
6    def __init__(self, name):
7        if name in {'V4', 'V5', 'V5E', 'V6', 'V6K', 'V7', 'V7MP', 'Div', 'Thumb', 'Thumb2',
8                    'VFP', 'VFP2', 'VFP3', 'VFPd32', 'VFPHP', 'VFP4', 'VFPVectorMode',
9                    'XScale', 'WMMX', 'WMMX2', 'NEON', 'NEONHP', 'NEON2'}:
10            self.name = name
11        else:
12            raise ValueError('Invalid ISA extension: {0} is not supported on this architecture'.format(name))
13
14    def __eq__(self, other):
15        return self.name == other.name
16
17    def __ne__(self, other):
18        return self.name != other.name
19
20    def __gt__(self, other):
21        return other in self.prerequisites
22
23    def __lt__(self, other):
24        return self in other.prerequisites
25
26    @property
27    def prerequisites(self):
28        return {
29            'V4': [Extension.V4],
30            'V5': [Extension.V4, Extension.V5],
31            'V5E': [Extension.V4, Extension.V5, Extension.V5E],
32            'V6': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6],
33            'V6K': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K],
34            'V7': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7],
35            'V7MP': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7,
36                     Extension.V7MP],
37            'Div': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7,
38                    Extension.V7MP, Extension.Div],
39            'Thumb': [Extension.Thumb],
40            'Thumb2': [Extension.Thumb, Extension.Thumb2],
41            'VFP': [Extension.VFP],
42            'VFP2': [Extension.VFP, Extension.VFP2],
43            'VFP3': [Extension.VFP, Extension.VFP2, Extension.VFP3],
44            'VFPd32': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPd32],
45            'VFPHP': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPHP],
46            'VFP4': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPHP, Extension.VFP4],
47            'VFPVectorMode': [Extension.VFP, Extension.VFP2, Extension.VFPVectorMode],
48            'XScale': [Extension.XScale],
49            'WMMX': [Extension.WMMX],
50            'WMMX2': [Extension.WMMX, Extension.WMMX2],
51            'NEON': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPd32, Extension.NEON],
52            'NEONHP': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPd32, Extension.NEON,
53                       Extension.NEONHP],
54            'NEON2': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPd32, Extension.NEON,
55                      Extension.NEONHP, Extension.NEON2],
56        }[self.name]
57
58    @property
59    def ancestors(self):
60        return {
61            'V4': [Extension.V4],
62            'V5': [Extension.V4, Extension.V5],
63            'V5E': [Extension.V4, Extension.V5. Extension.V5E],
64            'V6': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6],
65            'V6K': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K],
66            'V7': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7],
67            'V7MP': [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7,
68                     Extension.V7MP],
69            'Div': [Extension.Div],
70            'Thumb': [Extension.Thumb],
71            'Thumb2': [Extension.Thumb, Extension.Thumb2],
72            'VFP': [Extension.VFP],
73            'VFP2': [Extension.VFP, Extension.VFP2],
74            'VFP3': [Extension.VFP, Extension.VFP2, Extension.VFP3],
75            'VFPd32': [Extension.VFPd32],
76            'VFPHP': [Extension.VFPHP],
77            'VFP4': [Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFPHP, Extension.VFP4],
78            'VFPVectorMode': [Extension.VFPVectorMode],
79            'XScale': [Extension.XScale],
80            'WMMX': [Extension.WMMX],
81            'WMMX2': [Extension.WMMX, Extension.WMMX2],
82            'NEON': [Extension.NEON],
83            'NEONHP': [Extension.NEON, Extension.NEONHP],
84            'NEON2': [Extension.NEON, Extension.NEONHP, Extension.NEON2],
85        }[self.name]
86
87    def __add__(self, extension):
88        return Extensions(self, extension)
89
90    def __hash__(self):
91        return hash(self.name)
92
93    def __str__(self):
94        return self.name
95
96    V4, V5, V5E, V6, V6K, V7, V7MP = None, None, None, None, None, None, None
97    Div = None
98    Thumb, Thumb2 = None, None
99    VFP, VFP2, VFP3, VFP4 = None, None, None, None
100    VFPVectorMode, VFPd32, VFPHP = None, None, None
101    XScale, WMMX, WMMX2 = None, None, None
102    NEON, NEONHP, NEON2 = None, None, None
103    All = None
104
105Extension.V4 = Extension('V4')
106Extension.V5 = Extension('V5')
107Extension.V5E = Extension('V5E')
108Extension.V6 = Extension('V6')
109Extension.V6K = Extension('V6K')
110Extension.V7 = Extension('V7')
111Extension.V7MP = Extension('V7MP')
112Extension.Div = Extension('Div')
113Extension.Thumb = Extension('Thumb')
114Extension.Thumb2 = Extension('Thumb2')
115Extension.VFP = Extension('VFP')
116Extension.VFP2 = Extension('VFP2')
117Extension.VFP3 = Extension('VFP3')
118Extension.VFP4 = Extension('VFP4')
119Extension.VFPd32 = Extension('VFPd32')
120Extension.VFPHP = Extension('VFPHP')
121Extension.VFPVectorMode = Extension('VFPVectorMode')
122Extension.XScale = Extension('XScale')
123Extension.WMMX = Extension('WMMX')
124Extension.WMMX2 = Extension('WMMX2')
125Extension.NEON = Extension('NEON')
126Extension.NEONHP = Extension('NEONHP')
127Extension.NEON2 = Extension('NEON2')
128Extension.All = [Extension.V4, Extension.V5, Extension.V5E, Extension.V6, Extension.V6K, Extension.V7, Extension.V7MP,
129                 Extension.Div, Extension.Thumb, Extension.Thumb2,
130                 Extension.VFP, Extension.VFP2, Extension.VFP3, Extension.VFP4, Extension.VFPd32, Extension.VFPHP,
131                 Extension.VFPVectorMode, Extension.XScale, Extension.WMMX, Extension.WMMX2,
132                 Extension.NEON, Extension.NEONHP, Extension.NEON2]
133
134
135class Extensions:
136    def __init__(self, *args):
137        self.extensions = set()
138        for extension in args:
139            if extension is None:
140                pass
141            elif isinstance(extension, Extensions):
142                self.extensions.add(extension.extensions)
143            elif isinstance(extension, Extension):
144                self.extensions.add(extension)
145            else:
146                self.extensions.add(Extension(extension))
147
148    def __add__(self, extension):
149        extensions = set(self.extensions)
150        if isinstance(extension, Extension):
151            extensions.add(extension)
152        else:
153            extensions.add(Extension(extension))
154        return Extensions(*extensions)
155
156    def __sub__(self, extension):
157        extensions = set(self.extensions)
158        if extension in extensions:
159            del extensions[extension]
160        else:
161            raise KeyError('Extension set does not contain {0}'.format(extension))
162        return Extensions(*extensions)
163
164    def __str__(self):
165        extensions = list(reversed(sorted(self.extensions)))
166        for extension in extensions:
167            for ancestor in extension.ancestors:
168                if ancestor != extension and ancestor in extensions:
169                    extensions.remove(ancestor)
170        return ", ".join(sorted(map(str, extensions)))
171
172    def __contains__(self, item):
173        return item in self.extensions
174
175    def __len__(self):
176        return len(self.extensions)
177
178    def __not__(self):
179        return not self.extensions
180
181    def __iter__(self):
182        return iter(self.extensions)
183
184