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