start decoding sv EXTRAs and identifying them
[soc.git] / src / soc / sv / trans / svp64.py
index 541306f2efe06e9d310041e5f251a38fbb27c68b..42f0963952c965557b5fa034a840f912db305fde 100644 (file)
@@ -6,10 +6,18 @@
 
 This class takes raw svp64 assembly mnemonics (aliases excluded) and
 creates an EXT001-encoded "svp64 prefix" followed by a v3.0B opcode.
-It is very simple
+
+It is very simple and straightforward, the only weirdness being the
+extraction of the register information and conversion to v3.0B numbering.
+
+Encoding format of svp64: https://libre-soc.org/openpower/sv/svp64/
+Bugtracker: https://bugs.libre-soc.org/show_bug.cgi?id=578
 """
 
+import os, sys
+
 from soc.decoder.pseudo.pagereader import ISA
+from soc.decoder.power_enums import get_csv, find_wiki_dir
 
 
 def is_CR_3bit(regname):
@@ -20,6 +28,24 @@ def is_CR_5bit(regname):
 
 def is_GPR(regname):
     return regname in ['RA', 'RB', 'RC', 'RS', 'RT']
+def get_regtype(regname):
+    if is_CR_3bit(regname):
+        return "CR_3bit"
+    if is_CR_5bit(regname):
+        return "CR_5bit"
+    if is_GPR(regname):
+        return "GPR"
+
+
+class SVP64RM:
+    def __init__(self):
+        self.instrs = {}
+        pth = find_wiki_dir()
+        for fname in os.listdir(pth):
+            if fname.startswith("RM"):
+                for entry in get_csv(fname):
+                    self.instrs[entry['insn']] = entry
 
 
 class SVP64:
@@ -33,6 +59,7 @@ class SVP64:
 
     def translate(self, lst):
         isa = ISA() # reads the v3.0B pseudo-code markdown files
+        svp64 = SVP64RM() # reads the svp64 Remap entries for registers
         res = []
         for insn in lst:
             # find first space, to get opcode
@@ -54,10 +81,56 @@ class SVP64:
             if v30b_op not in isa.instr:
                 raise Exception("opcode %s of '%s' not supported" % \
                                 (v30b_op, insn))
+            if v30b_op not in svp64.instrs:
+                raise Exception("opcode %s of '%s' not an svp64 instruction" % \
+                                (v30b_op, insn))
+            isa.instr[v30b_op].regs[0]
+            v30b_regs = isa.instr[v30b_op].regs[0]
+            rm = svp64.instrs[v30b_op]
+            print ("v3.0B regs", opcode, v30b_regs)
+            print (rm)
+
+            # right.  the first thing to do is identify the ordering of
+            # the registers, by name.  the EXTRA2/3 ordering is in
+            # rm['0']..rm['3'] but those fields contain the names RA, BB
+            # etc.  we have to read the pseudocode to understand which
+            # reg is which in our instruction. sigh.
+
+            # first turn the svp64 rm into a "by name" dict, recording
+            # which position in the RM EXTRA it goes into
+            svp64_reg_byname = {}
+            for i in range(4):
+                rfield = rm[str(i)]
+                if not rfield or rfield == '0':
+                    continue
+                print ("EXTRA field", i, rfield)
+                rfield = rfield.split(";") # s:RA;d:CR1 etc.
+                for r in rfield:
+                    r = r[2:] # ignore s: and d:
+                    svp64_reg_byname[r] = i # this reg in EXTRA position 0-3
+            print ("EXTRA field index, by regname", svp64_reg_byname)
+
+            # okaaay now we identify the field value (opcode N,N,N) with
+            # the pseudo-code info (opcode RT, RA, RB)
+            opregfields = zip(fields, v30b_regs) # err that was easy
+
+            # now for each of those find its place in the EXTRA encoding
+            extras = {}
+            for field, regname in opregfields:
+                extra = svp64_reg_byname[regname]
+                regtype = get_regtype(regname)
+                extras[extra] = (field, regname, regtype)
+                print ("    ", extra, extras[extra])
+
+            etype = rm['Etype'] # Extra type: EXTRA3/EXTRA2
 
         return res
 
 if __name__ == '__main__':
     isa = SVP64(['slw 3, 1, 4',
-                 'extsw 5, 3'])
-
+                 'extsw 5, 3',
+                 'sv.extsw 5, 3',
+                 'sv.setb 5, 3',
+                 'sv.isel 5, 3, 2, 0'
+                ])
+    csvs = SVP64RM()