summaryrefslogtreecommitdiff
path: root/source/components/disassembler
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2015-12-18 18:35:46 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2015-12-18 18:35:46 +0000
commit1c6f3e7bf6ed0a9ff1bd466e319cdf456e6e91dc (patch)
tree9ffecbf2e9ce4e63aac5515363a488b761a02b03 /source/components/disassembler
parentb9098066cd6284319bca922f13e59517f774a103 (diff)
Notes
Diffstat (limited to 'source/components/disassembler')
-rw-r--r--source/components/disassembler/dmopcode.c124
-rw-r--r--source/components/disassembler/dmwalk.c49
2 files changed, 149 insertions, 24 deletions
diff --git a/source/components/disassembler/dmopcode.c b/source/components/disassembler/dmopcode.c
index 02c51bdefa41b..4615ebe869150 100644
--- a/source/components/disassembler/dmopcode.c
+++ b/source/components/disassembler/dmopcode.c
@@ -60,6 +60,10 @@ static void
AcpiDmMatchKeyword (
ACPI_PARSE_OBJECT *Op);
+static void
+AcpiDmConvertToElseIf (
+ ACPI_PARSE_OBJECT *Op);
+
/*******************************************************************************
*
@@ -683,6 +687,11 @@ AcpiDmDisassembleOneOp (
return;
}
+ if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
+ {
+ return; /* ElseIf macro was already emitted */
+ }
+
switch (Op->Common.DisasmOpcode)
{
case ACPI_DASM_MATCHOP:
@@ -955,6 +964,11 @@ AcpiDmDisassembleOneOp (
AcpiDmNamestring (Op->Common.Value.Name);
break;
+ case AML_ELSE_OP:
+
+ AcpiDmConvertToElseIf (Op);
+ break;
+
default:
/* Just get the opcode name and print it */
@@ -979,3 +993,113 @@ AcpiDmDisassembleOneOp (
break;
}
}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDmConvertToElseIf
+ *
+ * PARAMETERS: OriginalElseOp - ELSE Object to be examined
+ *
+ * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
+ *
+ * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
+ *
+ * EXAMPLE:
+ *
+ * This If..Else..If nested sequence:
+ *
+ * If (Arg0 == 1)
+ * {
+ * Local0 = 4
+ * }
+ * Else
+ * {
+ * If (Arg0 == 2)
+ * {
+ * Local0 = 5
+ * }
+ * }
+ *
+ * Is converted to this simpler If..ElseIf sequence:
+ *
+ * If (Arg0 == 1)
+ * {
+ * Local0 = 4
+ * }
+ * ElseIf (Arg0 == 2)
+ * {
+ * Local0 = 5
+ * }
+ *
+ * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
+ * macro that emits an Else opcode followed by an If opcode. This function
+ * reverses these AML sequences back to an ElseIf macro where possible. This
+ * can make the disassembled ASL code simpler and more like the original code.
+ *
+ ******************************************************************************/
+
+static void
+AcpiDmConvertToElseIf (
+ ACPI_PARSE_OBJECT *OriginalElseOp)
+{
+ ACPI_PARSE_OBJECT *IfOp;
+ ACPI_PARSE_OBJECT *ElseOp;
+
+
+ /* Examine the first child of the Else */
+
+ IfOp = OriginalElseOp->Common.Value.Arg;
+ if (!IfOp || (IfOp->Common.AmlOpcode != AML_IF_OP))
+ {
+ /* Not an Else..If sequence, cannot convert to ElseIf */
+
+ AcpiOsPrintf ("%s", "Else");
+ return;
+ }
+
+ /* Emit ElseIf, mark the IF as now an ELSEIF */
+
+ AcpiOsPrintf ("%s", "ElseIf");
+ IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
+
+ /* The IF parent will now be the same as the original ELSE parent */
+
+ IfOp->Common.Parent = OriginalElseOp->Common.Parent;
+
+ /*
+ * Update the NEXT pointers to restructure the parse tree, essentially
+ * promoting an If..Else block up to the same level as the original
+ * Else.
+ *
+ * Check if the IF has a corresponding ELSE peer
+ */
+ ElseOp = IfOp->Common.Next;
+ if (ElseOp &&
+ (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
+ {
+ /* If an ELSE matches the IF, promote it also */
+
+ ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
+ ElseOp->Common.Next = OriginalElseOp->Common.Next;
+ }
+ else
+ {
+ /* Otherwise, set the IF NEXT to the original ELSE NEXT */
+
+ IfOp->Common.Next = OriginalElseOp->Common.Next;
+ }
+
+ /* Detach the child IF block from the original ELSE */
+
+ OriginalElseOp->Common.Value.Arg = NULL;
+
+ /* Ignore the original ELSE from now on */
+
+ OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
+
+ /* Insert IF (now ELSEIF) as next peer of the original ELSE */
+
+ OriginalElseOp->Common.Next = IfOp;
+}
diff --git a/source/components/disassembler/dmwalk.c b/source/components/disassembler/dmwalk.c
index 4a094789a7038..664e709d69aaa 100644
--- a/source/components/disassembler/dmwalk.c
+++ b/source/components/disassembler/dmwalk.c
@@ -488,39 +488,40 @@ AcpiDmDescendingOp (
}
else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
(!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
+ (!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
(Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
{
+ /*
+ * This is a first-level element of a term list,
+ * indent a new line
+ */
+ switch (Op->Common.AmlOpcode)
+ {
+ case AML_NOOP_OP:
/*
- * This is a first-level element of a term list,
- * indent a new line
+ * Optionally just ignore this opcode. Some tables use
+ * NoOp opcodes for "padding" out packages that the BIOS
+ * changes dynamically. This can leave hundreds or
+ * thousands of NoOp opcodes that if disassembled,
+ * cannot be compiled because they are syntactically
+ * incorrect.
*/
- switch (Op->Common.AmlOpcode)
+ if (AcpiGbl_IgnoreNoopOperator)
{
- case AML_NOOP_OP:
- /*
- * Optionally just ignore this opcode. Some tables use
- * NoOp opcodes for "padding" out packages that the BIOS
- * changes dynamically. This can leave hundreds or
- * thousands of NoOp opcodes that if disassembled,
- * cannot be compiled because they are syntactically
- * incorrect.
- */
- if (AcpiGbl_IgnoreNoopOperator)
- {
- Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
- return (AE_OK);
- }
+ Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ return (AE_OK);
+ }
- /* Fallthrough */
+ /* Fallthrough */
- default:
+ default:
- AcpiDmIndent (Level);
- break;
- }
+ AcpiDmIndent (Level);
+ break;
+ }
- Info->LastLevel = Level;
- Info->Count = 0;
+ Info->LastLevel = Level;
+ Info->Count = 0;
}
/*