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