Sync ACPICA with Intel's version 20160930.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / disassembler / dmopcode.c
blob57e86f7bd37586d4c4b9b18bc9108fe8de26bbbd
1 /*******************************************************************************
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
5 ******************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acinterp.h"
49 #include "acnamesp.h"
50 #include "acdebug.h"
52 #ifdef ACPI_DISASSEMBLER
54 #define _COMPONENT ACPI_CA_DEBUGGER
55 ACPI_MODULE_NAME ("dmopcode")
58 /* Local prototypes */
60 static void
61 AcpiDmMatchKeyword (
62 ACPI_PARSE_OBJECT *Op);
64 static void
65 AcpiDmConvertToElseIf (
66 ACPI_PARSE_OBJECT *Op);
68 static void
69 AcpiDmPromoteSubtree (
70 ACPI_PARSE_OBJECT *StartOp);
73 /*******************************************************************************
75 * FUNCTION: AcpiDmDisplayTargetPathname
77 * PARAMETERS: Op - Parse object
79 * RETURN: None
81 * DESCRIPTION: For AML opcodes that have a target operand, display the full
82 * pathname for the target, in a comment field. Handles Return()
83 * statements also.
85 ******************************************************************************/
87 void
88 AcpiDmDisplayTargetPathname (
89 ACPI_PARSE_OBJECT *Op)
91 ACPI_PARSE_OBJECT *NextOp;
92 ACPI_PARSE_OBJECT *PrevOp = NULL;
93 char *Pathname;
94 const ACPI_OPCODE_INFO *OpInfo;
97 if (Op->Common.AmlOpcode == AML_RETURN_OP)
99 PrevOp = Op->Asl.Value.Arg;
101 else
103 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
104 if (!(OpInfo->Flags & AML_HAS_TARGET))
106 return;
109 /* Target is the last Op in the arg list */
111 NextOp = Op->Asl.Value.Arg;
112 while (NextOp)
114 PrevOp = NextOp;
115 NextOp = PrevOp->Asl.Next;
119 if (!PrevOp)
121 return;
124 /* We must have a namepath AML opcode */
126 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
128 return;
131 /* A null string is the "no target specified" case */
133 if (!PrevOp->Asl.Value.String)
135 return;
138 /* No node means "unresolved external reference" */
140 if (!PrevOp->Asl.Node)
142 AcpiOsPrintf (" /* External reference */");
143 return;
146 /* Ignore if path is already from the root */
148 if (*PrevOp->Asl.Value.String == '\\')
150 return;
153 /* Now: we can get the full pathname */
155 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
156 if (!Pathname)
158 return;
161 AcpiOsPrintf (" /* %s */", Pathname);
162 ACPI_FREE (Pathname);
166 /*******************************************************************************
168 * FUNCTION: AcpiDmNotifyDescription
170 * PARAMETERS: Op - Name() parse object
172 * RETURN: None
174 * DESCRIPTION: Emit a description comment for the value associated with a
175 * Notify() operator.
177 ******************************************************************************/
179 void
180 AcpiDmNotifyDescription (
181 ACPI_PARSE_OBJECT *Op)
183 ACPI_PARSE_OBJECT *NextOp;
184 ACPI_NAMESPACE_NODE *Node;
185 UINT8 NotifyValue;
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)
196 case AML_ZERO_OP:
197 case AML_ONE_OP:
199 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
200 break;
202 case AML_BYTE_OP:
204 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
205 break;
207 default:
208 return;
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,
214 * or Processor).
216 Node = Op->Asl.Node;
217 if (Node)
219 Type = Node->Type;
222 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
226 /*******************************************************************************
228 * FUNCTION: AcpiDmPredefinedDescription
230 * PARAMETERS: Op - Name() parse object
232 * RETURN: None
234 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
235 * Used for iASL compiler only.
237 ******************************************************************************/
239 void
240 AcpiDmPredefinedDescription (
241 ACPI_PARSE_OBJECT *Op)
243 #ifdef ACPI_ASL_COMPILER
244 const AH_PREDEFINED_NAME *Info;
245 char *NameString;
246 int LastCharIsDigit;
247 int LastCharsAreHex;
250 if (!Op)
252 return;
255 /* Ensure that the comment field is emitted only once */
257 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
259 return;
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] != '_')
268 return;
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.
279 LastCharIsDigit =
280 (isdigit ((int) NameString[3])); /* d */
281 LastCharsAreHex =
282 (isxdigit ((int) NameString[2]) && /* xx */
283 isxdigit ((int) NameString[3]));
285 switch (NameString[1])
287 case 'A':
289 if ((NameString[2] == 'C') && (LastCharIsDigit))
291 NameString = "_ACx";
293 else if ((NameString[2] == 'L') && (LastCharIsDigit))
295 NameString = "_ALx";
297 break;
299 case 'E':
301 if ((NameString[2] == 'J') && (LastCharIsDigit))
303 NameString = "_EJx";
305 else if (LastCharsAreHex)
307 NameString = "_Exx";
309 break;
311 case 'L':
313 if (LastCharsAreHex)
315 NameString = "_Lxx";
317 break;
319 case 'Q':
321 if (LastCharsAreHex)
323 NameString = "_Qxx";
325 break;
327 case 'T':
329 if (NameString[2] == '_')
331 NameString = "_T_x";
333 break;
335 case 'W':
337 if (LastCharsAreHex)
339 NameString = "_Wxx";
341 break;
343 default:
345 break;
348 /* Match the name in the info table */
350 Info = AcpiAhMatchPredefinedName (NameString);
351 if (Info)
353 AcpiOsPrintf (" // %4.4s: %s",
354 NameString, ACPI_CAST_PTR (char, Info->Description));
357 #endif
358 return;
362 /*******************************************************************************
364 * FUNCTION: AcpiDmFieldPredefinedDescription
366 * PARAMETERS: Op - Parse object
368 * RETURN: None
370 * DESCRIPTION: Emit a description comment for a resource descriptor tag
371 * (which is a predefined ACPI name.) Used for iASL compiler only.
373 ******************************************************************************/
375 void
376 AcpiDmFieldPredefinedDescription (
377 ACPI_PARSE_OBJECT *Op)
379 #ifdef ACPI_ASL_COMPILER
380 ACPI_PARSE_OBJECT *IndexOp;
381 char *Tag;
382 const ACPI_OPCODE_INFO *OpInfo;
383 const AH_PREDEFINED_NAME *Info;
386 if (!Op)
388 return;
391 /* Ensure that the comment field is emitted only once */
393 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
395 return;
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))
406 return;
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)
418 return;
421 /* Major cheat: We previously put the Tag ptr in the Node field */
423 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
424 if (!Tag)
426 return;
429 /* Match the name in the info table */
431 Info = AcpiAhMatchPredefinedName (Tag);
432 if (Info)
434 AcpiOsPrintf (" // %4.4s: %s", Tag,
435 ACPI_CAST_PTR (char, Info->Description));
438 #endif
439 return;
443 /*******************************************************************************
445 * FUNCTION: AcpiDmMethodFlags
447 * PARAMETERS: Op - Method Object to be examined
449 * RETURN: None
451 * DESCRIPTION: Decode control method flags
453 ******************************************************************************/
455 void
456 AcpiDmMethodFlags (
457 ACPI_PARSE_OBJECT *Op)
459 UINT32 Flags;
460 UINT32 Args;
463 /* The next Op contains the flags */
465 Op = AcpiPsGetDepthNext (NULL, Op);
466 Flags = (UINT8) Op->Common.Value.Integer;
467 Args = Flags & 0x07;
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 */
479 if (!(Flags & 0x08))
481 AcpiOsPrintf ("Not");
484 AcpiOsPrintf ("Serialized");
486 /* 3) SyncLevel */
488 if (Flags & 0xF0)
490 AcpiOsPrintf (", %u", Flags >> 4);
495 /*******************************************************************************
497 * FUNCTION: AcpiDmFieldFlags
499 * PARAMETERS: Op - Field Object to be examined
501 * RETURN: None
503 * DESCRIPTION: Decode Field definition flags
505 ******************************************************************************/
507 void
508 AcpiDmFieldFlags (
509 ACPI_PARSE_OBJECT *Op)
511 UINT32 Flags;
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
533 * RETURN: None
535 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
537 ******************************************************************************/
539 void
540 AcpiDmAddressSpace (
541 UINT8 SpaceId)
544 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
546 if (SpaceId == 0x7F)
548 AcpiOsPrintf ("FFixedHW, ");
550 else
552 AcpiOsPrintf ("0x%.2X, ", SpaceId);
555 else
557 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
562 /*******************************************************************************
564 * FUNCTION: AcpiDmRegionFlags
566 * PARAMETERS: Op - Object to be examined
568 * RETURN: None
570 * DESCRIPTION: Decode OperationRegion flags
572 ******************************************************************************/
574 void
575 AcpiDmRegionFlags (
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;
587 AcpiOsPrintf (", ");
588 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
592 /*******************************************************************************
594 * FUNCTION: AcpiDmMatchOp
596 * PARAMETERS: Op - Match Object to be examined
598 * RETURN: None
600 * DESCRIPTION: Decode Match opcode operands
602 ******************************************************************************/
604 void
605 AcpiDmMatchOp (
606 ACPI_PARSE_OBJECT *Op)
608 ACPI_PARSE_OBJECT *NextOp;
611 NextOp = AcpiPsGetDepthNext (NULL, Op);
612 NextOp = NextOp->Common.Next;
614 if (!NextOp)
616 /* Handle partial tree during single-step */
618 return;
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
637 * RETURN: None
639 * DESCRIPTION: Decode Match opcode operands
641 ******************************************************************************/
643 static void
644 AcpiDmMatchKeyword (
645 ACPI_PARSE_OBJECT *Op)
648 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
650 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
652 else
654 AcpiOsPrintf ("%s",
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
668 * RETURN: None
670 * DESCRIPTION: Disassemble a single AML opcode
672 ******************************************************************************/
674 void
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;
681 UINT32 Offset;
682 UINT32 Length;
683 ACPI_PARSE_OBJECT *Child;
684 ACPI_STATUS Status;
685 UINT8 *Aml;
686 const AH_DEVICE_ID *IdInfo;
689 if (!Op)
691 AcpiOsPrintf ("<NULL OP PTR>");
692 return;
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);
705 return;
707 case ACPI_DASM_LNOT_SUFFIX:
709 if (!AcpiGbl_CstyleDisassembly)
711 switch (Op->Common.AmlOpcode)
713 case AML_LEQUAL_OP:
714 AcpiOsPrintf ("LNotEqual");
715 break;
717 case AML_LGREATER_OP:
718 AcpiOsPrintf ("LLessEqual");
719 break;
721 case AML_LLESS_OP:
722 AcpiOsPrintf ("LGreaterEqual");
723 break;
725 default:
726 break;
730 Op->Common.DisasmOpcode = 0;
731 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
732 return;
734 default:
735 break;
738 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
740 /* The op and arguments */
742 switch (Op->Common.AmlOpcode)
744 case AML_LNOT_OP:
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;
754 else
756 AcpiOsPrintf ("%s", OpInfo->Name);
758 break;
760 case AML_BYTE_OP:
762 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
763 break;
765 case AML_WORD_OP:
767 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
769 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
771 else
773 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
775 break;
777 case AML_DWORD_OP:
779 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
781 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
783 else
785 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
787 break;
789 case AML_QWORD_OP:
791 AcpiOsPrintf ("0x%8.8X%8.8X",
792 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
793 break;
795 case AML_STRING_OP:
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);
806 if (IdInfo)
808 AcpiOsPrintf (" /* %s */", IdInfo->Description);
811 break;
813 case AML_BUFFER_OP:
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");
833 break;
835 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
837 AcpiOsPrintf (
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 (");
863 else
865 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
866 AcpiOsPrintf ("Buffer");
868 break;
870 case AML_INT_NAMEPATH_OP:
872 AcpiDmNamestring (Op->Common.Value.Name);
873 break;
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;
883 break;
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));
896 else
898 AcpiOsPrintf (" , %u", Offset);
901 AcpiDmCommaIfFieldMember (Op);
902 break;
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));
918 AcpiOsPrintf (")");
919 AcpiDmCommaIfFieldMember (Op);
920 break;
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)
932 AcpiOsPrintf ("\n");
934 Aml = Child->Named.Data;
935 Length = (UINT32) Child->Common.Value.Integer;
937 Info->Level += 1;
938 Info->MappingOp = Op;
939 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
941 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
943 Info->Level -= 1;
944 AcpiDmIndent (Info->Level);
946 else
948 AcpiDmNamestring (Child->Common.Value.Name);
951 AcpiOsPrintf (")");
952 AcpiDmCommaIfFieldMember (Op);
953 AcpiOsPrintf ("\n");
955 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
956 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
957 break;
959 case AML_INT_BYTELIST_OP:
961 AcpiDmByteList (Info, Op);
962 break;
964 case AML_INT_METHODCALL_OP:
966 Op = AcpiPsGetDepthNext (NULL, Op);
967 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
969 AcpiDmNamestring (Op->Common.Value.Name);
970 break;
972 case AML_ELSE_OP:
974 AcpiDmConvertToElseIf (Op);
975 break;
977 case AML_EXTERNAL_OP:
979 if (AcpiGbl_DmEmitExternalOpcodes)
981 AcpiOsPrintf ("/* Opcode 0x15 */ ");
983 /* Fallthrough */
985 else
987 break;
990 default:
992 /* Just get the opcode name and print it */
994 AcpiOsPrintf ("%s", OpInfo->Name);
997 #ifdef ACPI_DEBUGGER
999 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1000 (WalkState) &&
1001 (WalkState->Results) &&
1002 (WalkState->ResultCount))
1004 AcpiDbDecodeInternalObject (
1005 WalkState->Results->Results.ObjDesc [
1006 (WalkState->ResultCount - 1) %
1007 ACPI_RESULTS_FRAME_OBJ_NUM]);
1009 #endif
1011 break;
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
1026 * EXAMPLE:
1028 * This If..Else..If nested sequence:
1030 * If (Arg0 == 1)
1032 * Local0 = 4
1034 * Else
1036 * If (Arg0 == 2)
1038 * Local0 = 5
1042 * Is converted to this simpler If..ElseIf sequence:
1044 * If (Arg0 == 1)
1046 * Local0 = 4
1048 * ElseIf (Arg0 == 2)
1050 * Local0 = 5
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 ******************************************************************************/
1060 static void
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;
1076 if (!IfOp ||
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");
1083 return;
1086 /* Cannot have anything following the If...Else block */
1088 ElseOp = IfOp->Common.Next;
1089 if (ElseOp && ElseOp->Common.Next)
1091 AcpiOsPrintf ("%s", "Else");
1092 return;
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
1107 * Else.
1109 * Check if the IF has a corresponding ELSE peer
1111 ElseOp = IfOp->Common.Next;
1112 if (ElseOp &&
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);
1123 else
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
1151 * RETURN: None
1153 * DESCRIPTION: Promote an entire parse subtree up one level.
1155 ******************************************************************************/
1157 static void
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 */
1175 while (Op)
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;
1183 break;
1185 Op = Op->Common.Next;
1189 #endif /* ACPI_DISASSEMBLER */