b7e978dd561b3f267ba7d9acd1e9cf588889a07f
1 # Reads OpenPOWER ISA pages from http://libre-riscv.org/openpower/isa
2 """OpenPOWER ISA page parser
4 returns an OrderedDict of namedtuple "Ops" containing details of all
5 instructions listed in markdown files.
7 format must be strictly as follows (no optional sections) including whitespace:
15 if L = 0 then a <- [0]*32 || (RA)[32:63]
16 b <- [0]*32 || (RB)[32:63]
19 if a <u b then c <- 0b100
20 else if a >u b then c <- 0b010
22 CR[4*BF+32:4*BF+35] <- c || XER[SO]
24 Special Registers Altered:
35 * instruction registerlist
36 * instruction registerlist
38 4-space-indented pseudo-code
39 4-space-indented pseudo-code
41 Special Registers Altered:
42 4-space-indented register description
44 blank(s) (optional for convenience at end-of-page)
47 from collections
import namedtuple
, OrderedDict
51 opfields
= ("desc", "form", "opcode", "regs", "pcode", "sregs", "page")
52 Ops
= namedtuple("Ops", opfields
)
56 fdir
= os
.path
.abspath(os
.path
.dirname(__file__
))
57 fdir
= os
.path
.split(fdir
)[0]
58 fdir
= os
.path
.split(fdir
)[0]
59 fdir
= os
.path
.split(fdir
)[0]
60 fdir
= os
.path
.split(fdir
)[0]
61 return os
.path
.join(fdir
, "libreriscv", "openpower", "isa")
67 self
.instr
= OrderedDict()
70 for pth
in os
.listdir(os
.path
.join(get_isa_dir())):
71 print (get_isa_dir(), pth
)
72 assert pth
.endswith(".mdwn"), "only %s in isa dir" % pth
75 # code which helped add in the keyword "Pseudo-code:" automatically
76 rewrite
= self
.read_file_for_rewrite(pth
)
77 name
= os
.path
.join("/tmp", pth
)
78 with
open(name
, "w") as f
:
79 f
.write('\n'.join(rewrite
) + '\n')
81 def read_file_for_rewrite(self
, fname
):
82 pagename
= fname
.split('.')[0]
83 fname
= os
.path
.join(get_isa_dir(), fname
)
84 with
open(fname
) as f
:
88 l
= lines
.pop(0).rstrip() # get first line
93 assert l
.startswith('#'), ("# not found in line %s" % l
)
96 l
= lines
.pop(0).strip()
98 assert len(l
) == 0, ("blank line not found %s" % l
)
102 l
= lines
.pop(0).strip()
103 assert l
.endswith('-Form'), ("line with -Form expected %s" % l
)
106 # whitespace expected
107 l
= lines
.pop(0).strip()
108 assert len(l
) == 0, ("blank line not found %s" % l
)
111 # get list of opcodes
113 l
= lines
.pop(0).strip()
115 if len(l
) == 0: break
116 assert l
.startswith('*'), ("* not found in line %s" % l
)
118 rewrite
.append("Pseudo-code:")
122 l
= lines
.pop(0).rstrip()
124 if len(l
) == 0: break
125 assert l
.startswith(' '), ("4spcs not found in line %s" % l
)
127 # "Special Registers Altered" expected
128 l
= lines
.pop(0).rstrip()
129 assert l
.startswith("Special"), ("special not found %s" % l
)
132 # whitespace expected
133 l
= lines
.pop(0).strip()
134 assert len(l
) == 0, ("blank line not found %s" % l
)
139 l
= lines
.pop(0).rstrip()
141 if len(l
) == 0: break
142 assert l
.startswith(' '), ("4spcs not found in line %s" % l
)
144 # expect and drop whitespace
146 l
= lines
.pop(0).rstrip()
148 if len(l
) != 0: break
152 def read_file(self
, fname
):
153 pagename
= fname
.split('.')[0]
154 fname
= os
.path
.join(get_isa_dir(), fname
)
155 with
open(fname
) as f
:
156 lines
= f
.readlines()
158 # set up dict with current page name
159 d
= {'page': pagename
}
161 # line-by-line lexer/parser, quite straightforward: pops one
162 # line off the list and checks it. nothing complicated needed,
163 # all sections are mandatory so no need for a full LALR parser.
165 l
= lines
.pop(0).rstrip() # get first line
169 assert l
.startswith('#'), ("# not found in line %s" % l
)
170 d
['desc'] = l
[1:].strip()
172 # whitespace expected
173 l
= lines
.pop(0).strip()
175 assert len(l
) == 0, ("blank line not found %s" % l
)
178 l
= lines
.pop(0).strip()
179 assert l
.endswith('-Form'), ("line with -Form expected %s" % l
)
180 d
['form'] = l
.split('-')[0]
182 # whitespace expected
183 l
= lines
.pop(0).strip()
184 assert len(l
) == 0, ("blank line not found %s" % l
)
186 # get list of opcodes
189 l
= lines
.pop(0).strip()
190 if len(l
) == 0: break
191 assert l
.startswith('*'), ("* not found in line %s" % l
)
192 l
= l
[1:].split(' ') # lose star
193 l
= filter(lambda x
: len(x
) != 0, l
) # strip blanks
197 # "Pseudocode" expected
198 l
= lines
.pop(0).rstrip()
199 assert l
.startswith("Pseudo-code:"), ("pseudocode found %s" % l
)
201 # whitespace expected
202 l
= lines
.pop(0).strip()
204 assert len(l
) == 0, ("blank line not found %s" % l
)
209 l
= lines
.pop(0).rstrip()
210 if len(l
) == 0: break
211 assert l
.startswith(' '), ("4spcs not found in line %s" % l
)
212 l
= l
[4:] # lose 4 spaces
216 # "Special Registers Altered" expected
217 l
= lines
.pop(0).rstrip()
218 assert l
.startswith("Special"), ("special not found %s" % l
)
220 # whitespace expected
221 l
= lines
.pop(0).strip()
222 assert len(l
) == 0, ("blank line not found %s" % l
)
227 l
= lines
.pop(0).rstrip()
228 if len(l
) == 0: break
229 assert l
.startswith(' '), ("4spcs not found in line %s" % l
)
230 l
= l
[4:] # lose 4 spaces
238 # expect and drop whitespace
240 l
= lines
.pop(0).rstrip()
241 if len(l
) != 0: break
243 def add_op(self
, o
, d
):
244 opcode
, regs
= o
[0], o
[1:]
247 regs
[0] = regs
[0].split(",")
248 op
['opcode'] = opcode
249 self
.instr
[opcode
] = Ops(**op
)
251 # create list of instructions by form
253 fl
= self
.forms
.get(form
, [])
254 self
.forms
[form
] = fl
+ [opcode
]
256 # create list of instructions by page
258 pl
= self
.page
.get(page
, [])
259 self
.page
[page
] = pl
+ [opcode
]
261 def pprint_ops(self
):
262 for k
, v
in self
.instr
.items():
263 print ("# %s %s" % (v
.opcode
, v
.desc
))
264 print ("Form: %s Regs: %s" % (v
.form
, v
.regs
))
265 print ('\n'.join(map(lambda x
: " %s" % x
, v
.pcode
)))
267 print ('\n'.join(map(lambda x
: " %s" % x
, v
.sregs
)))
269 for k
, v
in isa
.forms
.items():
272 if __name__
== '__main__':