Path: blob/main/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c
48524 views
/*******************************************************************************1*2* Module Name: dmcstyle - Support for C-style operator disassembly3*4******************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acparser.h>154#include <contrib/dev/acpica/include/amlcode.h>155#include <contrib/dev/acpica/include/acdebug.h>156#include <contrib/dev/acpica/include/acconvert.h>157158159#define _COMPONENT ACPI_CA_DEBUGGER160ACPI_MODULE_NAME ("dmcstyle")161162163/* Local prototypes */164165static char *166AcpiDmGetCompoundSymbol (167UINT16 AslOpcode);168169static void170AcpiDmPromoteTarget (171ACPI_PARSE_OBJECT *Op,172ACPI_PARSE_OBJECT *Target);173174static BOOLEAN175AcpiDmIsValidTarget (176ACPI_PARSE_OBJECT *Op);177178static BOOLEAN179AcpiDmIsTargetAnOperand (180ACPI_PARSE_OBJECT *Target,181ACPI_PARSE_OBJECT *Operand,182BOOLEAN TopLevel);183184static BOOLEAN185AcpiDmIsOptimizationIgnored (186ACPI_PARSE_OBJECT *StoreOp,187ACPI_PARSE_OBJECT *StoreArgument);188189190/*******************************************************************************191*192* FUNCTION: AcpiDmCheckForSymbolicOpcode193*194* PARAMETERS: Op - Current parse object195* Walk - Current parse tree walk info196*197* RETURN: TRUE if opcode can be converted to symbolic, FALSE otherwise198*199* DESCRIPTION: This is the main code that implements disassembly of AML code200* to C-style operators. Called during descending phase of the201* parse tree walk.202*203******************************************************************************/204205BOOLEAN206AcpiDmCheckForSymbolicOpcode (207ACPI_PARSE_OBJECT *Op,208ACPI_OP_WALK_INFO *Info)209{210char *OperatorSymbol = NULL;211ACPI_PARSE_OBJECT *Argument1;212ACPI_PARSE_OBJECT *Argument2;213ACPI_PARSE_OBJECT *Target;214ACPI_PARSE_OBJECT *Target2;215216217/* Exit immediately if ASL+ not enabled */218219if (!AcpiGbl_CstyleDisassembly)220{221return (FALSE);222}223224/* Get the first operand */225226Argument1 = AcpiPsGetArg (Op, 0);227if (!Argument1)228{229return (FALSE);230}231232/* Get the second operand */233234Argument2 = Argument1->Common.Next;235236/* Setup the operator string for this opcode */237238switch (Op->Common.AmlOpcode)239{240case AML_ADD_OP:241OperatorSymbol = " + ";242break;243244case AML_SUBTRACT_OP:245OperatorSymbol = " - ";246break;247248case AML_MULTIPLY_OP:249OperatorSymbol = " * ";250break;251252case AML_DIVIDE_OP:253OperatorSymbol = " / ";254break;255256case AML_MOD_OP:257OperatorSymbol = " % ";258break;259260case AML_SHIFT_LEFT_OP:261OperatorSymbol = " << ";262break;263264case AML_SHIFT_RIGHT_OP:265OperatorSymbol = " >> ";266break;267268case AML_BIT_AND_OP:269OperatorSymbol = " & ";270break;271272case AML_BIT_OR_OP:273OperatorSymbol = " | ";274break;275276case AML_BIT_XOR_OP:277OperatorSymbol = " ^ ";278break;279280/* Logical operators, no target */281282case AML_LOGICAL_AND_OP:283OperatorSymbol = " && ";284break;285286case AML_LOGICAL_EQUAL_OP:287OperatorSymbol = " == ";288break;289290case AML_LOGICAL_GREATER_OP:291OperatorSymbol = " > ";292break;293294case AML_LOGICAL_LESS_OP:295OperatorSymbol = " < ";296break;297298case AML_LOGICAL_OR_OP:299OperatorSymbol = " || ";300break;301302case AML_LOGICAL_NOT_OP:303/*304* Check for the LNOT sub-opcodes. These correspond to305* LNotEqual, LLessEqual, and LGreaterEqual. There are306* no actual AML opcodes for these operators.307*/308switch (Argument1->Common.AmlOpcode)309{310case AML_LOGICAL_EQUAL_OP:311OperatorSymbol = " != ";312break;313314case AML_LOGICAL_GREATER_OP:315OperatorSymbol = " <= ";316break;317318case AML_LOGICAL_LESS_OP:319OperatorSymbol = " >= ";320break;321322default:323324/* Unary LNOT case, emit "!" immediately */325326AcpiOsPrintf ("!");327return (TRUE);328}329330Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;331Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;332333/* Save symbol string in the next child (not peer) */334335Argument2 = AcpiPsGetArg (Argument1, 0);336if (!Argument2)337{338return (FALSE);339}340341Argument2->Common.OperatorSymbol = OperatorSymbol;342return (TRUE);343344case AML_INDEX_OP:345/*346* Check for constant source operand. Note: although technically347* legal syntax, the iASL compiler does not support this with348* the symbolic operators for Index(). It doesn't make sense to349* use Index() with a constant anyway.350*/351if ((Argument1->Common.AmlOpcode == AML_STRING_OP) ||352(Argument1->Common.AmlOpcode == AML_BUFFER_OP) ||353(Argument1->Common.AmlOpcode == AML_PACKAGE_OP) ||354(Argument1->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))355{356Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;357return (FALSE);358}359360/* Index operator is [] */361362Argument1->Common.OperatorSymbol = " [";363Argument2->Common.OperatorSymbol = "]";364break;365366/* Unary operators */367368case AML_DECREMENT_OP:369OperatorSymbol = "--";370break;371372case AML_INCREMENT_OP:373OperatorSymbol = "++";374break;375376case AML_BIT_NOT_OP:377case AML_STORE_OP:378OperatorSymbol = NULL;379break;380381default:382return (FALSE);383}384385if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)386{387return (TRUE);388}389390/*391* This is the key to how the disassembly of the C-style operators392* works. We save the operator symbol in the first child, thus393* deferring symbol output until after the first operand has been394* emitted.395*/396if (!Argument1->Common.OperatorSymbol)397{398Argument1->Common.OperatorSymbol = OperatorSymbol;399}400401/*402* Check for a valid target as the 3rd (or sometimes 2nd) operand403*404* Compound assignment operator support:405* Attempt to optimize constructs of the form:406* Add (Local1, 0xFF, Local1)407* to:408* Local1 += 0xFF409*410* Only the math operators and Store() have a target.411* Logicals have no target.412*/413switch (Op->Common.AmlOpcode)414{415case AML_ADD_OP:416case AML_SUBTRACT_OP:417case AML_MULTIPLY_OP:418case AML_DIVIDE_OP:419case AML_MOD_OP:420case AML_SHIFT_LEFT_OP:421case AML_SHIFT_RIGHT_OP:422case AML_BIT_AND_OP:423case AML_BIT_OR_OP:424case AML_BIT_XOR_OP:425426/* Target is 3rd operand */427428Target = Argument2->Common.Next;429if (Op->Common.AmlOpcode == AML_DIVIDE_OP)430{431Target2 = Target->Common.Next;432433/*434* Divide has an extra target operand (Remainder).435* Default behavior is to simply ignore ASL+ conversion436* if the remainder target (modulo) is specified.437*/438if (!AcpiGbl_DoDisassemblerOptimizations)439{440if (AcpiDmIsValidTarget (Target))441{442Argument1->Common.OperatorSymbol = NULL;443Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;444return (FALSE);445}446447Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;448Target = Target2;449}450else451{452/*453* Divide has an extra target operand (Remainder).454* If both targets are specified, it cannot be converted455* to a C-style operator.456*/457if (AcpiDmIsValidTarget (Target) &&458AcpiDmIsValidTarget (Target2))459{460Argument1->Common.OperatorSymbol = NULL;461Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;462return (FALSE);463}464465if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */466{467/* Convert the Divide to Modulo */468469Op->Common.AmlOpcode = AML_MOD_OP;470471Argument1->Common.OperatorSymbol = " % ";472Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;473}474else /* Only second Target (quotient) is valid */475{476Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;477Target = Target2;478}479}480}481482/* Parser should ensure there is at least a placeholder target */483484if (!Target)485{486return (FALSE);487}488489if (!AcpiDmIsValidTarget (Target))490{491/* Not a valid target (placeholder only, from parser) */492break;493}494495/*496* Promote the target up to the first child in the parse497* tree. This is done because the target will be output498* first, in the form:499* <Target> = Operands...500*/501AcpiDmPromoteTarget (Op, Target);502503/* Check operands for conversion to a "Compound Assignment" */504505switch (Op->Common.AmlOpcode)506{507/* Commutative operators */508509case AML_ADD_OP:510case AML_MULTIPLY_OP:511case AML_BIT_AND_OP:512case AML_BIT_OR_OP:513case AML_BIT_XOR_OP:514/*515* For the commutative operators, we can convert to a516* compound statement only if at least one (either) operand517* is the same as the target.518*519* Add (A, B, A) --> A += B520* Add (B, A, A) --> A += B521* Add (B, C, A) --> A = (B + C)522*/523if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) ||524(AcpiDmIsTargetAnOperand (Target, Argument2, TRUE)))525{526Target->Common.OperatorSymbol =527AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);528529/* Convert operator to compound assignment */530531Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;532Argument1->Common.OperatorSymbol = NULL;533return (TRUE);534}535break;536537/* Non-commutative operators */538539case AML_SUBTRACT_OP:540case AML_DIVIDE_OP:541case AML_MOD_OP:542case AML_SHIFT_LEFT_OP:543case AML_SHIFT_RIGHT_OP:544/*545* For the non-commutative operators, we can convert to a546* compound statement only if the target is the same as the547* first operand.548*549* Subtract (A, B, A) --> A -= B550* Subtract (B, A, A) --> A = (B - A)551*/552if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)))553{554Target->Common.OperatorSymbol =555AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);556557/* Convert operator to compound assignment */558559Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;560Argument1->Common.OperatorSymbol = NULL;561return (TRUE);562}563break;564565default:566break;567}568569/*570* If we are within a C-style expression, emit an extra open571* paren. Implemented by examining the parent op.572*/573switch (Op->Common.Parent->Common.AmlOpcode)574{575case AML_ADD_OP:576case AML_SUBTRACT_OP:577case AML_MULTIPLY_OP:578case AML_DIVIDE_OP:579case AML_MOD_OP:580case AML_SHIFT_LEFT_OP:581case AML_SHIFT_RIGHT_OP:582case AML_BIT_AND_OP:583case AML_BIT_OR_OP:584case AML_BIT_XOR_OP:585case AML_LOGICAL_AND_OP:586case AML_LOGICAL_EQUAL_OP:587case AML_LOGICAL_GREATER_OP:588case AML_LOGICAL_LESS_OP:589case AML_LOGICAL_OR_OP:590591Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT;592AcpiOsPrintf ("(");593break;594595default:596break;597}598599/* Normal output for ASL/AML operators with a target operand */600601Target->Common.OperatorSymbol = " = (";602return (TRUE);603604/* Binary operators, no parens */605606case AML_DECREMENT_OP:607case AML_INCREMENT_OP:608return (TRUE);609610case AML_INDEX_OP:611612/* Target is optional, 3rd operand */613614Target = Argument2->Common.Next;615if (AcpiDmIsValidTarget (Target))616{617AcpiDmPromoteTarget (Op, Target);618619if (!Target->Common.OperatorSymbol)620{621Target->Common.OperatorSymbol = " = ";622}623}624return (TRUE);625626case AML_STORE_OP:627/*628* For Store, the Target is the 2nd operand. We know the target629* is valid, because it is not optional.630*631* Ignore any optimizations/folding if flag is set.632* Used for iASL/disassembler test suite only.633*/634if (AcpiDmIsOptimizationIgnored (Op, Argument1))635{636return (FALSE);637}638639/*640* Perform conversion.641* In the parse tree, simply swap the target with the642* source so that the target is processed first.643*/644Target = Argument1->Common.Next;645if (!Target)646{647return (FALSE);648}649650AcpiDmPromoteTarget (Op, Target);651if (!Target->Common.OperatorSymbol)652{653Target->Common.OperatorSymbol = " = ";654}655return (TRUE);656657case AML_BIT_NOT_OP:658659/* Target is optional, 2nd operand */660661Target = Argument1->Common.Next;662if (!Target)663{664return (FALSE);665}666667if (AcpiDmIsValidTarget (Target))668{669/* Valid target, not a placeholder */670671AcpiDmPromoteTarget (Op, Target);672Target->Common.OperatorSymbol = " = ~";673}674else675{676/* No target. Emit this prefix operator immediately */677678AcpiOsPrintf ("~");679}680return (TRUE);681682default:683break;684}685686/* All other operators, emit an open paren */687688AcpiOsPrintf ("(");689return (TRUE);690}691692693/*******************************************************************************694*695* FUNCTION: AcpiDmIsOptimizationIgnored696*697* PARAMETERS: StoreOp - Store operator parse object698* StoreArgument - Target associate with the Op699*700* RETURN: TRUE if this Store operator should not be converted/removed.701*702* DESCRIPTION: The following function implements "Do not optimize if a703* store is immediately followed by a math/bit operator that704* has no target".705*706* Function is ignored if DoDisassemblerOptimizations is TRUE.707* This is the default, ignore this function.708*709* Disables these types of optimizations, and simply emits710* legacy ASL code:711* Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2)712* --> INT2 = INT1 + 4713*714* Store (Not (INT1), INT2) --> Not (INT1, INT2)715* --> INT2 = ~INT1716*717* Used only for the ASL test suite. For the test suite, we718* don't want to perform some optimizations to ensure binary719* compatibility with the generation of the legacy ASL->AML.720* In other words, for all test modules we want exactly:721* (ASL+ -> AML) == (ASL- -> AML)722*723******************************************************************************/724725static BOOLEAN726AcpiDmIsOptimizationIgnored (727ACPI_PARSE_OBJECT *StoreOp,728ACPI_PARSE_OBJECT *StoreArgument)729{730ACPI_PARSE_OBJECT *Argument1;731ACPI_PARSE_OBJECT *Argument2;732ACPI_PARSE_OBJECT *Target;733734735/* No optimizations/folding for the typical case */736737if (AcpiGbl_DoDisassemblerOptimizations)738{739return (FALSE);740}741742/*743* Only a small subset of ASL/AML operators can be optimized.744* Can only optimize/fold if there is no target (or targets)745* specified for the operator. And of course, the operator746* is surrounded by a Store() operator.747*/748switch (StoreArgument->Common.AmlOpcode)749{750case AML_ADD_OP:751case AML_SUBTRACT_OP:752case AML_MULTIPLY_OP:753case AML_MOD_OP:754case AML_SHIFT_LEFT_OP:755case AML_SHIFT_RIGHT_OP:756case AML_BIT_AND_OP:757case AML_BIT_OR_OP:758case AML_BIT_XOR_OP:759case AML_INDEX_OP:760761/* These operators have two arguments and one target */762763Argument1 = StoreArgument->Common.Value.Arg;764Argument2 = Argument1->Common.Next;765Target = Argument2->Common.Next;766767if (!AcpiDmIsValidTarget (Target))768{769StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;770return (TRUE);771}772break;773774case AML_DIVIDE_OP:775776/* This operator has two arguments and two targets */777778Argument1 = StoreArgument->Common.Value.Arg;779Argument2 = Argument1->Common.Next;780Target = Argument2->Common.Next;781782if (!AcpiDmIsValidTarget (Target) ||783!AcpiDmIsValidTarget (Target->Common.Next))784{785StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;786return (TRUE);787}788break;789790case AML_BIT_NOT_OP:791792/* This operator has one operand and one target */793794Argument1 = StoreArgument->Common.Value.Arg;795Target = Argument1->Common.Next;796797if (!AcpiDmIsValidTarget (Target))798{799StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;800return (TRUE);801}802break;803804default:805break;806}807808return (FALSE);809}810811812/*******************************************************************************813*814* FUNCTION: AcpiDmCloseOperator815*816* PARAMETERS: Op - Current parse object817*818* RETURN: None819*820* DESCRIPTION: Closes an operator by adding a closing parentheses if and821* when necessary. Called during ascending phase of the822* parse tree walk.823*824******************************************************************************/825826void827AcpiDmCloseOperator (828ACPI_PARSE_OBJECT *Op)829{830831/* Always emit paren if ASL+ disassembly disabled */832833if (!AcpiGbl_CstyleDisassembly)834{835AcpiOsPrintf (")");836ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);837return;838}839840if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)841{842AcpiOsPrintf (")");843ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);844return;845}846847/* Check if we need to add an additional closing paren */848849switch (Op->Common.AmlOpcode)850{851case AML_ADD_OP:852case AML_SUBTRACT_OP:853case AML_MULTIPLY_OP:854case AML_DIVIDE_OP:855case AML_MOD_OP:856case AML_SHIFT_LEFT_OP:857case AML_SHIFT_RIGHT_OP:858case AML_BIT_AND_OP:859case AML_BIT_OR_OP:860case AML_BIT_XOR_OP:861case AML_LOGICAL_AND_OP:862case AML_LOGICAL_EQUAL_OP:863case AML_LOGICAL_GREATER_OP:864case AML_LOGICAL_LESS_OP:865case AML_LOGICAL_OR_OP:866867/* Emit paren only if this is not a compound assignment */868869if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND_ASSIGNMENT)870{871ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);872return;873}874875/* Emit extra close paren for assignment within an expression */876877if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT)878{879AcpiOsPrintf (")");880}881break;882883case AML_INDEX_OP:884885/* This is case for unsupported Index() source constants */886887if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN)888{889AcpiOsPrintf (")");890}891ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);892return;893894/* No need for parens for these */895896case AML_DECREMENT_OP:897case AML_INCREMENT_OP:898case AML_LOGICAL_NOT_OP:899case AML_BIT_NOT_OP:900case AML_STORE_OP:901ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);902return;903904default:905906/* Always emit paren for non-ASL+ operators */907break;908}909910AcpiOsPrintf (")");911ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);912913return;914}915916917/*******************************************************************************918*919* FUNCTION: AcpiDmGetCompoundSymbol920*921* PARAMETERS: AslOpcode922*923* RETURN: String containing the compound assignment symbol924*925* DESCRIPTION: Detect opcodes that can be converted to compound assignment,926* return the appropriate operator string.927*928******************************************************************************/929930static char *931AcpiDmGetCompoundSymbol (932UINT16 AmlOpcode)933{934char *Symbol;935936937switch (AmlOpcode)938{939case AML_ADD_OP:940Symbol = " += ";941break;942943case AML_SUBTRACT_OP:944Symbol = " -= ";945break;946947case AML_MULTIPLY_OP:948Symbol = " *= ";949break;950951case AML_DIVIDE_OP:952Symbol = " /= ";953break;954955case AML_MOD_OP:956Symbol = " %= ";957break;958959case AML_SHIFT_LEFT_OP:960Symbol = " <<= ";961break;962963case AML_SHIFT_RIGHT_OP:964Symbol = " >>= ";965break;966967case AML_BIT_AND_OP:968Symbol = " &= ";969break;970971case AML_BIT_OR_OP:972Symbol = " |= ";973break;974975case AML_BIT_XOR_OP:976Symbol = " ^= ";977break;978979default:980981/* No operator string for all other opcodes */982983return (NULL);984}985986return (Symbol);987}988989990/*******************************************************************************991*992* FUNCTION: AcpiDmPromoteTarget993*994* PARAMETERS: Op - Operator parse object995* Target - Target associate with the Op996*997* RETURN: None998*999* DESCRIPTION: Transform the parse tree by moving the target up to the first1000* child of the Op.1001*1002******************************************************************************/10031004static void1005AcpiDmPromoteTarget (1006ACPI_PARSE_OBJECT *Op,1007ACPI_PARSE_OBJECT *Target)1008{1009ACPI_PARSE_OBJECT *Child;101010111012/* Link target directly to the Op as first child */10131014Child = Op->Common.Value.Arg;1015Op->Common.Value.Arg = Target;1016Target->Common.Next = Child;10171018/* Find the last peer, it is linked to the target. Unlink it. */10191020while (Child->Common.Next != Target)1021{1022Child = Child->Common.Next;1023}10241025Child->Common.Next = NULL;1026}102710281029/*******************************************************************************1030*1031* FUNCTION: AcpiDmIsValidTarget1032*1033* PARAMETERS: Target - Target Op from the parse tree1034*1035* RETURN: TRUE if the Target is real. FALSE if it is just a placeholder1036* Op that was inserted by the parser.1037*1038* DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target.1039* In other words, determine if the optional target is used or1040* not. Note: If Target is NULL, something is seriously wrong,1041* probably with the parse tree.1042*1043******************************************************************************/10441045static BOOLEAN1046AcpiDmIsValidTarget (1047ACPI_PARSE_OBJECT *Target)1048{10491050if (!Target)1051{1052return (FALSE);1053}10541055if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&1056(Target->Common.Value.Arg == NULL))1057{1058return (FALSE);1059}10601061return (TRUE);1062}106310641065/*******************************************************************************1066*1067* FUNCTION: AcpiDmIsTargetAnOperand1068*1069* PARAMETERS: Target - Target associated with the expression1070* Operand - An operand associated with expression1071*1072* RETURN: TRUE if expression can be converted to a compound assignment.1073* FALSE otherwise.1074*1075* DESCRIPTION: Determine if the Target duplicates the operand, in order to1076* detect if the expression can be converted to a compound1077* assignment. (+=, *=, etc.)1078*1079******************************************************************************/10801081static BOOLEAN1082AcpiDmIsTargetAnOperand (1083ACPI_PARSE_OBJECT *Target,1084ACPI_PARSE_OBJECT *Operand,1085BOOLEAN TopLevel)1086{1087const ACPI_OPCODE_INFO *OpInfo;1088BOOLEAN Same;108910901091/*1092* Opcodes must match. Note: ignoring the difference between nameseg1093* and namepath for now. May be needed later.1094*/1095if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode)1096{1097return (FALSE);1098}10991100/* Nodes should match, even if they are NULL */11011102if (Target->Common.Node != Operand->Common.Node)1103{1104return (FALSE);1105}11061107/* Determine if a child exists */11081109OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode);1110if (OpInfo->Flags & AML_HAS_ARGS)1111{1112Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg,1113Operand->Common.Value.Arg, FALSE);1114if (!Same)1115{1116return (FALSE);1117}1118}11191120/* Check the next peer, as long as we are not at the top level */11211122if ((!TopLevel) &&1123Target->Common.Next)1124{1125Same = AcpiDmIsTargetAnOperand (Target->Common.Next,1126Operand->Common.Next, FALSE);1127if (!Same)1128{1129return (FALSE);1130}1131}11321133/* Suppress the duplicate operand at the top-level */11341135if (TopLevel)1136{1137Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;1138}1139return (TRUE);1140}114111421143