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