dswexec.c revision 241973
1191783Srmacklem/******************************************************************************
2191783Srmacklem *
3191783Srmacklem * Module Name: dswexec - Dispatcher method execution callbacks;
4191783Srmacklem *                        dispatch to interpreter.
5191783Srmacklem *
6191783Srmacklem *****************************************************************************/
7191783Srmacklem
8191783Srmacklem/*
9191783Srmacklem * Copyright (C) 2000 - 2012, Intel Corp.
10191783Srmacklem * All rights reserved.
11191783Srmacklem *
12191783Srmacklem * Redistribution and use in source and binary forms, with or without
13191783Srmacklem * modification, are permitted provided that the following conditions
14191783Srmacklem * are met:
15191783Srmacklem * 1. Redistributions of source code must retain the above copyright
16191783Srmacklem *    notice, this list of conditions, and the following disclaimer,
17191783Srmacklem *    without modification.
18191783Srmacklem * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19191783Srmacklem *    substantially similar to the "NO WARRANTY" disclaimer below
20191783Srmacklem *    ("Disclaimer") and any redistribution must be conditioned upon
21191783Srmacklem *    including a substantially similar Disclaimer requirement for further
22191783Srmacklem *    binary redistribution.
23191783Srmacklem * 3. Neither the names of the above-listed copyright holders nor the names
24191783Srmacklem *    of any contributors may be used to endorse or promote products derived
25191783Srmacklem *    from this software without specific prior written permission.
26191783Srmacklem *
27191783Srmacklem * Alternatively, this software may be distributed under the terms of the
28191783Srmacklem * GNU General Public License ("GPL") version 2 as published by the Free
29191783Srmacklem * Software Foundation.
30191783Srmacklem *
31191783Srmacklem * NO WARRANTY
32191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33191783Srmacklem * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34191783Srmacklem * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35191783Srmacklem * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36191783Srmacklem * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40191783Srmacklem * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41191783Srmacklem * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42191783Srmacklem * POSSIBILITY OF SUCH DAMAGES.
43191783Srmacklem */
44191783Srmacklem
45191783Srmacklem#define __DSWEXEC_C__
46191783Srmacklem
47191783Srmacklem#include <contrib/dev/acpica/include/acpi.h>
48191783Srmacklem#include <contrib/dev/acpica/include/accommon.h>
49191783Srmacklem#include <contrib/dev/acpica/include/acparser.h>
50191783Srmacklem#include <contrib/dev/acpica/include/amlcode.h>
51191783Srmacklem#include <contrib/dev/acpica/include/acdispat.h>
52191783Srmacklem#include <contrib/dev/acpica/include/acinterp.h>
53191783Srmacklem#include <contrib/dev/acpica/include/acnamesp.h>
54191783Srmacklem#include <contrib/dev/acpica/include/acdebug.h>
55191783Srmacklem
56191783Srmacklem
57191783Srmacklem#define _COMPONENT          ACPI_DISPATCHER
58191783Srmacklem        ACPI_MODULE_NAME    ("dswexec")
59191783Srmacklem
60191783Srmacklem/*
61191783Srmacklem * Dispatch table for opcode classes
62191783Srmacklem */
63191783Srmacklemstatic ACPI_EXECUTE_OP      AcpiGbl_OpTypeDispatch [] =
64191783Srmacklem{
65191783Srmacklem    AcpiExOpcode_0A_0T_1R,
66191783Srmacklem    AcpiExOpcode_1A_0T_0R,
67191783Srmacklem    AcpiExOpcode_1A_0T_1R,
68191783Srmacklem    AcpiExOpcode_1A_1T_0R,
69191783Srmacklem    AcpiExOpcode_1A_1T_1R,
70191783Srmacklem    AcpiExOpcode_2A_0T_0R,
71191783Srmacklem    AcpiExOpcode_2A_0T_1R,
72191783Srmacklem    AcpiExOpcode_2A_1T_1R,
73191783Srmacklem    AcpiExOpcode_2A_2T_1R,
74191783Srmacklem    AcpiExOpcode_3A_0T_0R,
75191783Srmacklem    AcpiExOpcode_3A_1T_1R,
76191783Srmacklem    AcpiExOpcode_6A_0T_1R
77191783Srmacklem};
78191783Srmacklem
79191783Srmacklem
80191783Srmacklem/*****************************************************************************
81191783Srmacklem *
82191783Srmacklem * FUNCTION:    AcpiDsGetPredicateValue
83191783Srmacklem *
84191783Srmacklem * PARAMETERS:  WalkState       - Current state of the parse tree walk
85191783Srmacklem *              ResultObj       - if non-zero, pop result from result stack
86191783Srmacklem *
87191783Srmacklem * RETURN:      Status
88192115Srmacklem *
89191783Srmacklem * DESCRIPTION: Get the result of a predicate evaluation
90191783Srmacklem *
91191783Srmacklem ****************************************************************************/
92191783Srmacklem
93191783SrmacklemACPI_STATUS
94191783SrmacklemAcpiDsGetPredicateValue (
95191783Srmacklem    ACPI_WALK_STATE         *WalkState,
96191783Srmacklem    ACPI_OPERAND_OBJECT     *ResultObj)
97191783Srmacklem{
98191783Srmacklem    ACPI_STATUS             Status = AE_OK;
99191783Srmacklem    ACPI_OPERAND_OBJECT     *ObjDesc;
100191783Srmacklem    ACPI_OPERAND_OBJECT     *LocalObjDesc = NULL;
101191783Srmacklem
102191783Srmacklem
103191783Srmacklem    ACPI_FUNCTION_TRACE_PTR (DsGetPredicateValue, WalkState);
104191783Srmacklem
105191783Srmacklem
106191783Srmacklem    WalkState->ControlState->Common.State = 0;
107191783Srmacklem
108191783Srmacklem    if (ResultObj)
109191783Srmacklem    {
110191783Srmacklem        Status = AcpiDsResultPop (&ObjDesc, WalkState);
111191783Srmacklem        if (ACPI_FAILURE (Status))
112191783Srmacklem        {
113191783Srmacklem            ACPI_EXCEPTION ((AE_INFO, Status,
114191783Srmacklem                "Could not get result from predicate evaluation"));
115191783Srmacklem
116191783Srmacklem            return_ACPI_STATUS (Status);
117191783Srmacklem        }
118191783Srmacklem    }
119191783Srmacklem    else
120191783Srmacklem    {
121191783Srmacklem        Status = AcpiDsCreateOperand (WalkState, WalkState->Op, 0);
122191783Srmacklem        if (ACPI_FAILURE (Status))
123191783Srmacklem        {
124191783Srmacklem            return_ACPI_STATUS (Status);
125191783Srmacklem        }
126191783Srmacklem
127220530Srmacklem        Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState);
128191783Srmacklem        if (ACPI_FAILURE (Status))
129192115Srmacklem        {
130191783Srmacklem            return_ACPI_STATUS (Status);
131191783Srmacklem        }
132191783Srmacklem
133191783Srmacklem        ObjDesc = WalkState->Operands [0];
134191783Srmacklem    }
135191783Srmacklem
136191783Srmacklem    if (!ObjDesc)
137191783Srmacklem    {
138191783Srmacklem        ACPI_ERROR ((AE_INFO,
139191783Srmacklem            "No predicate ObjDesc=%p State=%p",
140191783Srmacklem            ObjDesc, WalkState));
141191783Srmacklem
142191783Srmacklem        return_ACPI_STATUS (AE_AML_NO_OPERAND);
143191783Srmacklem    }
144191783Srmacklem
145191783Srmacklem    /*
146191783Srmacklem     * Result of predicate evaluation must be an Integer
147191783Srmacklem     * object. Implicitly convert the argument if necessary.
148191783Srmacklem     */
149191783Srmacklem    Status = AcpiExConvertToInteger (ObjDesc, &LocalObjDesc, 16);
150191783Srmacklem    if (ACPI_FAILURE (Status))
151191783Srmacklem    {
152191783Srmacklem        goto Cleanup;
153191783Srmacklem    }
154191783Srmacklem
155191783Srmacklem    if (LocalObjDesc->Common.Type != ACPI_TYPE_INTEGER)
156191783Srmacklem    {
157191783Srmacklem        ACPI_ERROR ((AE_INFO,
158191783Srmacklem            "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X",
159191783Srmacklem            ObjDesc, WalkState, ObjDesc->Common.Type));
160191783Srmacklem
161191783Srmacklem        Status = AE_AML_OPERAND_TYPE;
162191783Srmacklem        goto Cleanup;
163191783Srmacklem    }
164191783Srmacklem
165191783Srmacklem    /* Truncate the predicate to 32-bits if necessary */
166191783Srmacklem
167191783Srmacklem    AcpiExTruncateFor32bitTable (LocalObjDesc);
168191783Srmacklem
169191783Srmacklem    /*
170191783Srmacklem     * Save the result of the predicate evaluation on
171191783Srmacklem     * the control stack
172191783Srmacklem     */
173191783Srmacklem    if (LocalObjDesc->Integer.Value)
174191783Srmacklem    {
175191783Srmacklem        WalkState->ControlState->Common.Value = TRUE;
176191783Srmacklem    }
177191783Srmacklem    else
178191783Srmacklem    {
179191783Srmacklem        /*
180191783Srmacklem         * Predicate is FALSE, we will just toss the
181191783Srmacklem         * rest of the package
182191783Srmacklem         */
183191783Srmacklem        WalkState->ControlState->Common.Value = FALSE;
184191783Srmacklem        Status = AE_CTRL_FALSE;
185191783Srmacklem    }
186191783Srmacklem
187191783Srmacklem    /* Predicate can be used for an implicit return value */
188191783Srmacklem
189191783Srmacklem    (void) AcpiDsDoImplicitReturn (LocalObjDesc, WalkState, TRUE);
190191783Srmacklem
191191783Srmacklem
192191783SrmacklemCleanup:
193191783Srmacklem
194191783Srmacklem    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
195191783Srmacklem        WalkState->ControlState->Common.Value, WalkState->Op));
196191783Srmacklem
197191783Srmacklem     /* Break to debugger to display result */
198191783Srmacklem
199191783Srmacklem    ACPI_DEBUGGER_EXEC (AcpiDbDisplayResultObject (LocalObjDesc, WalkState));
200191783Srmacklem
201191783Srmacklem    /*
202191783Srmacklem     * Delete the predicate result object (we know that
203191783Srmacklem     * we don't need it anymore)
204191783Srmacklem     */
205191783Srmacklem    if (LocalObjDesc != ObjDesc)
206191783Srmacklem    {
207191783Srmacklem        AcpiUtRemoveReference (LocalObjDesc);
208191783Srmacklem    }
209191783Srmacklem    AcpiUtRemoveReference (ObjDesc);
210191783Srmacklem
211191783Srmacklem    WalkState->ControlState->Common.State = ACPI_CONTROL_NORMAL;
212191783Srmacklem    return_ACPI_STATUS (Status);
213192115Srmacklem}
214191783Srmacklem
215191783Srmacklem
216191783Srmacklem/*****************************************************************************
217192115Srmacklem *
218191783Srmacklem * FUNCTION:    AcpiDsExecBeginOp
219191783Srmacklem *
220191783Srmacklem * PARAMETERS:  WalkState       - Current state of the parse tree walk
221191783Srmacklem *              OutOp           - Where to return op if a new one is created
222191783Srmacklem *
223191783Srmacklem * RETURN:      Status
224191783Srmacklem *
225191783Srmacklem * DESCRIPTION: Descending callback used during the execution of control
226191783Srmacklem *              methods. This is where most operators and operands are
227191783Srmacklem *              dispatched to the interpreter.
228192115Srmacklem *
229191783Srmacklem ****************************************************************************/
230191783Srmacklem
231191783SrmacklemACPI_STATUS
232191783SrmacklemAcpiDsExecBeginOp (
233191783Srmacklem    ACPI_WALK_STATE         *WalkState,
234191783Srmacklem    ACPI_PARSE_OBJECT       **OutOp)
235191783Srmacklem{
236191783Srmacklem    ACPI_PARSE_OBJECT       *Op;
237191783Srmacklem    ACPI_STATUS             Status = AE_OK;
238191783Srmacklem    UINT32                  OpcodeClass;
239191783Srmacklem
240191783Srmacklem
241191783Srmacklem    ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState);
242191783Srmacklem
243191783Srmacklem
244191783Srmacklem    Op = WalkState->Op;
245191783Srmacklem    if (!Op)
246191783Srmacklem    {
247191783Srmacklem        Status = AcpiDsLoad2BeginOp (WalkState, OutOp);
248191783Srmacklem        if (ACPI_FAILURE (Status))
249191783Srmacklem        {
250191783Srmacklem            goto ErrorExit;
251191783Srmacklem        }
252191783Srmacklem
253191783Srmacklem        Op = *OutOp;
254191783Srmacklem        WalkState->Op = Op;
255211951Srmacklem        WalkState->Opcode = Op->Common.AmlOpcode;
256205941Srmacklem        WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
257191783Srmacklem
258191783Srmacklem        if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType))
259192115Srmacklem        {
260192115Srmacklem            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
261191783Srmacklem                "(%s) Popping scope for Op %p\n",
262192115Srmacklem                AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op));
263191783Srmacklem
264191783Srmacklem            Status = AcpiDsScopeStackPop (WalkState);
265191783Srmacklem            if (ACPI_FAILURE (Status))
266191783Srmacklem            {
267191783Srmacklem                goto ErrorExit;
268191783Srmacklem            }
269191783Srmacklem        }
270191783Srmacklem    }
271191783Srmacklem
272191783Srmacklem    if (Op == WalkState->Origin)
273191783Srmacklem    {
274191783Srmacklem        if (OutOp)
275191783Srmacklem        {
276191783Srmacklem            *OutOp = Op;
277191783Srmacklem        }
278191783Srmacklem
279191783Srmacklem        return_ACPI_STATUS (AE_OK);
280191783Srmacklem    }
281191783Srmacklem
282192115Srmacklem    /*
283216700Srmacklem     * If the previous opcode was a conditional, this opcode
284191783Srmacklem     * must be the beginning of the associated predicate.
285191783Srmacklem     * Save this knowledge in the current scope descriptor
286191783Srmacklem     */
287191783Srmacklem    if ((WalkState->ControlState) &&
288191783Srmacklem        (WalkState->ControlState->Common.State ==
289191783Srmacklem            ACPI_CONTROL_CONDITIONAL_EXECUTING))
290191783Srmacklem    {
291220645Srmacklem        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n",
292191783Srmacklem                        Op, WalkState));
293220648Srmacklem
294191783Srmacklem        WalkState->ControlState->Common.State = ACPI_CONTROL_PREDICATE_EXECUTING;
295191783Srmacklem
296191783Srmacklem        /* Save start of predicate */
297191783Srmacklem
298191783Srmacklem        WalkState->ControlState->Control.PredicateOp = Op;
299191783Srmacklem    }
300191783Srmacklem
301191783Srmacklem
302191783Srmacklem    OpcodeClass = WalkState->OpInfo->Class;
303191783Srmacklem
304191783Srmacklem    /* We want to send namepaths to the load code */
305191783Srmacklem
306191783Srmacklem    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
307191783Srmacklem    {
308191783Srmacklem        OpcodeClass = AML_CLASS_NAMED_OBJECT;
309191783Srmacklem    }
310191783Srmacklem
311191783Srmacklem    /*
312192121Srmacklem     * Handle the opcode based upon the opcode type
313191783Srmacklem     */
314192115Srmacklem    switch (OpcodeClass)
315191783Srmacklem    {
316192115Srmacklem    case AML_CLASS_CONTROL:
317191783Srmacklem
318191783Srmacklem        Status = AcpiDsExecBeginControlOp (WalkState, Op);
319191783Srmacklem        break;
320191783Srmacklem
321191783Srmacklem
322191783Srmacklem    case AML_CLASS_NAMED_OBJECT:
323191783Srmacklem
324191783Srmacklem        if (WalkState->WalkType & ACPI_WALK_METHOD)
325191783Srmacklem        {
326191783Srmacklem            /*
327207170Srmacklem             * Found a named object declaration during method execution;
328191783Srmacklem             * we must enter this object into the namespace. The created
329191783Srmacklem             * object is temporary and will be deleted upon completion of
330192115Srmacklem             * the execution of this method.
331220648Srmacklem             *
332191783Srmacklem             * Note 10/2010: Except for the Scope() op. This opcode does
333192115Srmacklem             * not actually create a new object, it refers to an existing
334191783Srmacklem             * object. However, for Scope(), we want to indeed open a
335191783Srmacklem             * new scope.
336191783Srmacklem             */
337191783Srmacklem            if (Op->Common.AmlOpcode != AML_SCOPE_OP)
338191783Srmacklem            {
339191783Srmacklem                Status = AcpiDsLoad2BeginOp (WalkState, NULL);
340191783Srmacklem            }
341191783Srmacklem            else
342192115Srmacklem            {
343191783Srmacklem                Status = AcpiDsScopeStackPush (Op->Named.Node,
344191783Srmacklem                            Op->Named.Node->Type, WalkState);
345191783Srmacklem                if (ACPI_FAILURE (Status))
346191783Srmacklem                {
347191783Srmacklem                    return_ACPI_STATUS (Status);
348191783Srmacklem                }
349191783Srmacklem            }
350191783Srmacklem        }
351191783Srmacklem        break;
352191783Srmacklem
353191783Srmacklem
354192337Srmacklem    case AML_CLASS_EXECUTE:
355191783Srmacklem    case AML_CLASS_CREATE:
356191783Srmacklem
357191783Srmacklem        break;
358191783Srmacklem
359191783Srmacklem
360191783Srmacklem    default:
361191783Srmacklem        break;
362191783Srmacklem    }
363191783Srmacklem
364191783Srmacklem    /* Nothing to do here during method execution */
365191783Srmacklem
366191783Srmacklem    return_ACPI_STATUS (Status);
367191783Srmacklem
368191783Srmacklem
369191783SrmacklemErrorExit:
370191783Srmacklem    Status = AcpiDsMethodError (Status, WalkState);
371191783Srmacklem    return_ACPI_STATUS (Status);
372191783Srmacklem}
373191783Srmacklem
374191783Srmacklem
375207082Srmacklem/*****************************************************************************
376191783Srmacklem *
377191783Srmacklem * FUNCTION:    AcpiDsExecEndOp
378191783Srmacklem *
379191783Srmacklem * PARAMETERS:  WalkState       - Current state of the parse tree walk
380191783Srmacklem *
381191783Srmacklem * RETURN:      Status
382191783Srmacklem *
383191783Srmacklem * DESCRIPTION: Ascending callback used during the execution of control
384191783Srmacklem *              methods. The only thing we really need to do here is to
385191783Srmacklem *              notice the beginning of IF, ELSE, and WHILE blocks.
386191783Srmacklem *
387191783Srmacklem ****************************************************************************/
388191783Srmacklem
389191783SrmacklemACPI_STATUS
390191783SrmacklemAcpiDsExecEndOp (
391191783Srmacklem    ACPI_WALK_STATE         *WalkState)
392191783Srmacklem{
393191783Srmacklem    ACPI_PARSE_OBJECT       *Op;
394191783Srmacklem    ACPI_STATUS             Status = AE_OK;
395191783Srmacklem    UINT32                  OpType;
396191783Srmacklem    UINT32                  OpClass;
397191783Srmacklem    ACPI_PARSE_OBJECT       *NextOp;
398191783Srmacklem    ACPI_PARSE_OBJECT       *FirstArg;
399191783Srmacklem
400191783Srmacklem
401191783Srmacklem    ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState);
402191783Srmacklem
403191783Srmacklem
404191783Srmacklem    Op      = WalkState->Op;
405191783Srmacklem    OpType  = WalkState->OpInfo->Type;
406191783Srmacklem    OpClass = WalkState->OpInfo->Class;
407191783Srmacklem
408191783Srmacklem    if (OpClass == AML_CLASS_UNKNOWN)
409191783Srmacklem    {
410191783Srmacklem        ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode));
411191783Srmacklem        return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
412191783Srmacklem    }
413191783Srmacklem
414191783Srmacklem    FirstArg = Op->Common.Value.Arg;
415191783Srmacklem
416191783Srmacklem    /* Init the walk state */
417191783Srmacklem
418191783Srmacklem    WalkState->NumOperands = 0;
419191783Srmacklem    WalkState->OperandIndex = 0;
420191783Srmacklem    WalkState->ReturnDesc = NULL;
421191783Srmacklem    WalkState->ResultObj = NULL;
422191783Srmacklem
423191783Srmacklem    /* Call debugger for single step support (DEBUG build only) */
424191783Srmacklem
425191783Srmacklem    ACPI_DEBUGGER_EXEC (Status = AcpiDbSingleStep (WalkState, Op, OpClass));
426191783Srmacklem    ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (Status)) {return_ACPI_STATUS (Status);});
427191783Srmacklem
428191783Srmacklem    /* Decode the Opcode Class */
429192115Srmacklem
430191783Srmacklem    switch (OpClass)
431191783Srmacklem    {
432191783Srmacklem    case AML_CLASS_ARGUMENT:    /* Constants, literals, etc. */
433191783Srmacklem
434191783Srmacklem        if (WalkState->Opcode == AML_INT_NAMEPATH_OP)
435191783Srmacklem        {
436191783Srmacklem            Status = AcpiDsEvaluateNamePath (WalkState);
437191783Srmacklem            if (ACPI_FAILURE (Status))
438191783Srmacklem            {
439191783Srmacklem                goto Cleanup;
440191783Srmacklem            }
441191783Srmacklem        }
442191783Srmacklem        break;
443191783Srmacklem
444191783Srmacklem
445191783Srmacklem    case AML_CLASS_EXECUTE:     /* Most operators with arguments */
446191783Srmacklem
447191783Srmacklem        /* Build resolved operand stack */
448191783Srmacklem
449191783Srmacklem        Status = AcpiDsCreateOperands (WalkState, FirstArg);
450191783Srmacklem        if (ACPI_FAILURE (Status))
451191783Srmacklem        {
452191783Srmacklem            goto Cleanup;
453191783Srmacklem        }
454191783Srmacklem
455191783Srmacklem        /*
456191783Srmacklem         * All opcodes require operand resolution, with the only exceptions
457191783Srmacklem         * being the ObjectType and SizeOf operators.
458191783Srmacklem         */
459191783Srmacklem        if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE))
460195510Srmacklem        {
461195510Srmacklem            /* Resolve all operands */
462195510Srmacklem
463191783Srmacklem            Status = AcpiExResolveOperands (WalkState->Opcode,
464191783Srmacklem                        &(WalkState->Operands [WalkState->NumOperands -1]),
465191783Srmacklem                        WalkState);
466191783Srmacklem        }
467191783Srmacklem
468191783Srmacklem        if (ACPI_SUCCESS (Status))
469191783Srmacklem        {
470191783Srmacklem            /*
471191783Srmacklem             * Dispatch the request to the appropriate interpreter handler
472191783Srmacklem             * routine. There is one routine per opcode "type" based upon the
473210786Srmacklem             * number of opcode arguments and return type.
474191783Srmacklem             */
475191783Srmacklem            Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState);
476191783Srmacklem        }
477191783Srmacklem        else
478191783Srmacklem        {
479191783Srmacklem            /*
480191783Srmacklem             * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
481191783Srmacklem             * Local is uninitialized.
482191783Srmacklem             */
483191783Srmacklem            if  ((Status == AE_AML_UNINITIALIZED_LOCAL) &&
484191783Srmacklem                (WalkState->Opcode == AML_STORE_OP) &&
485191783Srmacklem                (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
486191783Srmacklem                (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
487191783Srmacklem                (WalkState->Operands[0]->Reference.Class ==
488192115Srmacklem                 WalkState->Operands[1]->Reference.Class) &&
489191783Srmacklem                (WalkState->Operands[0]->Reference.Value ==
490191783Srmacklem                 WalkState->Operands[1]->Reference.Value))
491191783Srmacklem            {
492191783Srmacklem                Status = AE_OK;
493191783Srmacklem            }
494191783Srmacklem            else
495191783Srmacklem            {
496191783Srmacklem                ACPI_EXCEPTION ((AE_INFO, Status,
497191783Srmacklem                    "While resolving operands for [%s]",
498191783Srmacklem                    AcpiPsGetOpcodeName (WalkState->Opcode)));
499191783Srmacklem            }
500191783Srmacklem        }
501191783Srmacklem
502191783Srmacklem        /* Always delete the argument objects and clear the operand stack */
503191783Srmacklem
504192115Srmacklem        AcpiDsClearOperands (WalkState);
505191783Srmacklem
506191783Srmacklem        /*
507192115Srmacklem         * If a result object was returned from above, push it on the
508207082Srmacklem         * current result stack
509191783Srmacklem         */
510192115Srmacklem        if (ACPI_SUCCESS (Status) &&
511191783Srmacklem            WalkState->ResultObj)
512191783Srmacklem        {
513192115Srmacklem            Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
514191783Srmacklem        }
515216693Srmacklem        break;
516191783Srmacklem
517191783Srmacklem
518191783Srmacklem    default:
519200999Srmacklem
520200999Srmacklem        switch (OpType)
521191783Srmacklem        {
522191783Srmacklem        case AML_TYPE_CONTROL:    /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
523191783Srmacklem
524191783Srmacklem            /* 1 Operand, 0 ExternalResult, 0 InternalResult */
525191783Srmacklem
526191783Srmacklem            Status = AcpiDsExecEndControlOp (WalkState, Op);
527191783Srmacklem
528191783Srmacklem            break;
529191783Srmacklem
530191783Srmacklem
531191783Srmacklem        case AML_TYPE_METHOD_CALL:
532199616Srmacklem
533191783Srmacklem            /*
534191783Srmacklem             * If the method is referenced from within a package
535191783Srmacklem             * declaration, it is not a invocation of the method, just
536191783Srmacklem             * a reference to it.
537191783Srmacklem             */
538191783Srmacklem            if ((Op->Asl.Parent) &&
539191783Srmacklem               ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) ||
540191783Srmacklem                (Op->Asl.Parent->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)))
541191783Srmacklem            {
542191783Srmacklem                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
543191783Srmacklem                    "Method Reference in a Package, Op=%p\n", Op));
544191783Srmacklem
545191783Srmacklem                Op->Common.Node = (ACPI_NAMESPACE_NODE *) Op->Asl.Value.Arg->Asl.Node;
546191783Srmacklem                AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object);
547191783Srmacklem                return_ACPI_STATUS (AE_OK);
548191783Srmacklem            }
549191783Srmacklem
550191783Srmacklem            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", Op));
551191783Srmacklem
552191990Sattilio            /*
553191783Srmacklem             * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
554191783Srmacklem             * the method Node pointer
555199616Srmacklem             */
556191783Srmacklem            /* NextOp points to the op that holds the method name */
557191783Srmacklem
558191783Srmacklem            NextOp = FirstArg;
559191783Srmacklem
560220645Srmacklem            /* NextOp points to first argument op */
561191783Srmacklem
562220648Srmacklem            NextOp = NextOp->Common.Next;
563191783Srmacklem
564191783Srmacklem            /*
565191783Srmacklem             * Get the method's arguments and put them on the operand stack
566191783Srmacklem             */
567191783Srmacklem            Status = AcpiDsCreateOperands (WalkState, NextOp);
568191783Srmacklem            if (ACPI_FAILURE (Status))
569216700Srmacklem            {
570191783Srmacklem                break;
571191783Srmacklem            }
572191783Srmacklem
573191783Srmacklem            /*
574191783Srmacklem             * Since the operands will be passed to another control method,
575191783Srmacklem             * we must resolve all local references here (Local variables,
576192121Srmacklem             * arguments to *this* method, etc.)
577214255Srmacklem             */
578217432Srmacklem            Status = AcpiDsResolveOperands (WalkState);
579191783Srmacklem            if (ACPI_FAILURE (Status))
580192115Srmacklem            {
581191783Srmacklem                /* On error, clear all resolved operands */
582191783Srmacklem
583191783Srmacklem                AcpiDsClearOperands (WalkState);
584191783Srmacklem                break;
585192115Srmacklem            }
586192115Srmacklem
587192115Srmacklem            /*
588192115Srmacklem             * Tell the walk loop to preempt this running method and
589192115Srmacklem             * execute the new method
590192115Srmacklem             */
591192115Srmacklem            Status = AE_CTRL_TRANSFER;
592191783Srmacklem
593192115Srmacklem            /*
594191783Srmacklem             * Return now; we don't want to disturb anything,
595191783Srmacklem             * especially the operand count!
596191783Srmacklem             */
597191783Srmacklem            return_ACPI_STATUS (Status);
598192115Srmacklem
599191783Srmacklem
600191783Srmacklem        case AML_TYPE_CREATE_FIELD:
601191783Srmacklem
602            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
603                "Executing CreateField Buffer/Index Op=%p\n", Op));
604
605            Status = AcpiDsLoad2EndOp (WalkState);
606            if (ACPI_FAILURE (Status))
607            {
608                break;
609            }
610
611            Status = AcpiDsEvalBufferFieldOperands (WalkState, Op);
612            break;
613
614
615        case AML_TYPE_CREATE_OBJECT:
616
617            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
618                "Executing CreateObject (Buffer/Package) Op=%p\n", Op));
619
620            switch (Op->Common.Parent->Common.AmlOpcode)
621            {
622            case AML_NAME_OP:
623
624                /*
625                 * Put the Node on the object stack (Contains the ACPI Name
626                 * of this object)
627                 */
628                WalkState->Operands[0] = (void *) Op->Common.Parent->Common.Node;
629                WalkState->NumOperands = 1;
630
631                Status = AcpiDsCreateNode (WalkState,
632                            Op->Common.Parent->Common.Node,
633                            Op->Common.Parent);
634                if (ACPI_FAILURE (Status))
635                {
636                    break;
637                }
638
639                /* Fall through */
640                /*lint -fallthrough */
641
642            case AML_INT_EVAL_SUBTREE_OP:
643
644                Status = AcpiDsEvalDataObjectOperands (WalkState, Op,
645                            AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node));
646                break;
647
648            default:
649
650                Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL);
651                break;
652            }
653
654            /*
655             * If a result object was returned from above, push it on the
656             * current result stack
657             */
658            if (WalkState->ResultObj)
659            {
660                Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
661            }
662            break;
663
664
665        case AML_TYPE_NAMED_FIELD:
666        case AML_TYPE_NAMED_COMPLEX:
667        case AML_TYPE_NAMED_SIMPLE:
668        case AML_TYPE_NAMED_NO_OBJ:
669
670            Status = AcpiDsLoad2EndOp (WalkState);
671            if (ACPI_FAILURE (Status))
672            {
673                break;
674            }
675
676            if (Op->Common.AmlOpcode == AML_REGION_OP)
677            {
678                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
679                    "Executing OpRegion Address/Length Op=%p\n", Op));
680
681                Status = AcpiDsEvalRegionOperands (WalkState, Op);
682                if (ACPI_FAILURE (Status))
683                {
684                    break;
685                }
686            }
687            else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP)
688            {
689                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
690                    "Executing DataTableRegion Strings Op=%p\n", Op));
691
692                Status = AcpiDsEvalTableRegionOperands (WalkState, Op);
693                if (ACPI_FAILURE (Status))
694                {
695                    break;
696                }
697            }
698            else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
699            {
700                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
701                    "Executing BankField Op=%p\n", Op));
702
703                Status = AcpiDsEvalBankFieldOperands (WalkState, Op);
704                if (ACPI_FAILURE (Status))
705                {
706                    break;
707                }
708            }
709            break;
710
711
712        case AML_TYPE_UNDEFINED:
713
714            ACPI_ERROR ((AE_INFO,
715                "Undefined opcode type Op=%p", Op));
716            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
717
718
719        case AML_TYPE_BOGUS:
720
721            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
722                "Internal opcode=%X type Op=%p\n",
723                WalkState->Opcode, Op));
724            break;
725
726
727        default:
728
729            ACPI_ERROR ((AE_INFO,
730                "Unimplemented opcode, class=0x%X type=0x%X Opcode=-0x%X Op=%p",
731                OpClass, OpType, Op->Common.AmlOpcode, Op));
732
733            Status = AE_NOT_IMPLEMENTED;
734            break;
735        }
736    }
737
738    /*
739     * ACPI 2.0 support for 64-bit integers: Truncate numeric
740     * result value if we are executing from a 32-bit ACPI table
741     */
742    AcpiExTruncateFor32bitTable (WalkState->ResultObj);
743
744    /*
745     * Check if we just completed the evaluation of a
746     * conditional predicate
747     */
748    if ((ACPI_SUCCESS (Status)) &&
749        (WalkState->ControlState) &&
750        (WalkState->ControlState->Common.State ==
751            ACPI_CONTROL_PREDICATE_EXECUTING) &&
752        (WalkState->ControlState->Control.PredicateOp == Op))
753    {
754        Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj);
755        WalkState->ResultObj = NULL;
756    }
757
758
759Cleanup:
760
761    if (WalkState->ResultObj)
762    {
763        /* Break to debugger to display result */
764
765        ACPI_DEBUGGER_EXEC (AcpiDbDisplayResultObject (WalkState->ResultObj,
766                                WalkState));
767
768        /*
769         * Delete the result op if and only if:
770         * Parent will not use the result -- such as any
771         * non-nested type2 op in a method (parent will be method)
772         */
773        AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState);
774    }
775
776#ifdef _UNDER_DEVELOPMENT
777
778    if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd)
779    {
780        AcpiDbMethodEnd (WalkState);
781    }
782#endif
783
784    /* Invoke exception handler on error */
785
786    if (ACPI_FAILURE (Status))
787    {
788        Status = AcpiDsMethodError (Status, WalkState);
789    }
790
791    /* Always clear the object stack */
792
793    WalkState->NumOperands = 0;
794    return_ACPI_STATUS (Status);
795}
796