-# Reads OpenPOWER ISA pages from http://libre-riscv.org/openpower/isa
+# Reads OpenPOWER ISA pages from http://libre-soc.org/openpower/isa
"""OpenPOWER ISA page parser
returns an OrderedDict of namedtuple "Ops" containing details of all
blank(s) (optional for convenience at end-of-page)
"""
+from openpower.util import log
from collections import namedtuple, OrderedDict
from copy import copy
import os
+import re
opfields = ("desc", "form", "opcode", "regs", "pcode", "sregs", "page")
Ops = namedtuple("Ops", opfields)
fdir = os.path.split(fdir)[0]
fdir = os.path.split(fdir)[0]
fdir = os.path.split(fdir)[0]
- return os.path.join(fdir, "libreriscv", "openpower", "isa")
+ # print (fdir)
+ return os.path.join(fdir, "openpower", "isa")
-class ISA:
+pattern_opcode = r"[A-Za-z0-9_\.]+\.?"
+pattern_dynamic = r"[A-Za-z0-9_]+(?:\([A-Za-z0-9_]+\))*"
+pattern_static = r"[A-Za-z0-9]+\=[01]"
+regex_opcode = re.compile(f"^{pattern_opcode}$")
+regex_dynamic = re.compile(f"^{pattern_dynamic}(?:,{pattern_dynamic})*$")
+regex_static = re.compile(f"^\({pattern_static}(?:\s{pattern_static})*\)$")
+
+
+def operands(opcode, desc):
+ if desc is None:
+ return
+ desc = desc.replace("(", "")
+ desc = desc.replace(")", "")
+ desc = desc.replace(",", " ")
+ for operand in desc.split(" "):
+ operand = operand.strip()
+ if operand:
+ yield operand
+
+class ISA:
def __init__(self):
self.instr = OrderedDict()
self.forms = {}
self.page = {}
+ self.verbose = False
for pth in os.listdir(os.path.join(get_isa_dir())):
- print(get_isa_dir(), pth)
+ if self.verbose:
+ print("examining", get_isa_dir(), pth)
if "swp" in pth:
continue
- assert pth.endswith(".mdwn"), "only %s in isa dir" % pth
+ if not pth.endswith(".mdwn"):
+ log ("warning, file not .mdwn, skipping", pth)
+ continue
self.read_file(pth)
continue
# code which helped add in the keyword "Pseudo-code:" automatically
with open(name, "w") as f:
f.write('\n'.join(rewrite) + '\n')
+ def __iter__(self):
+ yield from self.instr.items()
+
def read_file_for_rewrite(self, fname):
pagename = fname.split('.')[0]
fname = os.path.join(get_isa_dir(), fname)
l = lines.pop(0).rstrip() # get first line
rewrite.append(l)
while lines:
- print(l)
+ if self.verbose:
+ print(l)
# look for HTML comment, if starting, skip line.
# XXX this is braindead! it doesn't look for the end
# so please put ending of comments on one line:
# <!-- line 1 comment -->
- # <!-- line 2 comment -->
- if l.startswith('<!--'):
+ # {some whitespace}<!-- line 2 comment -->
+ if l.strip().startswith('<!--'):
# print ("skipping comment", l)
l = lines.pop(0).rstrip() # get first line
continue
# whitespace expected
l = lines.pop(0).strip()
- print(repr(l))
+ if self.verbose:
+ print(repr(l))
assert len(l) == 0, ("blank line not found %s" % l)
rewrite.append(l)
# get pseudocode
while True:
l = lines.pop(0).rstrip()
+ if l.strip().startswith('<!--'):
+ # print ("skipping comment", l)
+ l = lines.pop(0).rstrip() # get first line
+ continue
rewrite.append(l)
if len(l) == 0:
break
while lines:
l = lines.pop(0).rstrip()
rewrite.append(l)
- if len(l) != 0 and not l.startswith('<!--'):
+ if len(l) != 0 and not l.strip().startswith('<!--'):
break
return rewrite
# all sections are mandatory so no need for a full LALR parser.
l = lines.pop(0).rstrip() # get first line
+ prefix_lines = 0
while lines:
- print(l)
+ if self.verbose:
+ print(l)
# look for HTML comment, if starting, skip line.
# XXX this is braindead! it doesn't look for the end
# so please put ending of comments on one line:
# <!-- line 1 comment -->
# <!-- line 2 comment -->
- if l.startswith('<!--'):
+ if l.strip().startswith('<!--'):
# print ("skipping comment", l)
l = lines.pop(0).rstrip() # get next line
+ prefix_lines += 1
continue
# Ignore blank lines before the first #
if len(l) == 0:
l = lines.pop(0).rstrip() # get next line
+ prefix_lines += 1
continue
# expect get heading
# whitespace expected
l = lines.pop(0).strip()
- print(repr(l))
+ prefix_lines += 1
+ if self.verbose:
+ print(repr(l))
assert len(l) == 0, ("blank line not found %s" % l)
# Form expected
l = lines.pop(0).strip()
+ prefix_lines += 1
assert l.endswith('-Form'), ("line with -Form expected %s" % l)
d['form'] = l.split('-')[0]
# whitespace expected
l = lines.pop(0).strip()
+ prefix_lines += 1
assert len(l) == 0, ("blank line not found %s" % l)
# get list of opcodes
- li = []
+ opcodes = []
while True:
l = lines.pop(0).strip()
+ prefix_lines += 1
if len(l) == 0:
break
assert l.startswith('*'), ("* not found in line %s" % l)
- l = l[1:].split(' ') # lose star
- l = filter(lambda x: len(x) != 0, l) # strip blanks
- li.append(list(l))
- opcodes = li
+ rest = l[1:].strip()
+
+ (opcode, _, rest) = map(str.strip, rest.partition(" "))
+ if regex_opcode.match(opcode) is None:
+ raise IOError(repr(opcode))
+ opcode = [opcode]
+
+ (dynamic, _, rest) = map(str.strip, rest.partition(" "))
+ if regex_dynamic.match(dynamic) is None and dynamic:
+ raise IOError(f"{l!r}: {dynamic!r}")
+ if dynamic:
+ opcode.append(dynamic.split(","))
+
+ static = rest
+ if regex_static.match(static) is None and static:
+ raise IOError(f"{l!r}: {static!r}")
+ if static:
+ opcode.extend(static[1:-1].split(" "))
+
+ opcodes.append(opcode)
# "Pseudocode" expected
l = lines.pop(0).rstrip()
+ prefix_lines += 1
assert l.startswith("Pseudo-code:"), ("pseudocode found %s" % l)
# whitespace expected
l = lines.pop(0).strip()
- print(repr(l))
+ prefix_lines += 1
+ if self.verbose:
+ print(repr(l))
assert len(l) == 0, ("blank line not found %s" % l)
# get pseudocode
- li = []
+
+ # fix parser line numbers by prepending the right number of
+ # blank lines to the parser input
+ li = [""] * prefix_lines
+ li += [l[4:]] # first line detected with 4-space
while True:
l = lines.pop(0).rstrip()
+ prefix_lines += 1
if len(l) == 0:
+ li.append(l)
break
+ if l.strip().startswith('<!--'):
+ li.append("")
+ continue
assert l.startswith(' '), ("4spcs not found in line %s" % l)
l = l[4:] # lose 4 spaces
li.append(l)
# "Special Registers Altered" expected
l = lines.pop(0).rstrip()
+ prefix_lines += 1
assert l.startswith("Special"), ("special not found %s" % l)
# whitespace expected
l = lines.pop(0).strip()
+ prefix_lines += 1
assert len(l) == 0, ("blank line not found %s" % l)
# get special regs
li = []
while lines:
l = lines.pop(0).rstrip()
+ prefix_lines += 1
if len(l) == 0:
break
assert l.startswith(' '), ("4spcs not found in line %s" % l)
for o in opcodes:
self.add_op(o, d)
- # expect and drop whitespace
+ # expect and drop whitespace and comments
while lines:
l = lines.pop(0).rstrip()
- if len(l) != 0 and not l.startswith('<!--'):
+ prefix_lines += 1
+ if len(l) != 0 and not l.strip().startswith('<!--'):
break
def add_op(self, o, d):
opcode, regs = o[0], o[1:]
op = copy(d)
op['regs'] = regs
- if len(regs) != 0:
- regs[0] = regs[0].split(",")
op['opcode'] = opcode
self.instr[opcode] = Ops(**op)