Merge branch 'vendor/BINUTILS225'
[dragonfly.git] / sys / contrib / dev / acpica / source / components / disassembler / dmcstyle.c
1 /*******************************************************************************
2  *
3  * Module Name: dmcstyle - Support for C-style operator disassembly
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdebug.h"
49
50 #ifdef ACPI_DISASSEMBLER
51
52 #define _COMPONENT          ACPI_CA_DEBUGGER
53         ACPI_MODULE_NAME    ("dmcstyle")
54
55
56 /* Local prototypes */
57
58 static char *
59 AcpiDmGetCompoundSymbol (
60    UINT16                   AslOpcode);
61
62 static void
63 AcpiDmPromoteTarget (
64     ACPI_PARSE_OBJECT       *Op,
65     ACPI_PARSE_OBJECT       *Target);
66
67 static BOOLEAN
68 AcpiDmIsValidTarget (
69     ACPI_PARSE_OBJECT       *Op);
70
71 static BOOLEAN
72 AcpiDmIsTargetAnOperand (
73     ACPI_PARSE_OBJECT       *Target,
74     ACPI_PARSE_OBJECT       *Operand,
75     BOOLEAN                 TopLevel);
76
77
78 /*******************************************************************************
79  *
80  * FUNCTION:    AcpiDmCheckForSymbolicOpcode
81  *
82  * PARAMETERS:  Op                  - Current parse object
83  *              Walk                - Current parse tree walk info
84  *
85  * RETURN:      TRUE if opcode can be converted to symbolic, FALSE otherwise
86  *
87  * DESCRIPTION: This is the main code that implements disassembly of AML code
88  *              to C-style operators. Called during descending phase of the
89  *              parse tree walk.
90  *
91  ******************************************************************************/
92
93 BOOLEAN
94 AcpiDmCheckForSymbolicOpcode (
95     ACPI_PARSE_OBJECT       *Op,
96     ACPI_OP_WALK_INFO       *Info)
97 {
98     char                    *OperatorSymbol = NULL;
99     ACPI_PARSE_OBJECT       *Child1;
100     ACPI_PARSE_OBJECT       *Child2;
101     ACPI_PARSE_OBJECT       *Target;
102
103
104     /* Exit immediately if ASL+ not enabled */
105
106     if (!AcpiGbl_CstyleDisassembly)
107     {
108         return (FALSE);
109     }
110
111     /* Get the first operand */
112
113     Child1 = AcpiPsGetArg (Op, 0);
114     if (!Child1)
115     {
116         return (FALSE);
117     }
118
119     /* Get the second operand */
120
121     Child2 = Child1->Common.Next;
122
123     /* Setup the operator string for this opcode */
124
125     switch (Op->Common.AmlOpcode)
126     {
127     case AML_ADD_OP:
128         OperatorSymbol = " + ";
129         break;
130
131     case AML_SUBTRACT_OP:
132         OperatorSymbol = " - ";
133         break;
134
135     case AML_MULTIPLY_OP:
136         OperatorSymbol = " * ";
137         break;
138
139     case AML_DIVIDE_OP:
140         OperatorSymbol = " / ";
141         break;
142
143     case AML_MOD_OP:
144         OperatorSymbol = " % ";
145         break;
146
147     case AML_SHIFT_LEFT_OP:
148         OperatorSymbol = " << ";
149         break;
150
151     case AML_SHIFT_RIGHT_OP:
152         OperatorSymbol = " >> ";
153         break;
154
155     case AML_BIT_AND_OP:
156         OperatorSymbol = " & ";
157         break;
158
159     case AML_BIT_OR_OP:
160         OperatorSymbol = " | ";
161         break;
162
163     case AML_BIT_XOR_OP:
164         OperatorSymbol = " ^ ";
165         break;
166
167     /* Logical operators, no target */
168
169     case AML_LAND_OP:
170         OperatorSymbol = " && ";
171         break;
172
173     case AML_LEQUAL_OP:
174         OperatorSymbol = " == ";
175         break;
176
177     case AML_LGREATER_OP:
178         OperatorSymbol = " > ";
179         break;
180
181     case AML_LLESS_OP:
182         OperatorSymbol = " < ";
183         break;
184
185     case AML_LOR_OP:
186         OperatorSymbol = " || ";
187         break;
188
189     case AML_LNOT_OP:
190         /*
191          * Check for the LNOT sub-opcodes. These correspond to
192          * LNotEqual, LLessEqual, and LGreaterEqual. There are
193          * no actual AML opcodes for these operators.
194          */
195         switch (Child1->Common.AmlOpcode)
196         {
197         case AML_LEQUAL_OP:
198             OperatorSymbol = " != ";
199             break;
200
201         case AML_LGREATER_OP:
202             OperatorSymbol = " <= ";
203             break;
204
205         case AML_LLESS_OP:
206             OperatorSymbol = " >= ";
207             break;
208
209         default:
210
211             /* Unary LNOT case, emit "!" immediately */
212
213             AcpiOsPrintf ("!");
214             return (TRUE);
215         }
216
217         Child1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
218         Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
219
220         /* Save symbol string in the next child (not peer) */
221
222         Child2 = AcpiPsGetArg (Child1, 0);
223         if (!Child2)
224         {
225             return (FALSE);
226         }
227
228         Child2->Common.OperatorSymbol = OperatorSymbol;
229         return (TRUE);
230
231     case AML_INDEX_OP:
232         /*
233          * Check for constant source operand. Note: although technically
234          * legal syntax, the iASL compiler does not support this with
235          * the symbolic operators for Index(). It doesn't make sense to
236          * use Index() with a constant anyway.
237          */
238         if ((Child1->Common.AmlOpcode == AML_STRING_OP)  ||
239             (Child1->Common.AmlOpcode == AML_BUFFER_OP)  ||
240             (Child1->Common.AmlOpcode == AML_PACKAGE_OP) ||
241             (Child1->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
242         {
243             Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;
244             return (FALSE);
245         }
246
247         /* Index operator is [] */
248
249         Child1->Common.OperatorSymbol = " [";
250         Child2->Common.OperatorSymbol = "]";
251         break;
252
253     /* Unary operators */
254
255     case AML_DECREMENT_OP:
256         OperatorSymbol = "--";
257         break;
258
259     case AML_INCREMENT_OP:
260         OperatorSymbol = "++";
261         break;
262
263     case AML_BIT_NOT_OP:
264     case AML_STORE_OP:
265         OperatorSymbol = NULL;
266         break;
267
268     default:
269         return (FALSE);
270     }
271
272     if (Child1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)
273     {
274         return (TRUE);
275     }
276
277     /*
278      * This is the key to how the disassembly of the C-style operators
279      * works. We save the operator symbol in the first child, thus
280      * deferring symbol output until after the first operand has been
281      * emitted.
282      */
283     if (!Child1->Common.OperatorSymbol)
284     {
285         Child1->Common.OperatorSymbol = OperatorSymbol;
286     }
287
288     /*
289      * Check for a valid target as the 3rd (or sometimes 2nd) operand
290      *
291      * Compound assignment operator support:
292      * Attempt to optimize constructs of the form:
293      *      Add (Local1, 0xFF, Local1)
294      * to:
295      *      Local1 += 0xFF
296      *
297      * Only the math operators and Store() have a target.
298      * Logicals have no target.
299      */
300     switch (Op->Common.AmlOpcode)
301     {
302     case AML_ADD_OP:
303     case AML_SUBTRACT_OP:
304     case AML_MULTIPLY_OP:
305     case AML_DIVIDE_OP:
306     case AML_MOD_OP:
307     case AML_SHIFT_LEFT_OP:
308     case AML_SHIFT_RIGHT_OP:
309     case AML_BIT_AND_OP:
310     case AML_BIT_OR_OP:
311     case AML_BIT_XOR_OP:
312
313         /* Target is 3rd operand */
314
315         Target = Child2->Common.Next;
316         if (Op->Common.AmlOpcode == AML_DIVIDE_OP)
317         {
318             /*
319              * Divide has an extra target operand (Remainder).
320              * If this extra target is specified, it cannot be converted
321              * to a C-style operator
322              */
323             if (AcpiDmIsValidTarget (Target))
324             {
325                 Child1->Common.OperatorSymbol = NULL;
326                 return (FALSE);
327             }
328
329             Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
330             Target = Target->Common.Next;
331         }
332
333         /* Parser should ensure there is at least a placeholder target */
334
335         if (!Target)
336         {
337             return (FALSE);
338         }
339
340         if (!AcpiDmIsValidTarget (Target))
341         {
342             /* Not a valid target (placeholder only, from parser) */
343             break;
344         }
345
346         /*
347          * Promote the target up to the first child in the parse
348          * tree. This is done because the target will be output
349          * first, in the form:
350          *     <Target> = Operands...
351          */
352         AcpiDmPromoteTarget (Op, Target);
353
354         /* Check operands for conversion to a "Compound Assignment" */
355
356         switch (Op->Common.AmlOpcode)
357         {
358             /* Commutative operators */
359
360         case AML_ADD_OP:
361         case AML_MULTIPLY_OP:
362         case AML_BIT_AND_OP:
363         case AML_BIT_OR_OP:
364         case AML_BIT_XOR_OP:
365             /*
366              * For the commutative operators, we can convert to a
367              * compound statement only if at least one (either) operand
368              * is the same as the target.
369              *
370              *      Add (A, B, A) --> A += B
371              *      Add (B, A, A) --> A += B
372              *      Add (B, C, A) --> A = (B + C)
373              */
374             if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) ||
375                 (AcpiDmIsTargetAnOperand (Target, Child2, TRUE)))
376             {
377                 Target->Common.OperatorSymbol =
378                     AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
379
380                 /* Convert operator to compound assignment */
381
382                 Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND;
383                 Child1->Common.OperatorSymbol = NULL;
384                 return (TRUE);
385             }
386             break;
387
388             /* Non-commutative operators */
389
390         case AML_SUBTRACT_OP:
391         case AML_DIVIDE_OP:
392         case AML_MOD_OP:
393         case AML_SHIFT_LEFT_OP:
394         case AML_SHIFT_RIGHT_OP:
395             /*
396              * For the non-commutative operators, we can convert to a
397              * compound statement only if the target is the same as the
398              * first operand.
399              *
400              *      Subtract (A, B, A) --> A -= B
401              *      Subtract (B, A, A) --> A = (B - A)
402              */
403             if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)))
404             {
405                 Target->Common.OperatorSymbol =
406                     AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
407
408                 /* Convert operator to compound assignment */
409
410                 Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND;
411                 Child1->Common.OperatorSymbol = NULL;
412                 return (TRUE);
413             }
414             break;
415
416         default:
417             break;
418         }
419
420         /*
421          * If we are within a C-style expression, emit an extra open
422          * paren. Implemented by examining the parent op.
423          */
424         switch (Op->Common.Parent->Common.AmlOpcode)
425         {
426         case AML_ADD_OP:
427         case AML_SUBTRACT_OP:
428         case AML_MULTIPLY_OP:
429         case AML_DIVIDE_OP:
430         case AML_MOD_OP:
431         case AML_SHIFT_LEFT_OP:
432         case AML_SHIFT_RIGHT_OP:
433         case AML_BIT_AND_OP:
434         case AML_BIT_OR_OP:
435         case AML_BIT_XOR_OP:
436         case AML_LAND_OP:
437         case AML_LEQUAL_OP:
438         case AML_LGREATER_OP:
439         case AML_LLESS_OP:
440         case AML_LOR_OP:
441
442             Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT;
443             AcpiOsPrintf ("(");
444             break;
445
446         default:
447             break;
448         }
449
450         /* Normal output for ASL/AML operators with a target operand */
451
452         Target->Common.OperatorSymbol = " = (";
453         return (TRUE);
454
455     /* Binary operators, no parens */
456
457     case AML_DECREMENT_OP:
458     case AML_INCREMENT_OP:
459         return (TRUE);
460
461     case AML_INDEX_OP:
462
463         /* Target is optional, 3rd operand */
464
465         Target = Child2->Common.Next;
466         if (AcpiDmIsValidTarget (Target))
467         {
468             AcpiDmPromoteTarget (Op, Target);
469
470             if (!Target->Common.OperatorSymbol)
471             {
472                 Target->Common.OperatorSymbol = " = ";
473             }
474         }
475         return (TRUE);
476
477     case AML_STORE_OP:
478         /*
479          * Target is the 2nd operand.
480          * We know the target is valid, it is not optional.
481          * In the parse tree, simply swap the target with the
482          * source so that the target is processed first.
483          */
484         Target = Child1->Common.Next;
485         if (!Target)
486         {
487             return (FALSE);
488         }
489
490         AcpiDmPromoteTarget (Op, Target);
491         if (!Target->Common.OperatorSymbol)
492         {
493             Target->Common.OperatorSymbol = " = ";
494         }
495         return (TRUE);
496
497     case AML_BIT_NOT_OP:
498
499         /* Target is optional, 2nd operand */
500
501         Target = Child1->Common.Next;
502         if (!Target)
503         {
504             return (FALSE);
505         }
506
507         if (AcpiDmIsValidTarget (Target))
508         {
509             /* Valid target, not a placeholder */
510
511             AcpiDmPromoteTarget (Op, Target);
512             Target->Common.OperatorSymbol = " = ~";
513         }
514         else
515         {
516             /* No target. Emit this prefix operator immediately */
517
518             AcpiOsPrintf ("~");
519         }
520         return (TRUE);
521
522     default:
523         break;
524     }
525
526     /* All other operators, emit an open paren */
527
528     AcpiOsPrintf ("(");
529     return (TRUE);
530 }
531
532
533 /*******************************************************************************
534  *
535  * FUNCTION:    AcpiDmCloseOperator
536  *
537  * PARAMETERS:  Op                  - Current parse object
538  *
539  * RETURN:      None
540  *
541  * DESCRIPTION: Closes an operator by adding a closing parentheses if and
542  *              when necessary. Called during ascending phase of the
543  *              parse tree walk.
544  *
545  ******************************************************************************/
546
547 void
548 AcpiDmCloseOperator (
549     ACPI_PARSE_OBJECT       *Op)
550 {
551
552     /* Always emit paren if ASL+ disassembly disabled */
553
554     if (!AcpiGbl_CstyleDisassembly)
555     {
556         AcpiOsPrintf (")");
557         return;
558     }
559
560     /* Check if we need to add an additional closing paren */
561
562     switch (Op->Common.AmlOpcode)
563     {
564     case AML_ADD_OP:
565     case AML_SUBTRACT_OP:
566     case AML_MULTIPLY_OP:
567     case AML_DIVIDE_OP:
568     case AML_MOD_OP:
569     case AML_SHIFT_LEFT_OP:
570     case AML_SHIFT_RIGHT_OP:
571     case AML_BIT_AND_OP:
572     case AML_BIT_OR_OP:
573     case AML_BIT_XOR_OP:
574     case AML_LAND_OP:
575     case AML_LEQUAL_OP:
576     case AML_LGREATER_OP:
577     case AML_LLESS_OP:
578     case AML_LOR_OP:
579
580         /* Emit paren only if this is not a compound assignment */
581
582         if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND)
583         {
584             return;
585         }
586
587         /* Emit extra close paren for assignment within an expression */
588
589         if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT)
590         {
591             AcpiOsPrintf (")");
592         }
593         break;
594
595     case AML_INDEX_OP:
596
597         /* This is case for unsupported Index() source constants */
598
599         if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN)
600         {
601             AcpiOsPrintf (")");
602         }
603         return;
604
605     /* No need for parens for these */
606
607     case AML_DECREMENT_OP:
608     case AML_INCREMENT_OP:
609     case AML_LNOT_OP:
610     case AML_BIT_NOT_OP:
611     case AML_STORE_OP:
612         return;
613
614     default:
615
616         /* Always emit paren for non-ASL+ operators */
617         break;
618     }
619
620     AcpiOsPrintf (")");
621 }
622
623
624 /*******************************************************************************
625  *
626  * FUNCTION:    AcpiDmGetCompoundSymbol
627  *
628  * PARAMETERS:  AslOpcode
629  *
630  * RETURN:      String containing the compound assignment symbol
631  *
632  * DESCRIPTION: Detect opcodes that can be converted to compound assignment,
633  *              return the appropriate operator string.
634  *
635  ******************************************************************************/
636
637 static char *
638 AcpiDmGetCompoundSymbol (
639    UINT16                   AmlOpcode)
640 {
641     char                    *Symbol;
642
643
644     switch (AmlOpcode)
645     {
646     case AML_ADD_OP:
647         Symbol = " += ";
648         break;
649
650     case AML_SUBTRACT_OP:
651         Symbol = " -= ";
652         break;
653
654     case AML_MULTIPLY_OP:
655         Symbol = " *= ";
656         break;
657
658     case AML_DIVIDE_OP:
659         Symbol = " /= ";
660         break;
661
662     case AML_MOD_OP:
663         Symbol = " %= ";
664         break;
665
666     case AML_SHIFT_LEFT_OP:
667         Symbol = " <<= ";
668         break;
669
670     case AML_SHIFT_RIGHT_OP:
671         Symbol = " >>= ";
672         break;
673
674     case AML_BIT_AND_OP:
675         Symbol = " &= ";
676         break;
677
678     case AML_BIT_OR_OP:
679         Symbol = " |= ";
680         break;
681
682     case AML_BIT_XOR_OP:
683         Symbol = " ^= ";
684         break;
685
686     default:
687
688         /* No operator string for all other opcodes */
689
690         return (NULL);
691     }
692
693     return (Symbol);
694 }
695
696
697 /*******************************************************************************
698  *
699  * FUNCTION:    AcpiDmPromoteTarget
700  *
701  * PARAMETERS:  Op                  - Operator parse object
702  *              Target              - Target associate with the Op
703  *
704  * RETURN:      None
705  *
706  * DESCRIPTION: Transform the parse tree by moving the target up to the first
707  *              child of the Op.
708  *
709  ******************************************************************************/
710
711 static void
712 AcpiDmPromoteTarget (
713     ACPI_PARSE_OBJECT       *Op,
714     ACPI_PARSE_OBJECT       *Target)
715 {
716     ACPI_PARSE_OBJECT       *Child;
717
718
719     /* Link target directly to the Op as first child */
720
721     Child = Op->Common.Value.Arg;
722     Op->Common.Value.Arg = Target;
723     Target->Common.Next = Child;
724
725     /* Find the last peer, it is linked to the target. Unlink it. */
726
727     while (Child->Common.Next != Target)
728     {
729         Child = Child->Common.Next;
730     }
731
732     Child->Common.Next = NULL;
733 }
734
735
736 /*******************************************************************************
737  *
738  * FUNCTION:    AcpiDmIsValidTarget
739  *
740  * PARAMETERS:  Target              - Target Op from the parse tree
741  *
742  * RETURN:      TRUE if the Target is real. FALSE if it is just a placeholder
743  *              Op that was inserted by the parser.
744  *
745  * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target.
746  *              In other words, determine if the optional target is used or
747  *              not. Note: If Target is NULL, something is seriously wrong,
748  *              probably with the parse tree.
749  *
750  ******************************************************************************/
751
752 static BOOLEAN
753 AcpiDmIsValidTarget (
754     ACPI_PARSE_OBJECT       *Target)
755 {
756
757     if (!Target)
758     {
759         return (FALSE);
760     }
761
762     if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
763         (Target->Common.Value.Arg == NULL))
764     {
765         return (FALSE);
766     }
767
768     return (TRUE);
769 }
770
771
772 /*******************************************************************************
773  *
774  * FUNCTION:    AcpiDmIsTargetAnOperand
775  *
776  * PARAMETERS:  Target              - Target associated with the expression
777  *              Operand             - An operand associated with expression
778  *
779  * RETURN:      TRUE if expression can be converted to a compound assignment.
780  *              FALSE otherwise.
781  *
782  * DESCRIPTION: Determine if the Target duplicates the operand, in order to
783  *              detect if the expression can be converted to a compound
784  *              assigment. (+=, *=, etc.)
785  *
786  ******************************************************************************/
787
788 static BOOLEAN
789 AcpiDmIsTargetAnOperand (
790     ACPI_PARSE_OBJECT       *Target,
791     ACPI_PARSE_OBJECT       *Operand,
792     BOOLEAN                 TopLevel)
793 {
794     const ACPI_OPCODE_INFO  *OpInfo;
795     BOOLEAN                 Same;
796
797
798     /*
799      * Opcodes must match. Note: ignoring the difference between nameseg
800      * and namepath for now. May be needed later.
801      */
802     if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode)
803     {
804         return (FALSE);
805     }
806
807     /* Nodes should match, even if they are NULL */
808
809     if (Target->Common.Node != Operand->Common.Node)
810     {
811         return (FALSE);
812     }
813
814     /* Determine if a child exists */
815
816     OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode);
817     if (OpInfo->Flags & AML_HAS_ARGS)
818     {
819         Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg,
820             Operand->Common.Value.Arg, FALSE);
821         if (!Same)
822         {
823             return (FALSE);
824         }
825     }
826
827     /* Check the next peer, as long as we are not at the top level */
828
829     if ((!TopLevel) &&
830          Target->Common.Next)
831     {
832         Same = AcpiDmIsTargetAnOperand (Target->Common.Next,
833             Operand->Common.Next, FALSE);
834         if (!Same)
835         {
836             return (FALSE);
837         }
838     }
839
840     /* Supress the duplicate operand at the top-level */
841
842     if (TopLevel)
843     {
844         Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
845     }
846     return (TRUE);
847 }
848
849 #endif