forked from intelxed/xed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrefine_regs.py
186 lines (169 loc) · 6.18 KB
/
refine_regs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env python
# -*- python -*-
#BEGIN_LEGAL
#
#Copyright (c) 2020 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#END_LEGAL
from __future__ import print_function
import re
from patterns import *
from genutil import *
import enumer
# $$ reg_info_t
class reg_info_t(object):
def __init__(self, name, type, width,
max_enclosing_reg,
ordinal,
hreg=False,
max_enclosing_reg_32=None,
display_str=None):
self.name = name.upper()
if display_str:
self.display_str = display_str.upper()
else:
self.display_str = self.name
self.type = type.upper()
self.width = width
self.max_enclosing_reg = max_enclosing_reg
self.max_enclosing_reg_32 = max_enclosing_reg_32
self.ordinal = ordinal
self.hreg = hreg # the AH,BH,CH,DH registers
if self.type == 'GPR':
if self.hreg:
self.rtype = self.type + str(self.width) + self.hreg
else:
self.rtype = self.type + str(self.width)
else:
self.rtype = self.type
def refine_regs_input(lines):
"""Return a list of reg_info_t. Skip comments and blank lines"""
global comment_pattern
all_ri = []
reg_width_dict = {}
for line in lines:
pline = comment_pattern.sub('',line).strip()
if pline == '':
continue
wrds = pline.split()
n = len(wrds)
# if there are only 3 fields, duplicate the first field as the 4th field
if n == 3:
n = 4
first = wrds[0]
wrds.append(first)
if n == 6 and (wrds[5] not in [ 'h', '-']):
die("regs-read: Illegal final token on line: " + line)
if n < 4 or n > 7:
die("regs-read: Bad number of tokens on line: " + line)
name = wrds[0]
rtype = wrds[1]
width = wrds[2]
max_enclosing_reg = wrds[3]
max_enclosing_reg_32 = None
if '/' in max_enclosing_reg:
(max_enclosing_reg, max_enclosing_reg_32) = max_enclosing_reg.split('/')
ordinal = 0
if n >= 5:
ordinal = int(wrds[4])
hreg = None
if n >= 6:
hreg = wrds[5]
if hreg != 'h':
hreg = None
# 7th operand is a display string to replace the name in the enumerations
display_str = None
if n >= 7:
display_str = wrds[6]
ri = reg_info_t(name,
rtype,
width,
max_enclosing_reg,
ordinal,
hreg,
max_enclosing_reg_32,
display_str)
all_ri.append(ri)
# CR/DR regs have slashes in the width for 32/64b mode. They
# are not relevant for the register enclosing computation that
# this code is facilitating.
if width == 'NA':
# the pseudo registers use NA as their width. We do not
# care about the enclosing register computation for them.
short_width = '1'
elif '/' in width:
short_width = re.sub(r'/.*','',width)
else:
short_width = width
iw = int(short_width)
if name in reg_width_dict:
if reg_width_dict[name] < iw:
reg_width_dict[name] = iw
else:
reg_width_dict[name] = iw
regs_name_list = []
regs_dict = {}
for ri in all_ri:
# add name to list to preserve original order
if ri.name not in regs_dict:
regs_dict[ri.name] = ri
regs_name_list.append(ri.name)
elif regs_dict[ri.name].width < ri.width: # replace narrower
regs_dict[ri.name] = ri
else:
old_enclosing = regs_dict[ri.name].max_enclosing_reg
a = reg_width_dict[old_enclosing]
b = reg_width_dict[ri.max_enclosing_reg]
print("LER: Comparing {} and {} for {}".format(old_enclosing,
ri.max_enclosing_reg,
ri.name))
if a < b:
# take the wider enclosing registers
print("\ttaking new wider version")
regs_dict[ri.name] = ri
# return a list resembling the original order
regs_list = []
for nm in regs_name_list:
regs_list.append(regs_dict[nm])
return regs_list
def _key_reg_ordinal(x):
return x.ordinal
def rearrange_regs(regs_list):
"""Return a list of enumer.enumer_values_t objects to be passed to
enum_txt_writer"""
groups = uniqueify( [ x.rtype for x in regs_list])
msgb("RGROUPS", str(groups))
enumvals = []
for g in groups:
k = list(filter(lambda x: x.rtype == g, regs_list))
k.sort(key=_key_reg_ordinal)
first = '%s_FIRST' % (g)
last = '%s_LAST' % (g)
# first
enumvals.append(enumer.enumer_value_t(k[0].name,
display_str=k[0].display_str))
enumvals.append(enumer.enumer_value_t(first,
value=k[0].name,
doxygen='//< PSEUDO'))
# everything in the middle
if len(k) > 1:
enumvals.extend(
[ enumer.enumer_value_t(x.name,
display_str=x.display_str) for x in k[1:] ] )
#last
enumvals.append(enumer.enumer_value_t(last,
value=k[-1].name,
doxygen='//<PSEUDO'))
return enumvals