1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
52 #ifdef ACPI_DISASSEMBLER
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmopcode")
58 /* Local prototypes */
62 ACPI_PARSE_OBJECT
*Op
);
65 AcpiDmConvertToElseIf (
66 ACPI_PARSE_OBJECT
*Op
);
69 AcpiDmPromoteSubtree (
70 ACPI_PARSE_OBJECT
*StartOp
);
73 /*******************************************************************************
75 * FUNCTION: AcpiDmDisplayTargetPathname
77 * PARAMETERS: Op - Parse object
81 * DESCRIPTION: For AML opcodes that have a target operand, display the full
82 * pathname for the target, in a comment field. Handles Return()
85 ******************************************************************************/
88 AcpiDmDisplayTargetPathname (
89 ACPI_PARSE_OBJECT
*Op
)
91 ACPI_PARSE_OBJECT
*NextOp
;
92 ACPI_PARSE_OBJECT
*PrevOp
= NULL
;
94 const ACPI_OPCODE_INFO
*OpInfo
;
97 if (Op
->Common
.AmlOpcode
== AML_RETURN_OP
)
99 PrevOp
= Op
->Asl
.Value
.Arg
;
103 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
104 if (!(OpInfo
->Flags
& AML_HAS_TARGET
))
109 /* Target is the last Op in the arg list */
111 NextOp
= Op
->Asl
.Value
.Arg
;
115 NextOp
= PrevOp
->Asl
.Next
;
124 /* We must have a namepath AML opcode */
126 if (PrevOp
->Asl
.AmlOpcode
!= AML_INT_NAMEPATH_OP
)
131 /* A null string is the "no target specified" case */
133 if (!PrevOp
->Asl
.Value
.String
)
138 /* No node means "unresolved external reference" */
140 if (!PrevOp
->Asl
.Node
)
142 AcpiOsPrintf (" /* External reference */");
146 /* Ignore if path is already from the root */
148 if (*PrevOp
->Asl
.Value
.String
== '\\')
153 /* Now: we can get the full pathname */
155 Pathname
= AcpiNsGetExternalPathname (PrevOp
->Asl
.Node
);
161 AcpiOsPrintf (" /* %s */", Pathname
);
162 ACPI_FREE (Pathname
);
166 /*******************************************************************************
168 * FUNCTION: AcpiDmNotifyDescription
170 * PARAMETERS: Op - Name() parse object
174 * DESCRIPTION: Emit a description comment for the value associated with a
177 ******************************************************************************/
180 AcpiDmNotifyDescription (
181 ACPI_PARSE_OBJECT
*Op
)
183 ACPI_PARSE_OBJECT
*NextOp
;
184 ACPI_NAMESPACE_NODE
*Node
;
186 UINT8 Type
= ACPI_TYPE_ANY
;
189 /* The notify value is the second argument */
191 NextOp
= Op
->Asl
.Value
.Arg
;
192 NextOp
= NextOp
->Asl
.Next
;
194 switch (NextOp
->Common
.AmlOpcode
)
199 NotifyValue
= (UINT8
) NextOp
->Common
.AmlOpcode
;
204 NotifyValue
= (UINT8
) NextOp
->Asl
.Value
.Integer
;
212 * Attempt to get the namespace node so we can determine the object type.
213 * Some notify values are dependent on the object type (Device, Thermal,
222 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue
, Type
));
226 /*******************************************************************************
228 * FUNCTION: AcpiDmPredefinedDescription
230 * PARAMETERS: Op - Name() parse object
234 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
235 * Used for iASL compiler only.
237 ******************************************************************************/
240 AcpiDmPredefinedDescription (
241 ACPI_PARSE_OBJECT
*Op
)
243 #ifdef ACPI_ASL_COMPILER
244 const AH_PREDEFINED_NAME
*Info
;
255 /* Ensure that the comment field is emitted only once */
257 if (Op
->Common
.DisasmFlags
& ACPI_PARSEOP_PREDEFINED_CHECKED
)
261 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_PREDEFINED_CHECKED
;
263 /* Predefined name must start with an underscore */
265 NameString
= ACPI_CAST_PTR (char, &Op
->Named
.Name
);
266 if (NameString
[0] != '_')
272 * Check for the special ACPI names:
273 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
274 * (where d=decimal_digit, x=hex_digit, a=anything)
276 * Convert these to the generic name for table lookup.
277 * Note: NameString is guaranteed to be upper case here.
280 (isdigit ((int) NameString
[3])); /* d */
282 (isxdigit ((int) NameString
[2]) && /* xx */
283 isxdigit ((int) NameString
[3]));
285 switch (NameString
[1])
289 if ((NameString
[2] == 'C') && (LastCharIsDigit
))
293 else if ((NameString
[2] == 'L') && (LastCharIsDigit
))
301 if ((NameString
[2] == 'J') && (LastCharIsDigit
))
305 else if (LastCharsAreHex
)
329 if (NameString
[2] == '_')
348 /* Match the name in the info table */
350 Info
= AcpiAhMatchPredefinedName (NameString
);
353 AcpiOsPrintf (" // %4.4s: %s",
354 NameString
, ACPI_CAST_PTR (char, Info
->Description
));
362 /*******************************************************************************
364 * FUNCTION: AcpiDmFieldPredefinedDescription
366 * PARAMETERS: Op - Parse object
370 * DESCRIPTION: Emit a description comment for a resource descriptor tag
371 * (which is a predefined ACPI name.) Used for iASL compiler only.
373 ******************************************************************************/
376 AcpiDmFieldPredefinedDescription (
377 ACPI_PARSE_OBJECT
*Op
)
379 #ifdef ACPI_ASL_COMPILER
380 ACPI_PARSE_OBJECT
*IndexOp
;
382 const ACPI_OPCODE_INFO
*OpInfo
;
383 const AH_PREDEFINED_NAME
*Info
;
391 /* Ensure that the comment field is emitted only once */
393 if (Op
->Common
.DisasmFlags
& ACPI_PARSEOP_PREDEFINED_CHECKED
)
397 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_PREDEFINED_CHECKED
;
400 * Op must be one of the Create* operators: CreateField, CreateBitField,
401 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
403 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
404 if (!(OpInfo
->Flags
& AML_CREATE
))
409 /* Second argument is the Index argument */
411 IndexOp
= Op
->Common
.Value
.Arg
;
412 IndexOp
= IndexOp
->Common
.Next
;
414 /* Index argument must be a namepath */
416 if (IndexOp
->Common
.AmlOpcode
!= AML_INT_NAMEPATH_OP
)
421 /* Major cheat: We previously put the Tag ptr in the Node field */
423 Tag
= ACPI_CAST_PTR (char, IndexOp
->Common
.Node
);
429 /* Match the name in the info table */
431 Info
= AcpiAhMatchPredefinedName (Tag
);
434 AcpiOsPrintf (" // %4.4s: %s", Tag
,
435 ACPI_CAST_PTR (char, Info
->Description
));
443 /*******************************************************************************
445 * FUNCTION: AcpiDmMethodFlags
447 * PARAMETERS: Op - Method Object to be examined
451 * DESCRIPTION: Decode control method flags
453 ******************************************************************************/
457 ACPI_PARSE_OBJECT
*Op
)
463 /* The next Op contains the flags */
465 Op
= AcpiPsGetDepthNext (NULL
, Op
);
466 Flags
= (UINT8
) Op
->Common
.Value
.Integer
;
469 /* Mark the Op as completed */
471 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
473 /* 1) Method argument count */
475 AcpiOsPrintf (", %u, ", Args
);
477 /* 2) Serialize rule */
481 AcpiOsPrintf ("Not");
484 AcpiOsPrintf ("Serialized");
490 AcpiOsPrintf (", %u", Flags
>> 4);
495 /*******************************************************************************
497 * FUNCTION: AcpiDmFieldFlags
499 * PARAMETERS: Op - Field Object to be examined
503 * DESCRIPTION: Decode Field definition flags
505 ******************************************************************************/
509 ACPI_PARSE_OBJECT
*Op
)
514 Op
= Op
->Common
.Next
;
515 Flags
= (UINT8
) Op
->Common
.Value
.Integer
;
517 /* Mark the Op as completed */
519 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
521 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes
[Flags
& 0x07]);
522 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule
[(Flags
& 0x10) >> 4]);
523 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules
[(Flags
& 0x60) >> 5]);
527 /*******************************************************************************
529 * FUNCTION: AcpiDmAddressSpace
531 * PARAMETERS: SpaceId - ID to be translated
535 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
537 ******************************************************************************/
544 if (SpaceId
>= ACPI_NUM_PREDEFINED_REGIONS
)
548 AcpiOsPrintf ("FFixedHW, ");
552 AcpiOsPrintf ("0x%.2X, ", SpaceId
);
557 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes
[SpaceId
]);
562 /*******************************************************************************
564 * FUNCTION: AcpiDmRegionFlags
566 * PARAMETERS: Op - Object to be examined
570 * DESCRIPTION: Decode OperationRegion flags
572 ******************************************************************************/
576 ACPI_PARSE_OBJECT
*Op
)
579 /* The next Op contains the SpaceId */
581 Op
= AcpiPsGetDepthNext (NULL
, Op
);
583 /* Mark the Op as completed */
585 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
588 AcpiDmAddressSpace ((UINT8
) Op
->Common
.Value
.Integer
);
592 /*******************************************************************************
594 * FUNCTION: AcpiDmMatchOp
596 * PARAMETERS: Op - Match Object to be examined
600 * DESCRIPTION: Decode Match opcode operands
602 ******************************************************************************/
606 ACPI_PARSE_OBJECT
*Op
)
608 ACPI_PARSE_OBJECT
*NextOp
;
611 NextOp
= AcpiPsGetDepthNext (NULL
, Op
);
612 NextOp
= NextOp
->Common
.Next
;
616 /* Handle partial tree during single-step */
621 /* Mark the two nodes that contain the encoding for the match keywords */
623 NextOp
->Common
.DisasmOpcode
= ACPI_DASM_MATCHOP
;
625 NextOp
= NextOp
->Common
.Next
;
626 NextOp
= NextOp
->Common
.Next
;
627 NextOp
->Common
.DisasmOpcode
= ACPI_DASM_MATCHOP
;
631 /*******************************************************************************
633 * FUNCTION: AcpiDmMatchKeyword
635 * PARAMETERS: Op - Match Object to be examined
639 * DESCRIPTION: Decode Match opcode operands
641 ******************************************************************************/
645 ACPI_PARSE_OBJECT
*Op
)
648 if (((UINT32
) Op
->Common
.Value
.Integer
) > ACPI_MAX_MATCH_OPCODE
)
650 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
655 AcpiGbl_MatchOps
[(ACPI_SIZE
) Op
->Common
.Value
.Integer
]);
660 /*******************************************************************************
662 * FUNCTION: AcpiDmDisassembleOneOp
664 * PARAMETERS: WalkState - Current walk info
665 * Info - Parse tree walk info
666 * Op - Op that is to be printed
670 * DESCRIPTION: Disassemble a single AML opcode
672 ******************************************************************************/
675 AcpiDmDisassembleOneOp (
676 ACPI_WALK_STATE
*WalkState
,
677 ACPI_OP_WALK_INFO
*Info
,
678 ACPI_PARSE_OBJECT
*Op
)
680 const ACPI_OPCODE_INFO
*OpInfo
= NULL
;
683 ACPI_PARSE_OBJECT
*Child
;
686 const AH_DEVICE_ID
*IdInfo
;
691 AcpiOsPrintf ("<NULL OP PTR>");
695 if (Op
->Common
.DisasmFlags
& ACPI_PARSEOP_ELSEIF
)
697 return; /* ElseIf macro was already emitted */
700 switch (Op
->Common
.DisasmOpcode
)
702 case ACPI_DASM_MATCHOP
:
704 AcpiDmMatchKeyword (Op
);
707 case ACPI_DASM_LNOT_SUFFIX
:
709 if (!AcpiGbl_CstyleDisassembly
)
711 switch (Op
->Common
.AmlOpcode
)
714 AcpiOsPrintf ("LNotEqual");
717 case AML_LGREATER_OP
:
718 AcpiOsPrintf ("LLessEqual");
722 AcpiOsPrintf ("LGreaterEqual");
730 Op
->Common
.DisasmOpcode
= 0;
731 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
738 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Common
.AmlOpcode
);
740 /* The op and arguments */
742 switch (Op
->Common
.AmlOpcode
)
746 Child
= Op
->Common
.Value
.Arg
;
747 if ((Child
->Common
.AmlOpcode
== AML_LEQUAL_OP
) ||
748 (Child
->Common
.AmlOpcode
== AML_LGREATER_OP
) ||
749 (Child
->Common
.AmlOpcode
== AML_LLESS_OP
))
751 Child
->Common
.DisasmOpcode
= ACPI_DASM_LNOT_SUFFIX
;
752 Op
->Common
.DisasmOpcode
= ACPI_DASM_LNOT_PREFIX
;
756 AcpiOsPrintf ("%s", OpInfo
->Name
);
762 AcpiOsPrintf ("0x%2.2X", (UINT32
) Op
->Common
.Value
.Integer
);
767 if (Op
->Common
.DisasmOpcode
== ACPI_DASM_EISAID
)
769 AcpiDmDecompressEisaId ((UINT32
) Op
->Common
.Value
.Integer
);
773 AcpiOsPrintf ("0x%4.4X", (UINT32
) Op
->Common
.Value
.Integer
);
779 if (Op
->Common
.DisasmOpcode
== ACPI_DASM_EISAID
)
781 AcpiDmDecompressEisaId ((UINT32
) Op
->Common
.Value
.Integer
);
785 AcpiOsPrintf ("0x%8.8X", (UINT32
) Op
->Common
.Value
.Integer
);
791 AcpiOsPrintf ("0x%8.8X%8.8X",
792 ACPI_FORMAT_UINT64 (Op
->Common
.Value
.Integer
));
797 AcpiUtPrintString (Op
->Common
.Value
.String
, ACPI_UINT16_MAX
);
799 /* For _HID/_CID strings, attempt to output a descriptive comment */
801 if (Op
->Common
.DisasmOpcode
== ACPI_DASM_HID_STRING
)
803 /* If we know about the ID, emit the description */
805 IdInfo
= AcpiAhMatchHardwareId (Op
->Common
.Value
.String
);
808 AcpiOsPrintf (" /* %s */", IdInfo
->Description
);
815 * Determine the type of buffer. We can have one of the following:
817 * 1) ResourceTemplate containing Resource Descriptors.
818 * 2) Unicode String buffer
819 * 3) ASCII String buffer
820 * 4) Raw data buffer (if none of the above)
822 * Since there are no special AML opcodes to differentiate these
823 * types of buffers, we have to closely look at the data in the
824 * buffer to determine the type.
826 if (!AcpiGbl_NoResourceDisassembly
)
828 Status
= AcpiDmIsResourceTemplate (WalkState
, Op
);
829 if (ACPI_SUCCESS (Status
))
831 Op
->Common
.DisasmOpcode
= ACPI_DASM_RESOURCE
;
832 AcpiOsPrintf ("ResourceTemplate");
835 else if (Status
== AE_AML_NO_RESOURCE_END_TAG
)
838 "/**** Is ResourceTemplate, "
839 "but EndTag not at buffer end ****/ ");
843 if (AcpiDmIsUuidBuffer (Op
))
845 Op
->Common
.DisasmOpcode
= ACPI_DASM_UUID
;
846 AcpiOsPrintf ("ToUUID (");
848 else if (AcpiDmIsUnicodeBuffer (Op
))
850 Op
->Common
.DisasmOpcode
= ACPI_DASM_UNICODE
;
851 AcpiOsPrintf ("Unicode (");
853 else if (AcpiDmIsStringBuffer (Op
))
855 Op
->Common
.DisasmOpcode
= ACPI_DASM_STRING
;
856 AcpiOsPrintf ("Buffer");
858 else if (AcpiDmIsPldBuffer (Op
))
860 Op
->Common
.DisasmOpcode
= ACPI_DASM_PLD_METHOD
;
861 AcpiOsPrintf ("ToPLD (");
865 Op
->Common
.DisasmOpcode
= ACPI_DASM_BUFFER
;
866 AcpiOsPrintf ("Buffer");
870 case AML_INT_NAMEPATH_OP
:
872 AcpiDmNamestring (Op
->Common
.Value
.Name
);
875 case AML_INT_NAMEDFIELD_OP
:
877 Length
= AcpiDmDumpName (Op
->Named
.Name
);
878 AcpiOsPrintf (",%*.s %u", (unsigned) (5 - Length
), " ",
879 (UINT32
) Op
->Common
.Value
.Integer
);
880 AcpiDmCommaIfFieldMember (Op
);
882 Info
->BitOffset
+= (UINT32
) Op
->Common
.Value
.Integer
;
885 case AML_INT_RESERVEDFIELD_OP
:
887 /* Offset() -- Must account for previous offsets */
889 Offset
= (UINT32
) Op
->Common
.Value
.Integer
;
890 Info
->BitOffset
+= Offset
;
892 if (Info
->BitOffset
% 8 == 0)
894 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info
->BitOffset
));
898 AcpiOsPrintf (" , %u", Offset
);
901 AcpiDmCommaIfFieldMember (Op
);
904 case AML_INT_ACCESSFIELD_OP
:
905 case AML_INT_EXTACCESSFIELD_OP
:
907 AcpiOsPrintf ("AccessAs (%s, ",
908 AcpiGbl_AccessTypes
[(UINT32
) (Op
->Common
.Value
.Integer
& 0x7)]);
910 AcpiDmDecodeAttribute ((UINT8
) (Op
->Common
.Value
.Integer
>> 8));
912 if (Op
->Common
.AmlOpcode
== AML_INT_EXTACCESSFIELD_OP
)
914 AcpiOsPrintf (" (0x%2.2X)", (unsigned)
915 ((Op
->Common
.Value
.Integer
>> 16) & 0xFF));
919 AcpiDmCommaIfFieldMember (Op
);
922 case AML_INT_CONNECTION_OP
:
924 * Two types of Connection() - one with a buffer object, the
925 * other with a namestring that points to a buffer object.
927 AcpiOsPrintf ("Connection (");
928 Child
= Op
->Common
.Value
.Arg
;
930 if (Child
->Common
.AmlOpcode
== AML_INT_BYTELIST_OP
)
934 Aml
= Child
->Named
.Data
;
935 Length
= (UINT32
) Child
->Common
.Value
.Integer
;
938 Info
->MappingOp
= Op
;
939 Op
->Common
.DisasmOpcode
= ACPI_DASM_RESOURCE
;
941 AcpiDmResourceTemplate (Info
, Op
->Common
.Parent
, Aml
, Length
);
944 AcpiDmIndent (Info
->Level
);
948 AcpiDmNamestring (Child
->Common
.Value
.Name
);
952 AcpiDmCommaIfFieldMember (Op
);
955 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
; /* for now, ignore in AcpiDmAscendingOp */
956 Child
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
959 case AML_INT_BYTELIST_OP
:
961 AcpiDmByteList (Info
, Op
);
964 case AML_INT_METHODCALL_OP
:
966 Op
= AcpiPsGetDepthNext (NULL
, Op
);
967 Op
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
969 AcpiDmNamestring (Op
->Common
.Value
.Name
);
974 AcpiDmConvertToElseIf (Op
);
977 case AML_EXTERNAL_OP
:
979 if (AcpiGbl_DmEmitExternalOpcodes
)
981 AcpiOsPrintf ("/* Opcode 0x15 */ ");
992 /* Just get the opcode name and print it */
994 AcpiOsPrintf ("%s", OpInfo
->Name
);
999 if ((Op
->Common
.AmlOpcode
== AML_INT_RETURN_VALUE_OP
) &&
1001 (WalkState
->Results
) &&
1002 (WalkState
->ResultCount
))
1004 AcpiDbDecodeInternalObject (
1005 WalkState
->Results
->Results
.ObjDesc
[
1006 (WalkState
->ResultCount
- 1) %
1007 ACPI_RESULTS_FRAME_OBJ_NUM
]);
1016 /*******************************************************************************
1018 * FUNCTION: AcpiDmConvertToElseIf
1020 * PARAMETERS: OriginalElseOp - ELSE Object to be examined
1022 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
1024 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1028 * This If..Else..If nested sequence:
1042 * Is converted to this simpler If..ElseIf sequence:
1048 * ElseIf (Arg0 == 2)
1053 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1054 * macro that emits an Else opcode followed by an If opcode. This function
1055 * reverses these AML sequences back to an ElseIf macro where possible. This
1056 * can make the disassembled ASL code simpler and more like the original code.
1058 ******************************************************************************/
1061 AcpiDmConvertToElseIf (
1062 ACPI_PARSE_OBJECT
*OriginalElseOp
)
1064 ACPI_PARSE_OBJECT
*IfOp
;
1065 ACPI_PARSE_OBJECT
*ElseOp
;
1069 * To be able to perform the conversion, two conditions must be satisfied:
1070 * 1) The first child of the Else must be an If statement.
1071 * 2) The If block can only be followed by an Else block and these must
1072 * be the only blocks under the original Else.
1074 IfOp
= OriginalElseOp
->Common
.Value
.Arg
;
1077 (IfOp
->Common
.AmlOpcode
!= AML_IF_OP
) ||
1078 (IfOp
->Asl
.Next
&& (IfOp
->Asl
.Next
->Common
.AmlOpcode
!= AML_ELSE_OP
)))
1080 /* Not a proper Else..If sequence, cannot convert to ElseIf */
1082 AcpiOsPrintf ("%s", "Else");
1086 /* Cannot have anything following the If...Else block */
1088 ElseOp
= IfOp
->Common
.Next
;
1089 if (ElseOp
&& ElseOp
->Common
.Next
)
1091 AcpiOsPrintf ("%s", "Else");
1095 /* Emit ElseIf, mark the IF as now an ELSEIF */
1097 AcpiOsPrintf ("%s", "ElseIf");
1098 IfOp
->Common
.DisasmFlags
|= ACPI_PARSEOP_ELSEIF
;
1100 /* The IF parent will now be the same as the original ELSE parent */
1102 IfOp
->Common
.Parent
= OriginalElseOp
->Common
.Parent
;
1105 * Update the NEXT pointers to restructure the parse tree, essentially
1106 * promoting an If..Else block up to the same level as the original
1109 * Check if the IF has a corresponding ELSE peer
1111 ElseOp
= IfOp
->Common
.Next
;
1113 (ElseOp
->Common
.AmlOpcode
== AML_ELSE_OP
))
1115 /* If an ELSE matches the IF, promote it also */
1117 ElseOp
->Common
.Parent
= OriginalElseOp
->Common
.Parent
;
1119 /* Promote the entire block under the ElseIf (All Next OPs) */
1121 AcpiDmPromoteSubtree (OriginalElseOp
);
1125 /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1127 IfOp
->Common
.Next
= OriginalElseOp
->Common
.Next
;
1130 /* Detach the child IF block from the original ELSE */
1132 OriginalElseOp
->Common
.Value
.Arg
= NULL
;
1134 /* Ignore the original ELSE from now on */
1136 OriginalElseOp
->Common
.DisasmFlags
|= ACPI_PARSEOP_IGNORE
;
1137 OriginalElseOp
->Common
.DisasmOpcode
= ACPI_DASM_LNOT_PREFIX
;
1139 /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1141 OriginalElseOp
->Common
.Next
= IfOp
;
1145 /*******************************************************************************
1147 * FUNCTION: AcpiDmPromoteSubtree
1149 * PARAMETERS: StartOpOp - Original parent of the entire subtree
1153 * DESCRIPTION: Promote an entire parse subtree up one level.
1155 ******************************************************************************/
1158 AcpiDmPromoteSubtree (
1159 ACPI_PARSE_OBJECT
*StartOp
)
1161 ACPI_PARSE_OBJECT
*Op
;
1162 ACPI_PARSE_OBJECT
*ParentOp
;
1165 /* New parent for subtree elements */
1167 ParentOp
= StartOp
->Common
.Parent
;
1169 /* First child starts the subtree */
1171 Op
= StartOp
->Common
.Value
.Arg
;
1173 /* Walk the top-level elements of the subtree */
1177 Op
->Common
.Parent
= ParentOp
;
1178 if (!Op
->Common
.Next
)
1180 /* Last Op in list, update its next field */
1182 Op
->Common
.Next
= StartOp
->Common
.Next
;
1185 Op
= Op
->Common
.Next
;
1189 #endif /* ACPI_DISASSEMBLER */