The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/acpica/components/disassembler/dmcstyle.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*******************************************************************************
    2  *
    3  * Module Name: dmcstyle - Support for C-style operator disassembly
    4  *
    5  ******************************************************************************/
    6 
    7 /******************************************************************************
    8  *
    9  * 1. Copyright Notice
   10  *
   11  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
   12  * All rights reserved.
   13  *
   14  * 2. License
   15  *
   16  * 2.1. This is your license from Intel Corp. under its intellectual property
   17  * rights. You may have additional license terms from the party that provided
   18  * you this software, covering your right to use that party's intellectual
   19  * property rights.
   20  *
   21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
   22  * copy of the source code appearing in this file ("Covered Code") an
   23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
   24  * base code distributed originally by Intel ("Original Intel Code") to copy,
   25  * make derivatives, distribute, use and display any portion of the Covered
   26  * Code in any form, with the right to sublicense such rights; and
   27  *
   28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
   29  * license (with the right to sublicense), under only those claims of Intel
   30  * patents that are infringed by the Original Intel Code, to make, use, sell,
   31  * offer to sell, and import the Covered Code and derivative works thereof
   32  * solely to the minimum extent necessary to exercise the above copyright
   33  * license, and in no event shall the patent license extend to any additions
   34  * to or modifications of the Original Intel Code. No other license or right
   35  * is granted directly or by implication, estoppel or otherwise;
   36  *
   37  * The above copyright and patent license is granted only if the following
   38  * conditions are met:
   39  *
   40  * 3. Conditions
   41  *
   42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
   43  * Redistribution of source code of any substantial portion of the Covered
   44  * Code or modification with rights to further distribute source must include
   45  * the above Copyright Notice, the above License, this list of Conditions,
   46  * and the following Disclaimer and Export Compliance provision. In addition,
   47  * Licensee must cause all Covered Code to which Licensee contributes to
   48  * contain a file documenting the changes Licensee made to create that Covered
   49  * Code and the date of any change. Licensee must include in that file the
   50  * documentation of any changes made by any predecessor Licensee. Licensee
   51  * must include a prominent statement that the modification is derived,
   52  * directly or indirectly, from Original Intel Code.
   53  *
   54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
   55  * Redistribution of source code of any substantial portion of the Covered
   56  * Code or modification without rights to further distribute source must
   57  * include the following Disclaimer and Export Compliance provision in the
   58  * documentation and/or other materials provided with distribution. In
   59  * addition, Licensee may not authorize further sublicense of source of any
   60  * portion of the Covered Code, and must include terms to the effect that the
   61  * license from Licensee to its licensee is limited to the intellectual
   62  * property embodied in the software Licensee provides to its licensee, and
   63  * not to intellectual property embodied in modifications its licensee may
   64  * make.
   65  *
   66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
   67  * substantial portion of the Covered Code or modification must reproduce the
   68  * above Copyright Notice, and the following Disclaimer and Export Compliance
   69  * provision in the documentation and/or other materials provided with the
   70  * distribution.
   71  *
   72  * 3.4. Intel retains all right, title, and interest in and to the Original
   73  * Intel Code.
   74  *
   75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
   76  * Intel shall be used in advertising or otherwise to promote the sale, use or
   77  * other dealings in products derived from or relating to the Covered Code
   78  * without prior written authorization from Intel.
   79  *
   80  * 4. Disclaimer and Export Compliance
   81  *
   82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
   83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
   84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
   85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
   86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
   87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
   88  * PARTICULAR PURPOSE.
   89  *
   90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
   91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
   92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
   93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
   94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
   95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
   96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
   97  * LIMITED REMEDY.
   98  *
   99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  100  * software or system incorporating such software without first obtaining any
  101  * required license or other approval from the U. S. Department of Commerce or
  102  * any other agency or department of the United States Government. In the
  103  * event Licensee exports any such software from the United States or
  104  * re-exports any such software from a foreign destination, Licensee shall
  105  * ensure that the distribution and export/re-export of the software is in
  106  * compliance with all laws, regulations, orders, or other restrictions of the
  107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  108  * any of its subsidiaries will export/re-export any technical data, process,
  109  * software, or service, directly or indirectly, to any country for which the
  110  * United States government or any agency thereof requires an export license,
  111  * other governmental approval, or letter of assurance, without first obtaining
  112  * such license, approval or letter.
  113  *
  114  *****************************************************************************
  115  *
  116  * Alternatively, you may choose to be licensed under the terms of the
  117  * following license:
  118  *
  119  * Redistribution and use in source and binary forms, with or without
  120  * modification, are permitted provided that the following conditions
  121  * are met:
  122  * 1. Redistributions of source code must retain the above copyright
  123  *    notice, this list of conditions, and the following disclaimer,
  124  *    without modification.
  125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  126  *    substantially similar to the "NO WARRANTY" disclaimer below
  127  *    ("Disclaimer") and any redistribution must be conditioned upon
  128  *    including a substantially similar Disclaimer requirement for further
  129  *    binary redistribution.
  130  * 3. Neither the names of the above-listed copyright holders nor the names
  131  *    of any contributors may be used to endorse or promote products derived
  132  *    from this software without specific prior written permission.
  133  *
  134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  145  *
  146  * Alternatively, you may choose to be licensed under the terms of the
  147  * GNU General Public License ("GPL") version 2 as published by the Free
  148  * Software Foundation.
  149  *
  150  *****************************************************************************/
  151 
  152 #include <contrib/dev/acpica/include/acpi.h>
  153 #include <contrib/dev/acpica/include/accommon.h>
  154 #include <contrib/dev/acpica/include/acparser.h>
  155 #include <contrib/dev/acpica/include/amlcode.h>
  156 #include <contrib/dev/acpica/include/acdebug.h>
  157 #include <contrib/dev/acpica/include/acconvert.h>
  158 
  159 
  160 #define _COMPONENT          ACPI_CA_DEBUGGER
  161         ACPI_MODULE_NAME    ("dmcstyle")
  162 
  163 
  164 /* Local prototypes */
  165 
  166 static char *
  167 AcpiDmGetCompoundSymbol (
  168    UINT16                   AslOpcode);
  169 
  170 static void
  171 AcpiDmPromoteTarget (
  172     ACPI_PARSE_OBJECT       *Op,
  173     ACPI_PARSE_OBJECT       *Target);
  174 
  175 static BOOLEAN
  176 AcpiDmIsValidTarget (
  177     ACPI_PARSE_OBJECT       *Op);
  178 
  179 static BOOLEAN
  180 AcpiDmIsTargetAnOperand (
  181     ACPI_PARSE_OBJECT       *Target,
  182     ACPI_PARSE_OBJECT       *Operand,
  183     BOOLEAN                 TopLevel);
  184 
  185 static BOOLEAN
  186 AcpiDmIsOptimizationIgnored (
  187     ACPI_PARSE_OBJECT       *StoreOp,
  188     ACPI_PARSE_OBJECT       *StoreArgument);
  189 
  190 
  191 /*******************************************************************************
  192  *
  193  * FUNCTION:    AcpiDmCheckForSymbolicOpcode
  194  *
  195  * PARAMETERS:  Op                  - Current parse object
  196  *              Walk                - Current parse tree walk info
  197  *
  198  * RETURN:      TRUE if opcode can be converted to symbolic, FALSE otherwise
  199  *
  200  * DESCRIPTION: This is the main code that implements disassembly of AML code
  201  *              to C-style operators. Called during descending phase of the
  202  *              parse tree walk.
  203  *
  204  ******************************************************************************/
  205 
  206 BOOLEAN
  207 AcpiDmCheckForSymbolicOpcode (
  208     ACPI_PARSE_OBJECT       *Op,
  209     ACPI_OP_WALK_INFO       *Info)
  210 {
  211     char                    *OperatorSymbol = NULL;
  212     ACPI_PARSE_OBJECT       *Argument1;
  213     ACPI_PARSE_OBJECT       *Argument2;
  214     ACPI_PARSE_OBJECT       *Target;
  215     ACPI_PARSE_OBJECT       *Target2;
  216 
  217 
  218     /* Exit immediately if ASL+ not enabled */
  219 
  220     if (!AcpiGbl_CstyleDisassembly)
  221     {
  222         return (FALSE);
  223     }
  224 
  225     /* Get the first operand */
  226 
  227     Argument1 = AcpiPsGetArg (Op, 0);
  228     if (!Argument1)
  229     {
  230         return (FALSE);
  231     }
  232 
  233     /* Get the second operand */
  234 
  235     Argument2 = Argument1->Common.Next;
  236 
  237     /* Setup the operator string for this opcode */
  238 
  239     switch (Op->Common.AmlOpcode)
  240     {
  241     case AML_ADD_OP:
  242         OperatorSymbol = " + ";
  243         break;
  244 
  245     case AML_SUBTRACT_OP:
  246         OperatorSymbol = " - ";
  247         break;
  248 
  249     case AML_MULTIPLY_OP:
  250         OperatorSymbol = " * ";
  251         break;
  252 
  253     case AML_DIVIDE_OP:
  254         OperatorSymbol = " / ";
  255         break;
  256 
  257     case AML_MOD_OP:
  258         OperatorSymbol = " % ";
  259         break;
  260 
  261     case AML_SHIFT_LEFT_OP:
  262         OperatorSymbol = " << ";
  263         break;
  264 
  265     case AML_SHIFT_RIGHT_OP:
  266         OperatorSymbol = " >> ";
  267         break;
  268 
  269     case AML_BIT_AND_OP:
  270         OperatorSymbol = " & ";
  271         break;
  272 
  273     case AML_BIT_OR_OP:
  274         OperatorSymbol = " | ";
  275         break;
  276 
  277     case AML_BIT_XOR_OP:
  278         OperatorSymbol = " ^ ";
  279         break;
  280 
  281     /* Logical operators, no target */
  282 
  283     case AML_LOGICAL_AND_OP:
  284         OperatorSymbol = " && ";
  285         break;
  286 
  287     case AML_LOGICAL_EQUAL_OP:
  288         OperatorSymbol = " == ";
  289         break;
  290 
  291     case AML_LOGICAL_GREATER_OP:
  292         OperatorSymbol = " > ";
  293         break;
  294 
  295     case AML_LOGICAL_LESS_OP:
  296         OperatorSymbol = " < ";
  297         break;
  298 
  299     case AML_LOGICAL_OR_OP:
  300         OperatorSymbol = " || ";
  301         break;
  302 
  303     case AML_LOGICAL_NOT_OP:
  304         /*
  305          * Check for the LNOT sub-opcodes. These correspond to
  306          * LNotEqual, LLessEqual, and LGreaterEqual. There are
  307          * no actual AML opcodes for these operators.
  308          */
  309         switch (Argument1->Common.AmlOpcode)
  310         {
  311         case AML_LOGICAL_EQUAL_OP:
  312             OperatorSymbol = " != ";
  313             break;
  314 
  315         case AML_LOGICAL_GREATER_OP:
  316             OperatorSymbol = " <= ";
  317             break;
  318 
  319         case AML_LOGICAL_LESS_OP:
  320             OperatorSymbol = " >= ";
  321             break;
  322 
  323         default:
  324 
  325             /* Unary LNOT case, emit "!" immediately */
  326 
  327             AcpiOsPrintf ("!");
  328             return (TRUE);
  329         }
  330 
  331         Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
  332         Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
  333 
  334         /* Save symbol string in the next child (not peer) */
  335 
  336         Argument2 = AcpiPsGetArg (Argument1, 0);
  337         if (!Argument2)
  338         {
  339             return (FALSE);
  340         }
  341 
  342         Argument2->Common.OperatorSymbol = OperatorSymbol;
  343         return (TRUE);
  344 
  345     case AML_INDEX_OP:
  346         /*
  347          * Check for constant source operand. Note: although technically
  348          * legal syntax, the iASL compiler does not support this with
  349          * the symbolic operators for Index(). It doesn't make sense to
  350          * use Index() with a constant anyway.
  351          */
  352         if ((Argument1->Common.AmlOpcode == AML_STRING_OP)  ||
  353             (Argument1->Common.AmlOpcode == AML_BUFFER_OP)  ||
  354             (Argument1->Common.AmlOpcode == AML_PACKAGE_OP) ||
  355             (Argument1->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
  356         {
  357             Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;
  358             return (FALSE);
  359         }
  360 
  361         /* Index operator is [] */
  362 
  363         Argument1->Common.OperatorSymbol = " [";
  364         Argument2->Common.OperatorSymbol = "]";
  365         break;
  366 
  367     /* Unary operators */
  368 
  369     case AML_DECREMENT_OP:
  370         OperatorSymbol = "--";
  371         break;
  372 
  373     case AML_INCREMENT_OP:
  374         OperatorSymbol = "++";
  375         break;
  376 
  377     case AML_BIT_NOT_OP:
  378     case AML_STORE_OP:
  379         OperatorSymbol = NULL;
  380         break;
  381 
  382     default:
  383         return (FALSE);
  384     }
  385 
  386     if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)
  387     {
  388         return (TRUE);
  389     }
  390 
  391     /*
  392      * This is the key to how the disassembly of the C-style operators
  393      * works. We save the operator symbol in the first child, thus
  394      * deferring symbol output until after the first operand has been
  395      * emitted.
  396      */
  397     if (!Argument1->Common.OperatorSymbol)
  398     {
  399         Argument1->Common.OperatorSymbol = OperatorSymbol;
  400     }
  401 
  402     /*
  403      * Check for a valid target as the 3rd (or sometimes 2nd) operand
  404      *
  405      * Compound assignment operator support:
  406      * Attempt to optimize constructs of the form:
  407      *      Add (Local1, 0xFF, Local1)
  408      * to:
  409      *      Local1 += 0xFF
  410      *
  411      * Only the math operators and Store() have a target.
  412      * Logicals have no target.
  413      */
  414     switch (Op->Common.AmlOpcode)
  415     {
  416     case AML_ADD_OP:
  417     case AML_SUBTRACT_OP:
  418     case AML_MULTIPLY_OP:
  419     case AML_DIVIDE_OP:
  420     case AML_MOD_OP:
  421     case AML_SHIFT_LEFT_OP:
  422     case AML_SHIFT_RIGHT_OP:
  423     case AML_BIT_AND_OP:
  424     case AML_BIT_OR_OP:
  425     case AML_BIT_XOR_OP:
  426 
  427         /* Target is 3rd operand */
  428 
  429         Target = Argument2->Common.Next;
  430         if (Op->Common.AmlOpcode == AML_DIVIDE_OP)
  431         {
  432             Target2 = Target->Common.Next;
  433 
  434             /*
  435              * Divide has an extra target operand (Remainder).
  436              * Default behavior is to simply ignore ASL+ conversion
  437              * if the remainder target (modulo) is specified.
  438              */
  439             if (!AcpiGbl_DoDisassemblerOptimizations)
  440             {
  441                 if (AcpiDmIsValidTarget (Target))
  442                 {
  443                     Argument1->Common.OperatorSymbol = NULL;
  444                     Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
  445                     return (FALSE);
  446                 }
  447 
  448                 Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
  449                 Target = Target2;
  450             }
  451             else
  452             {
  453                 /*
  454                  * Divide has an extra target operand (Remainder).
  455                  * If both targets are specified, it cannot be converted
  456                  * to a C-style operator.
  457                  */
  458                 if (AcpiDmIsValidTarget (Target) &&
  459                     AcpiDmIsValidTarget (Target2))
  460                 {
  461                     Argument1->Common.OperatorSymbol = NULL;
  462                     Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
  463                     return (FALSE);
  464                 }
  465 
  466                 if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */
  467                 {
  468                     /* Convert the Divide to Modulo */
  469 
  470                     Op->Common.AmlOpcode = AML_MOD_OP;
  471 
  472                     Argument1->Common.OperatorSymbol = " % ";
  473                     Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
  474                 }
  475                 else /* Only second Target (quotient) is valid */
  476                 {
  477                     Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
  478                     Target = Target2;
  479                 }
  480             }
  481         }
  482 
  483         /* Parser should ensure there is at least a placeholder target */
  484 
  485         if (!Target)
  486         {
  487             return (FALSE);
  488         }
  489 
  490         if (!AcpiDmIsValidTarget (Target))
  491         {
  492             /* Not a valid target (placeholder only, from parser) */
  493             break;
  494         }
  495 
  496         /*
  497          * Promote the target up to the first child in the parse
  498          * tree. This is done because the target will be output
  499          * first, in the form:
  500          *     <Target> = Operands...
  501          */
  502         AcpiDmPromoteTarget (Op, Target);
  503 
  504         /* Check operands for conversion to a "Compound Assignment" */
  505 
  506         switch (Op->Common.AmlOpcode)
  507         {
  508             /* Commutative operators */
  509 
  510         case AML_ADD_OP:
  511         case AML_MULTIPLY_OP:
  512         case AML_BIT_AND_OP:
  513         case AML_BIT_OR_OP:
  514         case AML_BIT_XOR_OP:
  515             /*
  516              * For the commutative operators, we can convert to a
  517              * compound statement only if at least one (either) operand
  518              * is the same as the target.
  519              *
  520              *      Add (A, B, A) --> A += B
  521              *      Add (B, A, A) --> A += B
  522              *      Add (B, C, A) --> A = (B + C)
  523              */
  524             if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) ||
  525                 (AcpiDmIsTargetAnOperand (Target, Argument2, TRUE)))
  526             {
  527                 Target->Common.OperatorSymbol =
  528                     AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
  529 
  530                 /* Convert operator to compound assignment */
  531 
  532                 Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
  533                 Argument1->Common.OperatorSymbol = NULL;
  534                 return (TRUE);
  535             }
  536             break;
  537 
  538             /* Non-commutative operators */
  539 
  540         case AML_SUBTRACT_OP:
  541         case AML_DIVIDE_OP:
  542         case AML_MOD_OP:
  543         case AML_SHIFT_LEFT_OP:
  544         case AML_SHIFT_RIGHT_OP:
  545             /*
  546              * For the non-commutative operators, we can convert to a
  547              * compound statement only if the target is the same as the
  548              * first operand.
  549              *
  550              *      Subtract (A, B, A) --> A -= B
  551              *      Subtract (B, A, A) --> A = (B - A)
  552              */
  553             if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)))
  554             {
  555                 Target->Common.OperatorSymbol =
  556                     AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
  557 
  558                 /* Convert operator to compound assignment */
  559 
  560                 Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
  561                 Argument1->Common.OperatorSymbol = NULL;
  562                 return (TRUE);
  563             }
  564             break;
  565 
  566         default:
  567             break;
  568         }
  569 
  570         /*
  571          * If we are within a C-style expression, emit an extra open
  572          * paren. Implemented by examining the parent op.
  573          */
  574         switch (Op->Common.Parent->Common.AmlOpcode)
  575         {
  576         case AML_ADD_OP:
  577         case AML_SUBTRACT_OP:
  578         case AML_MULTIPLY_OP:
  579         case AML_DIVIDE_OP:
  580         case AML_MOD_OP:
  581         case AML_SHIFT_LEFT_OP:
  582         case AML_SHIFT_RIGHT_OP:
  583         case AML_BIT_AND_OP:
  584         case AML_BIT_OR_OP:
  585         case AML_BIT_XOR_OP:
  586         case AML_LOGICAL_AND_OP:
  587         case AML_LOGICAL_EQUAL_OP:
  588         case AML_LOGICAL_GREATER_OP:
  589         case AML_LOGICAL_LESS_OP:
  590         case AML_LOGICAL_OR_OP:
  591 
  592             Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT;
  593             AcpiOsPrintf ("(");
  594             break;
  595 
  596         default:
  597             break;
  598         }
  599 
  600         /* Normal output for ASL/AML operators with a target operand */
  601 
  602         Target->Common.OperatorSymbol = " = (";
  603         return (TRUE);
  604 
  605     /* Binary operators, no parens */
  606 
  607     case AML_DECREMENT_OP:
  608     case AML_INCREMENT_OP:
  609         return (TRUE);
  610 
  611     case AML_INDEX_OP:
  612 
  613         /* Target is optional, 3rd operand */
  614 
  615         Target = Argument2->Common.Next;
  616         if (AcpiDmIsValidTarget (Target))
  617         {
  618             AcpiDmPromoteTarget (Op, Target);
  619 
  620             if (!Target->Common.OperatorSymbol)
  621             {
  622                 Target->Common.OperatorSymbol = " = ";
  623             }
  624         }
  625         return (TRUE);
  626 
  627     case AML_STORE_OP:
  628         /*
  629          * For Store, the Target is the 2nd operand. We know the target
  630          * is valid, because it is not optional.
  631          *
  632          * Ignore any optimizations/folding if flag is set.
  633          * Used for iASL/disassembler test suite only.
  634          */
  635         if (AcpiDmIsOptimizationIgnored (Op, Argument1))
  636         {
  637             return (FALSE);
  638         }
  639 
  640         /*
  641          * Perform conversion.
  642          * In the parse tree, simply swap the target with the
  643          * source so that the target is processed first.
  644          */
  645         Target = Argument1->Common.Next;
  646         if (!Target)
  647         {
  648             return (FALSE);
  649         }
  650 
  651         AcpiDmPromoteTarget (Op, Target);
  652         if (!Target->Common.OperatorSymbol)
  653         {
  654             Target->Common.OperatorSymbol = " = ";
  655         }
  656         return (TRUE);
  657 
  658     case AML_BIT_NOT_OP:
  659 
  660         /* Target is optional, 2nd operand */
  661 
  662         Target = Argument1->Common.Next;
  663         if (!Target)
  664         {
  665             return (FALSE);
  666         }
  667 
  668         if (AcpiDmIsValidTarget (Target))
  669         {
  670             /* Valid target, not a placeholder */
  671 
  672             AcpiDmPromoteTarget (Op, Target);
  673             Target->Common.OperatorSymbol = " = ~";
  674         }
  675         else
  676         {
  677             /* No target. Emit this prefix operator immediately */
  678 
  679             AcpiOsPrintf ("~");
  680         }
  681         return (TRUE);
  682 
  683     default:
  684         break;
  685     }
  686 
  687     /* All other operators, emit an open paren */
  688 
  689     AcpiOsPrintf ("(");
  690     return (TRUE);
  691 }
  692 
  693 
  694 /*******************************************************************************
  695  *
  696  * FUNCTION:    AcpiDmIsOptimizationIgnored
  697  *
  698  * PARAMETERS:  StoreOp             - Store operator parse object
  699  *              StoreArgument       - Target associate with the Op
  700  *
  701  * RETURN:      TRUE if this Store operator should not be converted/removed.
  702  *
  703  * DESCRIPTION: The following function implements "Do not optimize if a
  704  *              store is immediately followed by a math/bit operator that
  705  *              has no target".
  706  *
  707  *              Function is ignored if DoDisassemblerOptimizations is TRUE.
  708  *              This is the default, ignore this function.
  709  *
  710  *              Disables these types of optimizations, and simply emits
  711  *              legacy ASL code:
  712  *                  Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2)
  713  *                                              --> INT2 = INT1 + 4
  714  *
  715  *                  Store (Not (INT1), INT2)    --> Not (INT1, INT2)
  716  *                                              --> INT2 = ~INT1
  717  *
  718  *              Used only for the ASL test suite. For the test suite, we
  719  *              don't want to perform some optimizations to ensure binary
  720  *              compatibility with the generation of the legacy ASL->AML.
  721  *              In other words, for all test modules we want exactly:
  722  *                  (ASL+ -> AML) == (ASL- -> AML)
  723  *
  724  ******************************************************************************/
  725 
  726 static BOOLEAN
  727 AcpiDmIsOptimizationIgnored (
  728     ACPI_PARSE_OBJECT       *StoreOp,
  729     ACPI_PARSE_OBJECT       *StoreArgument)
  730 {
  731     ACPI_PARSE_OBJECT       *Argument1;
  732     ACPI_PARSE_OBJECT       *Argument2;
  733     ACPI_PARSE_OBJECT       *Target;
  734 
  735 
  736     /* No optimizations/folding for the typical case */
  737 
  738     if (AcpiGbl_DoDisassemblerOptimizations)
  739     {
  740         return (FALSE);
  741     }
  742 
  743     /*
  744      * Only a small subset of ASL/AML operators can be optimized.
  745      * Can only optimize/fold if there is no target (or targets)
  746      * specified for the operator. And of course, the operator
  747      * is surrounded by a Store() operator.
  748      */
  749     switch (StoreArgument->Common.AmlOpcode)
  750     {
  751     case AML_ADD_OP:
  752     case AML_SUBTRACT_OP:
  753     case AML_MULTIPLY_OP:
  754     case AML_MOD_OP:
  755     case AML_SHIFT_LEFT_OP:
  756     case AML_SHIFT_RIGHT_OP:
  757     case AML_BIT_AND_OP:
  758     case AML_BIT_OR_OP:
  759     case AML_BIT_XOR_OP:
  760     case AML_INDEX_OP:
  761 
  762         /* These operators have two arguments and one target */
  763 
  764         Argument1 = StoreArgument->Common.Value.Arg;
  765         Argument2 = Argument1->Common.Next;
  766         Target = Argument2->Common.Next;
  767 
  768         if (!AcpiDmIsValidTarget (Target))
  769         {
  770             StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
  771             return (TRUE);
  772         }
  773         break;
  774 
  775     case AML_DIVIDE_OP:
  776 
  777         /* This operator has two arguments and two targets */
  778 
  779         Argument1 = StoreArgument->Common.Value.Arg;
  780         Argument2 = Argument1->Common.Next;
  781         Target = Argument2->Common.Next;
  782 
  783         if (!AcpiDmIsValidTarget (Target) ||
  784             !AcpiDmIsValidTarget (Target->Common.Next))
  785         {
  786             StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
  787             return (TRUE);
  788         }
  789         break;
  790 
  791     case AML_BIT_NOT_OP:
  792 
  793         /* This operator has one operand and one target */
  794 
  795         Argument1 = StoreArgument->Common.Value.Arg;
  796         Target = Argument1->Common.Next;
  797 
  798         if (!AcpiDmIsValidTarget (Target))
  799         {
  800             StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
  801             return (TRUE);
  802         }
  803         break;
  804 
  805     default:
  806         break;
  807     }
  808 
  809     return (FALSE);
  810 }
  811 
  812 
  813 /*******************************************************************************
  814  *
  815  * FUNCTION:    AcpiDmCloseOperator
  816  *
  817  * PARAMETERS:  Op                  - Current parse object
  818  *
  819  * RETURN:      None
  820  *
  821  * DESCRIPTION: Closes an operator by adding a closing parentheses if and
  822  *              when necessary. Called during ascending phase of the
  823  *              parse tree walk.
  824  *
  825  ******************************************************************************/
  826 
  827 void
  828 AcpiDmCloseOperator (
  829     ACPI_PARSE_OBJECT       *Op)
  830 {
  831 
  832     /* Always emit paren if ASL+ disassembly disabled */
  833 
  834     if (!AcpiGbl_CstyleDisassembly)
  835     {
  836         AcpiOsPrintf (")");
  837         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  838         return;
  839     }
  840 
  841     if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)
  842     {
  843         AcpiOsPrintf (")");
  844         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  845         return;
  846     }
  847 
  848     /* Check if we need to add an additional closing paren */
  849 
  850     switch (Op->Common.AmlOpcode)
  851     {
  852     case AML_ADD_OP:
  853     case AML_SUBTRACT_OP:
  854     case AML_MULTIPLY_OP:
  855     case AML_DIVIDE_OP:
  856     case AML_MOD_OP:
  857     case AML_SHIFT_LEFT_OP:
  858     case AML_SHIFT_RIGHT_OP:
  859     case AML_BIT_AND_OP:
  860     case AML_BIT_OR_OP:
  861     case AML_BIT_XOR_OP:
  862     case AML_LOGICAL_AND_OP:
  863     case AML_LOGICAL_EQUAL_OP:
  864     case AML_LOGICAL_GREATER_OP:
  865     case AML_LOGICAL_LESS_OP:
  866     case AML_LOGICAL_OR_OP:
  867 
  868         /* Emit paren only if this is not a compound assignment */
  869 
  870         if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND_ASSIGNMENT)
  871         {
  872             ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  873             return;
  874         }
  875 
  876         /* Emit extra close paren for assignment within an expression */
  877 
  878         if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT)
  879         {
  880             AcpiOsPrintf (")");
  881         }
  882         break;
  883 
  884     case AML_INDEX_OP:
  885 
  886         /* This is case for unsupported Index() source constants */
  887 
  888         if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN)
  889         {
  890             AcpiOsPrintf (")");
  891         }
  892         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  893         return;
  894 
  895     /* No need for parens for these */
  896 
  897     case AML_DECREMENT_OP:
  898     case AML_INCREMENT_OP:
  899     case AML_LOGICAL_NOT_OP:
  900     case AML_BIT_NOT_OP:
  901     case AML_STORE_OP:
  902         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  903         return;
  904 
  905     default:
  906 
  907         /* Always emit paren for non-ASL+ operators */
  908         break;
  909     }
  910 
  911     AcpiOsPrintf (")");
  912     ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
  913 
  914     return;
  915 }
  916 
  917 
  918 /*******************************************************************************
  919  *
  920  * FUNCTION:    AcpiDmGetCompoundSymbol
  921  *
  922  * PARAMETERS:  AslOpcode
  923  *
  924  * RETURN:      String containing the compound assignment symbol
  925  *
  926  * DESCRIPTION: Detect opcodes that can be converted to compound assignment,
  927  *              return the appropriate operator string.
  928  *
  929  ******************************************************************************/
  930 
  931 static char *
  932 AcpiDmGetCompoundSymbol (
  933    UINT16                   AmlOpcode)
  934 {
  935     char                    *Symbol;
  936 
  937 
  938     switch (AmlOpcode)
  939     {
  940     case AML_ADD_OP:
  941         Symbol = " += ";
  942         break;
  943 
  944     case AML_SUBTRACT_OP:
  945         Symbol = " -= ";
  946         break;
  947 
  948     case AML_MULTIPLY_OP:
  949         Symbol = " *= ";
  950         break;
  951 
  952     case AML_DIVIDE_OP:
  953         Symbol = " /= ";
  954         break;
  955 
  956     case AML_MOD_OP:
  957         Symbol = " %= ";
  958         break;
  959 
  960     case AML_SHIFT_LEFT_OP:
  961         Symbol = " <<= ";
  962         break;
  963 
  964     case AML_SHIFT_RIGHT_OP:
  965         Symbol = " >>= ";
  966         break;
  967 
  968     case AML_BIT_AND_OP:
  969         Symbol = " &= ";
  970         break;
  971 
  972     case AML_BIT_OR_OP:
  973         Symbol = " |= ";
  974         break;
  975 
  976     case AML_BIT_XOR_OP:
  977         Symbol = " ^= ";
  978         break;
  979 
  980     default:
  981 
  982         /* No operator string for all other opcodes */
  983 
  984         return (NULL);
  985     }
  986 
  987     return (Symbol);
  988 }
  989 
  990 
  991 /*******************************************************************************
  992  *
  993  * FUNCTION:    AcpiDmPromoteTarget
  994  *
  995  * PARAMETERS:  Op                  - Operator parse object
  996  *              Target              - Target associate with the Op
  997  *
  998  * RETURN:      None
  999  *
 1000  * DESCRIPTION: Transform the parse tree by moving the target up to the first
 1001  *              child of the Op.
 1002  *
 1003  ******************************************************************************/
 1004 
 1005 static void
 1006 AcpiDmPromoteTarget (
 1007     ACPI_PARSE_OBJECT       *Op,
 1008     ACPI_PARSE_OBJECT       *Target)
 1009 {
 1010     ACPI_PARSE_OBJECT       *Child;
 1011 
 1012 
 1013     /* Link target directly to the Op as first child */
 1014 
 1015     Child = Op->Common.Value.Arg;
 1016     Op->Common.Value.Arg = Target;
 1017     Target->Common.Next = Child;
 1018 
 1019     /* Find the last peer, it is linked to the target. Unlink it. */
 1020 
 1021     while (Child->Common.Next != Target)
 1022     {
 1023         Child = Child->Common.Next;
 1024     }
 1025 
 1026     Child->Common.Next = NULL;
 1027 }
 1028 
 1029 
 1030 /*******************************************************************************
 1031  *
 1032  * FUNCTION:    AcpiDmIsValidTarget
 1033  *
 1034  * PARAMETERS:  Target              - Target Op from the parse tree
 1035  *
 1036  * RETURN:      TRUE if the Target is real. FALSE if it is just a placeholder
 1037  *              Op that was inserted by the parser.
 1038  *
 1039  * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target.
 1040  *              In other words, determine if the optional target is used or
 1041  *              not. Note: If Target is NULL, something is seriously wrong,
 1042  *              probably with the parse tree.
 1043  *
 1044  ******************************************************************************/
 1045 
 1046 static BOOLEAN
 1047 AcpiDmIsValidTarget (
 1048     ACPI_PARSE_OBJECT       *Target)
 1049 {
 1050 
 1051     if (!Target)
 1052     {
 1053         return (FALSE);
 1054     }
 1055 
 1056     if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
 1057         (Target->Common.Value.Arg == NULL))
 1058     {
 1059         return (FALSE);
 1060     }
 1061 
 1062     return (TRUE);
 1063 }
 1064 
 1065 
 1066 /*******************************************************************************
 1067  *
 1068  * FUNCTION:    AcpiDmIsTargetAnOperand
 1069  *
 1070  * PARAMETERS:  Target              - Target associated with the expression
 1071  *              Operand             - An operand associated with expression
 1072  *
 1073  * RETURN:      TRUE if expression can be converted to a compound assignment.
 1074  *              FALSE otherwise.
 1075  *
 1076  * DESCRIPTION: Determine if the Target duplicates the operand, in order to
 1077  *              detect if the expression can be converted to a compound
 1078  *              assignment. (+=, *=, etc.)
 1079  *
 1080  ******************************************************************************/
 1081 
 1082 static BOOLEAN
 1083 AcpiDmIsTargetAnOperand (
 1084     ACPI_PARSE_OBJECT       *Target,
 1085     ACPI_PARSE_OBJECT       *Operand,
 1086     BOOLEAN                 TopLevel)
 1087 {
 1088     const ACPI_OPCODE_INFO  *OpInfo;
 1089     BOOLEAN                 Same;
 1090 
 1091 
 1092     /*
 1093      * Opcodes must match. Note: ignoring the difference between nameseg
 1094      * and namepath for now. May be needed later.
 1095      */
 1096     if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode)
 1097     {
 1098         return (FALSE);
 1099     }
 1100 
 1101     /* Nodes should match, even if they are NULL */
 1102 
 1103     if (Target->Common.Node != Operand->Common.Node)
 1104     {
 1105         return (FALSE);
 1106     }
 1107 
 1108     /* Determine if a child exists */
 1109 
 1110     OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode);
 1111     if (OpInfo->Flags & AML_HAS_ARGS)
 1112     {
 1113         Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg,
 1114             Operand->Common.Value.Arg, FALSE);
 1115         if (!Same)
 1116         {
 1117             return (FALSE);
 1118         }
 1119     }
 1120 
 1121     /* Check the next peer, as long as we are not at the top level */
 1122 
 1123     if ((!TopLevel) &&
 1124          Target->Common.Next)
 1125     {
 1126         Same = AcpiDmIsTargetAnOperand (Target->Common.Next,
 1127             Operand->Common.Next, FALSE);
 1128         if (!Same)
 1129         {
 1130             return (FALSE);
 1131         }
 1132     }
 1133 
 1134     /* Suppress the duplicate operand at the top-level */
 1135 
 1136     if (TopLevel)
 1137     {
 1138         Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
 1139     }
 1140     return (TRUE);
 1141 }

Cache object: 60e987ddaf12ba982ee5ede3e54cf942


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.