42f0963952c965557b5fa034a840f912db305fde
[soc.git] / src / soc / sv / trans / svp64.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Copyright (C) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Funded by NLnet http://nlnet.nl
4
5 """SVP64 OpenPOWER v3.0B assembly translator
6
7 This class takes raw svp64 assembly mnemonics (aliases excluded) and
8 creates an EXT001-encoded "svp64 prefix" followed by a v3.0B opcode.
9
10 It is very simple and straightforward, the only weirdness being the
11 extraction of the register information and conversion to v3.0B numbering.
12
13 Encoding format of svp64: https://libre-soc.org/openpower/sv/svp64/
14 Bugtracker: https://bugs.libre-soc.org/show_bug.cgi?id=578
15 """
16
17 import os, sys
18
19 from soc.decoder.pseudo.pagereader import ISA
20 from soc.decoder.power_enums import get_csv, find_wiki_dir
21
22
23 def is_CR_3bit(regname):
24 return regname in ['BF', 'BFA']
25
26 def is_CR_5bit(regname):
27 return regname in ['BA', 'BB', 'BC', 'BI', 'BT']
28
29 def is_GPR(regname):
30 return regname in ['RA', 'RB', 'RC', 'RS', 'RT']
31
32 def get_regtype(regname):
33 if is_CR_3bit(regname):
34 return "CR_3bit"
35 if is_CR_5bit(regname):
36 return "CR_5bit"
37 if is_GPR(regname):
38 return "GPR"
39
40
41 class SVP64RM:
42 def __init__(self):
43 self.instrs = {}
44 pth = find_wiki_dir()
45 for fname in os.listdir(pth):
46 if fname.startswith("RM"):
47 for entry in get_csv(fname):
48 self.instrs[entry['insn']] = entry
49
50
51 class SVP64:
52 def __init__(self, lst):
53 self.lst = lst
54 self.trans = self.translate(lst)
55
56 def __iter__(self):
57 for insn in self.trans:
58 yield insn
59
60 def translate(self, lst):
61 isa = ISA() # reads the v3.0B pseudo-code markdown files
62 svp64 = SVP64RM() # reads the svp64 Remap entries for registers
63 res = []
64 for insn in lst:
65 # find first space, to get opcode
66 ls = insn.split(' ')
67 opcode = ls[0]
68 # now find opcode fields
69 fields = ''.join(ls[1:]).split(',')
70 fields = list(map(str.strip, fields))
71 print (opcode, fields)
72
73 # identify if is a svp64 mnemonic
74 if not opcode.startswith('sv.'):
75 res.append(insn) # unaltered
76 continue
77
78 # start working on decoding the svp64 op: sv.baseop.vec2.mode
79 opmodes = opcode.split(".")[1:] # strip leading "sv."
80 v30b_op = opmodes.pop(0) # first is the v3.0B
81 if v30b_op not in isa.instr:
82 raise Exception("opcode %s of '%s' not supported" % \
83 (v30b_op, insn))
84 if v30b_op not in svp64.instrs:
85 raise Exception("opcode %s of '%s' not an svp64 instruction" % \
86 (v30b_op, insn))
87 isa.instr[v30b_op].regs[0]
88 v30b_regs = isa.instr[v30b_op].regs[0]
89 rm = svp64.instrs[v30b_op]
90 print ("v3.0B regs", opcode, v30b_regs)
91 print (rm)
92
93 # right. the first thing to do is identify the ordering of
94 # the registers, by name. the EXTRA2/3 ordering is in
95 # rm['0']..rm['3'] but those fields contain the names RA, BB
96 # etc. we have to read the pseudocode to understand which
97 # reg is which in our instruction. sigh.
98
99 # first turn the svp64 rm into a "by name" dict, recording
100 # which position in the RM EXTRA it goes into
101 svp64_reg_byname = {}
102 for i in range(4):
103 rfield = rm[str(i)]
104 if not rfield or rfield == '0':
105 continue
106 print ("EXTRA field", i, rfield)
107 rfield = rfield.split(";") # s:RA;d:CR1 etc.
108 for r in rfield:
109 r = r[2:] # ignore s: and d:
110 svp64_reg_byname[r] = i # this reg in EXTRA position 0-3
111 print ("EXTRA field index, by regname", svp64_reg_byname)
112
113 # okaaay now we identify the field value (opcode N,N,N) with
114 # the pseudo-code info (opcode RT, RA, RB)
115 opregfields = zip(fields, v30b_regs) # err that was easy
116
117 # now for each of those find its place in the EXTRA encoding
118 extras = {}
119 for field, regname in opregfields:
120 extra = svp64_reg_byname[regname]
121 regtype = get_regtype(regname)
122 extras[extra] = (field, regname, regtype)
123 print (" ", extra, extras[extra])
124
125 etype = rm['Etype'] # Extra type: EXTRA3/EXTRA2
126
127 return res
128
129 if __name__ == '__main__':
130 isa = SVP64(['slw 3, 1, 4',
131 'extsw 5, 3',
132 'sv.extsw 5, 3',
133 'sv.setb 5, 3',
134 'sv.isel 5, 3, 2, 0'
135 ])
136 csvs = SVP64RM()