1274357Sjkim/******************************************************************************* 2274357Sjkim * 3274357Sjkim * Module Name: dmcstyle - Support for C-style operator disassembly 4274357Sjkim * 5274357Sjkim ******************************************************************************/ 6274357Sjkim 7316303Sjkim/****************************************************************************** 8316303Sjkim * 9316303Sjkim * 1. Copyright Notice 10316303Sjkim * 11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12274357Sjkim * All rights reserved. 13274357Sjkim * 14316303Sjkim * 2. License 15316303Sjkim * 16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property 17316303Sjkim * rights. You may have additional license terms from the party that provided 18316303Sjkim * you this software, covering your right to use that party's intellectual 19316303Sjkim * property rights. 20316303Sjkim * 21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an 23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy, 25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered 26316303Sjkim * Code in any form, with the right to sublicense such rights; and 27316303Sjkim * 28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29316303Sjkim * license (with the right to sublicense), under only those claims of Intel 30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell, 31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof 32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright 33316303Sjkim * license, and in no event shall the patent license extend to any additions 34316303Sjkim * to or modifications of the Original Intel Code. No other license or right 35316303Sjkim * is granted directly or by implication, estoppel or otherwise; 36316303Sjkim * 37316303Sjkim * The above copyright and patent license is granted only if the following 38316303Sjkim * conditions are met: 39316303Sjkim * 40316303Sjkim * 3. Conditions 41316303Sjkim * 42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43316303Sjkim * Redistribution of source code of any substantial portion of the Covered 44316303Sjkim * Code or modification with rights to further distribute source must include 45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions, 46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition, 47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to 48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered 49316303Sjkim * Code and the date of any change. Licensee must include in that file the 50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee 51316303Sjkim * must include a prominent statement that the modification is derived, 52316303Sjkim * directly or indirectly, from Original Intel Code. 53316303Sjkim * 54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55316303Sjkim * Redistribution of source code of any substantial portion of the Covered 56316303Sjkim * Code or modification without rights to further distribute source must 57316303Sjkim * include the following Disclaimer and Export Compliance provision in the 58316303Sjkim * documentation and/or other materials provided with distribution. In 59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any 60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the 61316303Sjkim * license from Licensee to its licensee is limited to the intellectual 62316303Sjkim * property embodied in the software Licensee provides to its licensee, and 63316303Sjkim * not to intellectual property embodied in modifications its licensee may 64316303Sjkim * make. 65316303Sjkim * 66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any 67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the 68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance 69316303Sjkim * provision in the documentation and/or other materials provided with the 70316303Sjkim * distribution. 71316303Sjkim * 72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original 73316303Sjkim * Intel Code. 74316303Sjkim * 75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or 77316303Sjkim * other dealings in products derived from or relating to the Covered Code 78316303Sjkim * without prior written authorization from Intel. 79316303Sjkim * 80316303Sjkim * 4. Disclaimer and Export Compliance 81316303Sjkim * 82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88316303Sjkim * PARTICULAR PURPOSE. 89316303Sjkim * 90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97316303Sjkim * LIMITED REMEDY. 98316303Sjkim * 99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this 100316303Sjkim * software or system incorporating such software without first obtaining any 101316303Sjkim * required license or other approval from the U. S. Department of Commerce or 102316303Sjkim * any other agency or department of the United States Government. In the 103316303Sjkim * event Licensee exports any such software from the United States or 104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall 105316303Sjkim * ensure that the distribution and export/re-export of the software is in 106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the 107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process, 109316303Sjkim * software, or service, directly or indirectly, to any country for which the 110316303Sjkim * United States government or any agency thereof requires an export license, 111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining 112316303Sjkim * such license, approval or letter. 113316303Sjkim * 114316303Sjkim ***************************************************************************** 115316303Sjkim * 116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 117316303Sjkim * following license: 118316303Sjkim * 119274357Sjkim * Redistribution and use in source and binary forms, with or without 120274357Sjkim * modification, are permitted provided that the following conditions 121274357Sjkim * are met: 122274357Sjkim * 1. Redistributions of source code must retain the above copyright 123274357Sjkim * notice, this list of conditions, and the following disclaimer, 124274357Sjkim * without modification. 125274357Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126274357Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 127274357Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 128274357Sjkim * including a substantially similar Disclaimer requirement for further 129274357Sjkim * binary redistribution. 130274357Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 131274357Sjkim * of any contributors may be used to endorse or promote products derived 132274357Sjkim * from this software without specific prior written permission. 133274357Sjkim * 134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145316303Sjkim * 146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 147274357Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 148274357Sjkim * Software Foundation. 149274357Sjkim * 150316303Sjkim *****************************************************************************/ 151274357Sjkim 152278970Sjkim#include <contrib/dev/acpica/include/acpi.h> 153278970Sjkim#include <contrib/dev/acpica/include/accommon.h> 154278970Sjkim#include <contrib/dev/acpica/include/acparser.h> 155278970Sjkim#include <contrib/dev/acpica/include/amlcode.h> 156278970Sjkim#include <contrib/dev/acpica/include/acdebug.h> 157316303Sjkim#include <contrib/dev/acpica/include/acconvert.h> 158274357Sjkim 159274357Sjkim 160274357Sjkim#define _COMPONENT ACPI_CA_DEBUGGER 161274357Sjkim ACPI_MODULE_NAME ("dmcstyle") 162274357Sjkim 163274357Sjkim 164274357Sjkim/* Local prototypes */ 165274357Sjkim 166274357Sjkimstatic char * 167274357SjkimAcpiDmGetCompoundSymbol ( 168274357Sjkim UINT16 AslOpcode); 169274357Sjkim 170274357Sjkimstatic void 171274357SjkimAcpiDmPromoteTarget ( 172274357Sjkim ACPI_PARSE_OBJECT *Op, 173274357Sjkim ACPI_PARSE_OBJECT *Target); 174274357Sjkim 175274357Sjkimstatic BOOLEAN 176274357SjkimAcpiDmIsValidTarget ( 177274357Sjkim ACPI_PARSE_OBJECT *Op); 178274357Sjkim 179274357Sjkimstatic BOOLEAN 180274357SjkimAcpiDmIsTargetAnOperand ( 181274357Sjkim ACPI_PARSE_OBJECT *Target, 182274357Sjkim ACPI_PARSE_OBJECT *Operand, 183274357Sjkim BOOLEAN TopLevel); 184274357Sjkim 185316303Sjkimstatic BOOLEAN 186316303SjkimAcpiDmIsOptimizationIgnored ( 187316303Sjkim ACPI_PARSE_OBJECT *StoreOp, 188316303Sjkim ACPI_PARSE_OBJECT *StoreArgument); 189274357Sjkim 190316303Sjkim 191274357Sjkim/******************************************************************************* 192274357Sjkim * 193274357Sjkim * FUNCTION: AcpiDmCheckForSymbolicOpcode 194274357Sjkim * 195274357Sjkim * PARAMETERS: Op - Current parse object 196274357Sjkim * Walk - Current parse tree walk info 197274357Sjkim * 198274357Sjkim * RETURN: TRUE if opcode can be converted to symbolic, FALSE otherwise 199274357Sjkim * 200274357Sjkim * DESCRIPTION: This is the main code that implements disassembly of AML code 201274357Sjkim * to C-style operators. Called during descending phase of the 202274357Sjkim * parse tree walk. 203274357Sjkim * 204274357Sjkim ******************************************************************************/ 205274357Sjkim 206274357SjkimBOOLEAN 207274357SjkimAcpiDmCheckForSymbolicOpcode ( 208274357Sjkim ACPI_PARSE_OBJECT *Op, 209274357Sjkim ACPI_OP_WALK_INFO *Info) 210274357Sjkim{ 211274357Sjkim char *OperatorSymbol = NULL; 212316303Sjkim ACPI_PARSE_OBJECT *Argument1; 213316303Sjkim ACPI_PARSE_OBJECT *Argument2; 214274357Sjkim ACPI_PARSE_OBJECT *Target; 215316303Sjkim ACPI_PARSE_OBJECT *Target2; 216274357Sjkim 217274357Sjkim 218274357Sjkim /* Exit immediately if ASL+ not enabled */ 219274357Sjkim 220274357Sjkim if (!AcpiGbl_CstyleDisassembly) 221274357Sjkim { 222274357Sjkim return (FALSE); 223274357Sjkim } 224274357Sjkim 225274357Sjkim /* Get the first operand */ 226274357Sjkim 227316303Sjkim Argument1 = AcpiPsGetArg (Op, 0); 228316303Sjkim if (!Argument1) 229274357Sjkim { 230274357Sjkim return (FALSE); 231274357Sjkim } 232274357Sjkim 233274357Sjkim /* Get the second operand */ 234274357Sjkim 235316303Sjkim Argument2 = Argument1->Common.Next; 236274357Sjkim 237274357Sjkim /* Setup the operator string for this opcode */ 238274357Sjkim 239274357Sjkim switch (Op->Common.AmlOpcode) 240274357Sjkim { 241274357Sjkim case AML_ADD_OP: 242274357Sjkim OperatorSymbol = " + "; 243274357Sjkim break; 244274357Sjkim 245274357Sjkim case AML_SUBTRACT_OP: 246274357Sjkim OperatorSymbol = " - "; 247274357Sjkim break; 248274357Sjkim 249274357Sjkim case AML_MULTIPLY_OP: 250274357Sjkim OperatorSymbol = " * "; 251274357Sjkim break; 252274357Sjkim 253274357Sjkim case AML_DIVIDE_OP: 254274357Sjkim OperatorSymbol = " / "; 255274357Sjkim break; 256274357Sjkim 257274357Sjkim case AML_MOD_OP: 258274357Sjkim OperatorSymbol = " % "; 259274357Sjkim break; 260274357Sjkim 261274357Sjkim case AML_SHIFT_LEFT_OP: 262274357Sjkim OperatorSymbol = " << "; 263274357Sjkim break; 264274357Sjkim 265274357Sjkim case AML_SHIFT_RIGHT_OP: 266274357Sjkim OperatorSymbol = " >> "; 267274357Sjkim break; 268274357Sjkim 269274357Sjkim case AML_BIT_AND_OP: 270274357Sjkim OperatorSymbol = " & "; 271274357Sjkim break; 272274357Sjkim 273274357Sjkim case AML_BIT_OR_OP: 274274357Sjkim OperatorSymbol = " | "; 275274357Sjkim break; 276274357Sjkim 277274357Sjkim case AML_BIT_XOR_OP: 278274357Sjkim OperatorSymbol = " ^ "; 279274357Sjkim break; 280274357Sjkim 281274357Sjkim /* Logical operators, no target */ 282274357Sjkim 283316303Sjkim case AML_LOGICAL_AND_OP: 284274357Sjkim OperatorSymbol = " && "; 285274357Sjkim break; 286274357Sjkim 287316303Sjkim case AML_LOGICAL_EQUAL_OP: 288274357Sjkim OperatorSymbol = " == "; 289274357Sjkim break; 290274357Sjkim 291316303Sjkim case AML_LOGICAL_GREATER_OP: 292274357Sjkim OperatorSymbol = " > "; 293274357Sjkim break; 294274357Sjkim 295316303Sjkim case AML_LOGICAL_LESS_OP: 296274357Sjkim OperatorSymbol = " < "; 297274357Sjkim break; 298274357Sjkim 299316303Sjkim case AML_LOGICAL_OR_OP: 300274357Sjkim OperatorSymbol = " || "; 301274357Sjkim break; 302274357Sjkim 303316303Sjkim case AML_LOGICAL_NOT_OP: 304274357Sjkim /* 305274357Sjkim * Check for the LNOT sub-opcodes. These correspond to 306274357Sjkim * LNotEqual, LLessEqual, and LGreaterEqual. There are 307274357Sjkim * no actual AML opcodes for these operators. 308274357Sjkim */ 309316303Sjkim switch (Argument1->Common.AmlOpcode) 310274357Sjkim { 311316303Sjkim case AML_LOGICAL_EQUAL_OP: 312274357Sjkim OperatorSymbol = " != "; 313274357Sjkim break; 314274357Sjkim 315316303Sjkim case AML_LOGICAL_GREATER_OP: 316274357Sjkim OperatorSymbol = " <= "; 317274357Sjkim break; 318274357Sjkim 319316303Sjkim case AML_LOGICAL_LESS_OP: 320274357Sjkim OperatorSymbol = " >= "; 321274357Sjkim break; 322274357Sjkim 323274357Sjkim default: 324274357Sjkim 325274357Sjkim /* Unary LNOT case, emit "!" immediately */ 326274357Sjkim 327274357Sjkim AcpiOsPrintf ("!"); 328274357Sjkim return (TRUE); 329274357Sjkim } 330274357Sjkim 331316303Sjkim Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; 332274357Sjkim Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 333274357Sjkim 334274357Sjkim /* Save symbol string in the next child (not peer) */ 335274357Sjkim 336316303Sjkim Argument2 = AcpiPsGetArg (Argument1, 0); 337316303Sjkim if (!Argument2) 338274357Sjkim { 339274357Sjkim return (FALSE); 340274357Sjkim } 341274357Sjkim 342316303Sjkim Argument2->Common.OperatorSymbol = OperatorSymbol; 343274357Sjkim return (TRUE); 344274357Sjkim 345274357Sjkim case AML_INDEX_OP: 346298714Sjkim /* 347298714Sjkim * Check for constant source operand. Note: although technically 348298714Sjkim * legal syntax, the iASL compiler does not support this with 349298714Sjkim * the symbolic operators for Index(). It doesn't make sense to 350298714Sjkim * use Index() with a constant anyway. 351298714Sjkim */ 352316303Sjkim if ((Argument1->Common.AmlOpcode == AML_STRING_OP) || 353316303Sjkim (Argument1->Common.AmlOpcode == AML_BUFFER_OP) || 354316303Sjkim (Argument1->Common.AmlOpcode == AML_PACKAGE_OP) || 355316303Sjkim (Argument1->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) 356298714Sjkim { 357298714Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN; 358298714Sjkim return (FALSE); 359298714Sjkim } 360298714Sjkim 361298714Sjkim /* Index operator is [] */ 362298714Sjkim 363316303Sjkim Argument1->Common.OperatorSymbol = " ["; 364316303Sjkim Argument2->Common.OperatorSymbol = "]"; 365274357Sjkim break; 366274357Sjkim 367274357Sjkim /* Unary operators */ 368274357Sjkim 369274357Sjkim case AML_DECREMENT_OP: 370274357Sjkim OperatorSymbol = "--"; 371274357Sjkim break; 372274357Sjkim 373274357Sjkim case AML_INCREMENT_OP: 374274357Sjkim OperatorSymbol = "++"; 375274357Sjkim break; 376274357Sjkim 377274357Sjkim case AML_BIT_NOT_OP: 378274357Sjkim case AML_STORE_OP: 379274357Sjkim OperatorSymbol = NULL; 380274357Sjkim break; 381274357Sjkim 382274357Sjkim default: 383274357Sjkim return (FALSE); 384274357Sjkim } 385274357Sjkim 386316303Sjkim if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX) 387274357Sjkim { 388274357Sjkim return (TRUE); 389274357Sjkim } 390274357Sjkim 391274357Sjkim /* 392274357Sjkim * This is the key to how the disassembly of the C-style operators 393274357Sjkim * works. We save the operator symbol in the first child, thus 394274357Sjkim * deferring symbol output until after the first operand has been 395274357Sjkim * emitted. 396274357Sjkim */ 397316303Sjkim if (!Argument1->Common.OperatorSymbol) 398274357Sjkim { 399316303Sjkim Argument1->Common.OperatorSymbol = OperatorSymbol; 400274357Sjkim } 401274357Sjkim 402274357Sjkim /* 403274357Sjkim * Check for a valid target as the 3rd (or sometimes 2nd) operand 404274357Sjkim * 405274357Sjkim * Compound assignment operator support: 406274357Sjkim * Attempt to optimize constructs of the form: 407274357Sjkim * Add (Local1, 0xFF, Local1) 408274357Sjkim * to: 409274357Sjkim * Local1 += 0xFF 410274357Sjkim * 411274357Sjkim * Only the math operators and Store() have a target. 412274357Sjkim * Logicals have no target. 413274357Sjkim */ 414274357Sjkim switch (Op->Common.AmlOpcode) 415274357Sjkim { 416274357Sjkim case AML_ADD_OP: 417274357Sjkim case AML_SUBTRACT_OP: 418274357Sjkim case AML_MULTIPLY_OP: 419274357Sjkim case AML_DIVIDE_OP: 420274357Sjkim case AML_MOD_OP: 421274357Sjkim case AML_SHIFT_LEFT_OP: 422274357Sjkim case AML_SHIFT_RIGHT_OP: 423274357Sjkim case AML_BIT_AND_OP: 424274357Sjkim case AML_BIT_OR_OP: 425274357Sjkim case AML_BIT_XOR_OP: 426274357Sjkim 427274357Sjkim /* Target is 3rd operand */ 428274357Sjkim 429316303Sjkim Target = Argument2->Common.Next; 430274357Sjkim if (Op->Common.AmlOpcode == AML_DIVIDE_OP) 431274357Sjkim { 432316303Sjkim Target2 = Target->Common.Next; 433316303Sjkim 434274357Sjkim /* 435274357Sjkim * Divide has an extra target operand (Remainder). 436316303Sjkim * Default behavior is to simply ignore ASL+ conversion 437316303Sjkim * if the remainder target (modulo) is specified. 438274357Sjkim */ 439316303Sjkim if (!AcpiGbl_DoDisassemblerOptimizations) 440274357Sjkim { 441316303Sjkim if (AcpiDmIsValidTarget (Target)) 442316303Sjkim { 443316303Sjkim Argument1->Common.OperatorSymbol = NULL; 444316303Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; 445316303Sjkim return (FALSE); 446316303Sjkim } 447316303Sjkim 448316303Sjkim Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 449316303Sjkim Target = Target2; 450274357Sjkim } 451316303Sjkim else 452316303Sjkim { 453316303Sjkim /* 454316303Sjkim * Divide has an extra target operand (Remainder). 455316303Sjkim * If both targets are specified, it cannot be converted 456316303Sjkim * to a C-style operator. 457316303Sjkim */ 458316303Sjkim if (AcpiDmIsValidTarget (Target) && 459316303Sjkim AcpiDmIsValidTarget (Target2)) 460316303Sjkim { 461316303Sjkim Argument1->Common.OperatorSymbol = NULL; 462316303Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; 463316303Sjkim return (FALSE); 464316303Sjkim } 465274357Sjkim 466316303Sjkim if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */ 467316303Sjkim { 468316303Sjkim /* Convert the Divide to Modulo */ 469316303Sjkim 470316303Sjkim Op->Common.AmlOpcode = AML_MOD_OP; 471316303Sjkim 472316303Sjkim Argument1->Common.OperatorSymbol = " % "; 473316303Sjkim Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 474316303Sjkim } 475316303Sjkim else /* Only second Target (quotient) is valid */ 476316303Sjkim { 477316303Sjkim Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 478316303Sjkim Target = Target2; 479316303Sjkim } 480316303Sjkim } 481274357Sjkim } 482274357Sjkim 483274357Sjkim /* Parser should ensure there is at least a placeholder target */ 484274357Sjkim 485274357Sjkim if (!Target) 486274357Sjkim { 487274357Sjkim return (FALSE); 488274357Sjkim } 489274357Sjkim 490274357Sjkim if (!AcpiDmIsValidTarget (Target)) 491274357Sjkim { 492274357Sjkim /* Not a valid target (placeholder only, from parser) */ 493274357Sjkim break; 494274357Sjkim } 495274357Sjkim 496274357Sjkim /* 497274357Sjkim * Promote the target up to the first child in the parse 498274357Sjkim * tree. This is done because the target will be output 499274357Sjkim * first, in the form: 500274357Sjkim * <Target> = Operands... 501274357Sjkim */ 502274357Sjkim AcpiDmPromoteTarget (Op, Target); 503274357Sjkim 504284583Sjkim /* Check operands for conversion to a "Compound Assignment" */ 505284583Sjkim 506284583Sjkim switch (Op->Common.AmlOpcode) 507274357Sjkim { 508284583Sjkim /* Commutative operators */ 509274357Sjkim 510284583Sjkim case AML_ADD_OP: 511284583Sjkim case AML_MULTIPLY_OP: 512284583Sjkim case AML_BIT_AND_OP: 513284583Sjkim case AML_BIT_OR_OP: 514284583Sjkim case AML_BIT_XOR_OP: 515284583Sjkim /* 516284583Sjkim * For the commutative operators, we can convert to a 517284583Sjkim * compound statement only if at least one (either) operand 518284583Sjkim * is the same as the target. 519284583Sjkim * 520284583Sjkim * Add (A, B, A) --> A += B 521284583Sjkim * Add (B, A, A) --> A += B 522284583Sjkim * Add (B, C, A) --> A = (B + C) 523284583Sjkim */ 524316303Sjkim if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) || 525316303Sjkim (AcpiDmIsTargetAnOperand (Target, Argument2, TRUE))) 526284583Sjkim { 527284583Sjkim Target->Common.OperatorSymbol = 528284583Sjkim AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); 529274357Sjkim 530284583Sjkim /* Convert operator to compound assignment */ 531284583Sjkim 532298714Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; 533316303Sjkim Argument1->Common.OperatorSymbol = NULL; 534284583Sjkim return (TRUE); 535284583Sjkim } 536284583Sjkim break; 537284583Sjkim 538284583Sjkim /* Non-commutative operators */ 539284583Sjkim 540284583Sjkim case AML_SUBTRACT_OP: 541284583Sjkim case AML_DIVIDE_OP: 542284583Sjkim case AML_MOD_OP: 543284583Sjkim case AML_SHIFT_LEFT_OP: 544284583Sjkim case AML_SHIFT_RIGHT_OP: 545284583Sjkim /* 546284583Sjkim * For the non-commutative operators, we can convert to a 547284583Sjkim * compound statement only if the target is the same as the 548284583Sjkim * first operand. 549284583Sjkim * 550284583Sjkim * Subtract (A, B, A) --> A -= B 551284583Sjkim * Subtract (B, A, A) --> A = (B - A) 552284583Sjkim */ 553316303Sjkim if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE))) 554284583Sjkim { 555284583Sjkim Target->Common.OperatorSymbol = 556284583Sjkim AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); 557284583Sjkim 558284583Sjkim /* Convert operator to compound assignment */ 559284583Sjkim 560298714Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; 561316303Sjkim Argument1->Common.OperatorSymbol = NULL; 562284583Sjkim return (TRUE); 563284583Sjkim } 564284583Sjkim break; 565284583Sjkim 566284583Sjkim default: 567284583Sjkim break; 568274357Sjkim } 569274357Sjkim 570274357Sjkim /* 571274357Sjkim * If we are within a C-style expression, emit an extra open 572274357Sjkim * paren. Implemented by examining the parent op. 573274357Sjkim */ 574274357Sjkim switch (Op->Common.Parent->Common.AmlOpcode) 575274357Sjkim { 576274357Sjkim case AML_ADD_OP: 577274357Sjkim case AML_SUBTRACT_OP: 578274357Sjkim case AML_MULTIPLY_OP: 579274357Sjkim case AML_DIVIDE_OP: 580274357Sjkim case AML_MOD_OP: 581274357Sjkim case AML_SHIFT_LEFT_OP: 582274357Sjkim case AML_SHIFT_RIGHT_OP: 583274357Sjkim case AML_BIT_AND_OP: 584274357Sjkim case AML_BIT_OR_OP: 585274357Sjkim case AML_BIT_XOR_OP: 586316303Sjkim case AML_LOGICAL_AND_OP: 587316303Sjkim case AML_LOGICAL_EQUAL_OP: 588316303Sjkim case AML_LOGICAL_GREATER_OP: 589316303Sjkim case AML_LOGICAL_LESS_OP: 590316303Sjkim case AML_LOGICAL_OR_OP: 591274357Sjkim 592274357Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT; 593274357Sjkim AcpiOsPrintf ("("); 594274357Sjkim break; 595274357Sjkim 596274357Sjkim default: 597274357Sjkim break; 598274357Sjkim } 599274357Sjkim 600274357Sjkim /* Normal output for ASL/AML operators with a target operand */ 601274357Sjkim 602274357Sjkim Target->Common.OperatorSymbol = " = ("; 603274357Sjkim return (TRUE); 604274357Sjkim 605274357Sjkim /* Binary operators, no parens */ 606274357Sjkim 607274357Sjkim case AML_DECREMENT_OP: 608274357Sjkim case AML_INCREMENT_OP: 609274357Sjkim return (TRUE); 610274357Sjkim 611274357Sjkim case AML_INDEX_OP: 612274357Sjkim 613274357Sjkim /* Target is optional, 3rd operand */ 614274357Sjkim 615316303Sjkim Target = Argument2->Common.Next; 616274357Sjkim if (AcpiDmIsValidTarget (Target)) 617274357Sjkim { 618274357Sjkim AcpiDmPromoteTarget (Op, Target); 619274357Sjkim 620274357Sjkim if (!Target->Common.OperatorSymbol) 621274357Sjkim { 622274357Sjkim Target->Common.OperatorSymbol = " = "; 623274357Sjkim } 624274357Sjkim } 625274357Sjkim return (TRUE); 626274357Sjkim 627274357Sjkim case AML_STORE_OP: 628274357Sjkim /* 629316303Sjkim * For Store, the Target is the 2nd operand. We know the target 630316303Sjkim * is valid, because it is not optional. 631316303Sjkim * 632316303Sjkim * Ignore any optimizations/folding if flag is set. 633316303Sjkim * Used for iASL/disassembler test suite only. 634316303Sjkim */ 635316303Sjkim if (AcpiDmIsOptimizationIgnored (Op, Argument1)) 636316303Sjkim { 637316303Sjkim return (FALSE); 638316303Sjkim } 639316303Sjkim 640316303Sjkim /* 641316303Sjkim * Perform conversion. 642274357Sjkim * In the parse tree, simply swap the target with the 643274357Sjkim * source so that the target is processed first. 644274357Sjkim */ 645316303Sjkim Target = Argument1->Common.Next; 646284583Sjkim if (!Target) 647284583Sjkim { 648284583Sjkim return (FALSE); 649284583Sjkim } 650284583Sjkim 651274357Sjkim AcpiDmPromoteTarget (Op, Target); 652274357Sjkim if (!Target->Common.OperatorSymbol) 653274357Sjkim { 654274357Sjkim Target->Common.OperatorSymbol = " = "; 655274357Sjkim } 656274357Sjkim return (TRUE); 657274357Sjkim 658274357Sjkim case AML_BIT_NOT_OP: 659274357Sjkim 660274357Sjkim /* Target is optional, 2nd operand */ 661274357Sjkim 662316303Sjkim Target = Argument1->Common.Next; 663274357Sjkim if (!Target) 664274357Sjkim { 665274357Sjkim return (FALSE); 666274357Sjkim } 667274357Sjkim 668274357Sjkim if (AcpiDmIsValidTarget (Target)) 669274357Sjkim { 670274357Sjkim /* Valid target, not a placeholder */ 671274357Sjkim 672274357Sjkim AcpiDmPromoteTarget (Op, Target); 673274357Sjkim Target->Common.OperatorSymbol = " = ~"; 674274357Sjkim } 675274357Sjkim else 676274357Sjkim { 677274357Sjkim /* No target. Emit this prefix operator immediately */ 678274357Sjkim 679274357Sjkim AcpiOsPrintf ("~"); 680274357Sjkim } 681274357Sjkim return (TRUE); 682274357Sjkim 683274357Sjkim default: 684274357Sjkim break; 685274357Sjkim } 686274357Sjkim 687316303Sjkim /* All other operators, emit an open paren */ 688316303Sjkim 689316303Sjkim AcpiOsPrintf ("("); 690316303Sjkim return (TRUE); 691316303Sjkim} 692316303Sjkim 693316303Sjkim 694316303Sjkim/******************************************************************************* 695316303Sjkim * 696316303Sjkim * FUNCTION: AcpiDmIsOptimizationIgnored 697316303Sjkim * 698316303Sjkim * PARAMETERS: StoreOp - Store operator parse object 699316303Sjkim * StoreArgument - Target associate with the Op 700316303Sjkim * 701316303Sjkim * RETURN: TRUE if this Store operator should not be converted/removed. 702316303Sjkim * 703316303Sjkim * DESCRIPTION: The following function implements "Do not optimize if a 704316303Sjkim * store is immediately followed by a math/bit operator that 705316303Sjkim * has no target". 706316303Sjkim * 707316303Sjkim * Function is ignored if DoDisassemblerOptimizations is TRUE. 708316303Sjkim * This is the default, ignore this function. 709316303Sjkim * 710316303Sjkim * Disables these types of optimizations, and simply emits 711316303Sjkim * legacy ASL code: 712316303Sjkim * Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2) 713316303Sjkim * --> INT2 = INT1 + 4 714316303Sjkim * 715316303Sjkim * Store (Not (INT1), INT2) --> Not (INT1, INT2) 716316303Sjkim * --> INT2 = ~INT1 717316303Sjkim * 718316303Sjkim * Used only for the ASL test suite. For the test suite, we 719316303Sjkim * don't want to perform some optimizations to ensure binary 720316303Sjkim * compatibility with the generation of the legacy ASL->AML. 721316303Sjkim * In other words, for all test modules we want exactly: 722316303Sjkim * (ASL+ -> AML) == (ASL- -> AML) 723316303Sjkim * 724316303Sjkim ******************************************************************************/ 725316303Sjkim 726316303Sjkimstatic BOOLEAN 727316303SjkimAcpiDmIsOptimizationIgnored ( 728316303Sjkim ACPI_PARSE_OBJECT *StoreOp, 729316303Sjkim ACPI_PARSE_OBJECT *StoreArgument) 730316303Sjkim{ 731316303Sjkim ACPI_PARSE_OBJECT *Argument1; 732316303Sjkim ACPI_PARSE_OBJECT *Argument2; 733316303Sjkim ACPI_PARSE_OBJECT *Target; 734316303Sjkim 735316303Sjkim 736316303Sjkim /* No optimizations/folding for the typical case */ 737316303Sjkim 738316303Sjkim if (AcpiGbl_DoDisassemblerOptimizations) 739316303Sjkim { 740316303Sjkim return (FALSE); 741316303Sjkim } 742316303Sjkim 743298714Sjkim /* 744316303Sjkim * Only a small subset of ASL/AML operators can be optimized. 745316303Sjkim * Can only optimize/fold if there is no target (or targets) 746316303Sjkim * specified for the operator. And of course, the operator 747316303Sjkim * is surrrounded by a Store() operator. 748298714Sjkim */ 749316303Sjkim switch (StoreArgument->Common.AmlOpcode) 750298714Sjkim { 751316303Sjkim case AML_ADD_OP: 752316303Sjkim case AML_SUBTRACT_OP: 753316303Sjkim case AML_MULTIPLY_OP: 754316303Sjkim case AML_MOD_OP: 755316303Sjkim case AML_SHIFT_LEFT_OP: 756316303Sjkim case AML_SHIFT_RIGHT_OP: 757316303Sjkim case AML_BIT_AND_OP: 758316303Sjkim case AML_BIT_OR_OP: 759316303Sjkim case AML_BIT_XOR_OP: 760316303Sjkim case AML_INDEX_OP: 761316303Sjkim 762316303Sjkim /* These operators have two arguments and one target */ 763316303Sjkim 764316303Sjkim Argument1 = StoreArgument->Common.Value.Arg; 765316303Sjkim Argument2 = Argument1->Common.Next; 766316303Sjkim Target = Argument2->Common.Next; 767316303Sjkim 768316303Sjkim if (!AcpiDmIsValidTarget (Target)) 769316303Sjkim { 770316303Sjkim StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; 771316303Sjkim return (TRUE); 772316303Sjkim } 773316303Sjkim break; 774316303Sjkim 775316303Sjkim case AML_DIVIDE_OP: 776316303Sjkim 777316303Sjkim /* This operator has two arguments and two targets */ 778316303Sjkim 779316303Sjkim Argument1 = StoreArgument->Common.Value.Arg; 780316303Sjkim Argument2 = Argument1->Common.Next; 781316303Sjkim Target = Argument2->Common.Next; 782316303Sjkim 783316303Sjkim if (!AcpiDmIsValidTarget (Target) || 784316303Sjkim !AcpiDmIsValidTarget (Target->Common.Next)) 785316303Sjkim { 786316303Sjkim StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; 787316303Sjkim return (TRUE); 788316303Sjkim } 789316303Sjkim break; 790316303Sjkim 791316303Sjkim case AML_BIT_NOT_OP: 792316303Sjkim 793316303Sjkim /* This operator has one operand and one target */ 794316303Sjkim 795316303Sjkim Argument1 = StoreArgument->Common.Value.Arg; 796316303Sjkim Target = Argument1->Common.Next; 797316303Sjkim 798316303Sjkim if (!AcpiDmIsValidTarget (Target)) 799316303Sjkim { 800316303Sjkim StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY; 801316303Sjkim return (TRUE); 802316303Sjkim } 803316303Sjkim break; 804316303Sjkim 805316303Sjkim default: 806316303Sjkim break; 807298714Sjkim } 808298714Sjkim 809316303Sjkim return (FALSE); 810274357Sjkim} 811274357Sjkim 812274357Sjkim 813274357Sjkim/******************************************************************************* 814274357Sjkim * 815274357Sjkim * FUNCTION: AcpiDmCloseOperator 816274357Sjkim * 817274357Sjkim * PARAMETERS: Op - Current parse object 818274357Sjkim * 819274357Sjkim * RETURN: None 820274357Sjkim * 821274357Sjkim * DESCRIPTION: Closes an operator by adding a closing parentheses if and 822274357Sjkim * when necessary. Called during ascending phase of the 823274357Sjkim * parse tree walk. 824274357Sjkim * 825274357Sjkim ******************************************************************************/ 826274357Sjkim 827274357Sjkimvoid 828274357SjkimAcpiDmCloseOperator ( 829274357Sjkim ACPI_PARSE_OBJECT *Op) 830274357Sjkim{ 831274357Sjkim 832274357Sjkim /* Always emit paren if ASL+ disassembly disabled */ 833274357Sjkim 834274357Sjkim if (!AcpiGbl_CstyleDisassembly) 835274357Sjkim { 836274357Sjkim AcpiOsPrintf (")"); 837316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 838274357Sjkim return; 839274357Sjkim } 840274357Sjkim 841316303Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY) 842316303Sjkim { 843316303Sjkim AcpiOsPrintf (")"); 844316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 845316303Sjkim return; 846316303Sjkim } 847316303Sjkim 848274357Sjkim /* Check if we need to add an additional closing paren */ 849274357Sjkim 850274357Sjkim switch (Op->Common.AmlOpcode) 851274357Sjkim { 852274357Sjkim case AML_ADD_OP: 853274357Sjkim case AML_SUBTRACT_OP: 854274357Sjkim case AML_MULTIPLY_OP: 855274357Sjkim case AML_DIVIDE_OP: 856274357Sjkim case AML_MOD_OP: 857274357Sjkim case AML_SHIFT_LEFT_OP: 858274357Sjkim case AML_SHIFT_RIGHT_OP: 859274357Sjkim case AML_BIT_AND_OP: 860274357Sjkim case AML_BIT_OR_OP: 861274357Sjkim case AML_BIT_XOR_OP: 862316303Sjkim case AML_LOGICAL_AND_OP: 863316303Sjkim case AML_LOGICAL_EQUAL_OP: 864316303Sjkim case AML_LOGICAL_GREATER_OP: 865316303Sjkim case AML_LOGICAL_LESS_OP: 866316303Sjkim case AML_LOGICAL_OR_OP: 867274357Sjkim 868274357Sjkim /* Emit paren only if this is not a compound assignment */ 869274357Sjkim 870298714Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND_ASSIGNMENT) 871274357Sjkim { 872316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 873274357Sjkim return; 874274357Sjkim } 875274357Sjkim 876274357Sjkim /* Emit extra close paren for assignment within an expression */ 877274357Sjkim 878274357Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT) 879274357Sjkim { 880274357Sjkim AcpiOsPrintf (")"); 881274357Sjkim } 882274357Sjkim break; 883274357Sjkim 884298714Sjkim case AML_INDEX_OP: 885274357Sjkim 886298714Sjkim /* This is case for unsupported Index() source constants */ 887298714Sjkim 888298714Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN) 889298714Sjkim { 890298714Sjkim AcpiOsPrintf (")"); 891298714Sjkim } 892316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 893298714Sjkim return; 894298714Sjkim 895274357Sjkim /* No need for parens for these */ 896274357Sjkim 897274357Sjkim case AML_DECREMENT_OP: 898274357Sjkim case AML_INCREMENT_OP: 899316303Sjkim case AML_LOGICAL_NOT_OP: 900274357Sjkim case AML_BIT_NOT_OP: 901274357Sjkim case AML_STORE_OP: 902316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 903274357Sjkim return; 904274357Sjkim 905274357Sjkim default: 906274357Sjkim 907274357Sjkim /* Always emit paren for non-ASL+ operators */ 908274357Sjkim break; 909274357Sjkim } 910274357Sjkim 911316303Sjkim AcpiOsPrintf (")"); 912316303Sjkim ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0); 913298714Sjkim 914298714Sjkim return; 915274357Sjkim} 916274357Sjkim 917274357Sjkim 918274357Sjkim/******************************************************************************* 919274357Sjkim * 920274357Sjkim * FUNCTION: AcpiDmGetCompoundSymbol 921274357Sjkim * 922274357Sjkim * PARAMETERS: AslOpcode 923274357Sjkim * 924274357Sjkim * RETURN: String containing the compound assignment symbol 925274357Sjkim * 926274357Sjkim * DESCRIPTION: Detect opcodes that can be converted to compound assignment, 927274357Sjkim * return the appropriate operator string. 928274357Sjkim * 929274357Sjkim ******************************************************************************/ 930274357Sjkim 931274357Sjkimstatic char * 932274357SjkimAcpiDmGetCompoundSymbol ( 933274357Sjkim UINT16 AmlOpcode) 934274357Sjkim{ 935274357Sjkim char *Symbol; 936274357Sjkim 937274357Sjkim 938274357Sjkim switch (AmlOpcode) 939274357Sjkim { 940274357Sjkim case AML_ADD_OP: 941274357Sjkim Symbol = " += "; 942274357Sjkim break; 943274357Sjkim 944274357Sjkim case AML_SUBTRACT_OP: 945274357Sjkim Symbol = " -= "; 946274357Sjkim break; 947274357Sjkim 948274357Sjkim case AML_MULTIPLY_OP: 949274357Sjkim Symbol = " *= "; 950274357Sjkim break; 951274357Sjkim 952274357Sjkim case AML_DIVIDE_OP: 953274357Sjkim Symbol = " /= "; 954274357Sjkim break; 955274357Sjkim 956274357Sjkim case AML_MOD_OP: 957274357Sjkim Symbol = " %= "; 958274357Sjkim break; 959274357Sjkim 960274357Sjkim case AML_SHIFT_LEFT_OP: 961274357Sjkim Symbol = " <<= "; 962274357Sjkim break; 963274357Sjkim 964274357Sjkim case AML_SHIFT_RIGHT_OP: 965274357Sjkim Symbol = " >>= "; 966274357Sjkim break; 967274357Sjkim 968274357Sjkim case AML_BIT_AND_OP: 969274357Sjkim Symbol = " &= "; 970274357Sjkim break; 971274357Sjkim 972274357Sjkim case AML_BIT_OR_OP: 973274357Sjkim Symbol = " |= "; 974274357Sjkim break; 975274357Sjkim 976274357Sjkim case AML_BIT_XOR_OP: 977274357Sjkim Symbol = " ^= "; 978274357Sjkim break; 979274357Sjkim 980274357Sjkim default: 981274357Sjkim 982274357Sjkim /* No operator string for all other opcodes */ 983298714Sjkim 984274357Sjkim return (NULL); 985274357Sjkim } 986274357Sjkim 987274357Sjkim return (Symbol); 988274357Sjkim} 989274357Sjkim 990274357Sjkim 991274357Sjkim/******************************************************************************* 992274357Sjkim * 993274357Sjkim * FUNCTION: AcpiDmPromoteTarget 994274357Sjkim * 995274357Sjkim * PARAMETERS: Op - Operator parse object 996274357Sjkim * Target - Target associate with the Op 997274357Sjkim * 998274357Sjkim * RETURN: None 999274357Sjkim * 1000274357Sjkim * DESCRIPTION: Transform the parse tree by moving the target up to the first 1001274357Sjkim * child of the Op. 1002274357Sjkim * 1003274357Sjkim ******************************************************************************/ 1004274357Sjkim 1005274357Sjkimstatic void 1006274357SjkimAcpiDmPromoteTarget ( 1007274357Sjkim ACPI_PARSE_OBJECT *Op, 1008274357Sjkim ACPI_PARSE_OBJECT *Target) 1009274357Sjkim{ 1010274357Sjkim ACPI_PARSE_OBJECT *Child; 1011274357Sjkim 1012274357Sjkim 1013274357Sjkim /* Link target directly to the Op as first child */ 1014274357Sjkim 1015274357Sjkim Child = Op->Common.Value.Arg; 1016274357Sjkim Op->Common.Value.Arg = Target; 1017274357Sjkim Target->Common.Next = Child; 1018274357Sjkim 1019274357Sjkim /* Find the last peer, it is linked to the target. Unlink it. */ 1020274357Sjkim 1021274357Sjkim while (Child->Common.Next != Target) 1022274357Sjkim { 1023274357Sjkim Child = Child->Common.Next; 1024274357Sjkim } 1025274357Sjkim 1026274357Sjkim Child->Common.Next = NULL; 1027274357Sjkim} 1028274357Sjkim 1029274357Sjkim 1030274357Sjkim/******************************************************************************* 1031274357Sjkim * 1032274357Sjkim * FUNCTION: AcpiDmIsValidTarget 1033274357Sjkim * 1034274357Sjkim * PARAMETERS: Target - Target Op from the parse tree 1035274357Sjkim * 1036274357Sjkim * RETURN: TRUE if the Target is real. FALSE if it is just a placeholder 1037274357Sjkim * Op that was inserted by the parser. 1038274357Sjkim * 1039274357Sjkim * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target. 1040274357Sjkim * In other words, determine if the optional target is used or 1041284583Sjkim * not. Note: If Target is NULL, something is seriously wrong, 1042284583Sjkim * probably with the parse tree. 1043274357Sjkim * 1044274357Sjkim ******************************************************************************/ 1045274357Sjkim 1046274357Sjkimstatic BOOLEAN 1047274357SjkimAcpiDmIsValidTarget ( 1048274357Sjkim ACPI_PARSE_OBJECT *Target) 1049274357Sjkim{ 1050274357Sjkim 1051284583Sjkim if (!Target) 1052284583Sjkim { 1053284583Sjkim return (FALSE); 1054284583Sjkim } 1055284583Sjkim 1056274357Sjkim if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 1057274357Sjkim (Target->Common.Value.Arg == NULL)) 1058274357Sjkim { 1059274357Sjkim return (FALSE); 1060274357Sjkim } 1061274357Sjkim 1062274357Sjkim return (TRUE); 1063274357Sjkim} 1064274357Sjkim 1065274357Sjkim 1066274357Sjkim/******************************************************************************* 1067274357Sjkim * 1068274357Sjkim * FUNCTION: AcpiDmIsTargetAnOperand 1069274357Sjkim * 1070274357Sjkim * PARAMETERS: Target - Target associated with the expression 1071274357Sjkim * Operand - An operand associated with expression 1072274357Sjkim * 1073274357Sjkim * RETURN: TRUE if expression can be converted to a compound assignment. 1074274357Sjkim * FALSE otherwise. 1075274357Sjkim * 1076274357Sjkim * DESCRIPTION: Determine if the Target duplicates the operand, in order to 1077274357Sjkim * detect if the expression can be converted to a compound 1078274357Sjkim * assigment. (+=, *=, etc.) 1079274357Sjkim * 1080274357Sjkim ******************************************************************************/ 1081274357Sjkim 1082274357Sjkimstatic BOOLEAN 1083274357SjkimAcpiDmIsTargetAnOperand ( 1084274357Sjkim ACPI_PARSE_OBJECT *Target, 1085274357Sjkim ACPI_PARSE_OBJECT *Operand, 1086274357Sjkim BOOLEAN TopLevel) 1087274357Sjkim{ 1088274357Sjkim const ACPI_OPCODE_INFO *OpInfo; 1089274357Sjkim BOOLEAN Same; 1090274357Sjkim 1091274357Sjkim 1092274357Sjkim /* 1093274357Sjkim * Opcodes must match. Note: ignoring the difference between nameseg 1094274357Sjkim * and namepath for now. May be needed later. 1095274357Sjkim */ 1096274357Sjkim if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode) 1097274357Sjkim { 1098274357Sjkim return (FALSE); 1099274357Sjkim } 1100274357Sjkim 1101274357Sjkim /* Nodes should match, even if they are NULL */ 1102274357Sjkim 1103274357Sjkim if (Target->Common.Node != Operand->Common.Node) 1104274357Sjkim { 1105274357Sjkim return (FALSE); 1106274357Sjkim } 1107274357Sjkim 1108274357Sjkim /* Determine if a child exists */ 1109274357Sjkim 1110274357Sjkim OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode); 1111274357Sjkim if (OpInfo->Flags & AML_HAS_ARGS) 1112274357Sjkim { 1113274357Sjkim Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg, 1114274357Sjkim Operand->Common.Value.Arg, FALSE); 1115274357Sjkim if (!Same) 1116274357Sjkim { 1117274357Sjkim return (FALSE); 1118274357Sjkim } 1119274357Sjkim } 1120274357Sjkim 1121274357Sjkim /* Check the next peer, as long as we are not at the top level */ 1122274357Sjkim 1123274357Sjkim if ((!TopLevel) && 1124274357Sjkim Target->Common.Next) 1125274357Sjkim { 1126274357Sjkim Same = AcpiDmIsTargetAnOperand (Target->Common.Next, 1127274357Sjkim Operand->Common.Next, FALSE); 1128274357Sjkim if (!Same) 1129274357Sjkim { 1130274357Sjkim return (FALSE); 1131274357Sjkim } 1132274357Sjkim } 1133274357Sjkim 1134274357Sjkim /* Supress the duplicate operand at the top-level */ 1135274357Sjkim 1136274357Sjkim if (TopLevel) 1137274357Sjkim { 1138274357Sjkim Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 1139274357Sjkim } 1140274357Sjkim return (TRUE); 1141274357Sjkim} 1142