decodetree.py 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2018 Linaro Limited
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2.1 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public
  15. # License along with this library; if not, see <http://www.gnu.org/licenses/>.
  16. #
  17. #
  18. # Generate a decoding tree from a specification file.
  19. # See the syntax and semantics in docs/devel/decodetree.rst.
  20. #
  21. import io
  22. import os
  23. import re
  24. import sys
  25. import getopt
  26. insnwidth = 32
  27. bitop_width = 32
  28. insnmask = 0xffffffff
  29. variablewidth = False
  30. fields = {}
  31. arguments = {}
  32. formats = {}
  33. allpatterns = []
  34. anyextern = False
  35. testforerror = False
  36. translate_prefix = 'trans'
  37. translate_scope = 'static '
  38. input_file = ''
  39. output_file = None
  40. output_fd = None
  41. output_null = False
  42. insntype = 'uint32_t'
  43. decode_function = 'decode'
  44. # An identifier for C.
  45. re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
  46. # Identifiers for Arguments, Fields, Formats and Patterns.
  47. re_arg_ident = '&[a-zA-Z0-9_]*'
  48. re_fld_ident = '%[a-zA-Z0-9_]*'
  49. re_fmt_ident = '@[a-zA-Z0-9_]*'
  50. re_pat_ident = '[a-zA-Z0-9_]*'
  51. # Local implementation of a topological sort. We use the same API that
  52. # the Python graphlib does, so that when QEMU moves forward to a
  53. # baseline of Python 3.9 or newer this code can all be dropped and
  54. # replaced with:
  55. # from graphlib import TopologicalSorter, CycleError
  56. #
  57. # https://docs.python.org/3.9/library/graphlib.html#graphlib.TopologicalSorter
  58. #
  59. # We only implement the parts of TopologicalSorter we care about:
  60. # ts = TopologicalSorter(graph=None)
  61. # create the sorter. graph is a dictionary whose keys are
  62. # nodes and whose values are lists of the predecessors of that node.
  63. # (That is, if graph contains "A" -> ["B", "C"] then we must output
  64. # B and C before A.)
  65. # ts.static_order()
  66. # returns a list of all the nodes in sorted order, or raises CycleError
  67. # CycleError
  68. # exception raised if there are cycles in the graph. The second
  69. # element in the args attribute is a list of nodes which form a
  70. # cycle; the first and last element are the same, eg [a, b, c, a]
  71. # (Our implementation doesn't give the order correctly.)
  72. #
  73. # For our purposes we can assume that the data set is always small
  74. # (typically 10 nodes or less, actual links in the graph very rare),
  75. # so we don't need to worry about efficiency of implementation.
  76. #
  77. # The core of this implementation is from
  78. # https://code.activestate.com/recipes/578272-topological-sort/
  79. # (but updated to Python 3), and is under the MIT license.
  80. class CycleError(ValueError):
  81. """Subclass of ValueError raised if cycles exist in the graph"""
  82. pass
  83. class TopologicalSorter:
  84. """Topologically sort a graph"""
  85. def __init__(self, graph=None):
  86. self.graph = graph
  87. def static_order(self):
  88. # We do the sort right here, unlike the stdlib version
  89. from functools import reduce
  90. data = {}
  91. r = []
  92. if not self.graph:
  93. return []
  94. # This code wants the values in the dict to be specifically sets
  95. for k, v in self.graph.items():
  96. data[k] = set(v)
  97. # Find all items that don't depend on anything.
  98. extra_items_in_deps = (reduce(set.union, data.values())
  99. - set(data.keys()))
  100. # Add empty dependencies where needed
  101. data.update({item:{} for item in extra_items_in_deps})
  102. while True:
  103. ordered = set(item for item, dep in data.items() if not dep)
  104. if not ordered:
  105. break
  106. r.extend(ordered)
  107. data = {item: (dep - ordered)
  108. for item, dep in data.items()
  109. if item not in ordered}
  110. if data:
  111. # This doesn't give as nice results as the stdlib, which
  112. # gives you the cycle by listing the nodes in order. Here
  113. # we only know the nodes in the cycle but not their order.
  114. raise CycleError(f'nodes are in a cycle', list(data.keys()))
  115. return r
  116. # end TopologicalSorter
  117. def error_with_file(file, lineno, *args):
  118. """Print an error message from file:line and args and exit."""
  119. global output_file
  120. global output_fd
  121. # For the test suite expected-errors case, don't print the
  122. # string "error: ", so they don't turn up as false positives
  123. # if you grep the meson logs for strings like that.
  124. end = 'error: ' if not testforerror else 'detected: '
  125. prefix = ''
  126. if file:
  127. prefix += f'{file}:'
  128. if lineno:
  129. prefix += f'{lineno}:'
  130. if prefix:
  131. prefix += ' '
  132. print(prefix, end=end, file=sys.stderr)
  133. print(*args, file=sys.stderr)
  134. if output_file and output_fd:
  135. output_fd.close()
  136. os.remove(output_file)
  137. exit(0 if testforerror else 1)
  138. # end error_with_file
  139. def error(lineno, *args):
  140. error_with_file(input_file, lineno, *args)
  141. # end error
  142. def output(*args):
  143. global output_fd
  144. for a in args:
  145. output_fd.write(a)
  146. def output_autogen():
  147. output('/* This file is autogenerated by scripts/decodetree.py. */\n\n')
  148. def str_indent(c):
  149. """Return a string with C spaces"""
  150. return ' ' * c
  151. def str_fields(fields):
  152. """Return a string uniquely identifying FIELDS"""
  153. r = ''
  154. for n in sorted(fields.keys()):
  155. r += '_' + n
  156. return r[1:]
  157. def whex(val):
  158. """Return a hex string for val padded for insnwidth"""
  159. global insnwidth
  160. return f'0x{val:0{insnwidth // 4}x}'
  161. def whexC(val):
  162. """Return a hex string for val padded for insnwidth,
  163. and with the proper suffix for a C constant."""
  164. suffix = ''
  165. if val >= 0x100000000:
  166. suffix = 'ull'
  167. elif val >= 0x80000000:
  168. suffix = 'u'
  169. return whex(val) + suffix
  170. def str_match_bits(bits, mask):
  171. """Return a string pretty-printing BITS/MASK"""
  172. global insnwidth
  173. i = 1 << (insnwidth - 1)
  174. space = 0x01010100
  175. r = ''
  176. while i != 0:
  177. if i & mask:
  178. if i & bits:
  179. r += '1'
  180. else:
  181. r += '0'
  182. else:
  183. r += '.'
  184. if i & space:
  185. r += ' '
  186. i >>= 1
  187. return r
  188. def is_pow2(x):
  189. """Return true iff X is equal to a power of 2."""
  190. return (x & (x - 1)) == 0
  191. def ctz(x):
  192. """Return the number of times 2 factors into X."""
  193. assert x != 0
  194. r = 0
  195. while ((x >> r) & 1) == 0:
  196. r += 1
  197. return r
  198. def is_contiguous(bits):
  199. if bits == 0:
  200. return -1
  201. shift = ctz(bits)
  202. if is_pow2((bits >> shift) + 1):
  203. return shift
  204. else:
  205. return -1
  206. def eq_fields_for_args(flds_a, arg):
  207. if len(flds_a) != len(arg.fields):
  208. return False
  209. # Only allow inference on default types
  210. for t in arg.types:
  211. if t != 'int':
  212. return False
  213. for k, a in flds_a.items():
  214. if k not in arg.fields:
  215. return False
  216. return True
  217. def eq_fields_for_fmts(flds_a, flds_b):
  218. if len(flds_a) != len(flds_b):
  219. return False
  220. for k, a in flds_a.items():
  221. if k not in flds_b:
  222. return False
  223. b = flds_b[k]
  224. if a.__class__ != b.__class__ or a != b:
  225. return False
  226. return True
  227. class Field:
  228. """Class representing a simple instruction field"""
  229. def __init__(self, sign, pos, len):
  230. self.sign = sign
  231. self.pos = pos
  232. self.len = len
  233. self.mask = ((1 << len) - 1) << pos
  234. def __str__(self):
  235. if self.sign:
  236. s = 's'
  237. else:
  238. s = ''
  239. return str(self.pos) + ':' + s + str(self.len)
  240. def str_extract(self, lvalue_formatter):
  241. global bitop_width
  242. s = 's' if self.sign else ''
  243. return f'{s}extract{bitop_width}(insn, {self.pos}, {self.len})'
  244. def referenced_fields(self):
  245. return []
  246. def __eq__(self, other):
  247. return self.sign == other.sign and self.mask == other.mask
  248. def __ne__(self, other):
  249. return not self.__eq__(other)
  250. # end Field
  251. class MultiField:
  252. """Class representing a compound instruction field"""
  253. def __init__(self, subs, mask):
  254. self.subs = subs
  255. self.sign = subs[0].sign
  256. self.mask = mask
  257. def __str__(self):
  258. return str(self.subs)
  259. def str_extract(self, lvalue_formatter):
  260. global bitop_width
  261. ret = '0'
  262. pos = 0
  263. for f in reversed(self.subs):
  264. ext = f.str_extract(lvalue_formatter)
  265. if pos == 0:
  266. ret = ext
  267. else:
  268. ret = f'deposit{bitop_width}({ret}, {pos}, {bitop_width - pos}, {ext})'
  269. pos += f.len
  270. return ret
  271. def referenced_fields(self):
  272. l = []
  273. for f in self.subs:
  274. l.extend(f.referenced_fields())
  275. return l
  276. def __ne__(self, other):
  277. if len(self.subs) != len(other.subs):
  278. return True
  279. for a, b in zip(self.subs, other.subs):
  280. if a.__class__ != b.__class__ or a != b:
  281. return True
  282. return False
  283. def __eq__(self, other):
  284. return not self.__ne__(other)
  285. # end MultiField
  286. class ConstField:
  287. """Class representing an argument field with constant value"""
  288. def __init__(self, value):
  289. self.value = value
  290. self.mask = 0
  291. self.sign = value < 0
  292. def __str__(self):
  293. return str(self.value)
  294. def str_extract(self, lvalue_formatter):
  295. return str(self.value)
  296. def referenced_fields(self):
  297. return []
  298. def __cmp__(self, other):
  299. return self.value - other.value
  300. # end ConstField
  301. class FunctionField:
  302. """Class representing a field passed through a function"""
  303. def __init__(self, func, base):
  304. self.mask = base.mask
  305. self.sign = base.sign
  306. self.base = base
  307. self.func = func
  308. def __str__(self):
  309. return self.func + '(' + str(self.base) + ')'
  310. def str_extract(self, lvalue_formatter):
  311. return (self.func + '(ctx, '
  312. + self.base.str_extract(lvalue_formatter) + ')')
  313. def referenced_fields(self):
  314. return self.base.referenced_fields()
  315. def __eq__(self, other):
  316. return self.func == other.func and self.base == other.base
  317. def __ne__(self, other):
  318. return not self.__eq__(other)
  319. # end FunctionField
  320. class ParameterField:
  321. """Class representing a pseudo-field read from a function"""
  322. def __init__(self, func):
  323. self.mask = 0
  324. self.sign = 0
  325. self.func = func
  326. def __str__(self):
  327. return self.func
  328. def str_extract(self, lvalue_formatter):
  329. return self.func + '(ctx)'
  330. def referenced_fields(self):
  331. return []
  332. def __eq__(self, other):
  333. return self.func == other.func
  334. def __ne__(self, other):
  335. return not self.__eq__(other)
  336. # end ParameterField
  337. class NamedField:
  338. """Class representing a field already named in the pattern"""
  339. def __init__(self, name, sign, len):
  340. self.mask = 0
  341. self.sign = sign
  342. self.len = len
  343. self.name = name
  344. def __str__(self):
  345. return self.name
  346. def str_extract(self, lvalue_formatter):
  347. global bitop_width
  348. s = 's' if self.sign else ''
  349. lvalue = lvalue_formatter(self.name)
  350. return f'{s}extract{bitop_width}({lvalue}, 0, {self.len})'
  351. def referenced_fields(self):
  352. return [self.name]
  353. def __eq__(self, other):
  354. return self.name == other.name
  355. def __ne__(self, other):
  356. return not self.__eq__(other)
  357. # end NamedField
  358. class Arguments:
  359. """Class representing the extracted fields of a format"""
  360. def __init__(self, nm, flds, types, extern):
  361. self.name = nm
  362. self.extern = extern
  363. self.fields = flds
  364. self.types = types
  365. def __str__(self):
  366. return self.name + ' ' + str(self.fields)
  367. def struct_name(self):
  368. return 'arg_' + self.name
  369. def output_def(self):
  370. if not self.extern:
  371. output('typedef struct {\n')
  372. for (n, t) in zip(self.fields, self.types):
  373. output(f' {t} {n};\n')
  374. output('} ', self.struct_name(), ';\n\n')
  375. # end Arguments
  376. class General:
  377. """Common code between instruction formats and instruction patterns"""
  378. def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds, w):
  379. self.name = name
  380. self.file = input_file
  381. self.lineno = lineno
  382. self.base = base
  383. self.fixedbits = fixb
  384. self.fixedmask = fixm
  385. self.undefmask = udfm
  386. self.fieldmask = fldm
  387. self.fields = flds
  388. self.width = w
  389. self.dangling = None
  390. def __str__(self):
  391. return self.name + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
  392. def str1(self, i):
  393. return str_indent(i) + self.__str__()
  394. def dangling_references(self):
  395. # Return a list of all named references which aren't satisfied
  396. # directly by this format/pattern. This will be either:
  397. # * a format referring to a field which is specified by the
  398. # pattern(s) using it
  399. # * a pattern referring to a field which is specified by the
  400. # format it uses
  401. # * a user error (referring to a field that doesn't exist at all)
  402. if self.dangling is None:
  403. # Compute this once and cache the answer
  404. dangling = []
  405. for n, f in self.fields.items():
  406. for r in f.referenced_fields():
  407. if r not in self.fields:
  408. dangling.append(r)
  409. self.dangling = dangling
  410. return self.dangling
  411. def output_fields(self, indent, lvalue_formatter):
  412. # We use a topological sort to ensure that any use of NamedField
  413. # comes after the initialization of the field it is referencing.
  414. graph = {}
  415. for n, f in self.fields.items():
  416. refs = f.referenced_fields()
  417. graph[n] = refs
  418. try:
  419. ts = TopologicalSorter(graph)
  420. for n in ts.static_order():
  421. # We only want to emit assignments for the keys
  422. # in our fields list, not for anything that ends up
  423. # in the tsort graph only because it was referenced as
  424. # a NamedField.
  425. try:
  426. f = self.fields[n]
  427. output(indent, lvalue_formatter(n), ' = ',
  428. f.str_extract(lvalue_formatter), ';\n')
  429. except KeyError:
  430. pass
  431. except CycleError as e:
  432. # The second element of args is a list of nodes which form
  433. # a cycle (there might be others too, but only one is reported).
  434. # Pretty-print it to tell the user.
  435. cycle = ' => '.join(e.args[1])
  436. error(self.lineno, 'field definitions form a cycle: ' + cycle)
  437. # end General
  438. class Format(General):
  439. """Class representing an instruction format"""
  440. def extract_name(self):
  441. global decode_function
  442. return decode_function + '_extract_' + self.name
  443. def output_extract(self):
  444. output('static void ', self.extract_name(), '(DisasContext *ctx, ',
  445. self.base.struct_name(), ' *a, ', insntype, ' insn)\n{\n')
  446. self.output_fields(str_indent(4), lambda n: 'a->' + n)
  447. output('}\n\n')
  448. # end Format
  449. class Pattern(General):
  450. """Class representing an instruction pattern"""
  451. def output_decl(self):
  452. global translate_scope
  453. global translate_prefix
  454. output('typedef ', self.base.base.struct_name(),
  455. ' arg_', self.name, ';\n')
  456. output(translate_scope, 'bool ', translate_prefix, '_', self.name,
  457. '(DisasContext *ctx, arg_', self.name, ' *a);\n')
  458. def output_code(self, i, extracted, outerbits, outermask):
  459. global translate_prefix
  460. ind = str_indent(i)
  461. arg = self.base.base.name
  462. output(ind, '/* ', self.file, ':', str(self.lineno), ' */\n')
  463. # We might have named references in the format that refer to fields
  464. # in the pattern, or named references in the pattern that refer
  465. # to fields in the format. This affects whether we extract the fields
  466. # for the format before or after the ones for the pattern.
  467. # For simplicity we don't allow cross references in both directions.
  468. # This is also where we catch the syntax error of referring to
  469. # a nonexistent field.
  470. fmt_refs = self.base.dangling_references()
  471. for r in fmt_refs:
  472. if r not in self.fields:
  473. error(self.lineno, f'format refers to undefined field {r}')
  474. pat_refs = self.dangling_references()
  475. for r in pat_refs:
  476. if r not in self.base.fields:
  477. error(self.lineno, f'pattern refers to undefined field {r}')
  478. if pat_refs and fmt_refs:
  479. error(self.lineno, ('pattern that uses fields defined in format '
  480. 'cannot use format that uses fields defined '
  481. 'in pattern'))
  482. if fmt_refs:
  483. # pattern fields first
  484. self.output_fields(ind, lambda n: 'u.f_' + arg + '.' + n)
  485. assert not extracted, "dangling fmt refs but it was already extracted"
  486. if not extracted:
  487. output(ind, self.base.extract_name(),
  488. '(ctx, &u.f_', arg, ', insn);\n')
  489. if not fmt_refs:
  490. # pattern fields last
  491. self.output_fields(ind, lambda n: 'u.f_' + arg + '.' + n)
  492. output(ind, 'if (', translate_prefix, '_', self.name,
  493. '(ctx, &u.f_', arg, ')) return true;\n')
  494. # Normal patterns do not have children.
  495. def build_tree(self):
  496. return
  497. def prop_masks(self):
  498. return
  499. def prop_format(self):
  500. return
  501. def prop_width(self):
  502. return
  503. # end Pattern
  504. class MultiPattern(General):
  505. """Class representing a set of instruction patterns"""
  506. def __init__(self, lineno):
  507. self.file = input_file
  508. self.lineno = lineno
  509. self.pats = []
  510. self.base = None
  511. self.fixedbits = 0
  512. self.fixedmask = 0
  513. self.undefmask = 0
  514. self.width = None
  515. def __str__(self):
  516. r = 'group'
  517. if self.fixedbits is not None:
  518. r += ' ' + str_match_bits(self.fixedbits, self.fixedmask)
  519. return r
  520. def output_decl(self):
  521. for p in self.pats:
  522. p.output_decl()
  523. def prop_masks(self):
  524. global insnmask
  525. fixedmask = insnmask
  526. undefmask = insnmask
  527. # Collect fixedmask/undefmask for all of the children.
  528. for p in self.pats:
  529. p.prop_masks()
  530. fixedmask &= p.fixedmask
  531. undefmask &= p.undefmask
  532. # Widen fixedmask until all fixedbits match
  533. repeat = True
  534. fixedbits = 0
  535. while repeat and fixedmask != 0:
  536. fixedbits = None
  537. for p in self.pats:
  538. thisbits = p.fixedbits & fixedmask
  539. if fixedbits is None:
  540. fixedbits = thisbits
  541. elif fixedbits != thisbits:
  542. fixedmask &= ~(fixedbits ^ thisbits)
  543. break
  544. else:
  545. repeat = False
  546. self.fixedbits = fixedbits
  547. self.fixedmask = fixedmask
  548. self.undefmask = undefmask
  549. def build_tree(self):
  550. for p in self.pats:
  551. p.build_tree()
  552. def prop_format(self):
  553. for p in self.pats:
  554. p.prop_format()
  555. def prop_width(self):
  556. width = None
  557. for p in self.pats:
  558. p.prop_width()
  559. if width is None:
  560. width = p.width
  561. elif width != p.width:
  562. error_with_file(self.file, self.lineno,
  563. 'width mismatch in patterns within braces')
  564. self.width = width
  565. # end MultiPattern
  566. class IncMultiPattern(MultiPattern):
  567. """Class representing an overlapping set of instruction patterns"""
  568. def output_code(self, i, extracted, outerbits, outermask):
  569. global translate_prefix
  570. ind = str_indent(i)
  571. for p in self.pats:
  572. if outermask != p.fixedmask:
  573. innermask = p.fixedmask & ~outermask
  574. innerbits = p.fixedbits & ~outermask
  575. output(ind, f'if ((insn & {whexC(innermask)}) == {whexC(innerbits)}) {{\n')
  576. output(ind, f' /* {str_match_bits(p.fixedbits, p.fixedmask)} */\n')
  577. p.output_code(i + 4, extracted, p.fixedbits, p.fixedmask)
  578. output(ind, '}\n')
  579. else:
  580. p.output_code(i, extracted, p.fixedbits, p.fixedmask)
  581. def build_tree(self):
  582. if not self.pats:
  583. error_with_file(self.file, self.lineno, 'empty pattern group')
  584. super().build_tree()
  585. #end IncMultiPattern
  586. class Tree:
  587. """Class representing a node in a decode tree"""
  588. def __init__(self, fm, tm):
  589. self.fixedmask = fm
  590. self.thismask = tm
  591. self.subs = []
  592. self.base = None
  593. def str1(self, i):
  594. ind = str_indent(i)
  595. r = ind + whex(self.fixedmask)
  596. if self.format:
  597. r += ' ' + self.format.name
  598. r += ' [\n'
  599. for (b, s) in self.subs:
  600. r += ind + f' {whex(b)}:\n'
  601. r += s.str1(i + 4) + '\n'
  602. r += ind + ']'
  603. return r
  604. def __str__(self):
  605. return self.str1(0)
  606. def output_code(self, i, extracted, outerbits, outermask):
  607. ind = str_indent(i)
  608. # If we identified all nodes below have the same format,
  609. # extract the fields now. But don't do it if the format relies
  610. # on named fields from the insn pattern, as those won't have
  611. # been initialised at this point.
  612. if not extracted and self.base and not self.base.dangling_references():
  613. output(ind, self.base.extract_name(),
  614. '(ctx, &u.f_', self.base.base.name, ', insn);\n')
  615. extracted = True
  616. # Attempt to aid the compiler in producing compact switch statements.
  617. # If the bits in the mask are contiguous, extract them.
  618. sh = is_contiguous(self.thismask)
  619. if sh > 0:
  620. # Propagate SH down into the local functions.
  621. def str_switch(b, sh=sh):
  622. return f'(insn >> {sh}) & {b >> sh:#x}'
  623. def str_case(b, sh=sh):
  624. return hex(b >> sh)
  625. else:
  626. def str_switch(b):
  627. return f'insn & {whexC(b)}'
  628. def str_case(b):
  629. return whexC(b)
  630. output(ind, 'switch (', str_switch(self.thismask), ') {\n')
  631. for b, s in sorted(self.subs):
  632. assert (self.thismask & ~s.fixedmask) == 0
  633. innermask = outermask | self.thismask
  634. innerbits = outerbits | b
  635. output(ind, 'case ', str_case(b), ':\n')
  636. output(ind, ' /* ',
  637. str_match_bits(innerbits, innermask), ' */\n')
  638. s.output_code(i + 4, extracted, innerbits, innermask)
  639. output(ind, ' break;\n')
  640. output(ind, '}\n')
  641. # end Tree
  642. class ExcMultiPattern(MultiPattern):
  643. """Class representing a non-overlapping set of instruction patterns"""
  644. def output_code(self, i, extracted, outerbits, outermask):
  645. # Defer everything to our decomposed Tree node
  646. self.tree.output_code(i, extracted, outerbits, outermask)
  647. @staticmethod
  648. def __build_tree(pats, outerbits, outermask):
  649. # Find the intersection of all remaining fixedmask.
  650. innermask = ~outermask & insnmask
  651. for i in pats:
  652. innermask &= i.fixedmask
  653. if innermask == 0:
  654. # Edge condition: One pattern covers the entire insnmask
  655. if len(pats) == 1:
  656. t = Tree(outermask, innermask)
  657. t.subs.append((0, pats[0]))
  658. return t
  659. text = 'overlapping patterns:'
  660. for p in pats:
  661. text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
  662. error_with_file(pats[0].file, pats[0].lineno, text)
  663. fullmask = outermask | innermask
  664. # Sort each element of pats into the bin selected by the mask.
  665. bins = {}
  666. for i in pats:
  667. fb = i.fixedbits & innermask
  668. if fb in bins:
  669. bins[fb].append(i)
  670. else:
  671. bins[fb] = [i]
  672. # We must recurse if any bin has more than one element or if
  673. # the single element in the bin has not been fully matched.
  674. t = Tree(fullmask, innermask)
  675. for b, l in bins.items():
  676. s = l[0]
  677. if len(l) > 1 or s.fixedmask & ~fullmask != 0:
  678. s = ExcMultiPattern.__build_tree(l, b | outerbits, fullmask)
  679. t.subs.append((b, s))
  680. return t
  681. def build_tree(self):
  682. super().build_tree()
  683. self.tree = self.__build_tree(self.pats, self.fixedbits,
  684. self.fixedmask)
  685. @staticmethod
  686. def __prop_format(tree):
  687. """Propagate Format objects into the decode tree"""
  688. # Depth first search.
  689. for (b, s) in tree.subs:
  690. if isinstance(s, Tree):
  691. ExcMultiPattern.__prop_format(s)
  692. # If all entries in SUBS have the same format, then
  693. # propagate that into the tree.
  694. f = None
  695. for (b, s) in tree.subs:
  696. if f is None:
  697. f = s.base
  698. if f is None:
  699. return
  700. if f is not s.base:
  701. return
  702. tree.base = f
  703. def prop_format(self):
  704. super().prop_format()
  705. self.__prop_format(self.tree)
  706. # end ExcMultiPattern
  707. def parse_field(lineno, name, toks):
  708. """Parse one instruction field from TOKS at LINENO"""
  709. global fields
  710. global insnwidth
  711. global re_C_ident
  712. # A "simple" field will have only one entry;
  713. # a "multifield" will have several.
  714. subs = []
  715. width = 0
  716. func = None
  717. for t in toks:
  718. if re.match('^!function=', t):
  719. if func:
  720. error(lineno, 'duplicate function')
  721. func = t.split('=')
  722. func = func[1]
  723. continue
  724. if re.fullmatch(re_C_ident + ':s[0-9]+', t):
  725. # Signed named field
  726. subtoks = t.split(':')
  727. n = subtoks[0]
  728. le = int(subtoks[1])
  729. f = NamedField(n, True, le)
  730. subs.append(f)
  731. width += le
  732. continue
  733. if re.fullmatch(re_C_ident + ':[0-9]+', t):
  734. # Unsigned named field
  735. subtoks = t.split(':')
  736. n = subtoks[0]
  737. le = int(subtoks[1])
  738. f = NamedField(n, False, le)
  739. subs.append(f)
  740. width += le
  741. continue
  742. if re.fullmatch('[0-9]+:s[0-9]+', t):
  743. # Signed field extract
  744. subtoks = t.split(':s')
  745. sign = True
  746. elif re.fullmatch('[0-9]+:[0-9]+', t):
  747. # Unsigned field extract
  748. subtoks = t.split(':')
  749. sign = False
  750. else:
  751. error(lineno, f'invalid field token "{t}"')
  752. po = int(subtoks[0])
  753. le = int(subtoks[1])
  754. if po + le > insnwidth:
  755. error(lineno, f'field {t} too large')
  756. f = Field(sign, po, le)
  757. subs.append(f)
  758. width += le
  759. if width > insnwidth:
  760. error(lineno, 'field too large')
  761. if len(subs) == 0:
  762. if func:
  763. f = ParameterField(func)
  764. else:
  765. error(lineno, 'field with no value')
  766. else:
  767. if len(subs) == 1:
  768. f = subs[0]
  769. else:
  770. mask = 0
  771. for s in subs:
  772. if mask & s.mask:
  773. error(lineno, 'field components overlap')
  774. mask |= s.mask
  775. f = MultiField(subs, mask)
  776. if func:
  777. f = FunctionField(func, f)
  778. if name in fields:
  779. error(lineno, 'duplicate field', name)
  780. fields[name] = f
  781. # end parse_field
  782. def parse_arguments(lineno, name, toks):
  783. """Parse one argument set from TOKS at LINENO"""
  784. global arguments
  785. global re_C_ident
  786. global anyextern
  787. flds = []
  788. types = []
  789. extern = False
  790. for n in toks:
  791. if re.fullmatch('!extern', n):
  792. extern = True
  793. anyextern = True
  794. continue
  795. if re.fullmatch(re_C_ident + ':' + re_C_ident, n):
  796. (n, t) = n.split(':')
  797. elif re.fullmatch(re_C_ident, n):
  798. t = 'int'
  799. else:
  800. error(lineno, f'invalid argument set token "{n}"')
  801. if n in flds:
  802. error(lineno, f'duplicate argument "{n}"')
  803. flds.append(n)
  804. types.append(t)
  805. if name in arguments:
  806. error(lineno, 'duplicate argument set', name)
  807. arguments[name] = Arguments(name, flds, types, extern)
  808. # end parse_arguments
  809. def lookup_field(lineno, name):
  810. global fields
  811. if name in fields:
  812. return fields[name]
  813. error(lineno, 'undefined field', name)
  814. def add_field(lineno, flds, new_name, f):
  815. if new_name in flds:
  816. error(lineno, 'duplicate field', new_name)
  817. flds[new_name] = f
  818. return flds
  819. def add_field_byname(lineno, flds, new_name, old_name):
  820. return add_field(lineno, flds, new_name, lookup_field(lineno, old_name))
  821. def infer_argument_set(flds):
  822. global arguments
  823. global decode_function
  824. for arg in arguments.values():
  825. if eq_fields_for_args(flds, arg):
  826. return arg
  827. name = decode_function + str(len(arguments))
  828. arg = Arguments(name, flds.keys(), ['int'] * len(flds), False)
  829. arguments[name] = arg
  830. return arg
  831. def infer_format(arg, fieldmask, flds, width):
  832. global arguments
  833. global formats
  834. global decode_function
  835. const_flds = {}
  836. var_flds = {}
  837. for n, c in flds.items():
  838. if c is ConstField:
  839. const_flds[n] = c
  840. else:
  841. var_flds[n] = c
  842. # Look for an existing format with the same argument set and fields
  843. for fmt in formats.values():
  844. if arg and fmt.base != arg:
  845. continue
  846. if fieldmask != fmt.fieldmask:
  847. continue
  848. if width != fmt.width:
  849. continue
  850. if not eq_fields_for_fmts(flds, fmt.fields):
  851. continue
  852. return (fmt, const_flds)
  853. name = decode_function + '_Fmt_' + str(len(formats))
  854. if not arg:
  855. arg = infer_argument_set(flds)
  856. fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds, width)
  857. formats[name] = fmt
  858. return (fmt, const_flds)
  859. # end infer_format
  860. def parse_generic(lineno, parent_pat, name, toks):
  861. """Parse one instruction format from TOKS at LINENO"""
  862. global fields
  863. global arguments
  864. global formats
  865. global allpatterns
  866. global re_arg_ident
  867. global re_fld_ident
  868. global re_fmt_ident
  869. global re_C_ident
  870. global insnwidth
  871. global insnmask
  872. global variablewidth
  873. is_format = parent_pat is None
  874. fixedmask = 0
  875. fixedbits = 0
  876. undefmask = 0
  877. width = 0
  878. flds = {}
  879. arg = None
  880. fmt = None
  881. for t in toks:
  882. # '&Foo' gives a format an explicit argument set.
  883. if re.fullmatch(re_arg_ident, t):
  884. tt = t[1:]
  885. if arg:
  886. error(lineno, 'multiple argument sets')
  887. if tt in arguments:
  888. arg = arguments[tt]
  889. else:
  890. error(lineno, 'undefined argument set', t)
  891. continue
  892. # '@Foo' gives a pattern an explicit format.
  893. if re.fullmatch(re_fmt_ident, t):
  894. tt = t[1:]
  895. if fmt:
  896. error(lineno, 'multiple formats')
  897. if tt in formats:
  898. fmt = formats[tt]
  899. else:
  900. error(lineno, 'undefined format', t)
  901. continue
  902. # '%Foo' imports a field.
  903. if re.fullmatch(re_fld_ident, t):
  904. tt = t[1:]
  905. flds = add_field_byname(lineno, flds, tt, tt)
  906. continue
  907. # 'Foo=%Bar' imports a field with a different name.
  908. if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
  909. (fname, iname) = t.split('=%')
  910. flds = add_field_byname(lineno, flds, fname, iname)
  911. continue
  912. # 'Foo=number' sets an argument field to a constant value
  913. if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
  914. (fname, value) = t.split('=')
  915. value = int(value)
  916. flds = add_field(lineno, flds, fname, ConstField(value))
  917. continue
  918. # Pattern of 0s, 1s, dots and dashes indicate required zeros,
  919. # required ones, or dont-cares.
  920. if re.fullmatch('[01.-]+', t):
  921. shift = len(t)
  922. fms = t.replace('0', '1')
  923. fms = fms.replace('.', '0')
  924. fms = fms.replace('-', '0')
  925. fbs = t.replace('.', '0')
  926. fbs = fbs.replace('-', '0')
  927. ubm = t.replace('1', '0')
  928. ubm = ubm.replace('.', '0')
  929. ubm = ubm.replace('-', '1')
  930. fms = int(fms, 2)
  931. fbs = int(fbs, 2)
  932. ubm = int(ubm, 2)
  933. fixedbits = (fixedbits << shift) | fbs
  934. fixedmask = (fixedmask << shift) | fms
  935. undefmask = (undefmask << shift) | ubm
  936. # Otherwise, fieldname:fieldwidth
  937. elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
  938. (fname, flen) = t.split(':')
  939. sign = False
  940. if flen[0] == 's':
  941. sign = True
  942. flen = flen[1:]
  943. shift = int(flen, 10)
  944. if shift + width > insnwidth:
  945. error(lineno, f'field {fname} exceeds insnwidth')
  946. f = Field(sign, insnwidth - width - shift, shift)
  947. flds = add_field(lineno, flds, fname, f)
  948. fixedbits <<= shift
  949. fixedmask <<= shift
  950. undefmask <<= shift
  951. else:
  952. error(lineno, f'invalid token "{t}"')
  953. width += shift
  954. if variablewidth and width < insnwidth and width % 8 == 0:
  955. shift = insnwidth - width
  956. fixedbits <<= shift
  957. fixedmask <<= shift
  958. undefmask <<= shift
  959. undefmask |= (1 << shift) - 1
  960. # We should have filled in all of the bits of the instruction.
  961. elif not (is_format and width == 0) and width != insnwidth:
  962. error(lineno, f'definition has {width} bits')
  963. # Do not check for fields overlapping fields; one valid usage
  964. # is to be able to duplicate fields via import.
  965. fieldmask = 0
  966. for f in flds.values():
  967. fieldmask |= f.mask
  968. # Fix up what we've parsed to match either a format or a pattern.
  969. if is_format:
  970. # Formats cannot reference formats.
  971. if fmt:
  972. error(lineno, 'format referencing format')
  973. # If an argument set is given, then there should be no fields
  974. # without a place to store it.
  975. if arg:
  976. for f in flds.keys():
  977. if f not in arg.fields:
  978. error(lineno, f'field {f} not in argument set {arg.name}')
  979. else:
  980. arg = infer_argument_set(flds)
  981. if name in formats:
  982. error(lineno, 'duplicate format name', name)
  983. fmt = Format(name, lineno, arg, fixedbits, fixedmask,
  984. undefmask, fieldmask, flds, width)
  985. formats[name] = fmt
  986. else:
  987. # Patterns can reference a format ...
  988. if fmt:
  989. # ... but not an argument simultaneously
  990. if arg:
  991. error(lineno, 'pattern specifies both format and argument set')
  992. if fixedmask & fmt.fixedmask:
  993. error(lineno, 'pattern fixed bits overlap format fixed bits')
  994. if width != fmt.width:
  995. error(lineno, 'pattern uses format of different width')
  996. fieldmask |= fmt.fieldmask
  997. fixedbits |= fmt.fixedbits
  998. fixedmask |= fmt.fixedmask
  999. undefmask |= fmt.undefmask
  1000. else:
  1001. (fmt, flds) = infer_format(arg, fieldmask, flds, width)
  1002. arg = fmt.base
  1003. for f in flds.keys():
  1004. if f not in arg.fields:
  1005. error(lineno, f'field {f} not in argument set {arg.name}')
  1006. if f in fmt.fields.keys():
  1007. error(lineno, f'field {f} set by format and pattern')
  1008. for f in arg.fields:
  1009. if f not in flds.keys() and f not in fmt.fields.keys():
  1010. error(lineno, f'field {f} not initialized')
  1011. pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
  1012. undefmask, fieldmask, flds, width)
  1013. parent_pat.pats.append(pat)
  1014. allpatterns.append(pat)
  1015. # Validate the masks that we have assembled.
  1016. if fieldmask & fixedmask:
  1017. error(lineno, 'fieldmask overlaps fixedmask ',
  1018. f'({whex(fieldmask)} & {whex(fixedmask)})')
  1019. if fieldmask & undefmask:
  1020. error(lineno, 'fieldmask overlaps undefmask ',
  1021. f'({whex(fieldmask)} & {whex(undefmask)})')
  1022. if fixedmask & undefmask:
  1023. error(lineno, 'fixedmask overlaps undefmask ',
  1024. f'({whex(fixedmask)} & {whex(undefmask)})')
  1025. if not is_format:
  1026. allbits = fieldmask | fixedmask | undefmask
  1027. if allbits != insnmask:
  1028. error(lineno, 'bits left unspecified ',
  1029. f'({whex(allbits ^ insnmask)})')
  1030. # end parse_general
  1031. def parse_file(f, parent_pat):
  1032. """Parse all of the patterns within a file"""
  1033. global re_arg_ident
  1034. global re_fld_ident
  1035. global re_fmt_ident
  1036. global re_pat_ident
  1037. # Read all of the lines of the file. Concatenate lines
  1038. # ending in backslash; discard empty lines and comments.
  1039. toks = []
  1040. lineno = 0
  1041. nesting = 0
  1042. nesting_pats = []
  1043. for line in f:
  1044. lineno += 1
  1045. # Expand and strip spaces, to find indent.
  1046. line = line.rstrip()
  1047. line = line.expandtabs()
  1048. len1 = len(line)
  1049. line = line.lstrip()
  1050. len2 = len(line)
  1051. # Discard comments
  1052. end = line.find('#')
  1053. if end >= 0:
  1054. line = line[:end]
  1055. t = line.split()
  1056. if len(toks) != 0:
  1057. # Next line after continuation
  1058. toks.extend(t)
  1059. else:
  1060. # Allow completely blank lines.
  1061. if len1 == 0:
  1062. continue
  1063. indent = len1 - len2
  1064. # Empty line due to comment.
  1065. if len(t) == 0:
  1066. # Indentation must be correct, even for comment lines.
  1067. if indent != nesting:
  1068. error(lineno, 'indentation ', indent, ' != ', nesting)
  1069. continue
  1070. start_lineno = lineno
  1071. toks = t
  1072. # Continuation?
  1073. if toks[-1] == '\\':
  1074. toks.pop()
  1075. continue
  1076. name = toks[0]
  1077. del toks[0]
  1078. # End nesting?
  1079. if name == '}' or name == ']':
  1080. if len(toks) != 0:
  1081. error(start_lineno, 'extra tokens after close brace')
  1082. # Make sure { } and [ ] nest properly.
  1083. if (name == '}') != isinstance(parent_pat, IncMultiPattern):
  1084. error(lineno, 'mismatched close brace')
  1085. try:
  1086. parent_pat = nesting_pats.pop()
  1087. except:
  1088. error(lineno, 'extra close brace')
  1089. nesting -= 2
  1090. if indent != nesting:
  1091. error(lineno, 'indentation ', indent, ' != ', nesting)
  1092. toks = []
  1093. continue
  1094. # Everything else should have current indentation.
  1095. if indent != nesting:
  1096. error(start_lineno, 'indentation ', indent, ' != ', nesting)
  1097. # Start nesting?
  1098. if name == '{' or name == '[':
  1099. if len(toks) != 0:
  1100. error(start_lineno, 'extra tokens after open brace')
  1101. if name == '{':
  1102. nested_pat = IncMultiPattern(start_lineno)
  1103. else:
  1104. nested_pat = ExcMultiPattern(start_lineno)
  1105. parent_pat.pats.append(nested_pat)
  1106. nesting_pats.append(parent_pat)
  1107. parent_pat = nested_pat
  1108. nesting += 2
  1109. toks = []
  1110. continue
  1111. # Determine the type of object needing to be parsed.
  1112. if re.fullmatch(re_fld_ident, name):
  1113. parse_field(start_lineno, name[1:], toks)
  1114. elif re.fullmatch(re_arg_ident, name):
  1115. parse_arguments(start_lineno, name[1:], toks)
  1116. elif re.fullmatch(re_fmt_ident, name):
  1117. parse_generic(start_lineno, None, name[1:], toks)
  1118. elif re.fullmatch(re_pat_ident, name):
  1119. parse_generic(start_lineno, parent_pat, name, toks)
  1120. else:
  1121. error(lineno, f'invalid token "{name}"')
  1122. toks = []
  1123. if nesting != 0:
  1124. error(lineno, 'missing close brace')
  1125. # end parse_file
  1126. class SizeTree:
  1127. """Class representing a node in a size decode tree"""
  1128. def __init__(self, m, w):
  1129. self.mask = m
  1130. self.subs = []
  1131. self.base = None
  1132. self.width = w
  1133. def str1(self, i):
  1134. ind = str_indent(i)
  1135. r = ind + whex(self.mask) + ' [\n'
  1136. for (b, s) in self.subs:
  1137. r += ind + f' {whex(b)}:\n'
  1138. r += s.str1(i + 4) + '\n'
  1139. r += ind + ']'
  1140. return r
  1141. def __str__(self):
  1142. return self.str1(0)
  1143. def output_code(self, i, extracted, outerbits, outermask):
  1144. ind = str_indent(i)
  1145. # If we need to load more bytes to test, do so now.
  1146. if extracted < self.width:
  1147. output(ind, f'insn = {decode_function}_load_bytes',
  1148. f'(ctx, insn, {extracted // 8}, {self.width // 8});\n')
  1149. extracted = self.width
  1150. # Attempt to aid the compiler in producing compact switch statements.
  1151. # If the bits in the mask are contiguous, extract them.
  1152. sh = is_contiguous(self.mask)
  1153. if sh > 0:
  1154. # Propagate SH down into the local functions.
  1155. def str_switch(b, sh=sh):
  1156. return f'(insn >> {sh}) & {b >> sh:#x}'
  1157. def str_case(b, sh=sh):
  1158. return hex(b >> sh)
  1159. else:
  1160. def str_switch(b):
  1161. return f'insn & {whexC(b)}'
  1162. def str_case(b):
  1163. return whexC(b)
  1164. output(ind, 'switch (', str_switch(self.mask), ') {\n')
  1165. for b, s in sorted(self.subs):
  1166. innermask = outermask | self.mask
  1167. innerbits = outerbits | b
  1168. output(ind, 'case ', str_case(b), ':\n')
  1169. output(ind, ' /* ',
  1170. str_match_bits(innerbits, innermask), ' */\n')
  1171. s.output_code(i + 4, extracted, innerbits, innermask)
  1172. output(ind, '}\n')
  1173. output(ind, 'return insn;\n')
  1174. # end SizeTree
  1175. class SizeLeaf:
  1176. """Class representing a leaf node in a size decode tree"""
  1177. def __init__(self, m, w):
  1178. self.mask = m
  1179. self.width = w
  1180. def str1(self, i):
  1181. return str_indent(i) + whex(self.mask)
  1182. def __str__(self):
  1183. return self.str1(0)
  1184. def output_code(self, i, extracted, outerbits, outermask):
  1185. global decode_function
  1186. ind = str_indent(i)
  1187. # If we need to load more bytes, do so now.
  1188. if extracted < self.width:
  1189. output(ind, f'insn = {decode_function}_load_bytes',
  1190. f'(ctx, insn, {extracted // 8}, {self.width // 8});\n')
  1191. extracted = self.width
  1192. output(ind, 'return insn;\n')
  1193. # end SizeLeaf
  1194. def build_size_tree(pats, width, outerbits, outermask):
  1195. global insnwidth
  1196. # Collect the mask of bits that are fixed in this width
  1197. innermask = 0xff << (insnwidth - width)
  1198. innermask &= ~outermask
  1199. minwidth = None
  1200. onewidth = True
  1201. for i in pats:
  1202. innermask &= i.fixedmask
  1203. if minwidth is None:
  1204. minwidth = i.width
  1205. elif minwidth != i.width:
  1206. onewidth = False;
  1207. if minwidth < i.width:
  1208. minwidth = i.width
  1209. if onewidth:
  1210. return SizeLeaf(innermask, minwidth)
  1211. if innermask == 0:
  1212. if width < minwidth:
  1213. return build_size_tree(pats, width + 8, outerbits, outermask)
  1214. pnames = []
  1215. for p in pats:
  1216. pnames.append(p.name + ':' + p.file + ':' + str(p.lineno))
  1217. error_with_file(pats[0].file, pats[0].lineno,
  1218. f'overlapping patterns size {width}:', pnames)
  1219. bins = {}
  1220. for i in pats:
  1221. fb = i.fixedbits & innermask
  1222. if fb in bins:
  1223. bins[fb].append(i)
  1224. else:
  1225. bins[fb] = [i]
  1226. fullmask = outermask | innermask
  1227. lens = sorted(bins.keys())
  1228. if len(lens) == 1:
  1229. b = lens[0]
  1230. return build_size_tree(bins[b], width + 8, b | outerbits, fullmask)
  1231. r = SizeTree(innermask, width)
  1232. for b, l in bins.items():
  1233. s = build_size_tree(l, width, b | outerbits, fullmask)
  1234. r.subs.append((b, s))
  1235. return r
  1236. # end build_size_tree
  1237. def prop_size(tree):
  1238. """Propagate minimum widths up the decode size tree"""
  1239. if isinstance(tree, SizeTree):
  1240. min = None
  1241. for (b, s) in tree.subs:
  1242. width = prop_size(s)
  1243. if min is None or min > width:
  1244. min = width
  1245. assert min >= tree.width
  1246. tree.width = min
  1247. else:
  1248. min = tree.width
  1249. return min
  1250. # end prop_size
  1251. def main():
  1252. global arguments
  1253. global formats
  1254. global allpatterns
  1255. global translate_scope
  1256. global translate_prefix
  1257. global output_fd
  1258. global output_file
  1259. global output_null
  1260. global input_file
  1261. global insnwidth
  1262. global insntype
  1263. global insnmask
  1264. global decode_function
  1265. global bitop_width
  1266. global variablewidth
  1267. global anyextern
  1268. global testforerror
  1269. decode_scope = 'static '
  1270. long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=',
  1271. 'static-decode=', 'varinsnwidth=', 'test-for-error',
  1272. 'output-null']
  1273. try:
  1274. (opts, args) = getopt.gnu_getopt(sys.argv[1:], 'o:vw:', long_opts)
  1275. except getopt.GetoptError as err:
  1276. error(0, err)
  1277. for o, a in opts:
  1278. if o in ('-o', '--output'):
  1279. output_file = a
  1280. elif o == '--decode':
  1281. decode_function = a
  1282. decode_scope = ''
  1283. elif o == '--static-decode':
  1284. decode_function = a
  1285. elif o == '--translate':
  1286. translate_prefix = a
  1287. translate_scope = ''
  1288. elif o in ('-w', '--insnwidth', '--varinsnwidth'):
  1289. if o == '--varinsnwidth':
  1290. variablewidth = True
  1291. insnwidth = int(a)
  1292. if insnwidth == 16:
  1293. insntype = 'uint16_t'
  1294. insnmask = 0xffff
  1295. elif insnwidth == 64:
  1296. insntype = 'uint64_t'
  1297. insnmask = 0xffffffffffffffff
  1298. bitop_width = 64
  1299. elif insnwidth != 32:
  1300. error(0, 'cannot handle insns of width', insnwidth)
  1301. elif o == '--test-for-error':
  1302. testforerror = True
  1303. elif o == '--output-null':
  1304. output_null = True
  1305. else:
  1306. assert False, 'unhandled option'
  1307. if len(args) < 1:
  1308. error(0, 'missing input file')
  1309. toppat = ExcMultiPattern(0)
  1310. for filename in args:
  1311. input_file = filename
  1312. f = open(filename, 'rt', encoding='utf-8')
  1313. parse_file(f, toppat)
  1314. f.close()
  1315. # We do not want to compute masks for toppat, because those masks
  1316. # are used as a starting point for build_tree. For toppat, we must
  1317. # insist that decode begins from naught.
  1318. for i in toppat.pats:
  1319. i.prop_masks()
  1320. toppat.build_tree()
  1321. toppat.prop_format()
  1322. if variablewidth:
  1323. for i in toppat.pats:
  1324. i.prop_width()
  1325. stree = build_size_tree(toppat.pats, 8, 0, 0)
  1326. prop_size(stree)
  1327. if output_null:
  1328. output_fd = open(os.devnull, 'wt', encoding='utf-8', errors="ignore")
  1329. elif output_file:
  1330. output_fd = open(output_file, 'wt', encoding='utf-8')
  1331. else:
  1332. output_fd = io.TextIOWrapper(sys.stdout.buffer,
  1333. encoding=sys.stdout.encoding,
  1334. errors="ignore")
  1335. output_autogen()
  1336. for n in sorted(arguments.keys()):
  1337. f = arguments[n]
  1338. f.output_def()
  1339. # A single translate function can be invoked for different patterns.
  1340. # Make sure that the argument sets are the same, and declare the
  1341. # function only once.
  1342. #
  1343. # If we're sharing formats, we're likely also sharing trans_* functions,
  1344. # but we can't tell which ones. Prevent issues from the compiler by
  1345. # suppressing redundant declaration warnings.
  1346. if anyextern:
  1347. output("#pragma GCC diagnostic push\n",
  1348. "#pragma GCC diagnostic ignored \"-Wredundant-decls\"\n",
  1349. "#ifdef __clang__\n"
  1350. "# pragma GCC diagnostic ignored \"-Wtypedef-redefinition\"\n",
  1351. "#endif\n\n")
  1352. out_pats = {}
  1353. for i in allpatterns:
  1354. if i.name in out_pats:
  1355. p = out_pats[i.name]
  1356. if i.base.base != p.base.base:
  1357. error(0, i.name, ' has conflicting argument sets')
  1358. else:
  1359. i.output_decl()
  1360. out_pats[i.name] = i
  1361. output('\n')
  1362. if anyextern:
  1363. output("#pragma GCC diagnostic pop\n\n")
  1364. for n in sorted(formats.keys()):
  1365. f = formats[n]
  1366. f.output_extract()
  1367. output(decode_scope, 'bool ', decode_function,
  1368. '(DisasContext *ctx, ', insntype, ' insn)\n{\n')
  1369. i4 = str_indent(4)
  1370. if len(allpatterns) != 0:
  1371. output(i4, 'union {\n')
  1372. for n in sorted(arguments.keys()):
  1373. f = arguments[n]
  1374. output(i4, i4, f.struct_name(), ' f_', f.name, ';\n')
  1375. output(i4, '} u;\n\n')
  1376. toppat.output_code(4, False, 0, 0)
  1377. output(i4, 'return false;\n')
  1378. output('}\n')
  1379. if variablewidth:
  1380. output('\n', decode_scope, insntype, ' ', decode_function,
  1381. '_load(DisasContext *ctx)\n{\n',
  1382. ' ', insntype, ' insn = 0;\n\n')
  1383. stree.output_code(4, 0, 0, 0)
  1384. output('}\n')
  1385. if output_file:
  1386. output_fd.close()
  1387. exit(1 if testforerror else 0)
  1388. # end main
  1389. if __name__ == '__main__':
  1390. main()