if referred to through GPR (GPR[RA]), add to read_regs in parser
[soc.git] / src / soc / decoder / pseudo / pagereader.py
index 14d6f823b4e1c6029a7527dc7fdcf8b384bfc6b3..f9e153491adb49e9d733063f74778d830200000f 100644 (file)
@@ -1,27 +1,86 @@
 # Reads OpenPOWER ISA pages from http://libre-riscv.org/openpower/isa
+"""OpenPOWER ISA page parser
+
+returns an OrderedDict of namedtuple "Ops" containing details of all
+instructions listed in markdown files.
+
+format must be strictly as follows (no optional sections) including whitespace:
+
+# Compare Logical
+
+X-Form
+
+* cmpl BF,L,RA,RB
+
+    if L = 0 then a <- [0]*32 || (RA)[32:63]
+                  b <- [0]*32 || (RB)[32:63]
+             else a <-  (RA)
+                  b <-  (RB)
+    if      a <u b then c <- 0b100
+    else if a >u b then c <- 0b010
+    else                c <-  0b001
+    CR[4*BF+32:4*BF+35] <- c || XER[SO]
+
+Special Registers Altered:
+
+    CR field BF
+    Another field
+
+this translates to:
+
+    # heading
+    blank
+    Some-Form
+    blank
+    * instruction registerlist
+    * instruction registerlist
+    blank
+    4-space-indented pseudo-code
+    4-space-indented pseudo-code
+    blank
+    Special Registers Altered:
+    4-space-indented register description
+    blank
+    blank(s) (optional for convenience at end-of-page)
+"""
+
 from collections import namedtuple, OrderedDict
 from copy import copy
 import os
 
-op = namedtuple("Ops", ("desc", "form", "opcode", "regs", "pcode", "sregs"))
+opfields = ("desc", "form", "opcode", "regs", "pcode", "sregs", "page")
+Ops = namedtuple("Ops", opfields)
+
+
+def get_isa_dir():
+    fdir = os.path.abspath(os.path.dirname(__file__))
+    fdir = os.path.split(fdir)[0]
+    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")
+
 
 class ISA:
 
     def __init__(self):
         self.instr = OrderedDict()
+        self.forms = {}
+        self.page = {}
+        for pth in os.listdir(os.path.join(get_isa_dir())):
+            print (get_isa_dir(), pth)
+            assert pth.endswith(".mdwn"), "only %s in isa dir" % pth
+            self.read_file(pth)
 
     def read_file(self, fname):
-        fdir = os.path.abspath(os.path.dirname(__file__))
-        fdir = os.path.split(fdir)[0]
-        fdir = os.path.split(fdir)[0]
-        fdir = os.path.split(fdir)[0]
-        fdir = os.path.split(fdir)[0]
-        print (fdir)
-        fname = os.path.join(fdir, "libreriscv", "openpower", "isa", fname)
+        pagename = fname.split('.')[0]
+        fname = os.path.join(get_isa_dir(), fname)
         with open(fname) as f:
             lines = f.readlines()
         
-        d = {}
+        # set up dict with current page name
+        d = {'page': pagename}
+
         l = lines.pop(0).rstrip() # get first line
         while lines:
             print (l)
@@ -74,7 +133,7 @@ class ISA:
 
             # get special regs
             li = []
-            while True:
+            while lines:
                 l = lines.pop(0).rstrip()
                 if len(l) == 0: break
                 assert l.startswith('    '), ("4spcs not found in line %s" % l)
@@ -84,27 +143,42 @@ class ISA:
 
             # add in opcode
             for o in opcodes:
-                opcode, regs = o[0], o[1:]
-                op = copy(d)
-                op['regs'] = regs
-                op['opcode'] = opcode
-                self.instr[opcode] = op
+                self.add_op(o, d)
 
             # expect and drop whitespace
             while lines:
                 l = lines.pop(0).rstrip()
                 if len(l) != 0: break
 
+    def add_op(self, o, d):
+        opcode, regs = o[0], o[1:]
+        op = copy(d)
+        op['regs'] = regs
+        regs[0] = regs[0].split(",")
+        op['opcode'] = opcode
+        self.instr[opcode] = Ops(**op)
+
+        # create list of instructions by form
+        form = op['form']
+        fl = self.forms.get(form, [])
+        self.forms[form] = fl + [opcode]
+
+        # create list of instructions by page
+        page = op['page']
+        pl = self.page.get(page, [])
+        self.page[page] = pl + [opcode]
+
     def pprint_ops(self):
         for k, v in self.instr.items():
-            print ("# %s %s" % (v['opcode'], v['desc']))
-            print ("Form: %s Regs: %s" % (v['form'], v['regs']))
-            print ('\n'.join(map(lambda x: "    %s" % x, v['pcode'])))
+            print ("# %s %s" % (v.opcode, v.desc))
+            print ("Form: %s Regs: %s" % (v.form, v.regs))
+            print ('\n'.join(map(lambda x: "    %s" % x, v.pcode)))
             print ("Specials")
-            print ('\n'.join(map(lambda x: "    %s" % x, v['sregs'])))
+            print ('\n'.join(map(lambda x: "    %s" % x, v.sregs)))
             print ()
+        for k, v in isa.forms.items():
+            print (k, v)
 
 if __name__ == '__main__':
     isa = ISA()
-    isa.read_file("fixedlogical.mdwn")
     isa.pprint_ops()