xref: /xnu-11215/tools/lldbmacros/sysreg.py (revision 8d741a5d)
1""" Please make sure you read the README file COMPLETELY BEFORE reading anything below.
2    It is very critical that you read coding guidelines in Section E in README file.
3
4    Note for adding new register support:
5
6    1. Add target register to "supported registers" in the docstring of DecodeSysreg
7    2. Populate _SYSREG_TO_DECODE_FUNC_MAP with your implementation, optionally using
8       _SYSREG_TO_DOCNAME_MAP
9    3. Populate _SUPPORTED_SYSREGS list with target register
10
11"""
12from xnu import *
13import os
14import sys
15import xml.etree.ElementTree as ET
16
17GREEN = '\033[0;32m'
18RED   = '\033[0;31m'
19NC    = '\033[0m'
20
21_SUPPORTED_SYSREGS = ['ESR_EL1']
22
23_SYSREG_DOC_PATH = os.path.dirname(os.path.abspath(__file__)) + '/sysregdoc/'
24
25_SYSREG_TO_DOCNAME_MAP = {
26    'ESR_EL1': 'AArch64-esr_el1.xml'
27}
28
29## Actual definition at the bottom of the file
30_SYSREG_TO_DECODE_FUNC_MAP = None
31
32# Macro: decode_sysreg
33@lldb_command('decode_sysreg')
34def DecodeSysreg(cmd_args=None):
35    """ Print out human-understandable explanation of a system register value
36        usage: decode_sysreg <sysreg> <value>
37        example: decode_sysreg esr_el1 0x96000021
38
39        supported registers:
40        ESR_EL1
41    """
42
43    ## For now, require exactly 2 arguments
44    if not cmd_args or len(cmd_args) != 2:
45        raise ArgumentError("Missing arguments.")
46
47    reg_name = cmd_args[0].upper()
48    reg_value = ArgumentStringToInt(cmd_args[1])
49
50    if reg_name not in _SUPPORTED_SYSREGS:
51        raise ArgumentError("{} is not supported".format(reg_name))
52
53    _SYSREG_TO_DECODE_FUNC_MAP[reg_name](reg_value)
54# EndMacro: decode_sysreg
55
56
57lldb_alias('decode_esr', 'decode_sysreg esr_el1')
58
59
60def PrintEsrEl1Explanation(regval):
61    """ Print out a detailed explanation of regval regarded as the value of
62        ESR_EL1, by parsing ARM machine readable specification
63    """
64    xmlfilename = _SYSREG_DOC_PATH + _SYSREG_TO_DOCNAME_MAP['ESR_EL1']
65    tree = ET.parse(xmlfilename)
66    root = tree.getroot()
67
68    ec = (regval >> 26) & ((1 << 6) - 1)
69    ecstring = '0b{:06b}'.format(ec)
70
71    print(_Colorify(VT.Green, 'EC == ' + ecstring))
72
73    ecxpath = './registers/register/reg_fieldsets/fields/field[@id="EC_31_26"]/field_values/field_value_instance[field_value="{}"]/field_value_description//para'.format(ecstring)
74    ec_desc_paras = root.findall(ecxpath)
75
76    if ec_desc_paras is None or len(ec_desc_paras) == 0:
77        print('EC not defined.')
78        print('\r\n')
79
80    for para in ec_desc_paras:
81        sys.stdout.write(para.text)
82        for child in para:
83            sys.stdout.write(_GetParaChildrenStr(child))
84            sys.stdout.write(child.tail)
85        print('\r\n')
86        print('\r\n')
87
88    iss = regval & ((1 << 25) - 1);
89    issstring = '0x{:07x}'.format(iss)
90    print(_Colorify(VT.Green, 'ISS == ' + issstring))
91    print('\r\n')
92
93    iss_condition_xpath = './registers/register/reg_fieldsets/fields/field[@id="EC_31_26"]/field_values/field_value_instance[field_value="{}"]/field_value_links_to'.format(ecstring)
94    iss_condition = root.find(iss_condition_xpath)
95    iss_condition_str = iss_condition.attrib['linked_field_condition']
96
97    iss_fields_xpath = './registers/register/reg_fieldsets/fields/field[@id="ISS_24_0"]/partial_fieldset/fields[fields_instance="{}"]//field'.format(iss_condition_str)
98    iss_fields = root.findall(iss_fields_xpath)
99
100    for field in iss_fields:
101        _PrintEsrIssField(field, regval)
102
103
104def _GetParaChildrenStr(elem):
105    """ Convert child tags of <para> element into text for printing
106    """
107
108    if elem.tag == 'binarynumber':
109        return elem.text
110    if elem.tag == 'arm-defined-word':
111        return elem.text
112    elif elem.tag == 'xref':
113        return elem.attrib['browsertext']
114    elif elem.tag == 'register_link':
115        return elem.text
116    else:
117        return _Colorify(VT.Red, '*unsupported text*')
118
119
120def _PrintEsrIssField(elem, regval):
121    """ Print detailed explanation of the ISS field of ESR
122    """
123
124    field_name_str = elem.find('field_name').text
125    field_msb = int(elem.find('field_msb').text)
126    field_lsb = int(elem.find('field_lsb').text)
127    fd_before_paras = elem.findall('./field_description[@order="before"]//para')
128    fd_after_paras = elem.findall('./field_description[@order="after"]//para')
129
130    field_bits = field_msb - field_lsb + 1
131    field_value = (regval >> field_lsb) & ((1 << field_bits) - 1)
132    field_value_string = ('0b{:0' + '{}'.format(field_bits) + 'b}').format(field_value)
133
134    print(_Colorify(VT.Green, _GetIndentedString(2, field_name_str) + ' == ' + field_value_string))
135
136    fv_desc_paras = elem.findall('./field_values/field_value_instance[field_value="{}"]/field_value_description//para'.format(field_value_string))
137
138    if fv_desc_paras and len(fv_desc_paras):
139        for para in fv_desc_paras:
140            sys.stdout.write(_GetIndentedString(2, ''))
141            sys.stdout.write(para.text)
142            for child in para:
143                sys.stdout.write(_GetParaChildrenStr(child))
144                sys.stdout.write((child.tail))
145        print('\r\n')
146        print('\r\n')
147    else:
148        print(_Colorify(VT.Red, _GetIndentedString(2, '(No matching value, dumping out full description)')))
149        for para in fd_before_paras:
150            sys.stdout.write(_GetIndentedString(2, ''))
151            sys.stdout.write(para.text)
152            for child in para:
153                sys.stdout.write(_GetParaChildrenStr(child))
154                sys.stdout.write(child.tail)
155            print('\r\n')
156            print('\r\n')
157
158        ## Dump all possible values
159        all_field_values = elem.findall('./field_values/field_value_instance//field_value')
160        all_field_values_str = [fv.text for fv in all_field_values]
161        if all_field_values_str != []:
162            print(_GetIndentedString(2, ', '.join(all_field_values_str)))
163
164        for para in fd_after_paras:
165            sys.stdout.write(_GetIndentedString(2, ''))
166            sys.stdout.write(para.text)
167            for child in para:
168                sys.stdout.write(_GetParaChildrenStr(child))
169                sys.stdout.write(child.tail)
170            print('\r\n')
171            print('\r\n')
172
173
174def _GetIndentedString(indentation, msg):
175    """ Return `msg` indented by `indentation` number of spaces
176    """
177    return ' ' * indentation + msg
178
179
180def _Colorify(color, msg):
181    """ Return `msg` enclosed by color codes
182    """
183    return color + msg + VT.Reset
184
185
186_SYSREG_TO_DECODE_FUNC_MAP = {
187    'ESR_EL1': PrintEsrEl1Explanation
188}
189