diff --git a/example4.xml b/example4.xml new file mode 100644 index 0000000..ab92e22 --- /dev/null +++ b/example4.xml @@ -0,0 +1,68 @@ + + + + + + + + pre / post indexing bit + + post, add offset after transfer + pre, add offset before transfer + + + + up / down bit + + down, subtract offset from base + up, addition offset to base + + + + byte / word bit + + transfer word quantity + transfer byte quantity + + + + write-back bit + + no write-back + write address into base + + + + load / store bit + + store to memory + load from memory + + + + base register + + + source / destination register + + + + offset is an immediate value + offset is a register + + + + + + unsigned number + + + + + shift applied to Rm + + + offset register + + + \ No newline at end of file diff --git a/schema.py b/schema.py index 7a4cec8..2959fa0 100644 --- a/schema.py +++ b/schema.py @@ -5,12 +5,13 @@ import yaml from config import Config from renderer import Renderer from structure import Structure +from xml_loader import XMLLoader class UnsupportedFormatException(Exception): ... class InstructionSetSchema: - VALID_EXTENSIONS = ("yaml", "json") + VALID_EXTENSIONS = ("yaml", "json", "xml") def __init__(self, path: str, configPath: str = "config.json") -> None: self.config = Config(configPath) @@ -31,6 +32,9 @@ class InstructionSetSchema: elif ext == "json": schema = json.load(f) + + elif ext == "xml": + schema = XMLLoader.load(f) self.structures = {} diff --git a/structure.py b/structure.py index 6cd1775..96623b0 100644 --- a/structure.py +++ b/structure.py @@ -28,7 +28,7 @@ class Structure: values[v] = d range_.values = values - return Structure(id_, data["bits"], ranges, data.get("start", 0)) + return Structure(id_, int(data["bits"]), ranges, data.get("start", 0)) def getSortedRanges(self) -> list[Range]: ranges = self.ranges.values() diff --git a/xml_loader.py b/xml_loader.py new file mode 100644 index 0000000..04a0283 --- /dev/null +++ b/xml_loader.py @@ -0,0 +1,65 @@ +from __future__ import annotations +from bs4 import BeautifulSoup +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from io import TextIOWrapper + +class XMLLoader: + def load(file_: TextIOWrapper) -> dict: + schema = {} + bs = BeautifulSoup(file_.read(), "xml") + structElmts = bs.findAll("structure") + structures = {} + + for structElmt in structElmts: + structures[structElmt.get("id")] = XMLLoader.parseStructure(structElmt) + + schema["structures"] = structures + return schema + + def parseStructure(structElmt: any) -> dict: + struct = {} + struct["bits"] = structElmt.get("bits") + ranges = {} + rangeElmts = structElmt.findAll("range") + for rangeElmt in rangeElmts: + span = rangeElmt.get("end") + "-" + rangeElmt.get("start") + ranges[span] = XMLLoader.parseRange(rangeElmt) + + struct["ranges"] = ranges + return struct + + def parseRange(rangeElmt: any) -> dict: + range_ = {} + range_["name"] = rangeElmt.get("name") + desc = rangeElmt.find("description") + if desc is not None: range_["description"] = desc.getText() + + valuesElmt = rangeElmt.find("values") + if valuesElmt is not None: + range_["values"] = XMLLoader.parseValues(valuesElmt) + + if rangeElmt.get("depends-on"): + range_["depends-on"] = rangeElmt.get("depends-on") + + return range_ + + def parseValues(valuesElmt: any) -> dict: + values = {} + caseElmts = valuesElmt.findAll("case") + + for caseElmt in caseElmts: + val = caseElmt.get("value") + desc = caseElmt.getText() + struct = caseElmt.get("structure") + + if struct: + values[val] = { + "description": desc, + "structure": struct + } + else: + values[val] = desc + + return values \ No newline at end of file