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