Hi Khushit,
On 9/24/26 12:18 PM, Khushit Shah wrote:
> Only few nits.
>
>> On 16 Sep 2026, at 8:15 PM, Eric Auger <[email protected]> wrote:
>>
>> !-------------------------------------------------------------------|
>> CAUTION: External Email
>>
>> |-------------------------------------------------------------------!
>>
>> We plan to reuse get_opcode() and extract_idregs_from_registers_json()
>> functions in another script. So let's move them into a module
> Nit: fullstop.
yes
>
>> No functional change intended.
>>
>> Signed-off-by: Eric Auger <[email protected]>
>> Reviewed-by: Khushit Shah <[email protected]>
>> ---
>> scripts/aarch64_sysreg_helpers.py | 121 +++++++++++++++++++
>> scripts/update-aarch64-cpu-sysregs-header.py | 97 +--------------
>> 2 files changed, 122 insertions(+), 96 deletions(-)
>> create mode 100644 scripts/aarch64_sysreg_helpers.py
>>
>> diff --git a/scripts/aarch64_sysreg_helpers.py
>> b/scripts/aarch64_sysreg_helpers.py
>> new file mode 100644
>> index 0000000000..24bbc5bb3d
>> --- /dev/null
>> +++ b/scripts/aarch64_sysreg_helpers.py
>> @@ -0,0 +1,121 @@
>> +#!/usr/bin/env python3
>> +
>> +# Helpers used in aarch64 sysreg definition generation
>> +#
>> +# Copyright (C) 2026 Red Hat, Inc.
>> +#
>> +# Authors: Eric Auger <[email protected]>
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +
>> +import json
>> +import os
>> +
>> +def is_demux_register(r):
>> + name = r.get('name', '')
>> +
>> + if name.startswith("CCSIDR"):
>> + return True
>> +
>> + return False
>> +
>> +# Some regs have op code values like 000x, 001x. Anyway we don't need
>> +# them. Besides some regs are undesired in the generated file such as
>> +# VMPIDR_EL2 and VPIDR_EL2 which are outside of the IDreg scope we
>> +# are interested in and are tricky to decode as their system accessor
>> +# refer to MPIDR_EL1/MIDR_EL1 respectively
>> +
>> +skiplist = ['ALLINT', 'PM', 'S1_', 'S3_', 'SVCR', \
>> + 'VMPIDR_EL2', 'VPIDR_EL2']
>> +
>> +# returns the int value of a given @opcode for a reg @encoding
>> +def get_opcode(encoding, opcode):
>> + fvalue = encoding.get(opcode)
>> + if fvalue:
>> + value = fvalue.get('value')
>> + if isinstance(value, str):
>> + value = value.strip("'")
>> + value = int(value, 2)
>> + return value
>> + return -1
>> +
>> +def extract_idregs_from_registers_json(filename):
>> + """
>> + Load a Registers.json file and extract all ID registers, decode their
>> + opcode and dump the information in target/arm/cpu-sysregs.h.inc
> ^^ does not apply now.
indeed
>> +
>> + Args:
>> + filename (str): The path to the Registers.json
>> + returns:
>> + idregs: list of ID regs and their encoding
>> + """
>> + if not os.path.exists(filename):
>> + print(f"Error: {filename} could not be found!")
>> + return {}
>> +
>> + try:
>> + with open(filename, 'r') as f:
>> + register_data = json.load(f)
>> +
>> + except json.JSONDecodeError:
>> + print(f"Could not decode json from '{filename}'!")
>> + return {}
>> + except Exception as e:
>> + print(f"Unexpected error while reading {filename}: {e}")
>> + return {}
>> +
>> + registers = [
>> + r for r in register_data
>> + if isinstance(r, dict)
>> + and r.get('_type') == 'Register'
>> + and not is_demux_register(r)
> Can we put is_demux_register inside loop?
done
>
>> + ]
>> +
>> + idregs = {}
>> +
>> + # Some regs have op code values like 000x, 001x. Anyway we don't need
>> + # them. Besides some regs are undesired in the generated file such as
>> + # VMPIDR_EL2 and VPIDR_EL2 which are outside of the IDreg scope we
>> + # are interested in and are tricky to decode as their system accessor
>> + # refer to MPIDR_EL1/MIDR_EL1 respectively
>> +
>> + skiplist = ['ALLINT', 'PM', 'S1_', 'S3_', 'SVCR', \
>> + 'VMPIDR_EL2', 'VPIDR_EL2’]
> I see the op1 of VMPIDR_EL2/VPIDR_EL2 is 0b100, why are they needed in the
> skip-list, as they will anyway be skipped...
see previous replies.
Note I have squashed the initial script + intro of the module + the
update because it is much simpler to maintain while staying functionaly
consistent.
Eric
>
> Warm Regards,
> Khushit
>> + for register in registers:
>> + reg_name = register.get('name')
>> +
>> + is_skipped = any(term in (reg_name or "").upper() for term in
>> skiplist)
>> +
>> + if reg_name and not is_skipped:
>> + accessors = register.get('accessors', [])
>> +
>> + for accessor in accessors:
>> + type = accessor.get('_type')
>> + if type in ['Accessors.SystemAccessor']:
>> + encoding_list = accessor.get('encoding')
>> +
>> + if isinstance(encoding_list, list) and encoding_list
>> and \
>> + isinstance(encoding_list[0], dict):
>> + encoding_wrapper = encoding_list[0]
>> + encoding_source = encoding_wrapper.get('encodings',
>> \
>> +
>> encoding_wrapper)
>> +
>> + if isinstance(encoding_source, dict):
>> + op0 = get_opcode(encoding_source, 'op0')
>> + op1 = get_opcode(encoding_source, 'op1')
>> + op2 = get_opcode(encoding_source, 'op2')
>> + crn = get_opcode(encoding_source, 'CRn')
>> + crm = get_opcode(encoding_source, 'CRm')
>> + encoding_str=f"{op0} {op1} {crn} {crm}
>> {op2}"
>> +
>> + # ID regs are assumed within this scope
>> + if op0 == 3 and (op1 == 0 or op1 == 1 or op1 == 3) and \
>> + crn == 0 and (crm >= 0 and crm <= 7) and (op2 >= 0 and
>> op2 <= 7):
>> + idregs[reg_name] = encoding_str
>> +
>> + return idregs
>> +
>> +
>> +
>> diff --git a/scripts/update-aarch64-cpu-sysregs-header.py
>> b/scripts/update-aarch64-cpu-sysregs-header.py
>> index ef1471a197..43107264e9 100755
>> --- a/scripts/update-aarch64-cpu-sysregs-header.py
>> +++ b/scripts/update-aarch64-cpu-sysregs-header.py
>> @@ -17,102 +17,7 @@
>> import json
>> import os
>> import sys
>> -
>> -def is_demux_register(r):
>> - name = r.get('name', '')
>> -
>> - if name.startswith("CCSIDR"):
>> - return True
>> -
>> - return False
>> -
>> -# Some regs have op code values like 000x, 001x. Anyway we don't need
>> -# them. Besides some regs are undesired in the generated file such as
>> -# VMPIDR_EL2 and VPIDR_EL2 which are outside of the IDreg scope we
>> -# are interested in and are tricky to decode as their system accessor
>> -# refer to MPIDR_EL1/MIDR_EL1 respectively
>> -
>> -skiplist = ['ALLINT', 'PM', 'S1_', 'S3_', 'SVCR', \
>> - 'VMPIDR_EL2', 'VPIDR_EL2']
>> -
>> -# returns the int value of a given @opcode for a reg @encoding
>> -def get_opcode(encoding, opcode):
>> - fvalue = encoding.get(opcode)
>> - if fvalue:
>> - value = fvalue.get('value')
>> - if isinstance(value, str):
>> - value = value.strip("'")
>> - value = int(value, 2)
>> - return value
>> - return -1
>> -
>> -def extract_idregs_from_registers_json(filename):
>> - """
>> - Load a Registers.json file and extract all ID registers, decode their
>> - opcode and dump the information in target/arm/cpu-sysregs.h.inc
>> -
>> - Args:
>> - filename (str): The path to the Registers.json
>> - returns:
>> - idregs: list of ID regs and their encoding
>> - """
>> - if not os.path.exists(filename):
>> - print(f"Error: {filename} could not be found!")
>> - return {}
>> -
>> - try:
>> - with open(filename, 'r') as f:
>> - register_data = json.load(f)
>> -
>> - except json.JSONDecodeError:
>> - print(f"Could not decode json from '{filename}'!")
>> - return {}
>> - except Exception as e:
>> - print(f"Unexpected error while reading {filename}: {e}")
>> - return {}
>> -
>> - registers = [
>> - r for r in register_data
>> - if isinstance(r, dict)
>> - and r.get('_type') == 'Register'
>> - and not is_demux_register(r)
>> - ]
>> -
>> - idregs = {}
>> -
>> - for register in registers:
>> - reg_name = register.get('name')
>> -
>> - is_skipped = any(term in (reg_name or "").upper() for term in
>> skiplist)
>> -
>> - if reg_name and not is_skipped:
>> - accessors = register.get('accessors', [])
>> -
>> - for accessor in accessors:
>> - type = accessor.get('_type')
>> - if type in ['Accessors.SystemAccessor']:
>> - encoding_list = accessor.get('encoding')
>> -
>> - if isinstance(encoding_list, list) and encoding_list
>> and \
>> - isinstance(encoding_list[0], dict):
>> - encoding_wrapper = encoding_list[0]
>> - encoding_source = encoding_wrapper.get('encodings',
>> \
>> -
>> encoding_wrapper)
>> -
>> - if isinstance(encoding_source, dict):
>> - op0 = get_opcode(encoding_source, 'op0')
>> - op1 = get_opcode(encoding_source, 'op1')
>> - op2 = get_opcode(encoding_source, 'op2')
>> - crn = get_opcode(encoding_source, 'CRn')
>> - crm = get_opcode(encoding_source, 'CRm')
>> - encoding_str=f"{op0} {op1} {crn} {crm}
>> {op2}"
>> -
>> - # ID regs are assumed within this scope
>> - if op0 == 3 and (op1 == 0 or op1 == 1 or op1 == 3) and \
>> - crn == 0 and (crm >= 0 and crm <= 7) and (op2 >= 0 and
>> op2 <= 7):
>> - idregs[reg_name] = encoding_str
>> -
>> - return idregs
>> +from aarch64_sysreg_helpers import extract_idregs_from_registers_json
>>
>> if __name__ == "__main__":
>> # Single arg expected: the path to the Registers.json file
>> --
>> 2.53.0
>>