power_insn: support PPC multi-records
[openpower-isa.git] / src / openpower / decoder / power_table.py
index da35cdb809f3a4d01c4dc81a148b53a2279f1a68..356c01643dcdac1671c45e56a5d2ef1e37fb7734 100644 (file)
@@ -3,7 +3,8 @@ from openpower.decoder.power_enums import find_wiki_dir
 from openpower.decoder.power_insn import (Database, MarkdownDatabase,
                                           FieldsDatabase, PPCDatabase,
                                           IntegerOpcode, PatternOpcode,
-                                          parse, Section)
+                                          parse, Section, BitSel,
+                                          FieldsOpcode)
 root = find_wiki_dir()
 root = pathlib.Path(root)
 mdwndb = MarkdownDatabase()
@@ -26,33 +27,89 @@ for insn in db:
     insns[str(insn.section.path)].append(insn)
     print (insn)
 
-def do_table(insns, section):
+def maxme(num, s):
+    return s.ljust(num)
+
+def binmaxed(num, v):
+    return format(v, "0%db" % num)
+
+# create one table
+def do_table(fname, insns, section, divpoint):
+    insns = insns[fname]
+    section = sections[fname]
     start, end = section.bitsel.start, section.bitsel.end
     print ("start-end", start, end)
     bitlen = end-start+1
-    half = bitlen // 2
-    xomask = ((1<<bitlen)-1) << start
+    half = divpoint
     lowermask = (1<<half)-1
     uppermask = (1<<(bitlen-half))-1
     table_entries = {}
+    # debug-print all opcodes first
+    opcode_per_insn = {}
+    for insn in insns:
+        #fields = []
+        #fields += [(insn.ppc.opcode.value, insn.ppc.bitsel)]
+        #opcode = FieldsOpcode(fields)
+        opcode = insn.ppc.opcode
+        if not isinstance(opcode, list):
+            opcode = [opcode]
+        for op in opcode:
+            print ("op", insn.name, op)
+        if insn.name not in opcode_per_insn:
+            opcode_per_insn[insn.name] = []
+        opcode_per_insn[insn.name] += opcode
+
+    maxnamelen = 0
     for i in range(1<<bitlen):
         # calculate row, column
         lower = i & lowermask
         upper = (i>>half) & uppermask
         print (i, bin(lower), bin(upper))
-        if lower not in table_entries:
-            table_entries[lower] = {}
-        table_entries[lower][upper] = i
+        if upper not in table_entries:
+            table_entries[upper] = {}
+        table_entries[upper][lower] = None
         # create an XO
-        key = i << start
+        key = i
         print ("search", i, hex(key))
         # start hunting
         for insn in insns:
-            opcode = insn.opcode
-            if not isinstance(opcode, list):
-                opcode = [opcode]
+            opcode = opcode_per_insn[insn.name]
             for op in opcode:
-                if ((op.value & op.mask & xomask) == (key & op.mask & xomask)):
-                    print ("match", i, hex(key), insn.name)
+                #print ("    search", i, hex(key), insn.name,
+                #                       hex(op.value), hex(op.mask))
+                if ((op.value & op.mask) == (key & op.mask)):
+                    print ("    match", i, hex(key), insn.name)
+                    assert (table_entries[upper][lower] is None,
+                            "entry %d %d should be empty "
+                            "contains %s conflicting %s" % \
+                            (lower, upper, str(table_entries[upper][lower]),
+                             insn.name))
+                    table_entries[upper][lower] = insn.name
+                    maxnamelen = max(maxnamelen, len(insn.name))
+                    continue
+
+    print (table_entries)
+    # now got the table: print it out
+
+    table = []
+    line = [" "*half]
+    for j in range(1<<(half)):
+        hdr = binmaxed(half, j)
+        line.append(maxme(maxnamelen, hdr))
+    line.append(" "*half)
+    table.append("|" + "|".join(line) + "|")
+    line = ["-"*half] + ["-"*maxnamelen] * (1<<(half)) + ["-"*half]
+    table.append("|" + "|".join(line) + "|")
+
+    for i in range(1<<(bitlen-half)):
+        hdr = binmaxed(half, i)
+        line = [hdr]
+        for j in range(1<<(half)):
+            line.append(maxme(maxnamelen, table_entries[i][j] or " "))
+        line.append(hdr)
+        table.append("|" + "|".join(line) + "|")
+
+    print ("\n".join(table))
+
+do_table('minor_30.csv', insns, sections, divpoint=2)
 
-do_table(insns['minor_30.csv'], sections['minor_30.csv'])