# Exercise the register functionality by exhaustively iterating
# through all supported registers on the system.
#
# This is launched via tests/guest-debug/run-test.py but you can also
# call it directly if using it for debugging/introspection:
#
# SPDX-License-Identifier: GPL-2.0-or-later

import gdb
import xml.etree.ElementTree as ET
from test_gdbstub import main, report


initial_vlen = 0


def fetch_xml_regmap():
    """
    Iterate through the XML descriptions and validate.

    We check for any duplicate registers and report them. Return a
    reg_map hash containing the names, regnums and initial values of
    all registers.
    """

    # First check the XML descriptions we have sent. Most arches
    # support XML but a few of the ancient ones don't in which case we
    # need to gracefully fail.

    try:
        xml = gdb.execute("maint print xml-tdesc", False, True)
    except (gdb.error):
        print("SKIP: target does not support XML")
        return None

    total_regs = 0
    reg_map = {}

    tree = ET.fromstring(xml)
    for f in tree.findall("feature"):
        name = f.attrib["name"]
        regs = f.findall("reg")

        total = len(regs)
        total_regs += total
        base = int(regs[0].attrib["regnum"])
        top = int(regs[-1].attrib["regnum"])

        print(f"feature: {name} has {total} registers from {base} to {top}")

        for r in regs:
            name = r.attrib["name"]
            regnum = int(r.attrib["regnum"])

            entry = { "name": name, "regnum": regnum }

            if name in reg_map:
                report(False, f"duplicate register {entry} vs {reg_map[name]}")
                continue

            reg_map[name] = entry

    # Validate we match
    report(total_regs == len(reg_map.keys()),
           f"counted all {total_regs} registers in XML")

    return reg_map


def get_register_by_regnum(reg_map, regnum):
    """
    Helper to find a register from the map via its XML regnum
    """
    for regname, entry in reg_map.items():
        if entry['regnum'] == regnum:
            return entry
    return None


def crosscheck_remote_xml(reg_map):
    """
    Cross-check the list of remote-registers with the XML info.
    """

    remote = gdb.execute("maint print remote-registers", False, True)
    r_regs = remote.split("\n")

    total_regs = len(reg_map.keys())
    total_r_regs = 0
    total_r_elided_regs = 0

    for r in r_regs:
        r = r.replace("long long", "long_long")
        r = r.replace("long double", "long_double")
        fields = r.split()
        # Some of the registers reported here are "pseudo" registers that
        # gdb invents based on actual registers so we need to filter them
        # out.
        if len(fields) == 8:
            r_name = fields[0]
            r_regnum = int(fields[6])

            # Some registers are "hidden" so don't have a name
            # although they still should have a register number
            if r_name == "''":
                total_r_elided_regs += 1
                x_reg = get_register_by_regnum(reg_map, r_regnum)
                if x_reg is not None:
                    x_reg["hidden"] = True
                continue

            # check in the XML
            try:
                x_reg = reg_map[r_name]
            except KeyError:
                report(False, f"{r_name} not in XML description")
                continue

            x_reg["seen"] = True
            x_regnum = x_reg["regnum"]
            if r_regnum != x_regnum:
                report(False, f"{r_name} {r_regnum} == {x_regnum} (xml)")
            else:
                total_r_regs += 1

    report(total_regs == total_r_regs + total_r_elided_regs,
           "All XML Registers accounted for")

    print(f"xml-tdesc has {total_regs} registers")
    print(f"remote-registers has {total_r_regs} registers")
    print(f"of which {total_r_elided_regs} are hidden")

    for x_key in reg_map.keys():
        x_reg = reg_map[x_key]
        if "hidden" in x_reg:
            print(f"{x_reg} elided by gdb")
        elif "seen" not in x_reg:
            print(f"{x_reg} wasn't seen in remote-registers")


def initial_register_read(reg_map):
    """
    Do an initial read of all registers that we know gdb cares about
    (so ignore the elided ones).
    """
    frame = gdb.selected_frame()

    for e in reg_map.values():
        name = e["name"]
        regnum = e["regnum"]

        try:
            if "hidden" in e:
                value = frame.read_register(regnum)
                e["initial"] = value
            elif "seen" in e:
                value = frame.read_register(name)
                e["initial"] = value

        except ValueError:
                report(False, f"failed to read reg: {name}")


def complete_and_diff(reg_map):
    """
    Let the program run to (almost) completion and then iterate
    through all the registers we know about and report which ones have
    changed.
    """
    # Let the program get to the end and we can check what changed
    b = gdb.Breakpoint("_exit")
    if b.pending: # workaround Microblaze weirdness
        b.delete()
        gdb.Breakpoint("_Exit")

    gdb.execute("continue")

    frame = gdb.selected_frame()
    changed = 0

    for e in reg_map.values():
        if "initial" in e and "hidden" not in e:
            name = e["name"]
            old_val = e["initial"]

            try:
                new_val = frame.read_register(name)
            except ValueError:
                report(False, f"failed to read {name} at end of run")
                continue

            if new_val != old_val:
                print(f"{name} changes from {old_val} to {new_val}")
                changed += 1

    # as long as something changed we can be confident its working
    report(changed > 0, f"{changed} registers were changed")


def run_test():
    "Run through the tests"

    reg_map = fetch_xml_regmap()

    if reg_map is not None:
        crosscheck_remote_xml(reg_map)
        initial_register_read(reg_map)
        complete_and_diff(reg_map)


main(run_test)
