···161161and::
162162163163 trans_addl_i(ctx, &arg_opi, insn)
164164+165165+Pattern Groups
166166+==============
167167+168168+Syntax::
169169+170170+ group := '{' ( pat_def | group )+ '}'
171171+172172+A *group* begins with a lone open-brace, with all subsequent lines
173173+indented two spaces, and ending with a lone close-brace. Groups
174174+may be nested, increasing the required indentation of the lines
175175+within the nested group to two spaces per nesting level.
176176+177177+Unlike ungrouped patterns, grouped patterns are allowed to overlap.
178178+Conflicts are resolved by selecting the patterns in order. If all
179179+of the fixedbits for a pattern match, its translate function will
180180+be called. If the translate function returns false, then subsequent
181181+patterns within the group will be matched.
182182+183183+The following example from PA-RISC shows specialization of the *or*
184184+instruction::
185185+186186+ {
187187+ {
188188+ nop 000010 ----- ----- 0000 001001 0 00000
189189+ copy 000010 00000 r1:5 0000 001001 0 rt:5
190190+ }
191191+ or 000010 rt2:5 r1:5 cf:4 001001 0 rt:5
192192+ }
193193+194194+When the *cf* field is zero, the instruction has no side effects,
195195+and may be specialized. When the *rt* field is zero, the output
196196+is discarded and so the instruction has no effect. When the *rt2*
197197+field is zero, the operation is ``reg[rt] | 0`` and so encodes
198198+the canonical register copy operation.
199199+200200+The output from the generator might look like::
201201+202202+ switch (insn & 0xfc000fe0) {
203203+ case 0x08000240:
204204+ /* 000010.. ........ ....0010 010..... */
205205+ if ((insn & 0x0000f000) == 0x00000000) {
206206+ /* 000010.. ........ 00000010 010..... */
207207+ if ((insn & 0x0000001f) == 0x00000000) {
208208+ /* 000010.. ........ 00000010 01000000 */
209209+ extract_decode_Fmt_0(&u.f_decode0, insn);
210210+ if (trans_nop(ctx, &u.f_decode0)) return true;
211211+ }
212212+ if ((insn & 0x03e00000) == 0x00000000) {
213213+ /* 00001000 000..... 00000010 010..... */
214214+ extract_decode_Fmt_1(&u.f_decode1, insn);
215215+ if (trans_copy(ctx, &u.f_decode1)) return true;
216216+ }
217217+ }
218218+ extract_decode_Fmt_2(&u.f_decode2, insn);
219219+ if (trans_or(ctx, &u.f_decode2)) return true;
220220+ return false;
221221+ }
+143-22
scripts/decodetree.py
···3131arguments = {}
3232formats = {}
3333patterns = []
3434+allpatterns = []
34353536translate_prefix = 'trans'
3637translate_scope = 'static '
···300301 self.fields = flds
301302302303 def __str__(self):
303303- r = self.name
304304- if self.base:
305305- r = r + ' ' + self.base.name
306306- else:
307307- r = r + ' ' + str(self.fields)
308308- r = r + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
309309- return r
304304+ return self.name + ' ' + str_match_bits(self.fixedbits, self.fixedmask)
310305311306 def str1(self, i):
312307 return str_indent(i) + self.__str__()
···353348# end Pattern
354349355350351351+class MultiPattern(General):
352352+ """Class representing an overlapping set of instruction patterns"""
353353+354354+ def __init__(self, lineno, pats, fixb, fixm, udfm):
355355+ self.file = input_file
356356+ self.lineno = lineno
357357+ self.pats = pats
358358+ self.base = None
359359+ self.fixedbits = fixb
360360+ self.fixedmask = fixm
361361+ self.undefmask = udfm
362362+363363+ def __str__(self):
364364+ r = "{"
365365+ for p in self.pats:
366366+ r = r + ' ' + str(p)
367367+ return r + "}"
368368+369369+ def output_decl(self):
370370+ for p in self.pats:
371371+ p.output_decl()
372372+373373+ def output_code(self, i, extracted, outerbits, outermask):
374374+ global translate_prefix
375375+ ind = str_indent(i)
376376+ for p in self.pats:
377377+ if outermask != p.fixedmask:
378378+ innermask = p.fixedmask & ~outermask
379379+ innerbits = p.fixedbits & ~outermask
380380+ output(ind, 'if ((insn & ',
381381+ '0x{0:08x}) == 0x{1:08x}'.format(innermask, innerbits),
382382+ ') {\n')
383383+ output(ind, ' /* ',
384384+ str_match_bits(p.fixedbits, p.fixedmask), ' */\n')
385385+ p.output_code(i + 4, extracted, p.fixedbits, p.fixedmask)
386386+ output(ind, '}\n')
387387+ else:
388388+ p.output_code(i, extracted, p.fixedbits, p.fixedmask)
389389+#end MultiPattern
390390+391391+356392def parse_field(lineno, name, toks):
357393 """Parse one instruction field from TOKS at LINENO"""
358394 global fields
···505541 global arguments
506542 global formats
507543 global patterns
544544+ global allpatterns
508545 global re_ident
509546 global insnwidth
510547 global insnmask
···649686 pat = Pattern(name, lineno, fmt, fixedbits, fixedmask,
650687 undefmask, fieldmask, flds)
651688 patterns.append(pat)
689689+ allpatterns.append(pat)
652690653691 # Validate the masks that we have assembled.
654692 if fieldmask & fixedmask:
···667705 .format(allbits ^ insnmask))
668706# end parse_general
669707708708+def build_multi_pattern(lineno, pats):
709709+ """Validate the Patterns going into a MultiPattern."""
710710+ global patterns
711711+ global insnmask
712712+713713+ if len(pats) < 2:
714714+ error(lineno, 'less than two patterns within braces')
715715+716716+ fixedmask = insnmask
717717+ undefmask = insnmask
718718+719719+ # Collect fixed/undefmask for all of the children.
720720+ # Move the defining lineno back to that of the first child.
721721+ for p in pats:
722722+ fixedmask &= p.fixedmask
723723+ undefmask &= p.undefmask
724724+ if p.lineno < lineno:
725725+ lineno = p.lineno
726726+727727+ repeat = True
728728+ while repeat:
729729+ if fixedmask == 0:
730730+ error(lineno, 'no overlap in patterns within braces')
731731+ fixedbits = None
732732+ for p in pats:
733733+ thisbits = p.fixedbits & fixedmask
734734+ if fixedbits is None:
735735+ fixedbits = thisbits
736736+ elif fixedbits != thisbits:
737737+ fixedmask &= ~(fixedbits ^ thisbits)
738738+ break
739739+ else:
740740+ repeat = False
741741+742742+ mp = MultiPattern(lineno, pats, fixedbits, fixedmask, undefmask)
743743+ patterns.append(mp)
744744+# end build_multi_pattern
670745671746def parse_file(f):
672747 """Parse all of the patterns within a file"""
673748749749+ global patterns
750750+674751 # Read all of the lines of the file. Concatenate lines
675752 # ending in backslash; discard empty lines and comments.
676753 toks = []
677754 lineno = 0
755755+ nesting = 0
756756+ saved_pats = []
757757+678758 for line in f:
679759 lineno += 1
680760761761+ # Expand and strip spaces, to find indent.
762762+ line = line.rstrip()
763763+ line = line.expandtabs()
764764+ len1 = len(line)
765765+ line = line.lstrip()
766766+ len2 = len(line)
767767+681768 # Discard comments
682769 end = line.find('#')
683770 if end >= 0:
···687774 if len(toks) != 0:
688775 # Next line after continuation
689776 toks.extend(t)
690690- elif len(t) == 0:
691691- # Empty line
692692- continue
693777 else:
778778+ # Allow completely blank lines.
779779+ if len1 == 0:
780780+ continue
781781+ indent = len1 - len2
782782+ # Empty line due to comment.
783783+ if len(t) == 0:
784784+ # Indentation must be correct, even for comment lines.
785785+ if indent != nesting:
786786+ error(lineno, 'indentation ', indent, ' != ', nesting)
787787+ continue
788788+ start_lineno = lineno
694789 toks = t
695790696791 # Continuation?
···698793 toks.pop()
699794 continue
700795701701- if len(toks) < 2:
702702- error(lineno, 'short line')
703703-704796 name = toks[0]
705797 del toks[0]
706798799799+ # End nesting?
800800+ if name == '}':
801801+ if nesting == 0:
802802+ error(start_lineno, 'mismatched close brace')
803803+ if len(toks) != 0:
804804+ error(start_lineno, 'extra tokens after close brace')
805805+ nesting -= 2
806806+ if indent != nesting:
807807+ error(start_lineno, 'indentation ', indent, ' != ', nesting)
808808+ pats = patterns
809809+ patterns = saved_pats.pop()
810810+ build_multi_pattern(lineno, pats)
811811+ toks = []
812812+ continue
813813+814814+ # Everything else should have current indentation.
815815+ if indent != nesting:
816816+ error(start_lineno, 'indentation ', indent, ' != ', nesting)
817817+818818+ # Start nesting?
819819+ if name == '{':
820820+ if len(toks) != 0:
821821+ error(start_lineno, 'extra tokens after open brace')
822822+ saved_pats.append(patterns)
823823+ patterns = []
824824+ nesting += 2
825825+ toks = []
826826+ continue
827827+707828 # Determine the type of object needing to be parsed.
708829 if name[0] == '%':
709709- parse_field(lineno, name[1:], toks)
830830+ parse_field(start_lineno, name[1:], toks)
710831 elif name[0] == '&':
711711- parse_arguments(lineno, name[1:], toks)
832832+ parse_arguments(start_lineno, name[1:], toks)
712833 elif name[0] == '@':
713713- parse_generic(lineno, True, name[1:], toks)
834834+ parse_generic(start_lineno, True, name[1:], toks)
714835 else:
715715- parse_generic(lineno, False, name, toks)
836836+ parse_generic(start_lineno, False, name, toks)
716837 toks = []
717838# end parse_file
718839···789910 innermask &= i.fixedmask
790911791912 if innermask == 0:
792792- pnames = []
913913+ text = 'overlapping patterns:'
793914 for p in pats:
794794- pnames.append(p.name + ':' + p.file + ':' + str(p.lineno))
795795- error_with_file(pats[0].file, pats[0].lineno,
796796- 'overlapping patterns:', pnames)
915915+ text += '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p)
916916+ error_with_file(pats[0].file, pats[0].lineno, text)
797917798918 fullmask = outermask | innermask
799919···846966 global arguments
847967 global formats
848968 global patterns
969969+ global allpatterns
849970 global translate_scope
850971 global translate_prefix
851972 global output_fd
···9071028 # Make sure that the argument sets are the same, and declare the
9081029 # function only once.
9091030 out_pats = {}
910910- for i in patterns:
10311031+ for i in allpatterns:
9111032 if i.name in out_pats:
9121033 p = out_pats[i.name]
9131034 if i.base.base != p.base.base:
+6
tests/decode/err_pattern_group_overlap1.decode
···11+one 00000000000000000000000000000000
22+{
33+ two 0000000000000000000000000000000 s:1
44+ three 000000000000000000000000000000 s:1 0
55+}
66+