Skip to content

Commit 2bf4390

Browse files
committed
Fixed binutils instruction matching
Signed-off-by: Afonso Oliveira <[email protected]>
1 parent 3496283 commit 2bf4390

File tree

1 file changed

+75
-14
lines changed

1 file changed

+75
-14
lines changed

ext/binutils-gdb/encoding.py

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ def parse_header_files(header_files):
3333
# Replace defined constants in the expression with their values
3434
value = evaluate_expression(value_expr, defines)
3535
defines[name] = value
36-
# Debug: Uncomment the following line to see parsed defines
37-
# print(f"Parsed Define: {name} = {hex(value)}")
3836
except Exception:
3937
# Skip defines that cannot be evaluated
4038
continue
@@ -95,9 +93,6 @@ def parse_instruction_files(instruction_files):
9593
Returns:
9694
instructions (list of dict): Each dict contains 'name', 'match_expr', 'mask_expr', 'class', 'flags', 'line_num', 'file'.
9795
"""
98-
# Updated pattern to capture the entire match and mask expressions and the flags
99-
# Example line:
100-
# {"fence", 0, INSN_CLASS_I, "P,Q", MATCH_FENCE, MASK_FENCE|MASK_RD|MASK_RS1|(MASK_IMM & ~MASK_PRED & ~MASK_SUCC), match_opcode, 0 },
10196
instr_pattern = re.compile(
10297
r'\{\s*"([\w\.]+)",\s*\d+,\s*(INSN_CLASS_\w+),\s*"[^"]*",\s*(MATCH_[^,]+),\s*(MASK_[^,]+),[^,]+,\s*([^}]+)\s*\},'
10398
)
@@ -115,6 +110,15 @@ def parse_instruction_files(instruction_files):
115110
match_expr = instr_match.group(3).strip()
116111
mask_expr = instr_match.group(4).strip()
117112
flags = instr_match.group(5).strip()
113+
114+
# Skip alias entries
115+
if 'INSN_ALIAS' in flags:
116+
continue
117+
118+
# Check if the instruction follows the naming pattern
119+
if not check_match_mask_pattern(instr_name, match_expr, mask_expr):
120+
continue # Skip instructions that don't follow the pattern
121+
118122
instructions.append({
119123
'name': instr_name,
120124
'class': instr_class,
@@ -124,8 +128,6 @@ def parse_instruction_files(instruction_files):
124128
'line_num': line_num,
125129
'file': instr_file
126130
})
127-
# Debug: Uncomment the following line to see parsed instructions
128-
# print(f"Parsed Instruction: {instr_name} at {instr_file}:{line_num}")
129131
except FileNotFoundError:
130132
print(f"Error: Instruction file '{instr_file}' not found.")
131133
sys.exit(1) # Exit if an instruction file is missing
@@ -210,32 +212,91 @@ def get_instruction_yaml_files(directory_path):
210212

211213
def parse_yaml_encoding(yaml_file_path):
212214
"""
213-
Parses the YAML file to extract the 'encoding: match' string.
215+
Parses the YAML file to extract the encoding match string.
216+
Handles the new YAML format with top-level encoding field.
214217
215218
Args:
216219
yaml_file_path (str): Path to the YAML file.
217220
218221
Returns:
219-
match_encoding (str): The 32-character match encoding string.
222+
match_encoding (str): The match encoding string.
220223
"""
221224
try:
222225
with open(yaml_file_path, 'r') as yaml_file:
223226
yaml_content = yaml.safe_load(yaml_file)
224-
if not isinstance(yaml_content, dict) or not yaml_content:
225-
print(f"Warning: YAML file '{yaml_file_path}' is empty or not properly formatted.")
227+
228+
# Handle case where yaml_content is None
229+
if yaml_content is None:
230+
print(f"Warning: Empty YAML file '{yaml_file_path}'.")
231+
return ''
232+
233+
if not isinstance(yaml_content, dict):
234+
print(f"Warning: Unexpected YAML format in '{yaml_file_path}'. Content type: {type(yaml_content)}")
226235
return ''
227-
instr_name = list(yaml_content.keys())[0]
228-
encoding = yaml_content[instr_name].get('encoding', {})
236+
237+
# Get encoding section directly from top level
238+
encoding = yaml_content.get('encoding', {})
239+
240+
if not isinstance(encoding, dict):
241+
print(f"Warning: Encoding is not a dictionary in '{yaml_file_path}'")
242+
return ''
243+
244+
# Get match value directly from encoding section
229245
match_encoding = encoding.get('match', '')
246+
230247
if not match_encoding:
231-
print(f"Warning: 'encoding.match' not found in YAML file '{yaml_file_path}'.")
248+
print(f"Warning: No 'encoding.match' found in YAML file '{yaml_file_path}'.")
249+
250+
# Remove any whitespace in the match encoding
251+
match_encoding = match_encoding.replace(' ', '')
252+
232253
return match_encoding
254+
233255
except FileNotFoundError:
234256
print(f"Error: YAML file '{yaml_file_path}' not found.")
235257
return ''
236258
except yaml.YAMLError as e:
237259
print(f"Error: Failed to parse YAML file '{yaml_file_path}': {e}")
238260
return ''
261+
except Exception as e:
262+
print(f"Error: Unexpected error processing '{yaml_file_path}': {e}")
263+
return ''
264+
265+
266+
def check_match_mask_pattern(instr_name, match_expr, mask_expr):
267+
"""
268+
Checks if the MATCH and MASK names follow the expected pattern based on instruction name.
269+
Allows both MATCH_NAME and MATCH_NAME_SUFFIX patterns.
270+
271+
Args:
272+
instr_name (str): The instruction name (e.g., "add" or "vfmin.vv")
273+
match_expr (str): The MATCH expression (e.g., "MATCH_ADD" or "MATCH_VFMINVV")
274+
mask_expr (str): The MASK expression (e.g., "MASK_ADD" or "MASK_VFMINVV")
275+
276+
Returns:
277+
bool: True if the pattern matches, False otherwise
278+
"""
279+
# Convert instruction name to uppercase and handle special characters
280+
normalized_name = instr_name.replace('.', '')
281+
normalized_name = normalized_name.replace('_', '')
282+
normalized_name = normalized_name.upper()
283+
284+
# Extract the base MATCH and MASK names (before any '|' operations)
285+
base_match = match_expr.split('|')[0].strip()
286+
base_mask = mask_expr.split('|')[0].strip()
287+
288+
# Remove MATCH_ and MASK_ prefixes
289+
if base_match.startswith('MATCH_'):
290+
base_match = base_match[6:] # Remove 'MATCH_'
291+
if base_mask.startswith('MASK_'):
292+
base_mask = base_mask[5:] # Remove 'MASK_'
293+
294+
# Remove any remaining underscores for comparison
295+
base_match = base_match.replace('_', '')
296+
base_mask = base_mask.replace('_', '')
297+
298+
# Now compare the normalized strings
299+
return base_match == normalized_name and base_mask == normalized_name
239300

240301
def main():
241302
"""

0 commit comments

Comments
 (0)