Disassembler: Fix for Divide() support, new support for test suite

Fixes a problem with complex expressions where an illegal mix
of legacy ASL and ASL+ could be emitted.

Adds new support for ASLTS that disables some disassembler
optimizations could be changed during a conversion to ASL+.
These expressions are now emitted in legacy ASL instead
of ASL+.
This commit is contained in:
Robert Moore 2016-09-29 14:04:23 -07:00
parent 14b4464b8b
commit 4b36740865
4 changed files with 109 additions and 9 deletions

View File

@ -633,6 +633,13 @@ AslDoOptions (
Gbl_CompileTimesFlag = TRUE;
break;
case 'd':
/* Disable disassembler code optimizations */
AcpiGbl_DoDisassemblerOptimizations = FALSE;
break;
case 'e':
/* iASL: Disable External opcode generation */

View File

@ -170,6 +170,9 @@ AcpiDmCheckForSymbolicOpcode (
ACPI_PARSE_OBJECT *Child1;
ACPI_PARSE_OBJECT *Child2;
ACPI_PARSE_OBJECT *Target;
ACPI_PARSE_OBJECT *GrandChild1;
ACPI_PARSE_OBJECT *GrandChild2;
ACPI_PARSE_OBJECT *GrandTarget = NULL;
/* Exit immediately if ASL+ not enabled */
@ -179,6 +182,14 @@ 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);
@ -395,6 +406,7 @@ AcpiDmCheckForSymbolicOpcode (
if (AcpiDmIsValidTarget (Target))
{
Child1->Common.OperatorSymbol = NULL;
Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
return (FALSE);
}
@ -411,6 +423,13 @@ 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;
}
@ -550,6 +569,69 @@ AcpiDmCheckForSymbolicOpcode (
/*
* Target is the 2nd operand.
* We know the target is valid, 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.
*/
if (!AcpiGbl_DoDisassemblerOptimizations)
{
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);
}
}
/*
* In the parse tree, simply swap the target with the
* source so that the target is processed first.
*/
@ -635,6 +717,7 @@ AcpiDmCloseOperator (
{
BOOLEAN IsCStyleOp = FALSE;
/* Always emit paren if ASL+ disassembly disabled */
if (!AcpiGbl_CstyleDisassembly)
@ -643,6 +726,14 @@ AcpiDmCloseOperator (
return;
}
/* Check for a non-ASL+ statement */
if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)
{
AcpiOsPrintf (")");
return;
}
/* Check if we need to add an additional closing paren */
switch (Op->Common.AmlOpcode)

View File

@ -394,6 +394,7 @@ ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_CstyleDisassembly, TRUE);
ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_ForceAmlDisassembly, FALSE);
ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Verbose, TRUE);
ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DmEmitExternalOpcodes, FALSE);
ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DoDisassemblerOptimizations, TRUE);
ACPI_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Disasm);
ACPI_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Listing);

View File

@ -989,7 +989,7 @@ typedef union acpi_parse_value
ACPI_PARSE_VALUE Value; /* Value or args associated with the opcode */\
UINT8 ArgListLength; /* Number of elements in the arg list */\
ACPI_DISASM_ONLY_MEMBERS (\
UINT8 DisasmFlags; /* Used during AML disassembly */\
UINT16 DisasmFlags; /* Used during AML disassembly */\
UINT8 DisasmOpcode; /* Subtype used for disassembly */\
char *OperatorSymbol;/* Used for C-style operator name strings */\
char AmlOpName[16]) /* Op name (debug only) */
@ -1109,14 +1109,15 @@ typedef struct acpi_parse_state
/* Parse object DisasmFlags */
#define ACPI_PARSEOP_IGNORE 0x01
#define ACPI_PARSEOP_PARAMETER_LIST 0x02
#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04
#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x08
#define ACPI_PARSEOP_CLOSING_PAREN 0x10
#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x20
#define ACPI_PARSEOP_ASSIGNMENT 0x40
#define ACPI_PARSEOP_ELSEIF 0x80
#define ACPI_PARSEOP_IGNORE 0x0001
#define ACPI_PARSEOP_PARAMETER_LIST 0x0002
#define ACPI_PARSEOP_EMPTY_TERMLIST 0x0004
#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x0008
#define ACPI_PARSEOP_CLOSING_PAREN 0x0010
#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x0020
#define ACPI_PARSEOP_ASSIGNMENT 0x0040
#define ACPI_PARSEOP_ELSEIF 0x0080
#define ACPI_PARSEOP_LEGACY_ASL_ONLY 0x0100
/*****************************************************************************