1 /******************************************************************************
2  *
3  * Module Name: aslfold - Constant folding
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "amlcode.h"
47 
48 #include "acdispat.h"
49 #include "acparser.h"
50 
51 #define _COMPONENT          ACPI_COMPILER
52         ACPI_MODULE_NAME    ("aslfold")
53 
54 /* Local prototypes */
55 
56 static ACPI_STATUS
57 OpcAmlEvaluationWalk1 (
58     ACPI_PARSE_OBJECT       *Op,
59     UINT32                  Level,
60     void                    *Context);
61 
62 static ACPI_STATUS
63 OpcAmlEvaluationWalk2 (
64     ACPI_PARSE_OBJECT       *Op,
65     UINT32                  Level,
66     void                    *Context);
67 
68 static ACPI_STATUS
69 OpcAmlCheckForConstant (
70     ACPI_PARSE_OBJECT       *Op,
71     UINT32                  Level,
72     void                    *Context);
73 
74 static void
75 OpcUpdateIntegerNode (
76     ACPI_PARSE_OBJECT       *Op,
77     UINT64                  Value);
78 
79 static ACPI_STATUS
80 TrTransformToStoreOp (
81     ACPI_PARSE_OBJECT       *Op,
82     ACPI_WALK_STATE         *WalkState);
83 
84 static ACPI_STATUS
85 TrSimpleConstantReduction (
86     ACPI_PARSE_OBJECT       *Op,
87     ACPI_WALK_STATE         *WalkState);
88 
89 static void
90 TrInstallReducedConstant (
91     ACPI_PARSE_OBJECT       *Op,
92     ACPI_OPERAND_OBJECT     *ObjDesc);
93 
94 
95 /*******************************************************************************
96  *
97  * FUNCTION:    OpcAmlConstantWalk
98  *
99  * PARAMETERS:  ASL_WALK_CALLBACK
100  *
101  * RETURN:      Status
102  *
103  * DESCRIPTION: Reduce an Op and its subtree to a constant if possible
104  *
105  ******************************************************************************/
106 
107 ACPI_STATUS
108 OpcAmlConstantWalk (
109     ACPI_PARSE_OBJECT       *Op,
110     UINT32                  Level,
111     void                    *Context)
112 {
113     ACPI_WALK_STATE         *WalkState;
114     ACPI_STATUS             Status = AE_OK;
115 
116 
117     if (Op->Asl.CompileFlags == 0)
118     {
119         return (AE_OK);
120     }
121 
122     /*
123      * Only interested in subtrees that could possibly contain
124      * expressions that can be evaluated at this time
125      */
126     if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
127           (Op->Asl.CompileFlags & NODE_IS_TARGET))
128     {
129         return (AE_OK);
130     }
131 
132     /* Create a new walk state */
133 
134     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
135     if (!WalkState)
136     {
137         return (AE_NO_MEMORY);
138     }
139 
140     WalkState->NextOp = NULL;
141     WalkState->Params = NULL;
142 
143     /*
144      * Examine the entire subtree -- all nodes must be constants
145      * or type 3/4/5 opcodes
146      */
147     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
148         OpcAmlCheckForConstant, NULL, WalkState);
149 
150     /*
151      * Did we find an entire subtree that contains all constants
152      * and type 3/4/5 opcodes?
153      */
154     switch (Status)
155     {
156     case AE_OK:
157 
158         /* Simple case, like Add(3,4) -> 7 */
159 
160         Status = TrSimpleConstantReduction (Op, WalkState);
161         break;
162 
163     case AE_CTRL_RETURN_VALUE:
164 
165         /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */
166 
167         Status = TrTransformToStoreOp (Op, WalkState);
168         break;
169 
170     case AE_TYPE:
171 
172         AcpiDsDeleteWalkState (WalkState);
173         return (AE_OK);
174 
175     default:
176         AcpiDsDeleteWalkState (WalkState);
177         break;
178     }
179 
180     if (ACPI_FAILURE (Status))
181     {
182         DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",
183             AcpiFormatException (Status));
184 
185         /* We could not resolve the subtree for some reason */
186 
187         AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
188             (char *) AcpiFormatException (Status));
189 
190         /* Set the subtree value to ZERO anyway. Eliminates further errors */
191 
192         OpcUpdateIntegerNode (Op, 0);
193     }
194 
195     /* Abort the walk of this subtree, we are done with it */
196 
197     return (AE_CTRL_DEPTH);
198 }
199 
200 
201 /*******************************************************************************
202  *
203  * FUNCTION:    OpcAmlCheckForConstant
204  *
205  * PARAMETERS:  ASL_WALK_CALLBACK
206  *
207  * RETURN:      Status
208  *
209  * DESCRIPTION: Check one Op for a type 3/4/5 AML opcode
210  *
211  ******************************************************************************/
212 
213 static ACPI_STATUS
214 OpcAmlCheckForConstant (
215     ACPI_PARSE_OBJECT       *Op,
216     UINT32                  Level,
217     void                    *Context)
218 {
219     ACPI_WALK_STATE         *WalkState = Context;
220     ACPI_STATUS             Status = AE_OK;
221 
222 
223     WalkState->Op = Op;
224     WalkState->Opcode = Op->Common.AmlOpcode;
225     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
226 
227     DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
228         Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
229 
230     /*
231      * TBD: Ignore buffer constants for now. The problem is that these
232      * constants have been transformed into RAW_DATA at this point, from
233      * the parse tree transform process which currently happens before
234      * the constant folding process. We may need to defer this transform
235      * for buffer until after the constant folding.
236      */
237     if (WalkState->Opcode == AML_BUFFER_OP)
238     {
239         DbgPrint (ASL_PARSE_OUTPUT,
240             "\nBuffer+Buffer->Buffer constant reduction is not supported yet");
241         Status = AE_TYPE;
242         goto CleanupAndExit;
243     }
244 
245     /*
246      * These opcodes do not appear in the OpcodeInfo table, but
247      * they represent constants, so abort the constant walk now.
248      */
249     if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||
250         (WalkState->Opcode == AML_RAW_DATA_WORD) ||
251         (WalkState->Opcode == AML_RAW_DATA_DWORD) ||
252         (WalkState->Opcode == AML_RAW_DATA_QWORD))
253     {
254         DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA");
255         Status = AE_TYPE;
256         goto CleanupAndExit;
257     }
258 
259     /* Type 3/4/5 opcodes have the AML_CONSTANT flag set */
260 
261     if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
262     {
263         /* Not 3/4/5 opcode, but maybe can convert to STORE */
264 
265         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
266         {
267             DbgPrint (ASL_PARSE_OUTPUT,
268                 "**** Valid Target, transform to Store ****\n");
269             return (AE_CTRL_RETURN_VALUE);
270         }
271 
272         /* Expression cannot be reduced */
273 
274         DbgPrint (ASL_PARSE_OUTPUT,
275             "**** Not a Type 3/4/5 opcode (%s) ****",
276              Op->Asl.ParseOpName);
277 
278         Status = AE_TYPE;
279         goto CleanupAndExit;
280     }
281 
282     /* Debug output */
283 
284     DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
285 
286     if (Op->Asl.CompileFlags & NODE_IS_TARGET)
287     {
288         if (Op->Asl.ParseOpcode == PARSEOP_ZERO)
289         {
290             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET");
291         }
292         else
293         {
294             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET");
295         }
296     }
297     if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
298     {
299         DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG");
300     }
301 
302 CleanupAndExit:
303 
304     /* Dump the node compile flags also */
305 
306     TrPrintNodeCompileFlags (Op->Asl.CompileFlags);
307     DbgPrint (ASL_PARSE_OUTPUT, "\n");
308     return (Status);
309 }
310 
311 
312 /*******************************************************************************
313  *
314  * FUNCTION:    TrSimpleConstantReduction
315  *
316  * PARAMETERS:  Op                  - Parent operator to be transformed
317  *              WalkState           - Current walk state
318  *
319  * RETURN:      Status
320  *
321  * DESCRIPTION: Reduce an entire AML operation to a single constant. The
322  *              operation must not have a target operand.
323  *
324  *              Add (32,64) --> 96
325  *
326  ******************************************************************************/
327 
328 static ACPI_STATUS
329 TrSimpleConstantReduction (
330     ACPI_PARSE_OBJECT       *Op,
331     ACPI_WALK_STATE         *WalkState)
332 {
333     ACPI_PARSE_OBJECT       *RootOp;
334     ACPI_PARSE_OBJECT       *OriginalParentOp;
335     ACPI_OPERAND_OBJECT     *ObjDesc;
336     ACPI_STATUS             Status;
337 
338 
339     DbgPrint (ASL_PARSE_OUTPUT,
340         "Simple subtree constant reduction, operator to constant\n");
341 
342     /* Allocate a new temporary root for this subtree */
343 
344     RootOp = TrAllocateNode (PARSEOP_INTEGER);
345     if (!RootOp)
346     {
347         return (AE_NO_MEMORY);
348     }
349 
350     RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
351 
352     OriginalParentOp = Op->Common.Parent;
353     Op->Common.Parent = RootOp;
354 
355     /* Hand off the subtree to the AML interpreter */
356 
357     WalkState->CallerReturnDesc = &ObjDesc;
358 
359     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
360         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
361 
362     /* Restore original parse tree */
363 
364     Op->Common.Parent = OriginalParentOp;
365 
366     if (ACPI_FAILURE (Status))
367     {
368         DbgPrint (ASL_PARSE_OUTPUT,
369             "Constant Subtree evaluation(1), %s\n",
370             AcpiFormatException (Status));
371         return (Status);
372     }
373 
374     /* Get the final result */
375 
376     Status = AcpiDsResultPop (&ObjDesc, WalkState);
377     if (ACPI_FAILURE (Status))
378     {
379         DbgPrint (ASL_PARSE_OUTPUT,
380             "Constant Subtree evaluation(2), %s\n",
381             AcpiFormatException (Status));
382         return (Status);
383     }
384 
385     /* Disconnect any existing children, install new constant */
386 
387     Op->Asl.Child = NULL;
388     TrInstallReducedConstant (Op, ObjDesc);
389 
390     UtSetParseOpName (Op);
391     return (AE_OK);
392 }
393 
394 
395 /*******************************************************************************
396  *
397  * FUNCTION:    TrTransformToStoreOp
398  *
399  * PARAMETERS:  Op                  - Parent operator to be transformed
400  *              WalkState           - Current walk state
401  *
402  * RETURN:      Status
403  *
404  * DESCRIPTION: Transforms a single AML operation with a constant and target
405  *              to a simple store operation:
406  *
407  *              Add (32,64,DATA) --> Store (96,DATA)
408  *
409  ******************************************************************************/
410 
411 static ACPI_STATUS
412 TrTransformToStoreOp (
413     ACPI_PARSE_OBJECT       *Op,
414     ACPI_WALK_STATE         *WalkState)
415 {
416     ACPI_PARSE_OBJECT       *OriginalTarget;
417     ACPI_PARSE_OBJECT       *NewTarget;
418     ACPI_PARSE_OBJECT       *Child1;
419     ACPI_PARSE_OBJECT       *Child2;
420     ACPI_OPERAND_OBJECT     *ObjDesc;
421     ACPI_PARSE_OBJECT       *NewParent;
422     ACPI_PARSE_OBJECT       *OriginalParent;
423     ACPI_STATUS             Status;
424 
425 
426     DbgPrint (ASL_PARSE_OUTPUT,
427         "Reduction/Transform to StoreOp: Store(Constant, Target)\n");
428 
429     /* Extract the operands */
430 
431     Child1 = Op->Asl.Child;
432     Child2 = Child1->Asl.Next;
433 
434     /*
435      * Special case for DIVIDE -- it has two targets. The first
436      * is for the remainder and if present, we will not attempt
437      * to reduce the expression.
438      */
439     if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
440     {
441         Child2 = Child2->Asl.Next;
442         if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
443         {
444             DbgPrint (ASL_PARSE_OUTPUT,
445                 "Cannot reduce DIVIDE - has two targets\n\n");
446             return (AE_OK);
447         }
448     }
449 
450     /*
451      * Create a NULL (zero) target so that we can use the
452      * interpreter to evaluate the expression.
453      */
454     NewTarget = TrCreateNullTarget ();
455     NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
456 
457     /* Handle one-operand cases (NOT, TOBCD, etc.) */
458 
459     if (!Child2->Asl.Next)
460     {
461         Child2 = Child1;
462     }
463 
464     /* Link in new NULL target as the last operand */
465 
466     OriginalTarget = Child2->Asl.Next;
467     Child2->Asl.Next = NewTarget;
468     NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
469 
470     NewParent = TrAllocateNode (PARSEOP_INTEGER);
471     NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
472 
473     OriginalParent = Op->Common.Parent;
474     Op->Common.Parent = NewParent;
475 
476     /* Hand off the subtree to the AML interpreter */
477 
478     WalkState->CallerReturnDesc = &ObjDesc;
479 
480     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
481         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
482     if (ACPI_FAILURE (Status))
483     {
484         DbgPrint (ASL_PARSE_OUTPUT,
485             "Constant Subtree evaluation(3), %s\n",
486             AcpiFormatException (Status));
487         goto EvalError;
488     }
489 
490     /* Get the final result */
491 
492     Status = AcpiDsResultPop (&ObjDesc, WalkState);
493     if (ACPI_FAILURE (Status))
494     {
495         DbgPrint (ASL_PARSE_OUTPUT,
496             "Constant Subtree evaluation(4), %s\n",
497             AcpiFormatException (Status));
498         goto EvalError;
499     }
500 
501     /* Truncate any subtree expressions, they have been evaluated */
502 
503     Child1->Asl.Child = NULL;
504 
505     /* Folded constant is in ObjDesc, store into Child1 */
506 
507     TrInstallReducedConstant (Child1, ObjDesc);
508 
509     /* Convert operator to STORE */
510 
511     Op->Asl.ParseOpcode = PARSEOP_STORE;
512     Op->Asl.AmlOpcode = AML_STORE_OP;
513     UtSetParseOpName (Op);
514     Op->Common.Parent = OriginalParent;
515 
516     /* First child is the folded constant */
517 
518     /* Second child will be the target */
519 
520     Child1->Asl.Next = OriginalTarget;
521     return (AE_OK);
522 
523 
524 EvalError:
525 
526     /* Restore original links */
527 
528     Op->Common.Parent = OriginalParent;
529     Child2->Asl.Next = OriginalTarget;
530     return (Status);
531 }
532 
533 
534 /*******************************************************************************
535  *
536  * FUNCTION:    TrInstallReducedConstant
537  *
538  * PARAMETERS:  Op                  - Parent operator to be transformed
539  *              ObjDesc             - Reduced constant to be installed
540  *
541  * RETURN:      None
542  *
543  * DESCRIPTION: Transform the original operator to a simple constant.
544  *              Handles Integers, Strings, and Buffers.
545  *
546  ******************************************************************************/
547 
548 static void
549 TrInstallReducedConstant (
550     ACPI_PARSE_OBJECT       *Op,
551     ACPI_OPERAND_OBJECT     *ObjDesc)
552 {
553     ACPI_PARSE_OBJECT       *LengthOp;
554     ACPI_PARSE_OBJECT       *DataOp;
555 
556 
557     TotalFolds++;
558     AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
559         Op->Asl.ParseOpName);
560 
561     /*
562      * Because we know we executed type 3/4/5 opcodes above, we know that
563      * the result must be either an Integer, String, or Buffer.
564      */
565     switch (ObjDesc->Common.Type)
566     {
567     case ACPI_TYPE_INTEGER:
568 
569         OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
570 
571         DbgPrint (ASL_PARSE_OUTPUT,
572             "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
573             Op->Asl.ParseOpName,
574             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
575         break;
576 
577     case ACPI_TYPE_STRING:
578 
579         Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
580         Op->Common.AmlOpcode = AML_STRING_OP;
581         Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
582         Op->Common.Value.String = ObjDesc->String.Pointer;
583 
584         DbgPrint (ASL_PARSE_OUTPUT,
585             "Constant expression reduced to (STRING) %s\n\n",
586             Op->Common.Value.String);
587         break;
588 
589     case ACPI_TYPE_BUFFER:
590         /*
591          * Create a new parse subtree of the form:
592          *
593          * BUFFER (Buffer AML opcode)
594          *    INTEGER (Buffer length in bytes)
595          *    RAW_DATA (Buffer byte data)
596          */
597         Op->Asl.ParseOpcode = PARSEOP_BUFFER;
598         Op->Common.AmlOpcode = AML_BUFFER_OP;
599         Op->Asl.CompileFlags = NODE_AML_PACKAGE;
600         UtSetParseOpName (Op);
601 
602         /* Child node is the buffer length */
603 
604         LengthOp = TrAllocateNode (PARSEOP_INTEGER);
605 
606         LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
607         LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
608         LengthOp->Asl.Parent = Op;
609         (void) OpcSetOptimalIntegerSize (LengthOp);
610 
611         Op->Asl.Child = LengthOp;
612 
613         /* Next child is the raw buffer data */
614 
615         DataOp = TrAllocateNode (PARSEOP_RAW_DATA);
616         DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
617         DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
618         DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
619         DataOp->Asl.Parent = Op;
620 
621         LengthOp->Asl.Next = DataOp;
622 
623         DbgPrint (ASL_PARSE_OUTPUT,
624             "Constant expression reduced to (BUFFER) length %X\n\n",
625             ObjDesc->Buffer.Length);
626         break;
627 
628     default:
629         break;
630     }
631 }
632 
633 
634 /*******************************************************************************
635  *
636  * FUNCTION:    OpcUpdateIntegerNode
637  *
638  * PARAMETERS:  Op                  - Current parse object
639  *              Value               - Value for the integer op
640  *
641  * RETURN:      None
642  *
643  * DESCRIPTION: Update node to the correct Integer type and value
644  *
645  ******************************************************************************/
646 
647 static void
648 OpcUpdateIntegerNode (
649     ACPI_PARSE_OBJECT       *Op,
650     UINT64                  Value)
651 {
652 
653     Op->Common.Value.Integer = Value;
654 
655     /*
656      * The AmlLength is used by the parser to indicate a constant,
657      * (if non-zero). Length is either (1/2/4/8)
658      */
659     switch (Op->Asl.AmlLength)
660     {
661     case 1:
662 
663         TrUpdateNode (PARSEOP_BYTECONST, Op);
664         Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
665         break;
666 
667     case 2:
668 
669         TrUpdateNode (PARSEOP_WORDCONST, Op);
670         Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
671         break;
672 
673     case 4:
674 
675         TrUpdateNode (PARSEOP_DWORDCONST, Op);
676         Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
677         break;
678 
679     case 8:
680 
681         TrUpdateNode (PARSEOP_QWORDCONST, Op);
682         Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
683         break;
684 
685     case 0:
686     default:
687 
688         OpcSetOptimalIntegerSize (Op);
689         TrUpdateNode (PARSEOP_INTEGER, Op);
690         break;
691     }
692 
693     Op->Asl.AmlLength = 0;
694 }
695 
696 
697 /*******************************************************************************
698  *
699  * FUNCTION:    OpcAmlEvaluationWalk1
700  *
701  * PARAMETERS:  ASL_WALK_CALLBACK
702  *
703  * RETURN:      Status
704  *
705  * DESCRIPTION: Descending callback for AML execution of constant subtrees
706  *
707  ******************************************************************************/
708 
709 static ACPI_STATUS
710 OpcAmlEvaluationWalk1 (
711     ACPI_PARSE_OBJECT       *Op,
712     UINT32                  Level,
713     void                    *Context)
714 {
715     ACPI_WALK_STATE         *WalkState = Context;
716     ACPI_STATUS             Status;
717     ACPI_PARSE_OBJECT       *OutOp;
718 
719 
720     WalkState->Op = Op;
721     WalkState->Opcode = Op->Common.AmlOpcode;
722     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
723 
724     /* Copy child pointer to Arg for compatibility with Interpreter */
725 
726     if (Op->Asl.Child)
727     {
728         Op->Common.Value.Arg = Op->Asl.Child;
729     }
730 
731     /* Call AML dispatcher */
732 
733     Status = AcpiDsExecBeginOp (WalkState, &OutOp);
734     if (ACPI_FAILURE (Status))
735     {
736         DbgPrint (ASL_PARSE_OUTPUT,
737             "%s Constant interpretation failed (1) - %s\n",
738             Op->Asl.ParseOpName, AcpiFormatException (Status));
739     }
740 
741     return (Status);
742 }
743 
744 
745 /*******************************************************************************
746  *
747  * FUNCTION:    OpcAmlEvaluationWalk2
748  *
749  * PARAMETERS:  ASL_WALK_CALLBACK
750  *
751  * RETURN:      Status
752  *
753  * DESCRIPTION: Ascending callback for AML execution of constant subtrees
754  *
755  ******************************************************************************/
756 
757 static ACPI_STATUS
758 OpcAmlEvaluationWalk2 (
759     ACPI_PARSE_OBJECT       *Op,
760     UINT32                  Level,
761     void                    *Context)
762 {
763     ACPI_WALK_STATE         *WalkState = Context;
764     ACPI_STATUS             Status;
765 
766 
767     WalkState->Op = Op;
768     WalkState->Opcode = Op->Common.AmlOpcode;
769     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
770 
771     /* Copy child pointer to Arg for compatibility with Interpreter */
772 
773     if (Op->Asl.Child)
774     {
775         Op->Common.Value.Arg = Op->Asl.Child;
776     }
777 
778     /* Call AML dispatcher */
779 
780     Status = AcpiDsExecEndOp (WalkState);
781     if (ACPI_FAILURE (Status))
782     {
783         DbgPrint (ASL_PARSE_OUTPUT,
784             "%s: Constant interpretation failed (2) - %s\n",
785             Op->Asl.ParseOpName, AcpiFormatException (Status));
786     }
787 
788     return (Status);
789 }
790