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