diff options
Diffstat (limited to 'source/components/disassembler/dmcstyle.c')
-rw-r--r-- | source/components/disassembler/dmcstyle.c | 348 |
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; } |