summaryrefslogtreecommitdiff
path: root/source/components/disassembler/dmcstyle.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/components/disassembler/dmcstyle.c')
-rw-r--r--source/components/disassembler/dmcstyle.c348
1 files changed, 202 insertions, 146 deletions
diff --git a/source/components/disassembler/dmcstyle.c b/source/components/disassembler/dmcstyle.c
index 939168f24257..f5e9560a9071 100644
--- a/source/components/disassembler/dmcstyle.c
+++ b/source/components/disassembler/dmcstyle.c
@@ -73,6 +73,11 @@ AcpiDmIsTargetAnOperand (
ACPI_PARSE_OBJECT *Operand,
BOOLEAN TopLevel);
+static BOOLEAN
+AcpiDmIsOptimizationIgnored (
+ ACPI_PARSE_OBJECT *StoreOp,
+ ACPI_PARSE_OBJECT *StoreArgument);
+
/*******************************************************************************
*
@@ -95,12 +100,10 @@ AcpiDmCheckForSymbolicOpcode (
ACPI_OP_WALK_INFO *Info)
{
char *OperatorSymbol = NULL;
- ACPI_PARSE_OBJECT *Child1;
- ACPI_PARSE_OBJECT *Child2;
+ ACPI_PARSE_OBJECT *Argument1;
+ ACPI_PARSE_OBJECT *Argument2;
ACPI_PARSE_OBJECT *Target;
- ACPI_PARSE_OBJECT *GrandChild1;
- ACPI_PARSE_OBJECT *GrandChild2;
- ACPI_PARSE_OBJECT *GrandTarget = NULL;
+ ACPI_PARSE_OBJECT *Target2;
/* Exit immediately if ASL+ not enabled */
@@ -110,25 +113,17 @@ AcpiDmCheckForSymbolicOpcode (
return (FALSE);
}
- /* Check for a non-ASL+ statement, propagate the flag */
-
- if (Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)
- {
- Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
- return (FALSE);
- }
-
/* Get the first operand */
- Child1 = AcpiPsGetArg (Op, 0);
- if (!Child1)
+ Argument1 = AcpiPsGetArg (Op, 0);
+ if (!Argument1)
{
return (FALSE);
}
/* Get the second operand */
- Child2 = Child1->Common.Next;
+ Argument2 = Argument1->Common.Next;
/* Setup the operator string for this opcode */
@@ -202,7 +197,7 @@ AcpiDmCheckForSymbolicOpcode (
* LNotEqual, LLessEqual, and LGreaterEqual. There are
* no actual AML opcodes for these operators.
*/
- switch (Child1->Common.AmlOpcode)
+ switch (Argument1->Common.AmlOpcode)
{
case AML_LEQUAL_OP:
OperatorSymbol = " != ";
@@ -224,19 +219,18 @@ AcpiDmCheckForSymbolicOpcode (
return (TRUE);
}
- Child1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
+ Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
- Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
/* Save symbol string in the next child (not peer) */
- Child2 = AcpiPsGetArg (Child1, 0);
- if (!Child2)
+ Argument2 = AcpiPsGetArg (Argument1, 0);
+ if (!Argument2)
{
return (FALSE);
}
- Child2->Common.OperatorSymbol = OperatorSymbol;
+ Argument2->Common.OperatorSymbol = OperatorSymbol;
return (TRUE);
case AML_INDEX_OP:
@@ -246,10 +240,10 @@ AcpiDmCheckForSymbolicOpcode (
* the symbolic operators for Index(). It doesn't make sense to
* use Index() with a constant anyway.
*/
- if ((Child1->Common.AmlOpcode == AML_STRING_OP) ||
- (Child1->Common.AmlOpcode == AML_BUFFER_OP) ||
- (Child1->Common.AmlOpcode == AML_PACKAGE_OP) ||
- (Child1->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
+ if ((Argument1->Common.AmlOpcode == AML_STRING_OP) ||
+ (Argument1->Common.AmlOpcode == AML_BUFFER_OP) ||
+ (Argument1->Common.AmlOpcode == AML_PACKAGE_OP) ||
+ (Argument1->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
{
Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;
return (FALSE);
@@ -257,8 +251,8 @@ AcpiDmCheckForSymbolicOpcode (
/* Index operator is [] */
- Child1->Common.OperatorSymbol = " [";
- Child2->Common.OperatorSymbol = "]";
+ Argument1->Common.OperatorSymbol = " [";
+ Argument2->Common.OperatorSymbol = "]";
break;
/* Unary operators */
@@ -280,7 +274,7 @@ AcpiDmCheckForSymbolicOpcode (
return (FALSE);
}
- if (Child1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)
+ if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)
{
return (TRUE);
}
@@ -291,9 +285,9 @@ AcpiDmCheckForSymbolicOpcode (
* deferring symbol output until after the first operand has been
* emitted.
*/
- if (!Child1->Common.OperatorSymbol)
+ if (!Argument1->Common.OperatorSymbol)
{
- Child1->Common.OperatorSymbol = OperatorSymbol;
+ Argument1->Common.OperatorSymbol = OperatorSymbol;
}
/*
@@ -323,23 +317,58 @@ AcpiDmCheckForSymbolicOpcode (
/* Target is 3rd operand */
- Target = Child2->Common.Next;
+ Target = Argument2->Common.Next;
if (Op->Common.AmlOpcode == AML_DIVIDE_OP)
{
+ Target2 = Target->Common.Next;
+
/*
* Divide has an extra target operand (Remainder).
- * If this extra target is specified, it cannot be converted
- * to a C-style operator
+ * Default behavior is to simply ignore ASL+ conversion
+ * if the remainder target (modulo) is specified.
*/
- if (AcpiDmIsValidTarget (Target))
+ if (!AcpiGbl_DoDisassemblerOptimizations)
{
- Child1->Common.OperatorSymbol = NULL;
- Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
- return (FALSE);
+ if (AcpiDmIsValidTarget (Target))
+ {
+ Argument1->Common.OperatorSymbol = NULL;
+ Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
+ return (FALSE);
+ }
+
+ Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ Target = Target2;
}
+ else
+ {
+ /*
+ * Divide has an extra target operand (Remainder).
+ * If both targets are specified, it cannot be converted
+ * to a C-style operator.
+ */
+ if (AcpiDmIsValidTarget (Target) &&
+ AcpiDmIsValidTarget (Target2))
+ {
+ Argument1->Common.OperatorSymbol = NULL;
+ Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
+ return (FALSE);
+ }
+
+ if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */
+ {
+ /* Convert the Divide to Modulo */
+
+ Op->Common.AmlOpcode = AML_MOD_OP;
- Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
- Target = Target->Common.Next;
+ Argument1->Common.OperatorSymbol = " % ";
+ Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ }
+ else /* Only second Target (quotient) is valid */
+ {
+ Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ Target = Target2;
+ }
+ }
}
/* Parser should ensure there is at least a placeholder target */
@@ -351,13 +380,6 @@ AcpiDmCheckForSymbolicOpcode (
if (!AcpiDmIsValidTarget (Target))
{
- if (Op->Common.Parent->Common.AmlOpcode == AML_STORE_OP)
- {
- Op->Common.DisasmFlags = 0;
- Child1->Common.OperatorSymbol = NULL;
- return (FALSE);
- }
-
/* Not a valid target (placeholder only, from parser) */
break;
}
@@ -390,8 +412,8 @@ AcpiDmCheckForSymbolicOpcode (
* Add (B, A, A) --> A += B
* Add (B, C, A) --> A = (B + C)
*/
- if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) ||
- (AcpiDmIsTargetAnOperand (Target, Child2, TRUE)))
+ if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) ||
+ (AcpiDmIsTargetAnOperand (Target, Argument2, TRUE)))
{
Target->Common.OperatorSymbol =
AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
@@ -399,7 +421,7 @@ AcpiDmCheckForSymbolicOpcode (
/* Convert operator to compound assignment */
Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
- Child1->Common.OperatorSymbol = NULL;
+ Argument1->Common.OperatorSymbol = NULL;
return (TRUE);
}
break;
@@ -419,7 +441,7 @@ AcpiDmCheckForSymbolicOpcode (
* Subtract (A, B, A) --> A -= B
* Subtract (B, A, A) --> A = (B - A)
*/
- if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)))
+ if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)))
{
Target->Common.OperatorSymbol =
AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
@@ -427,7 +449,7 @@ AcpiDmCheckForSymbolicOpcode (
/* Convert operator to compound assignment */
Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
- Child1->Common.OperatorSymbol = NULL;
+ Argument1->Common.OperatorSymbol = NULL;
return (TRUE);
}
break;
@@ -481,7 +503,7 @@ AcpiDmCheckForSymbolicOpcode (
/* Target is optional, 3rd operand */
- Target = Child2->Common.Next;
+ Target = Argument2->Common.Next;
if (AcpiDmIsValidTarget (Target))
{
AcpiDmPromoteTarget (Op, Target);
@@ -495,75 +517,23 @@ AcpiDmCheckForSymbolicOpcode (
case AML_STORE_OP:
/*
- * Target is the 2nd operand.
- * We know the target is valid, it is not optional.
+ * For Store, the Target is the 2nd operand. We know the target
+ * is valid, because it is not optional.
*
- * The following block implements "Ignore conversion if a store
- * is followed by a math/bit operator that has no target". Used
- * only for the ASL test suite.
+ * Ignore any optimizations/folding if flag is set.
+ * Used for iASL/disassembler test suite only.
*/
- if (!AcpiGbl_DoDisassemblerOptimizations)
+ if (AcpiDmIsOptimizationIgnored (Op, Argument1))
{
- switch (Child1->Common.AmlOpcode)
- {
- /* This operator has two operands and two targets */
-
- case AML_DIVIDE_OP:
-
- GrandChild1 = Child1->Common.Value.Arg;
- GrandChild2 = GrandChild1->Common.Next;
- GrandTarget = GrandChild2->Common.Next;
-
- if (GrandTarget && !AcpiDmIsValidTarget (GrandTarget))
- {
- Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
- return (FALSE);
- }
- GrandTarget = GrandTarget->Common.Next;
- break;
-
- case AML_ADD_OP:
- case AML_SUBTRACT_OP:
- case AML_MULTIPLY_OP:
- case AML_MOD_OP:
- case AML_SHIFT_LEFT_OP:
- case AML_SHIFT_RIGHT_OP:
- case AML_BIT_AND_OP:
- case AML_BIT_OR_OP:
- case AML_BIT_XOR_OP:
- case AML_INDEX_OP:
-
- /* These operators have two operands and a target */
-
- GrandChild1 = Child1->Common.Value.Arg;
- GrandChild2 = GrandChild1->Common.Next;
- GrandTarget = GrandChild2->Common.Next;
- break;
-
- case AML_BIT_NOT_OP:
-
- /* This operator has one operand and a target */
-
- GrandChild1 = Child1->Common.Value.Arg;
- GrandTarget = GrandChild1->Common.Next;
- break;
-
- default:
- break;
- }
-
- if (GrandTarget && !AcpiDmIsValidTarget (GrandTarget))
- {
- Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
- return (FALSE);
- }
+ return (FALSE);
}
/*
+ * Perform conversion.
* In the parse tree, simply swap the target with the
* source so that the target is processed first.
*/
- Target = Child1->Common.Next;
+ Target = Argument1->Common.Next;
if (!Target)
{
return (FALSE);
@@ -580,7 +550,7 @@ AcpiDmCheckForSymbolicOpcode (
/* Target is optional, 2nd operand */
- Target = Child1->Common.Next;
+ Target = Argument1->Common.Next;
if (!Target)
{
return (FALSE);
@@ -605,23 +575,129 @@ AcpiDmCheckForSymbolicOpcode (
break;
}
+ /* All other operators, emit an open paren */
+
+ AcpiOsPrintf ("(");
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDmIsOptimizationIgnored
+ *
+ * PARAMETERS: StoreOp - Store operator parse object
+ * StoreArgument - Target associate with the Op
+ *
+ * RETURN: TRUE if this Store operator should not be converted/removed.
+ *
+ * DESCRIPTION: The following function implements "Do not optimize if a
+ * store is immediately followed by a math/bit operator that
+ * has no target".
+ *
+ * Function is ignored if DoDisassemblerOptimizations is TRUE.
+ * This is the default, ignore this function.
+ *
+ * Disables these types of optimizations, and simply emits
+ * legacy ASL code:
+ * Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2)
+ * --> INT2 = INT1 + 4
+ *
+ * Store (Not (INT1), INT2) --> Not (INT1, INT2)
+ * --> INT2 = ~INT1
+ *
+ * Used only for the ASL test suite. For the test suite, we
+ * don't want to perform some optimizations to ensure binary
+ * compatibility with the generation of the legacy ASL->AML.
+ * In other words, for all test modules we want exactly:
+ * (ASL+ -> AML) == (ASL- -> AML)
+ *
+ ******************************************************************************/
+
+static BOOLEAN
+AcpiDmIsOptimizationIgnored (
+ ACPI_PARSE_OBJECT *StoreOp,
+ ACPI_PARSE_OBJECT *StoreArgument)
+{
+ ACPI_PARSE_OBJECT *Argument1;
+ ACPI_PARSE_OBJECT *Argument2;
+ ACPI_PARSE_OBJECT *Target;
+
+
+ /* No optimizations/folding for the typical case */
+
+ if (AcpiGbl_DoDisassemblerOptimizations)
+ {
+ return (FALSE);
+ }
+
/*
- * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens
- * output here. We also need to check the parent to see if this op
- * is part of a compound test (!=, >=, <=).
+ * Only a small subset of ASL/AML operators can be optimized.
+ * Can only optimize/fold if there is no target (or targets)
+ * specified for the operator. And of course, the operator
+ * is surrrounded by a Store() operator.
*/
- if ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) ||
- ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) &&
- (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)))
+ switch (StoreArgument->Common.AmlOpcode)
{
- /* Do Nothing. Paren already generated */
- return (TRUE);
- }
+ case AML_ADD_OP:
+ case AML_SUBTRACT_OP:
+ case AML_MULTIPLY_OP:
+ case AML_MOD_OP:
+ case AML_SHIFT_LEFT_OP:
+ case AML_SHIFT_RIGHT_OP:
+ case AML_BIT_AND_OP:
+ case AML_BIT_OR_OP:
+ case AML_BIT_XOR_OP:
+ case AML_INDEX_OP:
- /* All other operators, emit an open paren */
+ /* These operators have two arguments and one target */
- AcpiOsPrintf ("(");
- return (TRUE);
+ Argument1 = StoreArgument->Common.Value.Arg;
+ Argument2 = Argument1->Common.Next;
+ Target = Argument2->Common.Next;
+
+ if (!AcpiDmIsValidTarget (Target))
+ {
+ StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
+ return (TRUE);
+ }
+ break;
+
+ case AML_DIVIDE_OP:
+
+ /* This operator has two arguments and two targets */
+
+ Argument1 = StoreArgument->Common.Value.Arg;
+ Argument2 = Argument1->Common.Next;
+ Target = Argument2->Common.Next;
+
+ if (!AcpiDmIsValidTarget (Target) ||
+ !AcpiDmIsValidTarget (Target->Common.Next))
+ {
+ StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
+ return (TRUE);
+ }
+ break;
+
+ case AML_BIT_NOT_OP:
+
+ /* This operator has one operand and one target */
+
+ Argument1 = StoreArgument->Common.Value.Arg;
+ Target = Argument1->Common.Next;
+
+ if (!AcpiDmIsValidTarget (Target))
+ {
+ StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
+ return (TRUE);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return (FALSE);
}
@@ -643,8 +719,6 @@ void
AcpiDmCloseOperator (
ACPI_PARSE_OBJECT *Op)
{
- BOOLEAN IsCStyleOp = FALSE;
-
/* Always emit paren if ASL+ disassembly disabled */
@@ -654,8 +728,6 @@ AcpiDmCloseOperator (
return;
}
- /* Check for a non-ASL+ statement */
-
if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)
{
AcpiOsPrintf (")");
@@ -695,8 +767,6 @@ AcpiDmCloseOperator (
{
AcpiOsPrintf (")");
}
-
- IsCStyleOp = TRUE;
break;
case AML_INDEX_OP:
@@ -724,21 +794,7 @@ AcpiDmCloseOperator (
break;
}
- /*
- * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens
- * output here. We also need to check the parent to see if this op
- * is part of a compound test (!=, >=, <=).
- */
- if (IsCStyleOp &&
- ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) ||
- ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) &&
- (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX))))
- {
- return;
- }
-
AcpiOsPrintf (")");
- return;
}