diff options
| author | Jung-uk Kim <jkim@FreeBSD.org> | 2014-11-10 21:30:04 +0000 | 
|---|---|---|
| committer | Jung-uk Kim <jkim@FreeBSD.org> | 2014-11-10 21:30:04 +0000 | 
| commit | e8991236d498c9646c20a8acf0236cf3342dad6f (patch) | |
| tree | b4bd3052883fca1145eaa389311d46371584f6d9 /source/components/disassembler | |
| parent | d4e301bc21b6911ed7f5d6a86659c4882fa7ab55 (diff) | |
Notes
Diffstat (limited to 'source/components/disassembler')
| -rw-r--r-- | source/components/disassembler/dmbuffer.c | 203 | ||||
| -rw-r--r-- | source/components/disassembler/dmcstyle.c | 773 | ||||
| -rw-r--r-- | source/components/disassembler/dmopcode.c | 38 | ||||
| -rw-r--r-- | source/components/disassembler/dmutils.c | 15 | ||||
| -rw-r--r-- | source/components/disassembler/dmwalk.c | 50 | 
5 files changed, 1013 insertions, 66 deletions
| diff --git a/source/components/disassembler/dmbuffer.c b/source/components/disassembler/dmbuffer.c index 973e269e0944..afb0842e796d 100644 --- a/source/components/disassembler/dmbuffer.c +++ b/source/components/disassembler/dmbuffer.c @@ -79,6 +79,51 @@ AcpiDmPldBuffer (  #define ACPI_BUFFER_BYTES_PER_LINE      8 +/* Strings for ToPld */ + +static char *DmPanelList[] = +{ +    "TOP", +    "BOTTOM", +    "LEFT", +    "RIGHT", +    "FRONT", +    "BACK", +    "UNKNOWN", +    NULL +}; + +static char *DmVerticalPositionList[] = +{ +    "UPPER", +    "CENTER", +    "LOWER", +    NULL +}; + +static char *DmHorizontalPositionList[] = +{ +    "LEFT", +    "CENTER", +    "RIGHT", +    NULL +}; + +static char *DmShapeList[] = +{ +    "ROUND", +    "OVAL", +    "SQUARE", +    "VERTICALRECTANGLE", +    "HORIZONTALRECTANGLE", +    "VERTICALTRAPEZOID", +    "HORIZONTALTRAPEZOID", +    "UNKNOWN", +    "CHAMFERED", +    NULL +}; + +  /*******************************************************************************   *   * FUNCTION:    AcpiDmDisasmByteList @@ -232,8 +277,9 @@ AcpiDmByteList (          break;      case ACPI_DASM_PLD_METHOD: - +#if 0          AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount); +#endif          AcpiDmPldBuffer (Info->Level, ByteData, ByteCount);          break; @@ -434,11 +480,12 @@ AcpiDmIsUnicodeBuffer (          return (FALSE);      } -    /* For each word, 1st byte must be ascii, 2nd byte must be zero */ +    /* For each word, 1st byte must be ascii (1-0x7F), 2nd byte must be zero */      for (i = 0; i < (ByteCount - 2); i += 2)      { -        if ((!ACPI_IS_PRINT (ByteData[i])) || +        if ((ByteData[i] == 0) || +            (ByteData[i] > 0x7F) ||              (ByteData[(ACPI_SIZE) i + 1] != 0))          {              return (FALSE); @@ -534,9 +581,14 @@ AcpiDmIsPldBuffer (      ACPI_PARSE_OBJECT       *Op)  {      ACPI_NAMESPACE_NODE     *Node; +    ACPI_PARSE_OBJECT       *SizeOp;      ACPI_PARSE_OBJECT       *ParentOp; +    /* Buffer size is the buffer argument */ + +    SizeOp = Op->Common.Value.Arg; +      ParentOp = Op->Common.Parent;      if (!ParentOp)      { @@ -551,6 +603,9 @@ AcpiDmIsPldBuffer (          if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD))          { +            /* Ignore the Size argument in the disassembly of this buffer op */ + +            SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;              return (TRUE);          } @@ -573,6 +628,9 @@ AcpiDmIsPldBuffer (              if (ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__PLD))              { +                /* Ignore the Size argument in the disassembly of this buffer op */ + +                SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;                  return (TRUE);              }          } @@ -584,6 +642,51 @@ AcpiDmIsPldBuffer (  /*******************************************************************************   * + * FUNCTION:    AcpiDmFindNameByIndex + * + * PARAMETERS:  Index               - Index of array to check + *              List                - Array to reference + * + * RETURN:      String from List or empty string + * + * DESCRIPTION: Finds and returns the char string located at the given index + *              position in List. + * + ******************************************************************************/ + +static char * +AcpiDmFindNameByIndex ( +    UINT64                  Index, +    char                    **List) +{ +    char                     *Str; +    UINT32                   i; + + +    /* Bounds check */ + +    Str = List[0]; +    i = 0; + +    while(Str) +    { +        i++; +        Str = List[i]; +    } + +    if (Index >= i) +    { +        /* TBD: Add error msg */ + +        return (""); +    } + +    return (List[Index]); +} + + +/******************************************************************************* + *   * FUNCTION:    AcpiDmPldBuffer   *   * PARAMETERS:  Level               - Current source code indentation level @@ -596,9 +699,12 @@ AcpiDmIsPldBuffer (   *   ******************************************************************************/ -#define ACPI_PLD_OUTPUT08     "%*.s/* %18s : %-6.2X */\n", ACPI_MUL_4 (Level), " " -#define ACPI_PLD_OUTPUT16   "%*.s/* %18s : %-6.4X */\n", ACPI_MUL_4 (Level), " " -#define ACPI_PLD_OUTPUT24   "%*.s/* %18s : %-6.6X */\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUT08   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUT08P  "%*.s%-18s = 0x%X)\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUT16   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUT16P  "%*.s%-18s = 0x%X)\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUT24   "%*.s%-18s = 0x%X,\n", ACPI_MUL_4 (Level), " " +#define ACPI_PLD_OUTPUTSTR  "%*.s%-18s = \"%s\",\n", ACPI_MUL_4 (Level), " "  static void  AcpiDmPldBuffer ( @@ -625,47 +731,63 @@ AcpiDmPldBuffer (          return;      } +    AcpiOsPrintf ("\n"); +      /* First 32-bit dword */ -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Revision", PldInfo->Revision); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "IgnoreColor", PldInfo->IgnoreColor); -    AcpiOsPrintf (ACPI_PLD_OUTPUT24,"Color", PldInfo->Color); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Revision", PldInfo->Revision); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_IgnoreColor", PldInfo->IgnoreColor); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Red", PldInfo->Red); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Green", PldInfo->Green); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Blue", PldInfo->Blue);      /* Second 32-bit dword */ -    AcpiOsPrintf (ACPI_PLD_OUTPUT16,"Width", PldInfo->Width); -    AcpiOsPrintf (ACPI_PLD_OUTPUT16,"Height", PldInfo->Height); +    AcpiOsPrintf (ACPI_PLD_OUTPUT16,  "PLD_Width", PldInfo->Width); +    AcpiOsPrintf (ACPI_PLD_OUTPUT16,  "PLD_Height", PldInfo->Height);      /* Third 32-bit dword */ -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "UserVisible", PldInfo->UserVisible); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Dock", PldInfo->Dock); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Lid", PldInfo->Lid); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Panel", PldInfo->Panel); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "VerticalPosition", PldInfo->VerticalPosition); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "HorizontalPosition", PldInfo->HorizontalPosition); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Shape", PldInfo->Shape); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "GroupOrientation", PldInfo->GroupOrientation); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "GroupToken", PldInfo->GroupToken); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "GroupPosition", PldInfo->GroupPosition); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Bay", PldInfo->Bay); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_UserVisible", PldInfo->UserVisible); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Dock", PldInfo->Dock); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Lid", PldInfo->Lid); +    AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Panel", +        AcpiDmFindNameByIndex(PldInfo->Panel, DmPanelList)); +    AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_VerticalPosition", +        AcpiDmFindNameByIndex(PldInfo->VerticalPosition, DmVerticalPositionList)); +    AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_HorizontalPosition", +        AcpiDmFindNameByIndex(PldInfo->HorizontalPosition, DmHorizontalPositionList)); +    AcpiOsPrintf (ACPI_PLD_OUTPUTSTR, "PLD_Shape", +        AcpiDmFindNameByIndex(PldInfo->Shape, DmShapeList)); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupOrientation", PldInfo->GroupOrientation); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupToken", PldInfo->GroupToken); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_GroupPosition", PldInfo->GroupPosition); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Bay", PldInfo->Bay);      /* Fourth 32-bit dword */ -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Ejectable", PldInfo->Ejectable); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "OspmEjectRequired", PldInfo->OspmEjectRequired); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "CabinetNumber", PldInfo->CabinetNumber); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "CardCageNumber", PldInfo->CardCageNumber); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Reference", PldInfo->Reference); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Rotation", PldInfo->Rotation); -    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "Order", PldInfo->Order); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Ejectable", PldInfo->Ejectable); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_EjectRequired", PldInfo->OspmEjectRequired); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_CabinetNumber", PldInfo->CabinetNumber); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_CardCageNumber", PldInfo->CardCageNumber); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Reference", PldInfo->Reference); +    AcpiOsPrintf (ACPI_PLD_OUTPUT08,  "PLD_Rotation", PldInfo->Rotation); + +    if (ByteCount < ACPI_PLD_REV1_BUFFER_SIZE) +    { +        AcpiOsPrintf (ACPI_PLD_OUTPUT08P, "PLD_Order", PldInfo->Order); +    } +    else +    { +        AcpiOsPrintf (ACPI_PLD_OUTPUT08, "PLD_Order", PldInfo->Order); +    }      /* Fifth 32-bit dword */      if (ByteCount >= ACPI_PLD_REV1_BUFFER_SIZE)      { -        AcpiOsPrintf (ACPI_PLD_OUTPUT16,"VerticalOffset", PldInfo->VerticalOffset); -        AcpiOsPrintf (ACPI_PLD_OUTPUT16,"HorizontalOffset", PldInfo->HorizontalOffset); +        AcpiOsPrintf (ACPI_PLD_OUTPUT16, "PLD_VerticalOffset", PldInfo->VerticalOffset); +        AcpiOsPrintf (ACPI_PLD_OUTPUT16P, "PLD_HorizontalOffset", PldInfo->HorizontalOffset);      }      ACPI_FREE (PldInfo); @@ -692,6 +814,7 @@ AcpiDmUnicode (      UINT16                  *WordData;      UINT32                  WordCount;      UINT32                  i; +    int                     OutputValue;      /* Extract the buffer info as a WORD buffer */ @@ -704,7 +827,23 @@ AcpiDmUnicode (      AcpiOsPrintf ("\"");      for (i = 0; i < (WordCount - 1); i++)      { -        AcpiOsPrintf ("%c", (int) WordData[i]); +        OutputValue = (int) WordData[i]; + +        /* Handle values that must be escaped */ + +        if ((OutputValue == '\"') || +            (OutputValue == '\\')) +        { +            AcpiOsPrintf ("\\%c", OutputValue); +        } +        else if (!ACPI_IS_PRINT (OutputValue)) +        { +            AcpiOsPrintf ("\\x%2.2X", OutputValue); +        } +        else +        { +            AcpiOsPrintf ("%c", OutputValue); +        }      }      AcpiOsPrintf ("\")"); diff --git a/source/components/disassembler/dmcstyle.c b/source/components/disassembler/dmcstyle.c new file mode 100644 index 000000000000..4db1b96cef73 --- /dev/null +++ b/source/components/disassembler/dmcstyle.c @@ -0,0 +1,773 @@ +/******************************************************************************* + * + * Module Name: dmcstyle - Support for C-style operator disassembly + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions, and the following disclaimer, + *    without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + *    substantially similar to the "NO WARRANTY" disclaimer below + *    ("Disclaimer") and any redistribution must be conditioned upon + *    including a substantially similar Disclaimer requirement for further + *    binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + *    of any contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdisasm.h" +#include "acdebug.h" + +#ifdef ACPI_DISASSEMBLER + +#define _COMPONENT          ACPI_CA_DEBUGGER +        ACPI_MODULE_NAME    ("dmcstyle") + + +/* Local prototypes */ + +static char * +AcpiDmGetCompoundSymbol ( +   UINT16                   AslOpcode); + +static void +AcpiDmPromoteTarget ( +    ACPI_PARSE_OBJECT       *Op, +    ACPI_PARSE_OBJECT       *Target); + +static BOOLEAN +AcpiDmIsValidTarget ( +    ACPI_PARSE_OBJECT       *Op); + +static BOOLEAN +AcpiDmIsTargetAnOperand ( +    ACPI_PARSE_OBJECT       *Target, +    ACPI_PARSE_OBJECT       *Operand, +    BOOLEAN                 TopLevel); + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmCheckForSymbolicOpcode + * + * PARAMETERS:  Op                  - Current parse object + *              Walk                - Current parse tree walk info + * + * RETURN:      TRUE if opcode can be converted to symbolic, FALSE otherwise + * + * DESCRIPTION: This is the main code that implements disassembly of AML code + *              to C-style operators. Called during descending phase of the + *              parse tree walk. + * + ******************************************************************************/ + +BOOLEAN +AcpiDmCheckForSymbolicOpcode ( +    ACPI_PARSE_OBJECT       *Op, +    ACPI_OP_WALK_INFO       *Info) +{ +    char                    *OperatorSymbol = NULL; +    ACPI_PARSE_OBJECT       *Child1; +    ACPI_PARSE_OBJECT       *Child2; +    ACPI_PARSE_OBJECT       *Target; + + +    /* Exit immediately if ASL+ not enabled */ + +    if (!AcpiGbl_CstyleDisassembly) +    { +        return (FALSE); +    } + +    /* Get the first operand */ + +    Child1 = AcpiPsGetArg (Op, 0); +    if (!Child1) +    { +        return (FALSE); +    } + +    /* Get the second operand */ + +    Child2 = Child1->Common.Next; + +    /* Setup the operator string for this opcode */ + +    switch (Op->Common.AmlOpcode) +    { +    case AML_ADD_OP: +        OperatorSymbol = " + "; +        break; + +    case AML_SUBTRACT_OP: +        OperatorSymbol = " - "; +        break; + +    case AML_MULTIPLY_OP: +        OperatorSymbol = " * "; +        break; + +    case AML_DIVIDE_OP: +        OperatorSymbol = " / "; +        break; + +    case AML_MOD_OP: +        OperatorSymbol = " % "; +        break; + +    case AML_SHIFT_LEFT_OP: +        OperatorSymbol = " << "; +        break; + +    case AML_SHIFT_RIGHT_OP: +        OperatorSymbol = " >> "; +        break; + +    case AML_BIT_AND_OP: +        OperatorSymbol = " & "; +        break; + +    case AML_BIT_OR_OP: +        OperatorSymbol = " | "; +        break; + +    case AML_BIT_XOR_OP: +        OperatorSymbol = " ^ "; +        break; + +    /* Logical operators, no target */ + +    case AML_LAND_OP: +        OperatorSymbol = " && "; +        break; + +    case AML_LEQUAL_OP: +        OperatorSymbol = " == "; +        break; + +    case AML_LGREATER_OP: +        OperatorSymbol = " > "; +        break; + +    case AML_LLESS_OP: +        OperatorSymbol = " < "; +        break; + +    case AML_LOR_OP: +        OperatorSymbol = " || "; +        break; + +    case AML_LNOT_OP: +        /* +         * Check for the LNOT sub-opcodes. These correspond to +         * LNotEqual, LLessEqual, and LGreaterEqual. There are +         * no actual AML opcodes for these operators. +         */ +        switch (Child1->Common.AmlOpcode) +        { +        case AML_LEQUAL_OP: +            OperatorSymbol = " != "; +            break; + +        case AML_LGREATER_OP: +            OperatorSymbol = " <= "; +            break; + +        case AML_LLESS_OP: +            OperatorSymbol = " >= "; +            break; + +        default: + +            /* Unary LNOT case, emit "!" immediately */ + +            AcpiOsPrintf ("!"); +            return (TRUE); +        } + +        Child1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; +        Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; + +        /* Save symbol string in the next child (not peer) */ + +        Child2 = AcpiPsGetArg (Child1, 0); +        if (!Child2) +        { +            return (FALSE); +        } + +        Child2->Common.OperatorSymbol = OperatorSymbol; +        return (TRUE); + +#ifdef INDEX_SUPPORT +    case AML_INDEX_OP: +        Child1->Common.OperatorSymbol = " ["; +        Child2->Common.OperatorSymbol = "]"; +        break; +#endif + +    /* Unary operators */ + +    case AML_DECREMENT_OP: +        OperatorSymbol = "--"; +        break; + +    case AML_INCREMENT_OP: +        OperatorSymbol = "++"; +        break; + +    case AML_BIT_NOT_OP: +    case AML_STORE_OP: +        OperatorSymbol = NULL; +        break; + +    default: +        return (FALSE); +    } + +    if (Child1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX) +    { +        return (TRUE); +    } + +    /* +     * This is the key to how the disassembly of the C-style operators +     * works. We save the operator symbol in the first child, thus +     * deferring symbol output until after the first operand has been +     * emitted. +     */ +    if (!Child1->Common.OperatorSymbol) +    { +        Child1->Common.OperatorSymbol = OperatorSymbol; +    } + +    /* +     * Check for a valid target as the 3rd (or sometimes 2nd) operand +     * +     * Compound assignment operator support: +     * Attempt to optimize constructs of the form: +     *      Add (Local1, 0xFF, Local1) +     * to: +     *      Local1 += 0xFF +     * +     * Only the math operators and Store() have a target. +     * Logicals have no target. +     */ +    switch (Op->Common.AmlOpcode) +    { +    case AML_ADD_OP: +    case AML_SUBTRACT_OP: +    case AML_MULTIPLY_OP: +    case AML_DIVIDE_OP: +    case AML_MOD_OP: +    case AML_SHIFT_LEFT_OP: +    case AML_SHIFT_RIGHT_OP: +    case AML_BIT_AND_OP: +    case AML_BIT_OR_OP: +    case AML_BIT_XOR_OP: + +        /* Target is 3rd operand */ + +        Target = Child2->Common.Next; +        if (Op->Common.AmlOpcode == AML_DIVIDE_OP) +        { +            /* +             * Divide has an extra target operand (Remainder). +             * If this extra target is specified, it cannot be converted +             * to a C-style operator +             */ +            if (AcpiDmIsValidTarget (Target)) +            { +                Child1->Common.OperatorSymbol = NULL; +                return (FALSE); +            } + +            Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; +            Target = Target->Common.Next; +        } + +        /* Parser should ensure there is at least a placeholder target */ + +        if (!Target) +        { +            return (FALSE); +        } + +        if (!AcpiDmIsValidTarget (Target)) +        { +            /* Not a valid target (placeholder only, from parser) */ +            break; +        } + +        /* +         * Promote the target up to the first child in the parse +         * tree. This is done because the target will be output +         * first, in the form: +         *     <Target> = Operands... +         */ +        AcpiDmPromoteTarget (Op, Target); + +        /* +         * Check for possible conversion to a "Compound Assignment". +         * +         * Determine if either operand is the same as the target +         * and display compound assignment operator and other operand. +         */ +        if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) || +            (AcpiDmIsTargetAnOperand (Target, Child2, TRUE))) +        { +            Target->Common.OperatorSymbol = +                AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); + +            /* Convert operator to compound assignment */ + +            Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND; +            Child1->Common.OperatorSymbol = NULL; +            return (TRUE); +        } + +        /* +         * If we are within a C-style expression, emit an extra open +         * paren. Implemented by examining the parent op. +         */ +        switch (Op->Common.Parent->Common.AmlOpcode) +        { +        case AML_ADD_OP: +        case AML_SUBTRACT_OP: +        case AML_MULTIPLY_OP: +        case AML_DIVIDE_OP: +        case AML_MOD_OP: +        case AML_SHIFT_LEFT_OP: +        case AML_SHIFT_RIGHT_OP: +        case AML_BIT_AND_OP: +        case AML_BIT_OR_OP: +        case AML_BIT_XOR_OP: +        case AML_LAND_OP: +        case AML_LEQUAL_OP: +        case AML_LGREATER_OP: +        case AML_LLESS_OP: +        case AML_LOR_OP: + +            Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT; +            AcpiOsPrintf ("("); +            break; + +        default: +            break; +        } + +        /* Normal output for ASL/AML operators with a target operand */ + +        Target->Common.OperatorSymbol = " = ("; +        return (TRUE); + +    /* Binary operators, no parens */ + +    case AML_DECREMENT_OP: +    case AML_INCREMENT_OP: +        return (TRUE); + +#ifdef INDEX_SUPPORT +    case AML_INDEX_OP: + +        /* Target is optional, 3rd operand */ + +        Target = Child2->Common.Next; +        if (AcpiDmIsValidTarget (Target)) +        { +            AcpiDmPromoteTarget (Op, Target); + +            if (!Target->Common.OperatorSymbol) +            { +                Target->Common.OperatorSymbol = " = "; +            } +        } +        return (TRUE); +#endif + +    case AML_STORE_OP: +        /* +         * Target is the 2nd operand. +         * We know the target is valid, it is not optional. +         * In the parse tree, simply swap the target with the +         * source so that the target is processed first. +         */ +        Target = Child1->Common.Next; +        AcpiDmPromoteTarget (Op, Target); + +        if (!Target->Common.OperatorSymbol) +        { +            Target->Common.OperatorSymbol = " = "; +        } +        return (TRUE); + +    case AML_BIT_NOT_OP: + +        /* Target is optional, 2nd operand */ + +        Target = Child1->Common.Next; +        if (!Target) +        { +            return (FALSE); +        } + +        if (AcpiDmIsValidTarget (Target)) +        { +            /* Valid target, not a placeholder */ + +            AcpiDmPromoteTarget (Op, Target); +            Target->Common.OperatorSymbol = " = ~"; +        } +        else +        { +            /* No target. Emit this prefix operator immediately */ + +            AcpiOsPrintf ("~"); +        } +        return (TRUE); + +    default: +        break; +    } + +    /* All other operators, emit an open paren */ + +    AcpiOsPrintf ("("); +    return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmCloseOperator + * + * PARAMETERS:  Op                  - Current parse object + * + * RETURN:      None + * + * DESCRIPTION: Closes an operator by adding a closing parentheses if and + *              when necessary. Called during ascending phase of the + *              parse tree walk. + * + ******************************************************************************/ + +void +AcpiDmCloseOperator ( +    ACPI_PARSE_OBJECT       *Op) +{ + +    /* Always emit paren if ASL+ disassembly disabled */ + +    if (!AcpiGbl_CstyleDisassembly) +    { +        AcpiOsPrintf (")"); +        return; +    } + +    /* Check if we need to add an additional closing paren */ + +    switch (Op->Common.AmlOpcode) +    { +    case AML_ADD_OP: +    case AML_SUBTRACT_OP: +    case AML_MULTIPLY_OP: +    case AML_DIVIDE_OP: +    case AML_MOD_OP: +    case AML_SHIFT_LEFT_OP: +    case AML_SHIFT_RIGHT_OP: +    case AML_BIT_AND_OP: +    case AML_BIT_OR_OP: +    case AML_BIT_XOR_OP: +    case AML_LAND_OP: +    case AML_LEQUAL_OP: +    case AML_LGREATER_OP: +    case AML_LLESS_OP: +    case AML_LOR_OP: + +        /* Emit paren only if this is not a compound assignment */ + +        if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND) +        { +            return; +        } + +        /* Emit extra close paren for assignment within an expression */ + +        if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT) +        { +            AcpiOsPrintf (")"); +        } +        break; + + +    /* No need for parens for these */ + +#ifdef INDEX_SUPPORT +    case AML_INDEX_OP: +#endif +    case AML_DECREMENT_OP: +    case AML_INCREMENT_OP: +    case AML_LNOT_OP: +    case AML_BIT_NOT_OP: +    case AML_STORE_OP: +        return; + +    default: + +        /* Always emit paren for non-ASL+ operators */ +        break; +    } + +    AcpiOsPrintf (")"); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmGetCompoundSymbol + * + * PARAMETERS:  AslOpcode + * + * RETURN:      String containing the compound assignment symbol + * + * DESCRIPTION: Detect opcodes that can be converted to compound assignment, + *              return the appropriate operator string. + * + ******************************************************************************/ + +static char * +AcpiDmGetCompoundSymbol ( +   UINT16                   AmlOpcode) +{ +    char                    *Symbol; + + +    switch (AmlOpcode) +    { +    case AML_ADD_OP: +        Symbol = " += "; +        break; + +    case AML_SUBTRACT_OP: +        Symbol = " -= "; +        break; + +    case AML_MULTIPLY_OP: +        Symbol = " *= "; +        break; + +    case AML_DIVIDE_OP: +        Symbol = " /= "; +        break; + +    case AML_MOD_OP: +        Symbol = " %= "; +        break; + +    case AML_SHIFT_LEFT_OP: +        Symbol = " <<= "; +        break; + +    case AML_SHIFT_RIGHT_OP: +        Symbol = " >>= "; +        break; + +    case AML_BIT_AND_OP: +        Symbol = " &= "; +        break; + +    case AML_BIT_OR_OP: +        Symbol = " |= "; +        break; + +    case AML_BIT_XOR_OP: +        Symbol = " ^= "; +        break; + +    default: + +        /* No operator string for all other opcodes */ +        return (NULL); +    } + +    return (Symbol); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmPromoteTarget + * + * PARAMETERS:  Op                  - Operator parse object + *              Target              - Target associate with the Op + * + * RETURN:      None + * + * DESCRIPTION: Transform the parse tree by moving the target up to the first + *              child of the Op. + * + ******************************************************************************/ + +static void +AcpiDmPromoteTarget ( +    ACPI_PARSE_OBJECT       *Op, +    ACPI_PARSE_OBJECT       *Target) +{ +    ACPI_PARSE_OBJECT       *Child; + + +    /* Link target directly to the Op as first child */ + +    Child = Op->Common.Value.Arg; +    Op->Common.Value.Arg = Target; +    Target->Common.Next = Child; + +    /* Find the last peer, it is linked to the target. Unlink it. */ + +    while (Child->Common.Next != Target) +    { +        Child = Child->Common.Next; +    } + +    Child->Common.Next = NULL; +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmIsValidTarget + * + * PARAMETERS:  Target              - Target Op from the parse tree + * + * RETURN:      TRUE if the Target is real. FALSE if it is just a placeholder + *              Op that was inserted by the parser. + * + * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target. + *              In other words, determine if the optional target is used or + *              not. + * + ******************************************************************************/ + +static BOOLEAN +AcpiDmIsValidTarget ( +    ACPI_PARSE_OBJECT       *Target) +{ + +    if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && +        (Target->Common.Value.Arg == NULL)) +    { +        return (FALSE); +    } + +    return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION:    AcpiDmIsTargetAnOperand + * + * PARAMETERS:  Target              - Target associated with the expression + *              Operand             - An operand associated with expression + * + * RETURN:      TRUE if expression can be converted to a compound assignment. + *              FALSE otherwise. + * + * DESCRIPTION: Determine if the Target duplicates the operand, in order to + *              detect if the expression can be converted to a compound + *              assigment. (+=, *=, etc.) + * + ******************************************************************************/ + +static BOOLEAN +AcpiDmIsTargetAnOperand ( +    ACPI_PARSE_OBJECT       *Target, +    ACPI_PARSE_OBJECT       *Operand, +    BOOLEAN                 TopLevel) +{ +    const ACPI_OPCODE_INFO  *OpInfo; +    BOOLEAN                 Same; + + +    /* +     * Opcodes must match. Note: ignoring the difference between nameseg +     * and namepath for now. May be needed later. +     */ +    if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode) +    { +        return (FALSE); +    } + +    /* Nodes should match, even if they are NULL */ + +    if (Target->Common.Node != Operand->Common.Node) +    { +        return (FALSE); +    } + +    /* Determine if a child exists */ + +    OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode); +    if (OpInfo->Flags & AML_HAS_ARGS) +    { +        Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg, +            Operand->Common.Value.Arg, FALSE); +        if (!Same) +        { +            return (FALSE); +        } +    } + +    /* Check the next peer, as long as we are not at the top level */ + +    if ((!TopLevel) && +         Target->Common.Next) +    { +        Same = AcpiDmIsTargetAnOperand (Target->Common.Next, +            Operand->Common.Next, FALSE); +        if (!Same) +        { +            return (FALSE); +        } +    } + +    /* Supress the duplicate operand at the top-level */ + +    if (TopLevel) +    { +        Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; +    } +    return (TRUE); +} + +#endif diff --git a/source/components/disassembler/dmopcode.c b/source/components/disassembler/dmopcode.c index e3d9e6918e4c..e356e389927e 100644 --- a/source/components/disassembler/dmopcode.c +++ b/source/components/disassembler/dmopcode.c @@ -54,6 +54,7 @@  #define _COMPONENT          ACPI_CA_DEBUGGER          ACPI_MODULE_NAME    ("dmopcode") +  /* Local prototypes */  static void @@ -567,7 +568,6 @@ AcpiDmRegionFlags (      ACPI_PARSE_OBJECT       *Op)  { -      /* The next Op contains the SpaceId */      Op = AcpiPsGetDepthNext (NULL, Op); @@ -637,7 +637,6 @@ AcpiDmMatchKeyword (      ACPI_PARSE_OBJECT       *Op)  { -      if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)      {          AcpiOsPrintf ("/* Unknown Match Keyword encoding */"); @@ -694,27 +693,27 @@ AcpiDmDisassembleOneOp (      case ACPI_DASM_LNOT_SUFFIX: -        switch (Op->Common.AmlOpcode) +        if (!AcpiGbl_CstyleDisassembly)          { -        case AML_LEQUAL_OP: - -            AcpiOsPrintf ("LNotEqual"); -            break; - -        case AML_LGREATER_OP: - -            AcpiOsPrintf ("LLessEqual"); -            break; - -        case AML_LLESS_OP: +            switch (Op->Common.AmlOpcode) +            { +            case AML_LEQUAL_OP: +                AcpiOsPrintf ("LNotEqual"); +                break; -            AcpiOsPrintf ("LGreaterEqual"); -            break; +            case AML_LGREATER_OP: +                AcpiOsPrintf ("LLessEqual"); +                break; -        default: +            case AML_LLESS_OP: +                AcpiOsPrintf ("LGreaterEqual"); +                break; -            break; +            default: +                break; +            }          } +          Op->Common.DisasmOpcode = 0;          Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;          return; @@ -723,7 +722,6 @@ AcpiDmDisassembleOneOp (          break;      } -      OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);      /* The op and arguments */ @@ -845,7 +843,7 @@ AcpiDmDisassembleOneOp (          else if (AcpiDmIsPldBuffer (Op))          {              Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD; -            AcpiOsPrintf ("Buffer"); +            AcpiOsPrintf ("ToPLD (");          }          else          { diff --git a/source/components/disassembler/dmutils.c b/source/components/disassembler/dmutils.c index 700cfecc3092..c075b6904100 100644 --- a/source/components/disassembler/dmutils.c +++ b/source/components/disassembler/dmutils.c @@ -256,6 +256,13 @@ AcpiDmCommaIfListMember (      if (AcpiDmListType (Op->Common.Parent) & BLOCK_COMMA_LIST)      { +        /* Exit if Target has been marked IGNORE */ + +        if (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) +        { +            return (FALSE); +        } +          /* Check for a NULL target operand */          if ((Op->Common.Next->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && @@ -279,7 +286,13 @@ AcpiDmCommaIfListMember (              return (FALSE);          } -        AcpiOsPrintf (", "); +        /* Emit comma only if this is not a C-style operator */ + +        if (!Op->Common.OperatorSymbol) +        { +            AcpiOsPrintf (", "); +        } +          return (TRUE);      } diff --git a/source/components/disassembler/dmwalk.c b/source/components/disassembler/dmwalk.c index 92f27e506224..823ce1856b12 100644 --- a/source/components/disassembler/dmwalk.c +++ b/source/components/disassembler/dmwalk.c @@ -285,7 +285,8 @@ AcpiDmBlockType (      case AML_BUFFER_OP:          if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) || -            (Op->Common.DisasmOpcode == ACPI_DASM_UUID)) +            (Op->Common.DisasmOpcode == ACPI_DASM_UUID) || +            (Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))          {              return (BLOCK_NONE);          } @@ -301,6 +302,17 @@ AcpiDmBlockType (          return (BLOCK_PAREN); +    case AML_INT_METHODCALL_OP: + +        if (Op->Common.Parent && +            ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || +             (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) +        { +            /* This is a reference to a method, not an invocation */ + +            return (BLOCK_NONE); +        } +      default:          OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); @@ -477,13 +489,20 @@ AcpiDmDescendingOp (       * keep track of the current column.       */      Info->Count++; -    if (Info->Count /* +Info->LastLevel */ > 10) +    if (Info->Count /* +Info->LastLevel */ > 12)      {          Info->Count = 0;          AcpiOsPrintf ("\n");          AcpiDmIndent (Info->LastLevel + 1);      } +    /* If ASL+ is enabled, check for a C-style operator */ + +    if (AcpiDmCheckForSymbolicOpcode (Op, Info)) +    { +        return (AE_OK); +    } +      /* Print the opcode name */      AcpiDmDisassembleOneOp (NULL, Info, Op); @@ -563,7 +582,6 @@ AcpiDmDescendingOp (                  AcpiDmPredefinedDescription (Op);                  break; -              case AML_NAME_OP:                  /* Check for _HID and related EISAID() */ @@ -572,13 +590,11 @@ AcpiDmDescendingOp (                  AcpiOsPrintf (", ");                  break; -              case AML_REGION_OP:                  AcpiDmRegionFlags (Op);                  break; -              case AML_POWER_RES_OP:                  /* Mark the next two Ops as part of the parameter list */ @@ -591,7 +607,6 @@ AcpiDmDescendingOp (                  NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;                  return (AE_OK); -              case AML_PROCESSOR_OP:                  /* Mark the next three Ops as part of the parameter list */ @@ -607,20 +622,17 @@ AcpiDmDescendingOp (                  NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;                  return (AE_OK); -              case AML_MUTEX_OP:              case AML_DATA_REGION_OP:                  AcpiOsPrintf (", ");                  return (AE_OK); -              case AML_EVENT_OP:              case AML_ALIAS_OP:                  return (AE_OK); -              case AML_SCOPE_OP:              case AML_DEVICE_OP:              case AML_THERMAL_ZONE_OP: @@ -628,7 +640,6 @@ AcpiDmDescendingOp (                  AcpiOsPrintf (")");                  break; -              default:                  AcpiOsPrintf ("*** Unhandled named opcode %X\n", @@ -825,9 +836,9 @@ AcpiDmAscendingOp (      {      case BLOCK_PAREN: -        /* Completed an op that has arguments, add closing paren */ +        /* Completed an op that has arguments, add closing paren if needed */ -        AcpiOsPrintf (")"); +        AcpiDmCloseOperator (Op);          if (Op->Common.AmlOpcode == AML_NAME_OP)          { @@ -999,8 +1010,21 @@ AcpiDmAscendingOp (      {          Info->Level++;      } + +    /* +     * For ASL+, check for and emit a C-style symbol. If valid, the +     * symbol string has been deferred until after the first operand +     */ +    if (AcpiGbl_CstyleDisassembly) +    { +        if (Op->Asl.OperatorSymbol) +        { +            AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol); +            Op->Asl.OperatorSymbol = NULL; +        } +    } +      return (AE_OK);  } -  #endif  /* ACPI_DISASSEMBLER */ | 
