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