1100966Siwasaki/*******************************************************************************
2100966Siwasaki *
3100966Siwasaki * Module Name: dmopcode - AML disassembler, specific AML opcodes
4100966Siwasaki *
5100966Siwasaki ******************************************************************************/
6100966Siwasaki
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9100966Siwasaki * All rights reserved.
10100966Siwasaki *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25100966Siwasaki *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29100966Siwasaki *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43100966Siwasaki
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acparser.h>
47193341Sjkim#include <contrib/dev/acpica/include/amlcode.h>
48281075Sdim#include <contrib/dev/acpica/include/acinterp.h>
49281075Sdim#include <contrib/dev/acpica/include/acnamesp.h>
50306536Sjkim#include <contrib/dev/acpica/include/acdebug.h>
51100966Siwasaki
52100966Siwasaki
53102550Siwasaki#define _COMPONENT          ACPI_CA_DEBUGGER
54100966Siwasaki        ACPI_MODULE_NAME    ("dmopcode")
55100966Siwasaki
56281075Sdim
57151937Sjkim/* Local prototypes */
58100966Siwasaki
59151937Sjkimstatic void
60151937SjkimAcpiDmMatchKeyword (
61151937Sjkim    ACPI_PARSE_OBJECT       *Op);
62151937Sjkim
63306536Sjkimstatic void
64306536SjkimAcpiDmConvertToElseIf (
65306536Sjkim    ACPI_PARSE_OBJECT       *Op);
66151937Sjkim
67306536Sjkim
68100966Siwasaki/*******************************************************************************
69100966Siwasaki *
70281075Sdim * FUNCTION:    AcpiDmDisplayTargetPathname
71281075Sdim *
72281075Sdim * PARAMETERS:  Op              - Parse object
73281075Sdim *
74281075Sdim * RETURN:      None
75281075Sdim *
76281075Sdim * DESCRIPTION: For AML opcodes that have a target operand, display the full
77281075Sdim *              pathname for the target, in a comment field. Handles Return()
78281075Sdim *              statements also.
79281075Sdim *
80281075Sdim ******************************************************************************/
81281075Sdim
82281075Sdimvoid
83281075SdimAcpiDmDisplayTargetPathname (
84281075Sdim    ACPI_PARSE_OBJECT       *Op)
85281075Sdim{
86281075Sdim    ACPI_PARSE_OBJECT       *NextOp;
87281075Sdim    ACPI_PARSE_OBJECT       *PrevOp = NULL;
88281075Sdim    char                    *Pathname;
89281075Sdim    const ACPI_OPCODE_INFO  *OpInfo;
90281075Sdim
91281075Sdim
92281075Sdim    if (Op->Common.AmlOpcode == AML_RETURN_OP)
93281075Sdim    {
94281075Sdim        PrevOp = Op->Asl.Value.Arg;
95281075Sdim    }
96281075Sdim    else
97281075Sdim    {
98281075Sdim        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
99281075Sdim        if (!(OpInfo->Flags & AML_HAS_TARGET))
100281075Sdim        {
101281075Sdim            return;
102281075Sdim        }
103281075Sdim
104281075Sdim        /* Target is the last Op in the arg list */
105281075Sdim
106281075Sdim        NextOp = Op->Asl.Value.Arg;
107281075Sdim        while (NextOp)
108281075Sdim        {
109281075Sdim            PrevOp = NextOp;
110281075Sdim            NextOp = PrevOp->Asl.Next;
111281075Sdim        }
112281075Sdim    }
113281075Sdim
114281075Sdim    if (!PrevOp)
115281075Sdim    {
116281075Sdim        return;
117281075Sdim    }
118281075Sdim
119281075Sdim    /* We must have a namepath AML opcode */
120281075Sdim
121281075Sdim    if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
122281075Sdim    {
123281075Sdim        return;
124281075Sdim    }
125281075Sdim
126281075Sdim    /* A null string is the "no target specified" case */
127281075Sdim
128281075Sdim    if (!PrevOp->Asl.Value.String)
129281075Sdim    {
130281075Sdim        return;
131281075Sdim    }
132281075Sdim
133281075Sdim    /* No node means "unresolved external reference" */
134281075Sdim
135281075Sdim    if (!PrevOp->Asl.Node)
136281075Sdim    {
137281075Sdim        AcpiOsPrintf (" /* External reference */");
138281075Sdim        return;
139281075Sdim    }
140281075Sdim
141281075Sdim    /* Ignore if path is already from the root */
142281075Sdim
143281075Sdim    if (*PrevOp->Asl.Value.String == '\\')
144281075Sdim    {
145281075Sdim        return;
146281075Sdim    }
147281075Sdim
148281075Sdim    /* Now: we can get the full pathname */
149281075Sdim
150281075Sdim    Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
151281075Sdim    if (!Pathname)
152281075Sdim    {
153281075Sdim        return;
154281075Sdim    }
155281075Sdim
156281075Sdim    AcpiOsPrintf (" /* %s */", Pathname);
157281075Sdim    ACPI_FREE (Pathname);
158281075Sdim}
159281075Sdim
160281075Sdim
161281075Sdim/*******************************************************************************
162281075Sdim *
163281075Sdim * FUNCTION:    AcpiDmNotifyDescription
164281075Sdim *
165281075Sdim * PARAMETERS:  Op              - Name() parse object
166281075Sdim *
167281075Sdim * RETURN:      None
168281075Sdim *
169281075Sdim * DESCRIPTION: Emit a description comment for the value associated with a
170281075Sdim *              Notify() operator.
171281075Sdim *
172281075Sdim ******************************************************************************/
173281075Sdim
174281075Sdimvoid
175281075SdimAcpiDmNotifyDescription (
176281075Sdim    ACPI_PARSE_OBJECT       *Op)
177281075Sdim{
178281075Sdim    ACPI_PARSE_OBJECT       *NextOp;
179281075Sdim    ACPI_NAMESPACE_NODE     *Node;
180281075Sdim    UINT8                   NotifyValue;
181281075Sdim    UINT8                   Type = ACPI_TYPE_ANY;
182281075Sdim
183281075Sdim
184281075Sdim    /* The notify value is the second argument */
185281075Sdim
186281075Sdim    NextOp = Op->Asl.Value.Arg;
187281075Sdim    NextOp = NextOp->Asl.Next;
188281075Sdim
189281075Sdim    switch (NextOp->Common.AmlOpcode)
190281075Sdim    {
191281075Sdim    case AML_ZERO_OP:
192281075Sdim    case AML_ONE_OP:
193281075Sdim
194281075Sdim        NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
195281075Sdim        break;
196281075Sdim
197281075Sdim    case AML_BYTE_OP:
198281075Sdim
199281075Sdim        NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
200281075Sdim        break;
201281075Sdim
202281075Sdim    default:
203281075Sdim        return;
204281075Sdim    }
205281075Sdim
206281075Sdim    /*
207281075Sdim     * Attempt to get the namespace node so we can determine the object type.
208281075Sdim     * Some notify values are dependent on the object type (Device, Thermal,
209281075Sdim     * or Processor).
210281075Sdim     */
211281075Sdim    Node = Op->Asl.Node;
212281075Sdim    if (Node)
213281075Sdim    {
214281075Sdim        Type = Node->Type;
215281075Sdim    }
216281075Sdim
217281075Sdim    AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
218281075Sdim}
219281075Sdim
220281075Sdim
221281075Sdim/*******************************************************************************
222281075Sdim *
223237412Sjkim * FUNCTION:    AcpiDmPredefinedDescription
224237412Sjkim *
225237412Sjkim * PARAMETERS:  Op              - Name() parse object
226237412Sjkim *
227237412Sjkim * RETURN:      None
228237412Sjkim *
229237412Sjkim * DESCRIPTION: Emit a description comment for a predefined ACPI name.
230237412Sjkim *              Used for iASL compiler only.
231237412Sjkim *
232237412Sjkim ******************************************************************************/
233237412Sjkim
234237412Sjkimvoid
235237412SjkimAcpiDmPredefinedDescription (
236237412Sjkim    ACPI_PARSE_OBJECT       *Op)
237237412Sjkim{
238237412Sjkim#ifdef ACPI_ASL_COMPILER
239237412Sjkim    const AH_PREDEFINED_NAME    *Info;
240237412Sjkim    char                        *NameString;
241237412Sjkim    int                         LastCharIsDigit;
242237412Sjkim    int                         LastCharsAreHex;
243237412Sjkim
244237412Sjkim
245237412Sjkim    if (!Op)
246237412Sjkim    {
247237412Sjkim        return;
248237412Sjkim    }
249237412Sjkim
250237412Sjkim    /* Ensure that the comment field is emitted only once */
251237412Sjkim
252306536Sjkim    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
253237412Sjkim    {
254237412Sjkim        return;
255237412Sjkim    }
256306536Sjkim    Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
257237412Sjkim
258237412Sjkim    /* Predefined name must start with an underscore */
259237412Sjkim
260237412Sjkim    NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
261237412Sjkim    if (NameString[0] != '_')
262237412Sjkim    {
263237412Sjkim        return;
264237412Sjkim    }
265237412Sjkim
266237412Sjkim    /*
267237412Sjkim     * Check for the special ACPI names:
268237412Sjkim     * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
269237412Sjkim     * (where d=decimal_digit, x=hex_digit, a=anything)
270237412Sjkim     *
271237412Sjkim     * Convert these to the generic name for table lookup.
272237412Sjkim     * Note: NameString is guaranteed to be upper case here.
273237412Sjkim     */
274237412Sjkim    LastCharIsDigit =
275306536Sjkim        (isdigit ((int) NameString[3]));    /* d */
276237412Sjkim    LastCharsAreHex =
277306536Sjkim        (isxdigit ((int) NameString[2]) &&  /* xx */
278306536Sjkim         isxdigit ((int) NameString[3]));
279237412Sjkim
280237412Sjkim    switch (NameString[1])
281237412Sjkim    {
282237412Sjkim    case 'A':
283250838Sjkim
284237412Sjkim        if ((NameString[2] == 'C') && (LastCharIsDigit))
285237412Sjkim        {
286237412Sjkim            NameString = "_ACx";
287237412Sjkim        }
288237412Sjkim        else if ((NameString[2] == 'L') && (LastCharIsDigit))
289237412Sjkim        {
290237412Sjkim            NameString = "_ALx";
291237412Sjkim        }
292237412Sjkim        break;
293237412Sjkim
294237412Sjkim    case 'E':
295250838Sjkim
296237412Sjkim        if ((NameString[2] == 'J') && (LastCharIsDigit))
297237412Sjkim        {
298237412Sjkim            NameString = "_EJx";
299237412Sjkim        }
300237412Sjkim        else if (LastCharsAreHex)
301237412Sjkim        {
302237412Sjkim            NameString = "_Exx";
303237412Sjkim        }
304237412Sjkim        break;
305237412Sjkim
306237412Sjkim    case 'L':
307250838Sjkim
308237412Sjkim        if (LastCharsAreHex)
309237412Sjkim        {
310237412Sjkim            NameString = "_Lxx";
311237412Sjkim        }
312237412Sjkim        break;
313237412Sjkim
314237412Sjkim    case 'Q':
315250838Sjkim
316237412Sjkim        if (LastCharsAreHex)
317237412Sjkim        {
318237412Sjkim            NameString = "_Qxx";
319237412Sjkim        }
320237412Sjkim        break;
321237412Sjkim
322237412Sjkim    case 'T':
323250838Sjkim
324237412Sjkim        if (NameString[2] == '_')
325237412Sjkim        {
326237412Sjkim            NameString = "_T_x";
327237412Sjkim        }
328237412Sjkim        break;
329237412Sjkim
330237412Sjkim    case 'W':
331250838Sjkim
332237412Sjkim        if (LastCharsAreHex)
333237412Sjkim        {
334237412Sjkim            NameString = "_Wxx";
335237412Sjkim        }
336237412Sjkim        break;
337237412Sjkim
338237412Sjkim    default:
339250838Sjkim
340237412Sjkim        break;
341237412Sjkim    }
342237412Sjkim
343237412Sjkim    /* Match the name in the info table */
344237412Sjkim
345281075Sdim    Info = AcpiAhMatchPredefinedName (NameString);
346281075Sdim    if (Info)
347237412Sjkim    {
348281075Sdim        AcpiOsPrintf ("  // %4.4s: %s",
349281075Sdim            NameString, ACPI_CAST_PTR (char, Info->Description));
350237412Sjkim    }
351237412Sjkim
352237412Sjkim#endif
353237412Sjkim    return;
354237412Sjkim}
355237412Sjkim
356237412Sjkim
357237412Sjkim/*******************************************************************************
358237412Sjkim *
359237412Sjkim * FUNCTION:    AcpiDmFieldPredefinedDescription
360237412Sjkim *
361237412Sjkim * PARAMETERS:  Op              - Parse object
362237412Sjkim *
363237412Sjkim * RETURN:      None
364237412Sjkim *
365237412Sjkim * DESCRIPTION: Emit a description comment for a resource descriptor tag
366237412Sjkim *              (which is a predefined ACPI name.) Used for iASL compiler only.
367237412Sjkim *
368237412Sjkim ******************************************************************************/
369237412Sjkim
370237412Sjkimvoid
371237412SjkimAcpiDmFieldPredefinedDescription (
372237412Sjkim    ACPI_PARSE_OBJECT       *Op)
373237412Sjkim{
374237412Sjkim#ifdef ACPI_ASL_COMPILER
375237412Sjkim    ACPI_PARSE_OBJECT       *IndexOp;
376237412Sjkim    char                    *Tag;
377237412Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
378237412Sjkim    const AH_PREDEFINED_NAME *Info;
379237412Sjkim
380237412Sjkim
381237412Sjkim    if (!Op)
382237412Sjkim    {
383237412Sjkim        return;
384237412Sjkim    }
385237412Sjkim
386237412Sjkim    /* Ensure that the comment field is emitted only once */
387237412Sjkim
388306536Sjkim    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
389237412Sjkim    {
390237412Sjkim        return;
391237412Sjkim    }
392306536Sjkim    Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
393237412Sjkim
394237412Sjkim    /*
395237412Sjkim     * Op must be one of the Create* operators: CreateField, CreateBitField,
396237412Sjkim     * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
397237412Sjkim     */
398237412Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
399237412Sjkim    if (!(OpInfo->Flags & AML_CREATE))
400237412Sjkim    {
401237412Sjkim        return;
402237412Sjkim    }
403237412Sjkim
404237412Sjkim    /* Second argument is the Index argument */
405237412Sjkim
406237412Sjkim    IndexOp = Op->Common.Value.Arg;
407237412Sjkim    IndexOp = IndexOp->Common.Next;
408237412Sjkim
409237412Sjkim    /* Index argument must be a namepath */
410237412Sjkim
411237412Sjkim    if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
412237412Sjkim    {
413237412Sjkim        return;
414237412Sjkim    }
415237412Sjkim
416237412Sjkim    /* Major cheat: We previously put the Tag ptr in the Node field */
417237412Sjkim
418237412Sjkim    Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
419240716Sjkim    if (!Tag)
420240716Sjkim    {
421240716Sjkim        return;
422240716Sjkim    }
423237412Sjkim
424237412Sjkim    /* Match the name in the info table */
425237412Sjkim
426281075Sdim    Info = AcpiAhMatchPredefinedName (Tag);
427281075Sdim    if (Info)
428237412Sjkim    {
429281075Sdim        AcpiOsPrintf ("  // %4.4s: %s", Tag,
430281075Sdim            ACPI_CAST_PTR (char, Info->Description));
431237412Sjkim    }
432237412Sjkim
433237412Sjkim#endif
434237412Sjkim    return;
435237412Sjkim}
436237412Sjkim
437237412Sjkim
438237412Sjkim/*******************************************************************************
439237412Sjkim *
440100966Siwasaki * FUNCTION:    AcpiDmMethodFlags
441100966Siwasaki *
442100966Siwasaki * PARAMETERS:  Op              - Method Object to be examined
443100966Siwasaki *
444100966Siwasaki * RETURN:      None
445100966Siwasaki *
446100966Siwasaki * DESCRIPTION: Decode control method flags
447100966Siwasaki *
448100966Siwasaki ******************************************************************************/
449100966Siwasaki
450100966Siwasakivoid
451100966SiwasakiAcpiDmMethodFlags (
452100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
453100966Siwasaki{
454100966Siwasaki    UINT32                  Flags;
455100966Siwasaki    UINT32                  Args;
456100966Siwasaki
457100966Siwasaki
458100966Siwasaki    /* The next Op contains the flags */
459100966Siwasaki
460100966Siwasaki    Op = AcpiPsGetDepthNext (NULL, Op);
461117521Snjl    Flags = (UINT8) Op->Common.Value.Integer;
462100966Siwasaki    Args = Flags & 0x07;
463100966Siwasaki
464100966Siwasaki    /* Mark the Op as completed */
465100966Siwasaki
466100966Siwasaki    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
467100966Siwasaki
468100966Siwasaki    /* 1) Method argument count */
469100966Siwasaki
470209746Sjkim    AcpiOsPrintf (", %u, ", Args);
471100966Siwasaki
472100966Siwasaki    /* 2) Serialize rule */
473100966Siwasaki
474100966Siwasaki    if (!(Flags & 0x08))
475100966Siwasaki    {
476100966Siwasaki        AcpiOsPrintf ("Not");
477100966Siwasaki    }
478100966Siwasaki
479100966Siwasaki    AcpiOsPrintf ("Serialized");
480100966Siwasaki
481100966Siwasaki    /* 3) SyncLevel */
482100966Siwasaki
483100966Siwasaki    if (Flags & 0xF0)
484100966Siwasaki    {
485209746Sjkim        AcpiOsPrintf (", %u", Flags >> 4);
486100966Siwasaki    }
487100966Siwasaki}
488100966Siwasaki
489100966Siwasaki
490100966Siwasaki/*******************************************************************************
491100966Siwasaki *
492100966Siwasaki * FUNCTION:    AcpiDmFieldFlags
493100966Siwasaki *
494100966Siwasaki * PARAMETERS:  Op              - Field Object to be examined
495100966Siwasaki *
496100966Siwasaki * RETURN:      None
497100966Siwasaki *
498100966Siwasaki * DESCRIPTION: Decode Field definition flags
499100966Siwasaki *
500100966Siwasaki ******************************************************************************/
501100966Siwasaki
502100966Siwasakivoid
503100966SiwasakiAcpiDmFieldFlags (
504100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
505100966Siwasaki{
506100966Siwasaki    UINT32                  Flags;
507100966Siwasaki
508100966Siwasaki
509167802Sjkim    Op = Op->Common.Next;
510117521Snjl    Flags = (UINT8) Op->Common.Value.Integer;
511100966Siwasaki
512100966Siwasaki    /* Mark the Op as completed */
513100966Siwasaki
514100966Siwasaki    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
515100966Siwasaki
516167802Sjkim    AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
517100966Siwasaki    AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
518100966Siwasaki    AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
519100966Siwasaki}
520100966Siwasaki
521100966Siwasaki
522100966Siwasaki/*******************************************************************************
523100966Siwasaki *
524100966Siwasaki * FUNCTION:    AcpiDmAddressSpace
525100966Siwasaki *
526100966Siwasaki * PARAMETERS:  SpaceId         - ID to be translated
527100966Siwasaki *
528100966Siwasaki * RETURN:      None
529100966Siwasaki *
530100966Siwasaki * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
531100966Siwasaki *
532100966Siwasaki ******************************************************************************/
533100966Siwasaki
534100966Siwasakivoid
535100966SiwasakiAcpiDmAddressSpace (
536100966Siwasaki    UINT8                   SpaceId)
537100966Siwasaki{
538100966Siwasaki
539100966Siwasaki    if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
540100966Siwasaki    {
541100966Siwasaki        if (SpaceId == 0x7F)
542100966Siwasaki        {
543100966Siwasaki            AcpiOsPrintf ("FFixedHW, ");
544100966Siwasaki        }
545100966Siwasaki        else
546100966Siwasaki        {
547100966Siwasaki            AcpiOsPrintf ("0x%.2X, ", SpaceId);
548100966Siwasaki        }
549100966Siwasaki    }
550100966Siwasaki    else
551100966Siwasaki    {
552100966Siwasaki        AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
553100966Siwasaki    }
554100966Siwasaki}
555100966Siwasaki
556100966Siwasaki
557100966Siwasaki/*******************************************************************************
558100966Siwasaki *
559100966Siwasaki * FUNCTION:    AcpiDmRegionFlags
560100966Siwasaki *
561100966Siwasaki * PARAMETERS:  Op              - Object to be examined
562100966Siwasaki *
563100966Siwasaki * RETURN:      None
564100966Siwasaki *
565100966Siwasaki * DESCRIPTION: Decode OperationRegion flags
566100966Siwasaki *
567100966Siwasaki ******************************************************************************/
568100966Siwasaki
569100966Siwasakivoid
570100966SiwasakiAcpiDmRegionFlags (
571100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
572100966Siwasaki{
573100966Siwasaki
574100966Siwasaki    /* The next Op contains the SpaceId */
575100966Siwasaki
576100966Siwasaki    Op = AcpiPsGetDepthNext (NULL, Op);
577100966Siwasaki
578100966Siwasaki    /* Mark the Op as completed */
579100966Siwasaki
580100966Siwasaki    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
581100966Siwasaki
582100966Siwasaki    AcpiOsPrintf (", ");
583117521Snjl    AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
584100966Siwasaki}
585100966Siwasaki
586100966Siwasaki
587100966Siwasaki/*******************************************************************************
588100966Siwasaki *
589100966Siwasaki * FUNCTION:    AcpiDmMatchOp
590100966Siwasaki *
591100966Siwasaki * PARAMETERS:  Op              - Match Object to be examined
592100966Siwasaki *
593100966Siwasaki * RETURN:      None
594100966Siwasaki *
595100966Siwasaki * DESCRIPTION: Decode Match opcode operands
596100966Siwasaki *
597100966Siwasaki ******************************************************************************/
598100966Siwasaki
599100966Siwasakivoid
600100966SiwasakiAcpiDmMatchOp (
601100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
602100966Siwasaki{
603100966Siwasaki    ACPI_PARSE_OBJECT       *NextOp;
604100966Siwasaki
605100966Siwasaki
606100966Siwasaki    NextOp = AcpiPsGetDepthNext (NULL, Op);
607100966Siwasaki    NextOp = NextOp->Common.Next;
608100966Siwasaki
609100966Siwasaki    if (!NextOp)
610100966Siwasaki    {
611100966Siwasaki        /* Handle partial tree during single-step */
612100966Siwasaki
613100966Siwasaki        return;
614100966Siwasaki    }
615100966Siwasaki
616100966Siwasaki    /* Mark the two nodes that contain the encoding for the match keywords */
617100966Siwasaki
618100966Siwasaki    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
619100966Siwasaki
620100966Siwasaki    NextOp = NextOp->Common.Next;
621100966Siwasaki    NextOp = NextOp->Common.Next;
622100966Siwasaki    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
623100966Siwasaki}
624100966Siwasaki
625100966Siwasaki
626100966Siwasaki/*******************************************************************************
627100966Siwasaki *
628100966Siwasaki * FUNCTION:    AcpiDmMatchKeyword
629100966Siwasaki *
630100966Siwasaki * PARAMETERS:  Op              - Match Object to be examined
631100966Siwasaki *
632100966Siwasaki * RETURN:      None
633100966Siwasaki *
634100966Siwasaki * DESCRIPTION: Decode Match opcode operands
635100966Siwasaki *
636100966Siwasaki ******************************************************************************/
637100966Siwasaki
638151937Sjkimstatic void
639100966SiwasakiAcpiDmMatchKeyword (
640100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
641100966Siwasaki{
642100966Siwasaki
643167802Sjkim    if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
644100966Siwasaki    {
645100966Siwasaki        AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
646100966Siwasaki    }
647100966Siwasaki    else
648100966Siwasaki    {
649306536Sjkim        AcpiOsPrintf ("%s",
650306536Sjkim            AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
651100966Siwasaki    }
652100966Siwasaki}
653100966Siwasaki
654100966Siwasaki
655100966Siwasaki/*******************************************************************************
656100966Siwasaki *
657100966Siwasaki * FUNCTION:    AcpiDmDisassembleOneOp
658100966Siwasaki *
659100966Siwasaki * PARAMETERS:  WalkState           - Current walk info
660100966Siwasaki *              Info                - Parse tree walk info
661100966Siwasaki *              Op                  - Op that is to be printed
662100966Siwasaki *
663100966Siwasaki * RETURN:      None
664100966Siwasaki *
665100966Siwasaki * DESCRIPTION: Disassemble a single AML opcode
666100966Siwasaki *
667100966Siwasaki ******************************************************************************/
668100966Siwasaki
669100966Siwasakivoid
670100966SiwasakiAcpiDmDisassembleOneOp (
671100966Siwasaki    ACPI_WALK_STATE         *WalkState,
672100966Siwasaki    ACPI_OP_WALK_INFO       *Info,
673100966Siwasaki    ACPI_PARSE_OBJECT       *Op)
674100966Siwasaki{
675100966Siwasaki    const ACPI_OPCODE_INFO  *OpInfo = NULL;
676100966Siwasaki    UINT32                  Offset;
677100966Siwasaki    UINT32                  Length;
678167802Sjkim    ACPI_PARSE_OBJECT       *Child;
679167802Sjkim    ACPI_STATUS             Status;
680228110Sjkim    UINT8                   *Aml;
681281075Sdim    const AH_DEVICE_ID      *IdInfo;
682100966Siwasaki
683100966Siwasaki
684100966Siwasaki    if (!Op)
685100966Siwasaki    {
686100966Siwasaki        AcpiOsPrintf ("<NULL OP PTR>");
687100966Siwasaki        return;
688100966Siwasaki    }
689100966Siwasaki
690306536Sjkim    if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
691306536Sjkim    {
692306536Sjkim        return; /* ElseIf macro was already emitted */
693306536Sjkim    }
694306536Sjkim
695100966Siwasaki    switch (Op->Common.DisasmOpcode)
696100966Siwasaki    {
697100966Siwasaki    case ACPI_DASM_MATCHOP:
698100966Siwasaki
699100966Siwasaki        AcpiDmMatchKeyword (Op);
700100966Siwasaki        return;
701100966Siwasaki
702167802Sjkim    case ACPI_DASM_LNOT_SUFFIX:
703250838Sjkim
704281075Sdim        if (!AcpiGbl_CstyleDisassembly)
705167802Sjkim        {
706281075Sdim            switch (Op->Common.AmlOpcode)
707281075Sdim            {
708281075Sdim            case AML_LEQUAL_OP:
709281075Sdim                AcpiOsPrintf ("LNotEqual");
710281075Sdim                break;
711250838Sjkim
712281075Sdim            case AML_LGREATER_OP:
713281075Sdim                AcpiOsPrintf ("LLessEqual");
714281075Sdim                break;
715167802Sjkim
716281075Sdim            case AML_LLESS_OP:
717281075Sdim                AcpiOsPrintf ("LGreaterEqual");
718281075Sdim                break;
719250838Sjkim
720281075Sdim            default:
721281075Sdim                break;
722281075Sdim            }
723281075Sdim        }
724167802Sjkim
725167802Sjkim        Op->Common.DisasmOpcode = 0;
726167802Sjkim        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
727167802Sjkim        return;
728167802Sjkim
729100966Siwasaki    default:
730100966Siwasaki        break;
731100966Siwasaki    }
732100966Siwasaki
733167802Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
734167802Sjkim
735117521Snjl    /* The op and arguments */
736100966Siwasaki
737100966Siwasaki    switch (Op->Common.AmlOpcode)
738100966Siwasaki    {
739167802Sjkim    case AML_LNOT_OP:
740100966Siwasaki
741167802Sjkim        Child = Op->Common.Value.Arg;
742167802Sjkim        if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
743167802Sjkim            (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
744167802Sjkim            (Child->Common.AmlOpcode == AML_LLESS_OP))
745167802Sjkim        {
746167802Sjkim            Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
747167802Sjkim            Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
748167802Sjkim        }
749167802Sjkim        else
750167802Sjkim        {
751167802Sjkim            AcpiOsPrintf ("%s", OpInfo->Name);
752167802Sjkim        }
753100966Siwasaki        break;
754100966Siwasaki
755100966Siwasaki    case AML_BYTE_OP:
756100966Siwasaki
757117521Snjl        AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
758100966Siwasaki        break;
759100966Siwasaki
760100966Siwasaki    case AML_WORD_OP:
761100966Siwasaki
762100966Siwasaki        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
763100966Siwasaki        {
764281075Sdim            AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
765100966Siwasaki        }
766100966Siwasaki        else
767100966Siwasaki        {
768117521Snjl            AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
769100966Siwasaki        }
770100966Siwasaki        break;
771100966Siwasaki
772100966Siwasaki    case AML_DWORD_OP:
773100966Siwasaki
774100966Siwasaki        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
775100966Siwasaki        {
776281075Sdim            AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
777100966Siwasaki        }
778100966Siwasaki        else
779100966Siwasaki        {
780117521Snjl            AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
781100966Siwasaki        }
782100966Siwasaki        break;
783100966Siwasaki
784100966Siwasaki    case AML_QWORD_OP:
785100966Siwasaki
786202771Sjkim        AcpiOsPrintf ("0x%8.8X%8.8X",
787202771Sjkim            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
788100966Siwasaki        break;
789100966Siwasaki
790100966Siwasaki    case AML_STRING_OP:
791100966Siwasaki
792252279Sjkim        AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
793281075Sdim
794281075Sdim        /* For _HID/_CID strings, attempt to output a descriptive comment */
795281075Sdim
796281075Sdim        if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
797281075Sdim        {
798281075Sdim            /* If we know about the ID, emit the description */
799281075Sdim
800281075Sdim            IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
801281075Sdim            if (IdInfo)
802281075Sdim            {
803281075Sdim                AcpiOsPrintf (" /* %s */", IdInfo->Description);
804281075Sdim            }
805281075Sdim        }
806100966Siwasaki        break;
807100966Siwasaki
808100966Siwasaki    case AML_BUFFER_OP:
809100966Siwasaki        /*
810241973Sjkim         * Determine the type of buffer. We can have one of the following:
811100966Siwasaki         *
812100966Siwasaki         * 1) ResourceTemplate containing Resource Descriptors.
813100966Siwasaki         * 2) Unicode String buffer
814100966Siwasaki         * 3) ASCII String buffer
815100966Siwasaki         * 4) Raw data buffer (if none of the above)
816100966Siwasaki         *
817100966Siwasaki         * Since there are no special AML opcodes to differentiate these
818100966Siwasaki         * types of buffers, we have to closely look at the data in the
819100966Siwasaki         * buffer to determine the type.
820100966Siwasaki         */
821228110Sjkim        if (!AcpiGbl_NoResourceDisassembly)
822100966Siwasaki        {
823243347Sjkim            Status = AcpiDmIsResourceTemplate (WalkState, Op);
824228110Sjkim            if (ACPI_SUCCESS (Status))
825228110Sjkim            {
826228110Sjkim                Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
827228110Sjkim                AcpiOsPrintf ("ResourceTemplate");
828228110Sjkim                break;
829228110Sjkim            }
830228110Sjkim            else if (Status == AE_AML_NO_RESOURCE_END_TAG)
831228110Sjkim            {
832306536Sjkim                AcpiOsPrintf (
833306536Sjkim                    "/**** Is ResourceTemplate, "
834306536Sjkim                    "but EndTag not at buffer end ****/ ");
835228110Sjkim            }
836100966Siwasaki        }
837167802Sjkim
838281075Sdim        if (AcpiDmIsUuidBuffer (Op))
839167802Sjkim        {
840281075Sdim            Op->Common.DisasmOpcode = ACPI_DASM_UUID;
841281075Sdim            AcpiOsPrintf ("ToUUID (");
842281075Sdim        }
843281075Sdim        else if (AcpiDmIsUnicodeBuffer (Op))
844281075Sdim        {
845100966Siwasaki            Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
846100966Siwasaki            AcpiOsPrintf ("Unicode (");
847100966Siwasaki        }
848100966Siwasaki        else if (AcpiDmIsStringBuffer (Op))
849100966Siwasaki        {
850100966Siwasaki            Op->Common.DisasmOpcode = ACPI_DASM_STRING;
851100966Siwasaki            AcpiOsPrintf ("Buffer");
852100966Siwasaki        }
853239340Sjkim        else if (AcpiDmIsPldBuffer (Op))
854239340Sjkim        {
855239340Sjkim            Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
856281075Sdim            AcpiOsPrintf ("ToPLD (");
857239340Sjkim        }
858100966Siwasaki        else
859100966Siwasaki        {
860100966Siwasaki            Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
861100966Siwasaki            AcpiOsPrintf ("Buffer");
862100966Siwasaki        }
863100966Siwasaki        break;
864100966Siwasaki
865100966Siwasaki    case AML_INT_NAMEPATH_OP:
866100966Siwasaki
867100966Siwasaki        AcpiDmNamestring (Op->Common.Value.Name);
868100966Siwasaki        break;
869100966Siwasaki
870100966Siwasaki    case AML_INT_NAMEDFIELD_OP:
871100966Siwasaki
872193267Sjkim        Length = AcpiDmDumpName (Op->Named.Name);
873209746Sjkim        AcpiOsPrintf (",%*.s  %u", (unsigned) (5 - Length), " ",
874151937Sjkim            (UINT32) Op->Common.Value.Integer);
875100966Siwasaki        AcpiDmCommaIfFieldMember (Op);
876100966Siwasaki
877117521Snjl        Info->BitOffset += (UINT32) Op->Common.Value.Integer;
878100966Siwasaki        break;
879100966Siwasaki
880100966Siwasaki    case AML_INT_RESERVEDFIELD_OP:
881100966Siwasaki
882100966Siwasaki        /* Offset() -- Must account for previous offsets */
883100966Siwasaki
884117521Snjl        Offset = (UINT32) Op->Common.Value.Integer;
885100966Siwasaki        Info->BitOffset += Offset;
886100966Siwasaki
887100966Siwasaki        if (Info->BitOffset % 8 == 0)
888100966Siwasaki        {
889228110Sjkim            AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
890100966Siwasaki        }
891100966Siwasaki        else
892100966Siwasaki        {
893209746Sjkim            AcpiOsPrintf ("    ,   %u", Offset);
894100966Siwasaki        }
895100966Siwasaki
896100966Siwasaki        AcpiDmCommaIfFieldMember (Op);
897100966Siwasaki        break;
898100966Siwasaki
899100966Siwasaki    case AML_INT_ACCESSFIELD_OP:
900228110Sjkim    case AML_INT_EXTACCESSFIELD_OP:
901100966Siwasaki
902228110Sjkim        AcpiOsPrintf ("AccessAs (%s, ",
903228110Sjkim            AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
904100966Siwasaki
905228110Sjkim        AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
906228110Sjkim
907228110Sjkim        if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
908228110Sjkim        {
909306536Sjkim            AcpiOsPrintf (" (0x%2.2X)", (unsigned)
910306536Sjkim                ((Op->Common.Value.Integer >> 16) & 0xFF));
911228110Sjkim        }
912228110Sjkim
913107325Siwasaki        AcpiOsPrintf (")");
914100966Siwasaki        AcpiDmCommaIfFieldMember (Op);
915100966Siwasaki        break;
916100966Siwasaki
917228110Sjkim    case AML_INT_CONNECTION_OP:
918228110Sjkim        /*
919228110Sjkim         * Two types of Connection() - one with a buffer object, the
920228110Sjkim         * other with a namestring that points to a buffer object.
921228110Sjkim         */
922228110Sjkim        AcpiOsPrintf ("Connection (");
923228110Sjkim        Child = Op->Common.Value.Arg;
924228110Sjkim
925228110Sjkim        if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
926228110Sjkim        {
927228110Sjkim            AcpiOsPrintf ("\n");
928228110Sjkim
929228110Sjkim            Aml = Child->Named.Data;
930228110Sjkim            Length = (UINT32) Child->Common.Value.Integer;
931228110Sjkim
932228110Sjkim            Info->Level += 1;
933281075Sdim            Info->MappingOp = Op;
934228110Sjkim            Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
935281075Sdim
936228110Sjkim            AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
937228110Sjkim
938228110Sjkim            Info->Level -= 1;
939228110Sjkim            AcpiDmIndent (Info->Level);
940228110Sjkim        }
941228110Sjkim        else
942228110Sjkim        {
943228110Sjkim            AcpiDmNamestring (Child->Common.Value.Name);
944228110Sjkim        }
945228110Sjkim
946228110Sjkim        AcpiOsPrintf (")");
947228110Sjkim        AcpiDmCommaIfFieldMember (Op);
948228110Sjkim        AcpiOsPrintf ("\n");
949228110Sjkim
950228110Sjkim        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
951228110Sjkim        Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
952228110Sjkim        break;
953228110Sjkim
954100966Siwasaki    case AML_INT_BYTELIST_OP:
955100966Siwasaki
956100966Siwasaki        AcpiDmByteList (Info, Op);
957100966Siwasaki        break;
958100966Siwasaki
959100966Siwasaki    case AML_INT_METHODCALL_OP:
960100966Siwasaki
961100966Siwasaki        Op = AcpiPsGetDepthNext (NULL, Op);
962100966Siwasaki        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
963100966Siwasaki
964100966Siwasaki        AcpiDmNamestring (Op->Common.Value.Name);
965100966Siwasaki        break;
966100966Siwasaki
967306536Sjkim    case AML_ELSE_OP:
968306536Sjkim
969306536Sjkim        AcpiDmConvertToElseIf (Op);
970306536Sjkim        break;
971306536Sjkim
972306536Sjkim    case AML_EXTERNAL_OP:
973306536Sjkim
974306536Sjkim        if (AcpiGbl_DmEmitExternalOpcodes)
975306536Sjkim        {
976306536Sjkim            AcpiOsPrintf ("/* Opcode 0x15 */ ");
977306536Sjkim
978306536Sjkim            /* Fallthrough */
979306536Sjkim        }
980306536Sjkim        else
981306536Sjkim        {
982306536Sjkim            break;
983306536Sjkim        }
984306536Sjkim
985100966Siwasaki    default:
986100966Siwasaki
987100966Siwasaki        /* Just get the opcode name and print it */
988100966Siwasaki
989100966Siwasaki        AcpiOsPrintf ("%s", OpInfo->Name);
990100966Siwasaki
991100966Siwasaki
992102550Siwasaki#ifdef ACPI_DEBUGGER
993100966Siwasaki
994100966Siwasaki        if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
995100966Siwasaki            (WalkState) &&
996100966Siwasaki            (WalkState->Results) &&
997167802Sjkim            (WalkState->ResultCount))
998100966Siwasaki        {
999306536Sjkim            AcpiDbDecodeInternalObject (
1000151937Sjkim                WalkState->Results->Results.ObjDesc [
1001167802Sjkim                    (WalkState->ResultCount - 1) %
1002167802Sjkim                        ACPI_RESULTS_FRAME_OBJ_NUM]);
1003100966Siwasaki        }
1004100966Siwasaki#endif
1005167802Sjkim
1006100966Siwasaki        break;
1007100966Siwasaki    }
1008100966Siwasaki}
1009100966Siwasaki
1010306536Sjkim
1011306536Sjkim/*******************************************************************************
1012306536Sjkim *
1013306536Sjkim * FUNCTION:    AcpiDmConvertToElseIf
1014306536Sjkim *
1015306536Sjkim * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
1016306536Sjkim *
1017306536Sjkim * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
1018306536Sjkim *
1019306536Sjkim * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1020306536Sjkim *
1021306536Sjkim * EXAMPLE:
1022306536Sjkim *
1023306536Sjkim * This If..Else..If nested sequence:
1024306536Sjkim *
1025306536Sjkim *        If (Arg0 == 1)
1026306536Sjkim *        {
1027306536Sjkim *            Local0 = 4
1028306536Sjkim *        }
1029306536Sjkim *        Else
1030306536Sjkim *        {
1031306536Sjkim *            If (Arg0 == 2)
1032306536Sjkim *            {
1033306536Sjkim *                Local0 = 5
1034306536Sjkim *            }
1035306536Sjkim *        }
1036306536Sjkim *
1037306536Sjkim * Is converted to this simpler If..ElseIf sequence:
1038306536Sjkim *
1039306536Sjkim *        If (Arg0 == 1)
1040306536Sjkim *        {
1041306536Sjkim *            Local0 = 4
1042306536Sjkim *        }
1043306536Sjkim *        ElseIf (Arg0 == 2)
1044306536Sjkim *        {
1045306536Sjkim *            Local0 = 5
1046306536Sjkim *        }
1047306536Sjkim *
1048306536Sjkim * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1049306536Sjkim * macro that emits an Else opcode followed by an If opcode. This function
1050306536Sjkim * reverses these AML sequences back to an ElseIf macro where possible. This
1051306536Sjkim * can make the disassembled ASL code simpler and more like the original code.
1052306536Sjkim *
1053306536Sjkim ******************************************************************************/
1054306536Sjkim
1055306536Sjkimstatic void
1056306536SjkimAcpiDmConvertToElseIf (
1057306536Sjkim    ACPI_PARSE_OBJECT       *OriginalElseOp)
1058306536Sjkim{
1059306536Sjkim    ACPI_PARSE_OBJECT       *IfOp;
1060306536Sjkim    ACPI_PARSE_OBJECT       *ElseOp;
1061306536Sjkim
1062306536Sjkim
1063306536Sjkim    /*
1064306536Sjkim     * To be able to perform the conversion, two conditions must be satisfied:
1065306536Sjkim     * 1) The first child of the Else must be an If statement.
1066306536Sjkim     * 2) The If block can only be followed by an Else block and these must
1067306536Sjkim     *    be the only blocks under the original Else.
1068306536Sjkim     */
1069306536Sjkim    IfOp = OriginalElseOp->Common.Value.Arg;
1070306536Sjkim    if (!IfOp ||
1071306536Sjkim        (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1072306536Sjkim        (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1073306536Sjkim    {
1074306536Sjkim        /* Not an Else..If sequence, cannot convert to ElseIf */
1075306536Sjkim
1076306536Sjkim        AcpiOsPrintf ("%s", "Else");
1077306536Sjkim        return;
1078306536Sjkim    }
1079306536Sjkim
1080306536Sjkim    /* Emit ElseIf, mark the IF as now an ELSEIF */
1081306536Sjkim
1082306536Sjkim    AcpiOsPrintf ("%s", "ElseIf");
1083306536Sjkim    IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1084306536Sjkim
1085306536Sjkim    /* The IF parent will now be the same as the original ELSE parent */
1086306536Sjkim
1087306536Sjkim    IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1088306536Sjkim
1089306536Sjkim    /*
1090306536Sjkim     * Update the NEXT pointers to restructure the parse tree, essentially
1091306536Sjkim     * promoting an If..Else block up to the same level as the original
1092306536Sjkim     * Else.
1093306536Sjkim     *
1094306536Sjkim     * Check if the IF has a corresponding ELSE peer
1095306536Sjkim     */
1096306536Sjkim    ElseOp = IfOp->Common.Next;
1097306536Sjkim    if (ElseOp &&
1098306536Sjkim        (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1099306536Sjkim    {
1100306536Sjkim        /* If an ELSE matches the IF, promote it also */
1101306536Sjkim
1102306536Sjkim        ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1103306536Sjkim        ElseOp->Common.Next = OriginalElseOp->Common.Next;
1104306536Sjkim    }
1105306536Sjkim    else
1106306536Sjkim    {
1107306536Sjkim        /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1108306536Sjkim
1109306536Sjkim        IfOp->Common.Next = OriginalElseOp->Common.Next;
1110306536Sjkim    }
1111306536Sjkim
1112306536Sjkim    /* Detach the child IF block from the original ELSE */
1113306536Sjkim
1114306536Sjkim    OriginalElseOp->Common.Value.Arg = NULL;
1115306536Sjkim
1116306536Sjkim    /* Ignore the original ELSE from now on */
1117306536Sjkim
1118306536Sjkim    OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1119306536Sjkim    OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1120306536Sjkim
1121306536Sjkim    /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1122306536Sjkim
1123306536Sjkim    OriginalElseOp->Common.Next = IfOp;
1124306536Sjkim}
1125