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 850