diff options
Diffstat (limited to 'compiler/dtexpress.c')
| -rw-r--r-- | compiler/dtexpress.c | 284 |
1 files changed, 151 insertions, 133 deletions
diff --git a/compiler/dtexpress.c b/compiler/dtexpress.c index 20a2e3eb1d06..cb7620eeb37a 100644 --- a/compiler/dtexpress.c +++ b/compiler/dtexpress.c @@ -45,6 +45,7 @@ #include "aslcompiler.h" #include "dtcompiler.h" +#include "dtparser.y.h" #define _COMPONENT DT_COMPILER ACPI_MODULE_NAME ("dtexpress") @@ -52,11 +53,6 @@ /* Local prototypes */ -static UINT64 -DtResolveInteger ( - DT_FIELD *Field, - char *IntegerString); - static void DtInsertLabelField ( DT_FIELD *Field); @@ -65,204 +61,226 @@ static DT_FIELD * DtLookupLabel ( char *Name); +/* Global used for errors during parse and related functions */ + +DT_FIELD *Gbl_CurrentField; + /****************************************************************************** * * FUNCTION: DtResolveIntegerExpression * * PARAMETERS: Field - Field object with Integer expression + * ReturnValue - Where the integer is returned * - * RETURN: A 64-bit integer value + * RETURN: Status, and the resolved 64-bit integer value * * DESCRIPTION: Resolve an integer expression to a single value. Supports - * both integer constants and labels. Supported operators are: - * +,-,*,/,%,|,&,^ + * both integer constants and labels. * *****************************************************************************/ -UINT64 +ACPI_STATUS DtResolveIntegerExpression ( - DT_FIELD *Field) + DT_FIELD *Field, + UINT64 *ReturnValue) { - char *IntegerString; - char *Operator; - UINT64 Value; - UINT64 Value2; + UINT64 Result; DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", Field->Value); - strcpy (MsgBuffer, Field->Value); /* Must take a copy for strtok() */ + Gbl_CurrentField = Field; - /* Obtain and resolve the first operand */ + Result = DtEvaluateExpression (Field->Value); + *ReturnValue = Result; + return (AE_OK); +} - IntegerString = strtok (MsgBuffer, " "); - if (!IntegerString) - { - DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); - return (0); - } - Value = DtResolveInteger (Field, IntegerString); - DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V1: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (Value)); +/****************************************************************************** + * + * FUNCTION: DtDoOperator + * + * PARAMETERS: LeftValue - First 64-bit operand + * Operator - Parse token for the operator (EXPOP_*) + * RightValue - Second 64-bit operand + * + * RETURN: 64-bit result of the requested operation + * + * DESCRIPTION: Perform the various 64-bit integer math functions + * + *****************************************************************************/ - /* - * Consume the entire expression string. For the rest of the - * expression string, values are of the form: - * <operator> <integer> - */ - while (1) +UINT64 +DtDoOperator ( + UINT64 LeftValue, + UINT32 Operator, + UINT64 RightValue) +{ + UINT64 Result; + + + /* Perform the requested operation */ + + switch (Operator) { - Operator = strtok (NULL, " "); - if (!Operator) - { - /* Normal exit */ + case EXPOP_ONES_COMPLIMENT: + Result = ~RightValue; + break; - DbgPrint (ASL_DEBUG_OUTPUT, "Expression Resolved to: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (Value)); + case EXPOP_LOGICAL_NOT: + Result = !RightValue; + break; - return (Value); - } + case EXPOP_MULTIPLY: + Result = LeftValue * RightValue; + break; - IntegerString = strtok (NULL, " "); - if (!IntegerString || - (strlen (Operator) > 1)) + case EXPOP_DIVIDE: + if (!RightValue) { - /* No corresponding operand for operator or invalid operator */ + DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, + Gbl_CurrentField, Gbl_CurrentField->Value); + return (0); + } + Result = LeftValue / RightValue; + break; - DtError (ASL_ERROR, ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); + case EXPOP_MODULO: + if (!RightValue) + { + DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, + Gbl_CurrentField, Gbl_CurrentField->Value); return (0); } + Result = LeftValue % RightValue; + break; - Value2 = DtResolveInteger (Field, IntegerString); - DbgPrint (ASL_DEBUG_OUTPUT, "Integer resolved to V2: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64 (Value2)); + case EXPOP_ADD: + Result = LeftValue + RightValue; + break; - /* Perform the requested operation */ + case EXPOP_SUBTRACT: + Result = LeftValue - RightValue; + break; - switch (*Operator) - { - case '-': - Value -= Value2; - break; + case EXPOP_SHIFT_RIGHT: + Result = LeftValue >> RightValue; + break; - case '+': - Value += Value2; - break; + case EXPOP_SHIFT_LEFT: + Result = LeftValue << RightValue; + break; - case '*': - Value *= Value2; - break; + case EXPOP_LESS: + Result = LeftValue < RightValue; + break; - case '|': - Value |= Value2; - break; + case EXPOP_GREATER: + Result = LeftValue > RightValue; + break; - case '&': - Value &= Value2; - break; + case EXPOP_LESS_EQUAL: + Result = LeftValue <= RightValue; + break; - case '^': - Value ^= Value2; - break; + case EXPOP_GREATER_EQUAL: + Result = LeftValue >= RightValue; + break; - case '/': - if (!Value2) - { - DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value); - return (0); - } - Value /= Value2; - break; + case EXPOP_EQUAL: + Result = LeftValue = RightValue; + break; - case '%': - if (!Value2) - { - DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, Field, Field->Value); - return (0); - } - Value %= Value2; - break; + case EXPOP_NOT_EQUAL: + Result = LeftValue != RightValue; + break; - default: + case EXPOP_AND: + Result = LeftValue & RightValue; + break; - /* Unknown operator */ + case EXPOP_XOR: + Result = LeftValue ^ RightValue; + break; - DtFatal (ASL_MSG_INVALID_EXPRESSION, Field, Field->Value); - break; - } + case EXPOP_OR: + Result = LeftValue | RightValue; + break; + + case EXPOP_LOGICAL_AND: + Result = LeftValue && RightValue; + break; + + case EXPOP_LOGICAL_OR: + Result = LeftValue || RightValue; + break; + + default: + + /* Unknown operator */ + + DtFatal (ASL_MSG_INVALID_EXPRESSION, + Gbl_CurrentField, Gbl_CurrentField->Value); + return (0); } - return (Value); + DbgPrint (ASL_DEBUG_OUTPUT, + "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", + Gbl_CurrentField->Value, + ACPI_FORMAT_UINT64 (LeftValue), + DtGetOpName (Operator), + ACPI_FORMAT_UINT64 (RightValue), + ACPI_FORMAT_UINT64 (Result)); + + return (Result); } /****************************************************************************** * - * FUNCTION: DtResolveInteger - * - * PARAMETERS: Field - Field object with string to be resolved - * IntegerString - Integer to be resolved + * FUNCTION: DtResolveLabel * - * RETURN: A 64-bit integer value + * PARAMETERS: LabelString - Contains the label * - * DESCRIPTION: Resolve a single integer string to a value. Supports both - * integer constants and labels. + * RETURN: Table offset associated with the label * - * NOTE: References to labels must begin with a dollar sign ($) + * DESCRIPTION: Lookup a lable and return its value. * *****************************************************************************/ -static UINT64 -DtResolveInteger ( - DT_FIELD *Field, - char *IntegerString) +UINT64 +DtResolveLabel ( + char *LabelString) { DT_FIELD *LabelField; - UINT64 Value = 0; - char *Message = NULL; - ACPI_STATUS Status; - DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Integer: %s\n", IntegerString); + DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); /* Resolve a label reference to an integer (table offset) */ - if (*IntegerString == '$') + if (*LabelString != '$') { - LabelField = DtLookupLabel (IntegerString); - if (!LabelField) - { - DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, Field, IntegerString); - return (0); - } - - /* All we need from the label is the offset in the table */ - - Value = LabelField->TableOffset; - return (Value); + return (0); } - /* Convert string to an actual integer */ - - Status = DtStrtoul64 (IntegerString, &Value); - if (ACPI_FAILURE (Status)) + LabelField = DtLookupLabel (LabelString); + if (!LabelField) { - if (Status == AE_LIMIT) - { - Message = "Constant larger than 64 bits"; - } - else if (Status == AE_BAD_CHARACTER) - { - Message = "Invalid character in constant"; - } - - DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, Message); + DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, + Gbl_CurrentField, LabelString); + return (0); } - return (Value); + /* All we need from the label is the offset in the table */ + + DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", + LabelField->TableOffset); + + return (LabelField->TableOffset); } |
