decodetree.py 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387
  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 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 os
  22. import re
  23. import sys
  24. import getopt
  25. insnwidth = 32
  26. insnmask = 0xffffffff
  27. variablewidth = False
  28. fields = {}
  29. arguments = {}
  30. formats = {}
  31. allpatterns = []
  32. anyextern = False
  33. translate_prefix = 'trans'
  34. translate_scope = 'static '
  35. input_file = ''
  36. output_file = None
  37. output_fd = None
  38. insntype = 'uint32_t'
  39. decode_function = 'decode'
  40. re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
  41. def error_with_file(file, lineno, *args):
  42. """Print an error message from file:line and args and exit."""
  43. global output_file
  44. global output_fd
  45. prefix = ''
  46. if file:
  47. prefix += '{0}:'.format(file)
  48. if lineno:
  49. prefix += '{0}:'.format(lineno)
  50. if prefix:
  51. prefix += ' '
  52. print(prefix, end='error: ', file=sys.stderr)
  53. print(*args, file=sys.stderr)
  54. if output_file and output_fd:
  55. output_fd.close()
  56. os.remove(output_file)
  57. exit(1)
  58. # end error_with_file
  59. def error(lineno, *args):
  60. error_with_file(input_file, lineno, *args)
  61. # end error
  62. def output(*args):
  63. global output_fd
  64. for a in args:
  65. output_fd.write(a)
  66. def output_autogen():
  67. output('/* This file is autogenerated by scripts/decodetree.py. */\n\n')
  68. def str_indent(c):
  69. """Return a string with C spaces"""
  70. return ' ' * c
  71. def str_fields(fields):
  72. """Return a string uniquely identifing FIELDS"""
  73. r = ''
  74. for n in sorted(fields.keys()):
  75. r += '_' + n
  76. return r[1:]
  77. def str_match_bits(bits, mask):
  78. """Return a string pretty-printing BITS/MASK"""
  79. global insnwidth
  80. i = 1 << (insnwidth - 1)
  81. space = 0x01010100
  82. r = ''
  83. while i != 0:
  84. if i & mask:
  85. if i & bits:
  86. r += '1'
  87. else:
  88. r += '0'
  89. else:
  90. r += '.'
  91. if i & space:
  92. r += ' '
  93. i >>= 1
  94. return r
  95. def is_pow2(x):
  96. """Return true iff X is equal to a power of 2."""
  97. return (x & (x - 1)) == 0
  98. def ctz(x):
  99. """Return the number of times 2 factors into X."""
  100. assert x != 0
  101. r = 0
  102. while ((x >> r) & 1) == 0:
  103. r += 1
  104. return r
  105. def is_contiguous(bits):
  106. if bits == 0:
  107. return -1
  108. shift = ctz(bits)
  109. if is_pow2((bits >> shift) + 1):
  110. return shift
  111. else:
  112. return -1
  113. def eq_fields_for_args(flds_a, flds_b):
  114. if len(flds_a) != len(flds_b):
  115. return False
  116. for k, a in flds_a.items():
  117. if k not in flds_b:
  118. return False
  119. return True
  120. def eq_fields_for_fmts(flds_a, flds_b):
  121. if len(flds_a) != len(flds_b):
  122. return False
  123. for k, a in flds_a.items():
  124. if k not in flds_b:
  125. return False
  126. b = flds_b[k]
  127. if a.__class__ != b.__class__ or a != b:
  128. return False
  129. return True
  130. class Field:
  131. """Class representing a simple instruction field"""
  132. def __init__(self, sign, pos, len):
  133. self.sign = sign
  134. self.pos = pos
  135. self.len = len
  136. self.mask = ((1 << len) - 1) << pos
  137. def __str__(self):
  138. if self.sign:
  139. s = 's'
  140. else:
  141. s = ''
  142. return str(self.pos) + ':' + s + str(self.len)
  143. def str_extract(self):
  144. if self.sign:
  145. extr = 'sextract32'
  146. else:
  147. extr = 'extract32'
  148. return '{0}(insn, {1}, {2})'.format(extr, self.pos, self.len)
  149. def __eq__(self, other):
  150. return self.sign == other.sign and self.mask == other.mask
  151. def __ne__(self, other):
  152. return not self.__eq__(other)
  153. # end Field
  154. class MultiField:
  155. """Class representing a compound instruction field"""
  156. def __init__(self, subs, mask):
  157. self.subs = subs
  158. self.sign = subs[0].sign
  159. self.mask = mask
  160. def __str__(self):
  161. return str(self.subs)
  162. def str_extract(self):
  163. ret = '0'
  164. pos = 0
  165. for f in reversed(self.subs):
  166. if pos == 0:
  167. ret = f.str_extract()
  168. else:
  169. ret = 'deposit32({0}, {1}, {2}, {3})' \
  170. .format(ret, pos, 32 - pos, f.str_extract())
  171. pos += f.len
  172. return ret
  173. def __ne__(self, other):
  174. if len(self.subs) != len(other.subs):
  175. return True
  176. for a, b in zip(self.subs, other.subs):
  177. if a.__class__ != b.__class__ or a != b:
  178. return True
  179. return False
  180. def __eq__(self, other):
  181. return not self.__ne__(other)
  182. # end MultiField
  183. class ConstField:
  184. """Class representing an argument field with constant value"""
  185. def __init__(self, value):
  186. self.value = value
  187. self.mask = 0
  188. self.sign = value < 0
  189. def __str__(self):
  190. return str(self.value)
  191. def str_extract(self):
  192. return str(self.value)
  193. def __cmp__(self, other):
  194. return self.value - other.value
  195. # end ConstField
  196. class FunctionField:
  197. """Class representing a field passed through a function"""
  198. def __init__(self, func, base):
  199. self.mask = base.mask
  200. self.sign = base.sign
  201. self.base = base
  202. self.func = func
  203. def __str__(self):
  204. return self.func + '(' + str(self.base) + ')'
  205. def str_extract(self):
  206. return self.func + '(ctx, ' + self.base.str_extract() + ')'
  207. def __eq__(self, other):
  208. return self.func == other.func and self.base == other.base
  209. def __ne__(self, other):
  210. return not self.__eq__(other)
  211. # end FunctionField
  212. class ParameterField:
  213. """Class representing a pseudo-field read from a function"""
  214. def __init__(self, func):
  215. self.mask = 0
  216. self.sign = 0
  217. self.func = func
  218. def __str__(self):
  219. return self.func
  220. def str_extract(self):
  221. return self.func + '(ctx)'
  222. def __eq__(self, other):
  223. return self.func == other.func
  224. def __ne__(self, other):
  225. return not self.__eq__(other)
  226. # end ParameterField
  227. class Arguments:
  228. """Class representing the extracted fields of a format"""
  229. def __init__(self, nm, flds, extern):
  230. self.name = nm
  231. self.extern = extern
  232. self.fields = sorted(flds)
  233. def __str__(self):
  234. return self.name + ' ' + str(self.fields)
  235. def struct_name(self):
  236. return 'arg_' + self.name
  237. def output_def(self):
  238. if not self.extern:
  239. output('typedef struct {\n')
  240. for n in self.fields:
  241. output(' int ', n, ';\n')
  242. output('} ', self.struct_name(), ';\n\n')
  243. # end Arguments
  244. class General:
  245. """Common code between instruction formats and instruction patterns"""
  246. def __init__(self, name, lineno, base, fixb, fixm, udfm, fldm, flds, w):
  247. self.name = name
  248. self.file = input_file
  249. self.lineno = lineno
  250. self.base = base
  251. self.fixedbits = fixb
  252. self.fixedmask = fixm
  253. self.undefmask = udfm
  254. self.fieldmask = fldm
  255. self.fields = flds
  256. self.width = w
  257. def __str__(self):
  258. return self.name + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
  259. def str1(self, i):
  260. return str_indent(i) + self.__str__()
  261. # end General
  262. class Format(General):
  263. """Class representing an instruction format"""
  264. def extract_name(self):
  265. global decode_function
  266. return decode_function + '_extract_' + self.name
  267. def output_extract(self):
  268. output('static void ', self.extract_name(), '(DisasContext *ctx, ',
  269. self.base.struct_name(), ' *a, ', insntype, ' insn)\n{\n')
  270. for n, f in self.fields.items():
  271. output(' a->', n, ' = ', f.str_extract(), ';\n')
  272. output('}\n\n')
  273. # end Format
  274. class Pattern(General):
  275. """Class representing an instruction pattern"""
  276. def output_decl(self):
  277. global translate_scope
  278. global translate_prefix
  279. output('typedef ', self.base.base.struct_name(),
  280. ' arg_', self.name, ';\n')
  281. output(translate_scope, 'bool ', translate_prefix, '_', self.name,
  282. '(DisasContext *ctx, arg_', self.name, ' *a);\n')
  283. def output_code(self, i, extracted, outerbits, outermask):
  284. global translate_prefix
  285. ind = str_indent(i)
  286. arg = self.base.base.name
  287. output(ind, '/* ', self.file, ':', str(self.lineno), ' */\n')
  288. if not extracted:
  289. output(ind, self.base.extract_name(),
  290. '(ctx, &u.f_', arg, ', insn);\n')
  291. for n, f in self.fields.items():
  292. output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
  293. output(ind, 'if (', translate_prefix, '_', self.name,
  294. '(ctx, &u.f_', arg, ')) return true;\n')
  295. # Normal patterns do not have children.
  296. def build_tree(self):
  297. return
  298. def prop_masks(self):
  299. return
  300. def prop_format(self):
  301. return
  302. def prop_width(self):
  303. return
  304. # end Pattern
  305. class MultiPattern(General):
  306. """Class representing a set of instruction patterns"""
  307. def __init__(self, lineno):
  308. self.file = input_file
  309. self.lineno = lineno
  310. self.pats = []
  311. self.base = None
  312. self.fixedbits = 0
  313. self.fixedmask = 0
  314. self.undefmask = 0
  315. self.width = None
  316. def __str__(self):
  317. r = 'group'
  318. if self.fixedbits is not None:
  319. r += ' ' + str_match_bits(self.fixedbits, self.fixedmask)
  320. return r
  321. def output_decl(self):
  322. for p in self.pats:
  323. p.output_decl()
  324. def prop_masks(self):
  325. global insnmask
  326. fixedmask = insnmask
  327. undefmask = insnmask
  328. # Collect fixedmask/undefmask for all of the children.
  329. for p in self.pats:
  330. p.prop_masks()
  331. fixedmask &= p.fixedmask
  332. undefmask &= p.undefmask
  333. # Widen fixedmask until all fixedbits match
  334. repeat = True
  335. fixedbits = 0
  336. while repeat and fixedmask != 0:
  337. fixedbits = None
  338. for p in self.pats:
  339. thisbits = p.fixedbits & fixedmask
  340. if fixedbits is None:
  341. fixedbits = thisbits
  342. elif fixedbits != thisbits:
  343. fixedmask &= ~(fixedbits ^ thisbits)
  344. break
  345. else:
  346. repeat = False
  347. self.fixedbits = fixedbits
  348. self.fixedmask = fixedmask
  349. self.undefmask = undefmask
  350. def build_tree(self):
  351. for p in self.pats:
  352. p.build_tree()
  353. def prop_format(self):
  354. for p in self.pats:
  355. p.build_tree()
  356. def prop_width(self):
  357. width = None
  358. for p in self.pats:
  359. p.prop_width()
  360. if width is None:
  361. width = p.width
  362. elif width != p.width:
  363. error_with_file(self.file, self.lineno,
  364. 'width mismatch in patterns within braces')
  365. self.width = width
  366. # end MultiPattern
  367. class IncMultiPattern(MultiPattern):
  368. """Class representing an overlapping set of instruction patterns"""
  369. def output_code(self, i, extracted, outerbits, outermask):
  370. global translate_prefix
  371. ind = str_indent(i)
  372. for p in self.pats:
  373. if outermask != p.fixedmask:
  374. innermask = p.fixedmask & ~outermask
  375. innerbits = p.fixedbits & ~outermask
  376. output(ind, 'if ((insn & ',
  377. '0x{0:08x}) == 0x{1:08x}'.format(innermask, innerbits),
  378. ') {\n')
  379. output(ind, ' /* ',
  380. str_match_bits(p.fixedbits, p.fixedmask), ' */\n')
  381. p.output_code(i + 4, extracted, p.fixedbits, p.fixedmask)
  382. output(ind, '}\n')
  383. else:
  384. p.output_code(i, extracted, p.fixedbits, p.fixedmask)
  385. #end IncMultiPattern
  386. class Tree:
  387. """Class representing a node in a decode tree"""
  388. def __init__(self, fm, tm):
  389. self.fixedmask = fm
  390. self.thismask = tm
  391. self.subs = []
  392. self.base = None
  393. def str1(self, i):
  394. ind = str_indent(i)
  395. r = '{0}{1:08x}'.format(ind, self.fixedmask)
  396. if self.format:
  397. r += ' ' + self.format.name
  398. r += ' [\n'
  399. for (b, s) in self.subs:
  400. r += '{0} {1:08x}:\n'.format(ind, b)
  401. r += s.str1(i + 4) + '\n'
  402. r += ind + ']'
  403. return r
  404. def __str__(self):
  405. return self.str1(0)
  406. def output_code(self, i, extracted, outerbits, outermask):
  407. ind = str_indent(i)
  408. # If we identified all nodes below have the same format,
  409. # extract the fields now.
  410. if not extracted and self.base:
  411. output(ind, self.base.extract_name(),
  412. '(ctx, &u.f_', self.base.base.name, ', insn);\n')
  413. extracted = True
  414. # Attempt to aid the compiler in producing compact switch statements.
  415. # If the bits in the mask are contiguous, extract them.
  416. sh = is_contiguous(self.thismask)
  417. if sh > 0:
  418. # Propagate SH down into the local functions.
  419. def str_switch(b, sh=sh):
  420. return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
  421. def str_case(b, sh=sh):
  422. return '0x{0:x}'.format(b >> sh)
  423. else:
  424. def str_switch(b):
  425. return 'insn & 0x{0:08x}'.format(b)
  426. def str_case(b):
  427. return '0x{0:08x}'.format(b)
  428. output(ind, 'switch (', str_switch(self.thismask), ') {\n')
  429. for b, s in sorted(self.subs):
  430. assert (self.thismask & ~s.fixedmask) == 0
  431. innermask = outermask | self.thismask
  432. innerbits = outerbits | b
  433. output(ind, 'case ', str_case(b), ':\n')
  434. output(ind, ' /* ',
  435. str_match_bits(innerbits, innermask), ' */\n')
  436. s.output_code(i + 4, extracted, innerbits, innermask)
  437. output(ind, ' return false;\n')
  438. output(ind, '}\n')
  439. # end Tree
  440. class ExcMultiPattern(MultiPattern):
  441. """Class representing a non-overlapping set of instruction patterns"""
  442. def output_code(self, i, extracted, outerbits, outermask):
  443. # Defer everything to our decomposed Tree node
  444. self.tree.output_code(i, extracted, outerbits, outermask)
  445. @staticmethod
  446. def __build_tree(pats, outerbits, outermask):
  447. # Find the intersection of all remaining fixedmask.
  448. innermask = ~outermask & insnmask
  449. for i in pats:
  450. innermask &= i.fixedmask
  451. if innermask == 0:
  452. # Edge condition: One pattern covers the entire insnmask
  453. if len(pats) == 1:
  454. t = Tree(outermask, innermask)
  455. t.subs.append((0, pats[0]))
  456. return t
  457. text = 'overlapping patterns:'
  458. for p in pats:
  459. text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
  460. error_with_file(pats[0].file, pats[0].lineno, text)
  461. fullmask = outermask | innermask
  462. # Sort each element of pats into the bin selected by the mask.
  463. bins = {}
  464. for i in pats:
  465. fb = i.fixedbits & innermask
  466. if fb in bins:
  467. bins[fb].append(i)
  468. else:
  469. bins[fb] = [i]
  470. # We must recurse if any bin has more than one element or if
  471. # the single element in the bin has not been fully matched.
  472. t = Tree(fullmask, innermask)
  473. for b, l in bins.items():
  474. s = l[0]
  475. if len(l) > 1 or s.fixedmask & ~fullmask != 0:
  476. s = ExcMultiPattern.__build_tree(l, b | outerbits, fullmask)
  477. t.subs.append((b, s))
  478. return t
  479. def build_tree(self):
  480. super().prop_format()
  481. self.tree = self.__build_tree(self.pats, self.fixedbits,
  482. self.fixedmask)
  483. @staticmethod
  484. def __prop_format(tree):
  485. """Propagate Format objects into the decode tree"""
  486. # Depth first search.
  487. for (b, s) in tree.subs:
  488. if isinstance(s, Tree):
  489. ExcMultiPattern.__prop_format(s)
  490. # If all entries in SUBS have the same format, then
  491. # propagate that into the tree.
  492. f = None
  493. for (b, s) in tree.subs:
  494. if f is None:
  495. f = s.base
  496. if f is None:
  497. return
  498. if f is not s.base:
  499. return
  500. tree.base = f
  501. def prop_format(self):
  502. super().prop_format()
  503. self.__prop_format(self.tree)
  504. # end ExcMultiPattern
  505. def parse_field(lineno, name, toks):
  506. """Parse one instruction field from TOKS at LINENO"""
  507. global fields
  508. global re_ident
  509. global insnwidth
  510. # A "simple" field will have only one entry;
  511. # a "multifield" will have several.
  512. subs = []
  513. width = 0
  514. func = None
  515. for t in toks:
  516. if re.fullmatch('!function=' + re_ident, t):
  517. if func:
  518. error(lineno, 'duplicate function')
  519. func = t.split('=')
  520. func = func[1]
  521. continue
  522. if re.fullmatch('[0-9]+:s[0-9]+', t):
  523. # Signed field extract
  524. subtoks = t.split(':s')
  525. sign = True
  526. elif re.fullmatch('[0-9]+:[0-9]+', t):
  527. # Unsigned field extract
  528. subtoks = t.split(':')
  529. sign = False
  530. else:
  531. error(lineno, 'invalid field token "{0}"'.format(t))
  532. po = int(subtoks[0])
  533. le = int(subtoks[1])
  534. if po + le > insnwidth:
  535. error(lineno, 'field {0} too large'.format(t))
  536. f = Field(sign, po, le)
  537. subs.append(f)
  538. width += le
  539. if width > insnwidth:
  540. error(lineno, 'field too large')
  541. if len(subs) == 0:
  542. if func:
  543. f = ParameterField(func)
  544. else:
  545. error(lineno, 'field with no value')
  546. else:
  547. if len(subs) == 1:
  548. f = subs[0]
  549. else:
  550. mask = 0
  551. for s in subs:
  552. if mask & s.mask:
  553. error(lineno, 'field components overlap')
  554. mask |= s.mask
  555. f = MultiField(subs, mask)
  556. if func:
  557. f = FunctionField(func, f)
  558. if name in fields:
  559. error(lineno, 'duplicate field', name)
  560. fields[name] = f
  561. # end parse_field
  562. def parse_arguments(lineno, name, toks):
  563. """Parse one argument set from TOKS at LINENO"""
  564. global arguments
  565. global re_ident
  566. global anyextern
  567. flds = []
  568. extern = False
  569. for t in toks:
  570. if re.fullmatch('!extern', t):
  571. extern = True
  572. anyextern = True
  573. continue
  574. if not re.fullmatch(re_ident, t):
  575. error(lineno, 'invalid argument set token "{0}"'.format(t))
  576. if t in flds:
  577. error(lineno, 'duplicate argument "{0}"'.format(t))
  578. flds.append(t)
  579. if name in arguments:
  580. error(lineno, 'duplicate argument set', name)
  581. arguments[name] = Arguments(name, flds, extern)
  582. # end parse_arguments
  583. def lookup_field(lineno, name):
  584. global fields
  585. if name in fields:
  586. return fields[name]
  587. error(lineno, 'undefined field', name)
  588. def add_field(lineno, flds, new_name, f):
  589. if new_name in flds:
  590. error(lineno, 'duplicate field', new_name)
  591. flds[new_name] = f
  592. return flds
  593. def add_field_byname(lineno, flds, new_name, old_name):
  594. return add_field(lineno, flds, new_name, lookup_field(lineno, old_name))
  595. def infer_argument_set(flds):
  596. global arguments
  597. global decode_function
  598. for arg in arguments.values():
  599. if eq_fields_for_args(flds, arg.fields):
  600. return arg
  601. name = decode_function + str(len(arguments))
  602. arg = Arguments(name, flds.keys(), False)
  603. arguments[name] = arg
  604. return arg
  605. def infer_format(arg, fieldmask, flds, width):
  606. global arguments
  607. global formats
  608. global decode_function
  609. const_flds = {}
  610. var_flds = {}
  611. for n, c in flds.items():
  612. if c is ConstField:
  613. const_flds[n] = c
  614. else:
  615. var_flds[n] = c
  616. # Look for an existing format with the same argument set and fields
  617. for fmt in formats.values():
  618. if arg and fmt.base != arg:
  619. continue
  620. if fieldmask != fmt.fieldmask:
  621. continue
  622. if width != fmt.width:
  623. continue
  624. if not eq_fields_for_fmts(flds, fmt.fields):
  625. continue
  626. return (fmt, const_flds)
  627. name = decode_function + '_Fmt_' + str(len(formats))
  628. if not arg:
  629. arg = infer_argument_set(flds)
  630. fmt = Format(name, 0, arg, 0, 0, 0, fieldmask, var_flds, width)
  631. formats[name] = fmt
  632. return (fmt, const_flds)
  633. # end infer_format
  634. def parse_generic(lineno, parent_pat, name, toks):
  635. """Parse one instruction format from TOKS at LINENO"""
  636. global fields
  637. global arguments
  638. global formats
  639. global allpatterns
  640. global re_ident
  641. global insnwidth
  642. global insnmask
  643. global variablewidth
  644. is_format = parent_pat is None
  645. fixedmask = 0
  646. fixedbits = 0
  647. undefmask = 0
  648. width = 0
  649. flds = {}
  650. arg = None
  651. fmt = None
  652. for t in toks:
  653. # '&Foo' gives a format an explcit argument set.
  654. if t[0] == '&':
  655. tt = t[1:]
  656. if arg:
  657. error(lineno, 'multiple argument sets')
  658. if tt in arguments:
  659. arg = arguments[tt]
  660. else:
  661. error(lineno, 'undefined argument set', t)
  662. continue
  663. # '@Foo' gives a pattern an explicit format.
  664. if t[0] == '@':
  665. tt = t[1:]
  666. if fmt:
  667. error(lineno, 'multiple formats')
  668. if tt in formats:
  669. fmt = formats[tt]
  670. else:
  671. error(lineno, 'undefined format', t)
  672. continue
  673. # '%Foo' imports a field.
  674. if t[0] == '%':
  675. tt = t[1:]
  676. flds = add_field_byname(lineno, flds, tt, tt)
  677. continue
  678. # 'Foo=%Bar' imports a field with a different name.
  679. if re.fullmatch(re_ident + '=%' + re_ident, t):
  680. (fname, iname) = t.split('=%')
  681. flds = add_field_byname(lineno, flds, fname, iname)
  682. continue
  683. # 'Foo=number' sets an argument field to a constant value
  684. if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
  685. (fname, value) = t.split('=')
  686. value = int(value)
  687. flds = add_field(lineno, flds, fname, ConstField(value))
  688. continue
  689. # Pattern of 0s, 1s, dots and dashes indicate required zeros,
  690. # required ones, or dont-cares.
  691. if re.fullmatch('[01.-]+', t):
  692. shift = len(t)
  693. fms = t.replace('0', '1')
  694. fms = fms.replace('.', '0')
  695. fms = fms.replace('-', '0')
  696. fbs = t.replace('.', '0')
  697. fbs = fbs.replace('-', '0')
  698. ubm = t.replace('1', '0')
  699. ubm = ubm.replace('.', '0')
  700. ubm = ubm.replace('-', '1')
  701. fms = int(fms, 2)
  702. fbs = int(fbs, 2)
  703. ubm = int(ubm, 2)
  704. fixedbits = (fixedbits << shift) | fbs
  705. fixedmask = (fixedmask << shift) | fms
  706. undefmask = (undefmask << shift) | ubm
  707. # Otherwise, fieldname:fieldwidth
  708. elif re.fullmatch(re_ident + ':s?[0-9]+', t):
  709. (fname, flen) = t.split(':')
  710. sign = False
  711. if flen[0] == 's':
  712. sign = True
  713. flen = flen[1:]
  714. shift = int(flen, 10)
  715. if shift + width > insnwidth:
  716. error(lineno, 'field {0} exceeds insnwidth'.format(fname))
  717. f = Field(sign, insnwidth - width - shift, shift)
  718. flds = add_field(lineno, flds, fname, f)
  719. fixedbits <<= shift
  720. fixedmask <<= shift
  721. undefmask <<= shift
  722. else:
  723. error(lineno, 'invalid token "{0}"'.format(t))
  724. width += shift
  725. if variablewidth and width < insnwidth and width % 8 == 0:
  726. shift = insnwidth - width
  727. fixedbits <<= shift
  728. fixedmask <<= shift
  729. undefmask <<= shift
  730. undefmask |= (1 << shift) - 1
  731. # We should have filled in all of the bits of the instruction.
  732. elif not (is_format and width == 0) and width != insnwidth:
  733. error(lineno, 'definition has {0} bits'.format(width))
  734. # Do not check for fields overlaping fields; one valid usage
  735. # is to be able to duplicate fields via import.
  736. fieldmask = 0
  737. for f in flds.values():
  738. fieldmask |= f.mask
  739. # Fix up what we've parsed to match either a format or a pattern.
  740. if is_format:
  741. # Formats cannot reference formats.
  742. if fmt:
  743. error(lineno, 'format referencing format')
  744. # If an argument set is given, then there should be no fields
  745. # without a place to store it.
  746. if arg:
  747. for f in flds.keys():
  748. if f not in arg.fields:
  749. error(lineno, 'field {0} not in argument set {1}'
  750. .format(f, arg.name))
  751. else:
  752. arg = infer_argument_set(flds)
  753. if name in formats:
  754. error(lineno, 'duplicate format name', name)
  755. fmt = Format(name, lineno, arg, fixedbits, fixedmask,
  756. undefmask, fieldmask, flds, width)
  757. formats[name] = fmt
  758. else:
  759. # Patterns can reference a format ...
  760. if fmt:
  761. # ... but not an argument simultaneously
  762. if arg:
  763. error(lineno, 'pattern specifies both format and argument set')
  764. if fixedmask & fmt.fixedmask:
  765. error(lineno, 'pattern fixed bits overlap format fixed bits')
  766. if width != fmt.width:
  767. error(lineno, 'pattern uses format of different width')
  768. fieldmask |= fmt.fieldmask
  769. fixedbits |= fmt.fixedbits
  770. fixedmask |= fmt.fixedmask
  771. undefmask |= fmt.undefmask
  772. else:
  773. (fmt, flds) = infer_format(arg, fieldmask, flds, width)
  774. arg = fmt.base
  775. for f in flds.keys():
  776. if f not in arg.fields:
  777. error(lineno, 'field {0} not in argument set {1}'
  778. .format(f, arg.name))
  779. if f in fmt.fields.keys():
  780. error(lineno, 'field {0} set by format and pattern'.format(f))
  781. for f in arg.fields:
  782. if f not in flds.keys() and f not in fmt.fields.keys():
  783. error(lineno, 'field {0} not initialized'.format(f))
  784. pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
  785. undefmask, fieldmask, flds, width)
  786. parent_pat.pats.append(pat)
  787. allpatterns.append(pat)
  788. # Validate the masks that we have assembled.
  789. if fieldmask & fixedmask:
  790. error(lineno, 'fieldmask overlaps fixedmask (0x{0:08x} & 0x{1:08x})'
  791. .format(fieldmask, fixedmask))
  792. if fieldmask & undefmask:
  793. error(lineno, 'fieldmask overlaps undefmask (0x{0:08x} & 0x{1:08x})'
  794. .format(fieldmask, undefmask))
  795. if fixedmask & undefmask:
  796. error(lineno, 'fixedmask overlaps undefmask (0x{0:08x} & 0x{1:08x})'
  797. .format(fixedmask, undefmask))
  798. if not is_format:
  799. allbits = fieldmask | fixedmask | undefmask
  800. if allbits != insnmask:
  801. error(lineno, 'bits left unspecified (0x{0:08x})'
  802. .format(allbits ^ insnmask))
  803. # end parse_general
  804. def parse_file(f, parent_pat):
  805. """Parse all of the patterns within a file"""
  806. # Read all of the lines of the file. Concatenate lines
  807. # ending in backslash; discard empty lines and comments.
  808. toks = []
  809. lineno = 0
  810. nesting = 0
  811. nesting_pats = []
  812. for line in f:
  813. lineno += 1
  814. # Expand and strip spaces, to find indent.
  815. line = line.rstrip()
  816. line = line.expandtabs()
  817. len1 = len(line)
  818. line = line.lstrip()
  819. len2 = len(line)
  820. # Discard comments
  821. end = line.find('#')
  822. if end >= 0:
  823. line = line[:end]
  824. t = line.split()
  825. if len(toks) != 0:
  826. # Next line after continuation
  827. toks.extend(t)
  828. else:
  829. # Allow completely blank lines.
  830. if len1 == 0:
  831. continue
  832. indent = len1 - len2
  833. # Empty line due to comment.
  834. if len(t) == 0:
  835. # Indentation must be correct, even for comment lines.
  836. if indent != nesting:
  837. error(lineno, 'indentation ', indent, ' != ', nesting)
  838. continue
  839. start_lineno = lineno
  840. toks = t
  841. # Continuation?
  842. if toks[-1] == '\\':
  843. toks.pop()
  844. continue
  845. name = toks[0]
  846. del toks[0]
  847. # End nesting?
  848. if name == '}' or name == ']':
  849. if len(toks) != 0:
  850. error(start_lineno, 'extra tokens after close brace')
  851. # Make sure { } and [ ] nest properly.
  852. if (name == '}') != isinstance(parent_pat, IncMultiPattern):
  853. error(lineno, 'mismatched close brace')
  854. try:
  855. parent_pat = nesting_pats.pop()
  856. except:
  857. error(lineno, 'extra close brace')
  858. nesting -= 2
  859. if indent != nesting:
  860. error(lineno, 'indentation ', indent, ' != ', nesting)
  861. toks = []
  862. continue
  863. # Everything else should have current indentation.
  864. if indent != nesting:
  865. error(start_lineno, 'indentation ', indent, ' != ', nesting)
  866. # Start nesting?
  867. if name == '{' or name == '[':
  868. if len(toks) != 0:
  869. error(start_lineno, 'extra tokens after open brace')
  870. if name == '{':
  871. nested_pat = IncMultiPattern(start_lineno)
  872. else:
  873. nested_pat = ExcMultiPattern(start_lineno)
  874. parent_pat.pats.append(nested_pat)
  875. nesting_pats.append(parent_pat)
  876. parent_pat = nested_pat
  877. nesting += 2
  878. toks = []
  879. continue
  880. # Determine the type of object needing to be parsed.
  881. if name[0] == '%':
  882. parse_field(start_lineno, name[1:], toks)
  883. elif name[0] == '&':
  884. parse_arguments(start_lineno, name[1:], toks)
  885. elif name[0] == '@':
  886. parse_generic(start_lineno, None, name[1:], toks)
  887. else:
  888. parse_generic(start_lineno, parent_pat, name, toks)
  889. toks = []
  890. if nesting != 0:
  891. error(lineno, 'missing close brace')
  892. # end parse_file
  893. class SizeTree:
  894. """Class representing a node in a size decode tree"""
  895. def __init__(self, m, w):
  896. self.mask = m
  897. self.subs = []
  898. self.base = None
  899. self.width = w
  900. def str1(self, i):
  901. ind = str_indent(i)
  902. r = '{0}{1:08x}'.format(ind, self.mask)
  903. r += ' [\n'
  904. for (b, s) in self.subs:
  905. r += '{0} {1:08x}:\n'.format(ind, b)
  906. r += s.str1(i + 4) + '\n'
  907. r += ind + ']'
  908. return r
  909. def __str__(self):
  910. return self.str1(0)
  911. def output_code(self, i, extracted, outerbits, outermask):
  912. ind = str_indent(i)
  913. # If we need to load more bytes to test, do so now.
  914. if extracted < self.width:
  915. output(ind, 'insn = ', decode_function,
  916. '_load_bytes(ctx, insn, {0}, {1});\n'
  917. .format(extracted // 8, self.width // 8));
  918. extracted = self.width
  919. # Attempt to aid the compiler in producing compact switch statements.
  920. # If the bits in the mask are contiguous, extract them.
  921. sh = is_contiguous(self.mask)
  922. if sh > 0:
  923. # Propagate SH down into the local functions.
  924. def str_switch(b, sh=sh):
  925. return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
  926. def str_case(b, sh=sh):
  927. return '0x{0:x}'.format(b >> sh)
  928. else:
  929. def str_switch(b):
  930. return 'insn & 0x{0:08x}'.format(b)
  931. def str_case(b):
  932. return '0x{0:08x}'.format(b)
  933. output(ind, 'switch (', str_switch(self.mask), ') {\n')
  934. for b, s in sorted(self.subs):
  935. innermask = outermask | self.mask
  936. innerbits = outerbits | b
  937. output(ind, 'case ', str_case(b), ':\n')
  938. output(ind, ' /* ',
  939. str_match_bits(innerbits, innermask), ' */\n')
  940. s.output_code(i + 4, extracted, innerbits, innermask)
  941. output(ind, '}\n')
  942. output(ind, 'return insn;\n')
  943. # end SizeTree
  944. class SizeLeaf:
  945. """Class representing a leaf node in a size decode tree"""
  946. def __init__(self, m, w):
  947. self.mask = m
  948. self.width = w
  949. def str1(self, i):
  950. ind = str_indent(i)
  951. return '{0}{1:08x}'.format(ind, self.mask)
  952. def __str__(self):
  953. return self.str1(0)
  954. def output_code(self, i, extracted, outerbits, outermask):
  955. global decode_function
  956. ind = str_indent(i)
  957. # If we need to load more bytes, do so now.
  958. if extracted < self.width:
  959. output(ind, 'insn = ', decode_function,
  960. '_load_bytes(ctx, insn, {0}, {1});\n'
  961. .format(extracted // 8, self.width // 8));
  962. extracted = self.width
  963. output(ind, 'return insn;\n')
  964. # end SizeLeaf
  965. def build_size_tree(pats, width, outerbits, outermask):
  966. global insnwidth
  967. # Collect the mask of bits that are fixed in this width
  968. innermask = 0xff << (insnwidth - width)
  969. innermask &= ~outermask
  970. minwidth = None
  971. onewidth = True
  972. for i in pats:
  973. innermask &= i.fixedmask
  974. if minwidth is None:
  975. minwidth = i.width
  976. elif minwidth != i.width:
  977. onewidth = False;
  978. if minwidth < i.width:
  979. minwidth = i.width
  980. if onewidth:
  981. return SizeLeaf(innermask, minwidth)
  982. if innermask == 0:
  983. if width < minwidth:
  984. return build_size_tree(pats, width + 8, outerbits, outermask)
  985. pnames = []
  986. for p in pats:
  987. pnames.append(p.name + ':' + p.file + ':' + str(p.lineno))
  988. error_with_file(pats[0].file, pats[0].lineno,
  989. 'overlapping patterns size {0}:'.format(width), pnames)
  990. bins = {}
  991. for i in pats:
  992. fb = i.fixedbits & innermask
  993. if fb in bins:
  994. bins[fb].append(i)
  995. else:
  996. bins[fb] = [i]
  997. fullmask = outermask | innermask
  998. lens = sorted(bins.keys())
  999. if len(lens) == 1:
  1000. b = lens[0]
  1001. return build_size_tree(bins[b], width + 8, b | outerbits, fullmask)
  1002. r = SizeTree(innermask, width)
  1003. for b, l in bins.items():
  1004. s = build_size_tree(l, width, b | outerbits, fullmask)
  1005. r.subs.append((b, s))
  1006. return r
  1007. # end build_size_tree
  1008. def prop_size(tree):
  1009. """Propagate minimum widths up the decode size tree"""
  1010. if isinstance(tree, SizeTree):
  1011. min = None
  1012. for (b, s) in tree.subs:
  1013. width = prop_size(s)
  1014. if min is None or min > width:
  1015. min = width
  1016. assert min >= tree.width
  1017. tree.width = min
  1018. else:
  1019. min = tree.width
  1020. return min
  1021. # end prop_size
  1022. def main():
  1023. global arguments
  1024. global formats
  1025. global allpatterns
  1026. global translate_scope
  1027. global translate_prefix
  1028. global output_fd
  1029. global output_file
  1030. global input_file
  1031. global insnwidth
  1032. global insntype
  1033. global insnmask
  1034. global decode_function
  1035. global variablewidth
  1036. global anyextern
  1037. decode_scope = 'static '
  1038. long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=',
  1039. 'static-decode=', 'varinsnwidth=']
  1040. try:
  1041. (opts, args) = getopt.getopt(sys.argv[1:], 'o:vw:', long_opts)
  1042. except getopt.GetoptError as err:
  1043. error(0, err)
  1044. for o, a in opts:
  1045. if o in ('-o', '--output'):
  1046. output_file = a
  1047. elif o == '--decode':
  1048. decode_function = a
  1049. decode_scope = ''
  1050. elif o == '--static-decode':
  1051. decode_function = a
  1052. elif o == '--translate':
  1053. translate_prefix = a
  1054. translate_scope = ''
  1055. elif o in ('-w', '--insnwidth', '--varinsnwidth'):
  1056. if o == '--varinsnwidth':
  1057. variablewidth = True
  1058. insnwidth = int(a)
  1059. if insnwidth == 16:
  1060. insntype = 'uint16_t'
  1061. insnmask = 0xffff
  1062. elif insnwidth != 32:
  1063. error(0, 'cannot handle insns of width', insnwidth)
  1064. else:
  1065. assert False, 'unhandled option'
  1066. if len(args) < 1:
  1067. error(0, 'missing input file')
  1068. toppat = ExcMultiPattern(0)
  1069. for filename in args:
  1070. input_file = filename
  1071. f = open(filename, 'r')
  1072. parse_file(f, toppat)
  1073. f.close()
  1074. # We do not want to compute masks for toppat, because those masks
  1075. # are used as a starting point for build_tree. For toppat, we must
  1076. # insist that decode begins from naught.
  1077. for i in toppat.pats:
  1078. i.prop_masks()
  1079. toppat.build_tree()
  1080. toppat.prop_format()
  1081. if variablewidth:
  1082. for i in toppat.pats:
  1083. i.prop_width()
  1084. stree = build_size_tree(toppat.pats, 8, 0, 0)
  1085. prop_size(stree)
  1086. if output_file:
  1087. output_fd = open(output_file, 'w')
  1088. else:
  1089. output_fd = sys.stdout
  1090. output_autogen()
  1091. for n in sorted(arguments.keys()):
  1092. f = arguments[n]
  1093. f.output_def()
  1094. # A single translate function can be invoked for different patterns.
  1095. # Make sure that the argument sets are the same, and declare the
  1096. # function only once.
  1097. #
  1098. # If we're sharing formats, we're likely also sharing trans_* functions,
  1099. # but we can't tell which ones. Prevent issues from the compiler by
  1100. # suppressing redundant declaration warnings.
  1101. if anyextern:
  1102. output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n",
  1103. "# pragma GCC diagnostic push\n",
  1104. "# pragma GCC diagnostic ignored \"-Wredundant-decls\"\n",
  1105. "# ifdef __clang__\n"
  1106. "# pragma GCC diagnostic ignored \"-Wtypedef-redefinition\"\n",
  1107. "# endif\n",
  1108. "#endif\n\n")
  1109. out_pats = {}
  1110. for i in allpatterns:
  1111. if i.name in out_pats:
  1112. p = out_pats[i.name]
  1113. if i.base.base != p.base.base:
  1114. error(0, i.name, ' has conflicting argument sets')
  1115. else:
  1116. i.output_decl()
  1117. out_pats[i.name] = i
  1118. output('\n')
  1119. if anyextern:
  1120. output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n",
  1121. "# pragma GCC diagnostic pop\n",
  1122. "#endif\n\n")
  1123. for n in sorted(formats.keys()):
  1124. f = formats[n]
  1125. f.output_extract()
  1126. output(decode_scope, 'bool ', decode_function,
  1127. '(DisasContext *ctx, ', insntype, ' insn)\n{\n')
  1128. i4 = str_indent(4)
  1129. if len(allpatterns) != 0:
  1130. output(i4, 'union {\n')
  1131. for n in sorted(arguments.keys()):
  1132. f = arguments[n]
  1133. output(i4, i4, f.struct_name(), ' f_', f.name, ';\n')
  1134. output(i4, '} u;\n\n')
  1135. toppat.output_code(4, False, 0, 0)
  1136. output(i4, 'return false;\n')
  1137. output('}\n')
  1138. if variablewidth:
  1139. output('\n', decode_scope, insntype, ' ', decode_function,
  1140. '_load(DisasContext *ctx)\n{\n',
  1141. ' ', insntype, ' insn = 0;\n\n')
  1142. stree.output_code(4, 0, 0, 0)
  1143. output('}\n')
  1144. if output_file:
  1145. output_fd.close()
  1146. # end main
  1147. if __name__ == '__main__':
  1148. main()