dtexpress.c revision 229989
197049Speter/******************************************************************************
2166124Srafan *
397049Speter * Module Name: dtexpress.c - Support for integer expressions and labels
497049Speter *
597049Speter *****************************************************************************/
697049Speter
797049Speter/*
897049Speter * Copyright (C) 2000 - 2012, Intel Corp.
997049Speter * All rights reserved.
1097049Speter *
1197049Speter * Redistribution and use in source and binary forms, with or without
1297049Speter * modification, are permitted provided that the following conditions
1397049Speter * are met:
1497049Speter * 1. Redistributions of source code must retain the above copyright
1597049Speter *    notice, this list of conditions, and the following disclaimer,
1697049Speter *    without modification.
1797049Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1897049Speter *    substantially similar to the "NO WARRANTY" disclaimer below
1997049Speter *    ("Disclaimer") and any redistribution must be conditioned upon
2097049Speter *    including a substantially similar Disclaimer requirement for further
2197049Speter *    binary redistribution.
2297049Speter * 3. Neither the names of the above-listed copyright holders nor the names
2397049Speter *    of any contributors may be used to endorse or promote products derived
2497049Speter *    from this software without specific prior written permission.
2597049Speter *
2697049Speter * Alternatively, this software may be distributed under the terms of the
2797049Speter * GNU General Public License ("GPL") version 2 as published by the Free
2897049Speter * Software Foundation.
2997049Speter *
3097049Speter * NO WARRANTY
3197049Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3297049Speter * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3350276Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3450276Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3550276Speter * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3650276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3750276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3850276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3950276Speter * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4050276Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41166124Srafan * POSSIBILITY OF SUCH DAMAGES.
4250276Speter */
4397049Speter
4497049Speter#define __DTEXPRESS_C__
4597049Speter
4697049Speter#include <contrib/dev/acpica/compiler/aslcompiler.h>
4797049Speter#include <contrib/dev/acpica/compiler/dtcompiler.h>
4897049Speter#include "dtparser.y.h"
4997049Speter
5097049Speter#define _COMPONENT          DT_COMPILER
5197049Speter        ACPI_MODULE_NAME    ("dtexpress")
5297049Speter
5397049Speter
5497049Speter/* Local prototypes */
5597049Speter
5697049Speterstatic void
5797049SpeterDtInsertLabelField (
5897049Speter    DT_FIELD                *Field);
5997049Speter
6097049Speterstatic DT_FIELD *
6197049SpeterDtLookupLabel (
6297049Speter    char                    *Name);
6397049Speter
6497049Speter/* Global used for errors during parse and related functions */
6597049Speter
6697049SpeterDT_FIELD                *Gbl_CurrentField;
6797049Speter
6897049Speter
6997049Speter/******************************************************************************
7097049Speter *
7197049Speter * FUNCTION:    DtResolveIntegerExpression
7297049Speter *
7397049Speter * PARAMETERS:  Field               - Field object with Integer expression
7497049Speter *              ReturnValue         - Where the integer is returned
7597049Speter *
7697049Speter * RETURN:      Status, and the resolved 64-bit integer value
7797049Speter *
7897049Speter * DESCRIPTION: Resolve an integer expression to a single value. Supports
7997049Speter *              both integer constants and labels.
8097049Speter *
8197049Speter *****************************************************************************/
8297049Speter
8397049SpeterACPI_STATUS
8497049SpeterDtResolveIntegerExpression (
8597049Speter    DT_FIELD                *Field,
8697049Speter    UINT64                  *ReturnValue)
8797049Speter{
8897049Speter    UINT64                  Result;
8997049Speter
9097049Speter
9197049Speter    DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n",
9297049Speter        Field->Value);
9397049Speter
9497049Speter    Gbl_CurrentField = Field;
9597049Speter
9697049Speter    Result = DtEvaluateExpression (Field->Value);
9797049Speter    *ReturnValue = Result;
9897049Speter    return (AE_OK);
9997049Speter}
10097049Speter
10197049Speter
10297049Speter/******************************************************************************
10397049Speter *
10497049Speter * FUNCTION:    DtDoOperator
10597049Speter *
10697049Speter * PARAMETERS:  LeftValue           - First 64-bit operand
10797049Speter *              Operator            - Parse token for the operator (EXPOP_*)
10897049Speter *              RightValue          - Second 64-bit operand
10997049Speter *
11097049Speter * RETURN:      64-bit result of the requested operation
11197049Speter *
11297049Speter * DESCRIPTION: Perform the various 64-bit integer math functions
11397049Speter *
11497049Speter *****************************************************************************/
11597049Speter
11697049SpeterUINT64
11797049SpeterDtDoOperator (
11897049Speter    UINT64                  LeftValue,
11997049Speter    UINT32                  Operator,
12097049Speter    UINT64                  RightValue)
12197049Speter{
12297049Speter    UINT64                  Result;
12397049Speter
12497049Speter
12597049Speter    /* Perform the requested operation */
12697049Speter
12797049Speter    switch (Operator)
12897049Speter    {
12997049Speter    case EXPOP_ONES_COMPLIMENT:
13097049Speter        Result = ~RightValue;
13197049Speter        break;
13297049Speter
13397049Speter    case EXPOP_LOGICAL_NOT:
13497049Speter        Result = !RightValue;
13597049Speter        break;
13697049Speter
13797049Speter    case EXPOP_MULTIPLY:
13897049Speter        Result = LeftValue * RightValue;
13997049Speter        break;
14097049Speter
14197049Speter    case EXPOP_DIVIDE:
14297049Speter        if (!RightValue)
14397049Speter        {
14497049Speter            DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
14597049Speter                Gbl_CurrentField, Gbl_CurrentField->Value);
14697049Speter            return (0);
14797049Speter        }
14897049Speter        Result = LeftValue / RightValue;
14997049Speter        break;
15097049Speter
15197049Speter    case EXPOP_MODULO:
15297049Speter        if (!RightValue)
15397049Speter        {
15497049Speter            DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
15597049Speter                Gbl_CurrentField, Gbl_CurrentField->Value);
15697049Speter            return (0);
15797049Speter        }
15897049Speter        Result = LeftValue % RightValue;
15997049Speter        break;
16097049Speter
16197049Speter    case EXPOP_ADD:
16250276Speter        Result = LeftValue + RightValue;
16376726Speter        break;
16497049Speter
16550276Speter    case EXPOP_SUBTRACT:
16697049Speter        Result = LeftValue - RightValue;
16776726Speter        break;
16876726Speter
16976726Speter    case EXPOP_SHIFT_RIGHT:
17076726Speter        Result = LeftValue >> RightValue;
17150276Speter        break;
17276726Speter
17376726Speter    case EXPOP_SHIFT_LEFT:
17476726Speter        Result = LeftValue << RightValue;
17576726Speter        break;
17650276Speter
17750276Speter    case EXPOP_LESS:
17876726Speter        Result = LeftValue < RightValue;
17950276Speter        break;
18076726Speter
18150276Speter    case EXPOP_GREATER:
18250276Speter        Result = LeftValue > RightValue;
18397049Speter        break;
18497049Speter
18597049Speter    case EXPOP_LESS_EQUAL:
18697049Speter        Result = LeftValue <= RightValue;
18797049Speter        break;
18897049Speter
18997049Speter    case EXPOP_GREATER_EQUAL:
19097049Speter        Result = LeftValue >= RightValue;
19197049Speter        break;
19276726Speter
19397049Speter    case EXPOP_EQUAL:
19497049Speter        Result = LeftValue = RightValue;
19597049Speter        break;
19697049Speter
19776726Speter    case EXPOP_NOT_EQUAL:
19897049Speter        Result = LeftValue != RightValue;
19997049Speter        break;
20097049Speter
20197049Speter    case EXPOP_AND:
20297049Speter        Result = LeftValue & RightValue;
20397049Speter        break;
20497049Speter
20597049Speter    case EXPOP_XOR:
20697049Speter        Result = LeftValue ^ RightValue;
20797049Speter        break;
20897049Speter
20997049Speter    case EXPOP_OR:
21097049Speter        Result = LeftValue | RightValue;
21197049Speter        break;
21297049Speter
213166124Srafan    case EXPOP_LOGICAL_AND:
214166124Srafan        Result = LeftValue && RightValue;
21597049Speter        break;
21697049Speter
21797049Speter    case EXPOP_LOGICAL_OR:
21897049Speter        Result = LeftValue || RightValue;
21997049Speter        break;
22097049Speter
22197049Speter   default:
22297049Speter
22397049Speter        /* Unknown operator */
22497049Speter
22597049Speter        DtFatal (ASL_MSG_INVALID_EXPRESSION,
22697049Speter            Gbl_CurrentField, Gbl_CurrentField->Value);
22797049Speter        return (0);
22897049Speter    }
22997049Speter
23097049Speter    DbgPrint (ASL_DEBUG_OUTPUT,
23197049Speter        "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n",
23297049Speter        Gbl_CurrentField->Value,
233166124Srafan        ACPI_FORMAT_UINT64 (LeftValue),
23497049Speter        DtGetOpName (Operator),
23597049Speter        ACPI_FORMAT_UINT64 (RightValue),
23697049Speter        ACPI_FORMAT_UINT64 (Result));
23797049Speter
23897049Speter    return (Result);
23997049Speter}
24097049Speter
24197049Speter
24297049Speter/******************************************************************************
24397049Speter *
24497049Speter * FUNCTION:    DtResolveLabel
24597049Speter *
24697049Speter * PARAMETERS:  LabelString         - Contains the label
24797049Speter *
24897049Speter * RETURN:      Table offset associated with the label
24997049Speter *
25097049Speter * DESCRIPTION: Lookup a lable and return its value.
25197049Speter *
25297049Speter *****************************************************************************/
25397049Speter
25497049SpeterUINT64
25597049SpeterDtResolveLabel (
25697049Speter    char                    *LabelString)
25797049Speter{
25897049Speter    DT_FIELD                *LabelField;
25997049Speter
26097049Speter
26197049Speter    DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString);
26297049Speter
26397049Speter    /* Resolve a label reference to an integer (table offset) */
26497049Speter
26597049Speter    if (*LabelString != '$')
26697049Speter    {
26797049Speter        return (0);
26897049Speter    }
269166124Srafan
27097049Speter    LabelField = DtLookupLabel (LabelString);
271166124Srafan    if (!LabelField)
272166124Srafan    {
273166124Srafan        DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL,
274166124Srafan            Gbl_CurrentField, LabelString);
27597049Speter        return (0);
27697049Speter    }
27797049Speter
27897049Speter    /* All we need from the label is the offset in the table */
27997049Speter
28097049Speter    DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n",
28197049Speter        LabelField->TableOffset);
28297049Speter
28397049Speter    return (LabelField->TableOffset);
28497049Speter}
28597049Speter
28697049Speter
28797049Speter/******************************************************************************
28897049Speter *
28997049Speter * FUNCTION:    DtDetectAllLabels
29097049Speter *
29197049Speter * PARAMETERS:  FieldList           - Field object at start of generic list
29297049Speter *
29397049Speter * RETURN:      None
29497049Speter *
29597049Speter * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as
29697049Speter *              a UEFI table.) and insert them into the global label list.
29797049Speter *
29897049Speter *****************************************************************************/
29997049Speter
30097049Spetervoid
30197049SpeterDtDetectAllLabels (
30297049Speter    DT_FIELD                *FieldList)
30397049Speter{
30497049Speter    ACPI_DMTABLE_INFO       *Info;
30597049Speter    DT_FIELD                *GenericField;
30697049Speter    UINT32                  TableOffset;
30797049Speter
30897049Speter
30997049Speter    TableOffset = Gbl_CurrentTableOffset;
31097049Speter    GenericField = FieldList;
31197049Speter
31297049Speter    /*
31397049Speter     * Process all "Label:" fields within the parse tree. We need
31497049Speter     * to know the offsets for all labels before we can compile
31597049Speter     * the parse tree in order to handle forward references. Traverse
31697049Speter     * tree and get/set all field lengths of all operators in order to
31797049Speter     * determine the label offsets.
31897049Speter     */
31997049Speter    while (GenericField)
32097049Speter    {
32197049Speter        Info = DtGetGenericTableInfo (GenericField->Name);
32297049Speter        if (Info)
32397049Speter        {
32497049Speter            /* Maintain table offsets */
32597049Speter
32697049Speter            GenericField->TableOffset = TableOffset;
32797049Speter            TableOffset += DtGetFieldLength (GenericField, Info);
32897049Speter
32997049Speter            /* Insert all labels in the global label list */
33097049Speter
33197049Speter            if (Info->Opcode == ACPI_DMT_LABEL)
33297049Speter            {
33397049Speter                DtInsertLabelField (GenericField);
33497049Speter            }
33597049Speter        }
33697049Speter
33797049Speter        GenericField = GenericField->Next;
33897049Speter    }
33997049Speter}
34097049Speter
34197049Speter
34297049Speter/******************************************************************************
34397049Speter *
34497049Speter * FUNCTION:    DtInsertLabelField
34597049Speter *
34697049Speter * PARAMETERS:  Field               - Field object with Label to be inserted
34750276Speter *
34850276Speter * RETURN:      None
34976726Speter *
35076726Speter * DESCRIPTION: Insert a label field into the global label list
35176726Speter *
35276726Speter *****************************************************************************/
35376726Speter
35476726Speterstatic void
35576726SpeterDtInsertLabelField (
35650276Speter    DT_FIELD                *Field)
357{
358
359    DbgPrint (ASL_DEBUG_OUTPUT,
360        "DtInsertLabelField: Found Label : %s at output table offset %X\n",
361        Field->Value, Field->TableOffset);
362
363    Field->NextLabel = Gbl_LabelList;
364    Gbl_LabelList = Field;
365}
366
367
368/******************************************************************************
369 *
370 * FUNCTION:    DtLookupLabel
371 *
372 * PARAMETERS:  Name                - Label to be resolved
373 *
374 * RETURN:      Field object associated with the label
375 *
376 * DESCRIPTION: Lookup a label in the global label list. Used during the
377 *              resolution of integer expressions.
378 *
379 *****************************************************************************/
380
381static DT_FIELD *
382DtLookupLabel (
383    char                    *Name)
384{
385    DT_FIELD                *LabelField;
386
387
388    /* Skip a leading $ */
389
390    if (*Name == '$')
391    {
392        Name++;
393    }
394
395    /* Search global list */
396
397    LabelField = Gbl_LabelList;
398    while (LabelField)
399    {
400        if (!ACPI_STRCMP (Name, LabelField->Value))
401        {
402            return (LabelField);
403        }
404        LabelField = LabelField->NextLabel;
405    }
406
407    return (NULL);
408}
409