• Home
  • History
  • Annotate
  • only in this directory
dtexpress.c revision 220663
1133808Spjd/******************************************************************************
2156878Spjd *
3133808Spjd * Module Name: dtexpress.c - Support for integer expressions and labels
4133808Spjd *
5133808Spjd *****************************************************************************/
6133808Spjd
7133808Spjd/*
8133808Spjd * Copyright (C) 2000 - 2011, Intel Corp.
9133808Spjd * All rights reserved.
10133808Spjd *
11133808Spjd * Redistribution and use in source and binary forms, with or without
12133808Spjd * modification, are permitted provided that the following conditions
13155174Spjd * are met:
14133808Spjd * 1. Redistributions of source code must retain the above copyright
15133808Spjd *    notice, this list of conditions, and the following disclaimer,
16133808Spjd *    without modification.
17133808Spjd * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18133808Spjd *    substantially similar to the "NO WARRANTY" disclaimer below
19133808Spjd *    ("Disclaimer") and any redistribution must be conditioned upon
20133808Spjd *    including a substantially similar Disclaimer requirement for further
21133808Spjd *    binary redistribution.
22133808Spjd * 3. Neither the names of the above-listed copyright holders nor the names
23133808Spjd *    of any contributors may be used to endorse or promote products derived
24133808Spjd *    from this software without specific prior written permission.
25133808Spjd *
26133808Spjd * Alternatively, this software may be distributed under the terms of the
27133808Spjd * GNU General Public License ("GPL") version 2 as published by the Free
28133808Spjd * Software Foundation.
29133808Spjd *
30133808Spjd * NO WARRANTY
31133808Spjd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32133808Spjd * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33133808Spjd * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34133808Spjd * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35133808Spjd * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36133808Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37133808Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38134136Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39134136Spjd * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40134136Spjd * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41134136Spjd * POSSIBILITY OF SUCH DAMAGES.
42134168Spjd */
43139295Spjd
44142727Spjd#define __DTEXPRESS_C__
45163888Spjd
46134136Spjd#include <contrib/dev/acpica/compiler/aslcompiler.h>
47163888Spjd#include <contrib/dev/acpica/compiler/dtcompiler.h>
48133808Spjd#include "dtparser.y.h"
49133808Spjd
50133808Spjd#define _COMPONENT          DT_COMPILER
51133808Spjd        ACPI_MODULE_NAME    ("dtexpress")
52133808Spjd
53155546Spjd
54133808Spjd/* Local prototypes */
55133808Spjd
56133808Spjdstatic void
57133808SpjdDtInsertLabelField (
58133808Spjd    DT_FIELD                *Field);
59134124Spjd
60134168Spjdstatic DT_FIELD *
61163888SpjdDtLookupLabel (
62134124Spjd    char                    *Name);
63134168Spjd
64163888Spjd/* Global used for errors during parse and related functions */
65163888Spjd
66133808SpjdDT_FIELD                *Gbl_CurrentField;
67133808Spjd
68133808Spjd
69133808Spjd/******************************************************************************
70133808Spjd *
71133808Spjd * FUNCTION:    DtResolveIntegerExpression
72133808Spjd *
73133808Spjd * PARAMETERS:  Field               - Field object with Integer expression
74133808Spjd *              ReturnValue         - Where the integer is returned
75133808Spjd *
76133808Spjd * RETURN:      Status, and the resolved 64-bit integer value
77133808Spjd *
78133808Spjd * DESCRIPTION: Resolve an integer expression to a single value. Supports
79133808Spjd *              both integer constants and labels.
80133808Spjd *
81133808Spjd *****************************************************************************/
82133808Spjd
83133808SpjdACPI_STATUS
84133808SpjdDtResolveIntegerExpression (
85133808Spjd    DT_FIELD                *Field,
86133808Spjd    UINT64                  *ReturnValue)
87133808Spjd{
88133808Spjd    UINT64                  Result;
89133808Spjd
90133808Spjd
91133808Spjd    DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n",
92133808Spjd        Field->Value);
93133808Spjd
94133808Spjd    Gbl_CurrentField = Field;
95133808Spjd
96133808Spjd    Result = DtEvaluateExpression (Field->Value);
97133808Spjd    *ReturnValue = Result;
98134168Spjd    return (AE_OK);
99134168Spjd}
100134168Spjd
101134168Spjd
102134168Spjd/******************************************************************************
103133808Spjd *
104133808Spjd * FUNCTION:    DtDoOperator
105133808Spjd *
106134168Spjd * PARAMETERS:  LeftValue           - First 64-bit operand
107134168Spjd *              Operator            - Parse token for the operator (EXPOP_*)
108134168Spjd *              RightValue          - Second 64-bit operand
109134168Spjd *
110133808Spjd * RETURN:      64-bit result of the requested operation
111133808Spjd *
112133808Spjd * DESCRIPTION: Perform the various 64-bit integer math functions
113133808Spjd *
114133808Spjd *****************************************************************************/
115133808Spjd
116156612SpjdUINT64
117156612SpjdDtDoOperator (
118133808Spjd    UINT64                  LeftValue,
119156612Spjd    UINT32                  Operator,
120156612Spjd    UINT64                  RightValue)
121156612Spjd{
122156612Spjd    UINT64                  Result;
123133808Spjd
124133808Spjd
125133808Spjd    /* Perform the requested operation */
126133808Spjd
127133808Spjd    switch (Operator)
128133808Spjd    {
129133808Spjd    case EXPOP_ONES_COMPLIMENT:
130133808Spjd        Result = ~RightValue;
131133808Spjd        break;
132133808Spjd
133133808Spjd    case EXPOP_LOGICAL_NOT:
134133808Spjd        Result = !RightValue;
135133808Spjd        break;
136133808Spjd
137133808Spjd    case EXPOP_MULTIPLY:
138133808Spjd        Result = LeftValue * RightValue;
139133808Spjd        break;
140133808Spjd
141133808Spjd    case EXPOP_DIVIDE:
142133808Spjd        if (!RightValue)
143133808Spjd        {
144133808Spjd            DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
145133808Spjd                Gbl_CurrentField, Gbl_CurrentField->Value);
146139295Spjd            return (0);
147133808Spjd        }
148133808Spjd        Result = LeftValue / RightValue;
149133808Spjd        break;
150133808Spjd
151133808Spjd    case EXPOP_MODULO:
152133808Spjd        if (!RightValue)
153133808Spjd        {
154133808Spjd            DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO,
155133808Spjd                Gbl_CurrentField, Gbl_CurrentField->Value);
156133808Spjd            return (0);
157133808Spjd        }
158133808Spjd        Result = LeftValue % RightValue;
159133808Spjd        break;
160133808Spjd
161133808Spjd    case EXPOP_ADD:
162133808Spjd        Result = LeftValue + RightValue;
163133808Spjd        break;
164133808Spjd
165133808Spjd    case EXPOP_SUBTRACT:
166157630Spjd        Result = LeftValue - RightValue;
167133808Spjd        break;
168133808Spjd
169133808Spjd    case EXPOP_SHIFT_RIGHT:
170133808Spjd        Result = LeftValue >> RightValue;
171133808Spjd        break;
172139295Spjd
173139671Spjd    case EXPOP_SHIFT_LEFT:
174139295Spjd        Result = LeftValue << RightValue;
175139671Spjd        break;
176133808Spjd
177156612Spjd    case EXPOP_LESS:
178156612Spjd        Result = LeftValue < RightValue;
179156612Spjd        break;
180156612Spjd
181156612Spjd    case EXPOP_GREATER:
182156612Spjd        Result = LeftValue > RightValue;
183156612Spjd        break;
184156612Spjd
185156612Spjd    case EXPOP_LESS_EQUAL:
186200821Smav        Result = LeftValue <= RightValue;
187200821Smav        break;
188200821Smav
189156612Spjd    case EXPOP_GREATER_EQUAL:
190156612Spjd        Result = LeftValue >= RightValue;
191156612Spjd        break;
192156612Spjd
193156612Spjd    case EXPOP_EQUAL:
194156612Spjd        Result = LeftValue = RightValue;
195156612Spjd        break;
196133808Spjd
197133808Spjd    case EXPOP_NOT_EQUAL:
198133808Spjd        Result = LeftValue != RightValue;
199133808Spjd        break;
200133808Spjd
201133808Spjd    case EXPOP_AND:
202133808Spjd        Result = LeftValue & RightValue;
203133808Spjd        break;
204133808Spjd
205133808Spjd    case EXPOP_XOR:
206133808Spjd        Result = LeftValue ^ RightValue;
207156612Spjd        break;
208133808Spjd
209133808Spjd    case EXPOP_OR:
210133808Spjd        Result = LeftValue | RightValue;
211156612Spjd        break;
212156612Spjd
213156612Spjd    case EXPOP_LOGICAL_AND:
214156612Spjd        Result = LeftValue && RightValue;
215156612Spjd        break;
216156612Spjd
217156612Spjd    case EXPOP_LOGICAL_OR:
218156612Spjd        Result = LeftValue || RightValue;
219133808Spjd        break;
220133808Spjd
221133808Spjd   default:
222134124Spjd
223133808Spjd        /* Unknown operator */
224133808Spjd
225156612Spjd        DtFatal (ASL_MSG_INVALID_EXPRESSION,
226156612Spjd            Gbl_CurrentField, Gbl_CurrentField->Value);
227156612Spjd        return (0);
228156612Spjd    }
229156612Spjd
230156612Spjd    DbgPrint (ASL_DEBUG_OUTPUT,
231156612Spjd        "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n",
232133808Spjd        Gbl_CurrentField->Value,
233139295Spjd        ACPI_FORMAT_UINT64 (LeftValue),
234133808Spjd        DtGetOpName (Operator),
235139295Spjd        ACPI_FORMAT_UINT64 (RightValue),
236133808Spjd        ACPI_FORMAT_UINT64 (Result));
237137258Spjd
238155540Spjd    return (Result);
239155540Spjd}
240133808Spjd
241133808Spjd
242133808Spjd/******************************************************************************
243133808Spjd *
244133808Spjd * FUNCTION:    DtResolveLabel
245148440Spjd *
246148440Spjd * PARAMETERS:  LabelString         - Contains the label
247133808Spjd *
248133808Spjd * RETURN:      Table offset associated with the label
249133808Spjd *
250133808Spjd * DESCRIPTION: Lookup a lable and return its value.
251133808Spjd *
252157630Spjd *****************************************************************************/
253157630Spjd
254157630SpjdUINT64
255157630SpjdDtResolveLabel (
256133808Spjd    char                    *LabelString)
257133808Spjd{
258139671Spjd    DT_FIELD                *LabelField;
259139671Spjd
260139671Spjd
261133808Spjd    DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString);
262133808Spjd
263133808Spjd    /* Resolve a label reference to an integer (table offset) */
264133808Spjd
265133808Spjd    if (*LabelString != '$')
266133808Spjd    {
267133808Spjd        return (0);
268133808Spjd    }
269133808Spjd
270133808Spjd    LabelField = DtLookupLabel (LabelString);
271133808Spjd    if (!LabelField)
272133808Spjd    {
273133808Spjd        DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL,
274133808Spjd            Gbl_CurrentField, LabelString);
275133808Spjd        return (0);
276139295Spjd    }
277133808Spjd
278133808Spjd    /* All we need from the label is the offset in the table */
279133808Spjd
280133808Spjd    DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n",
281133808Spjd        LabelField->TableOffset);
282133808Spjd
283133808Spjd    return (LabelField->TableOffset);
284142727Spjd}
285133808Spjd
286133808Spjd
287133808Spjd/******************************************************************************
288133808Spjd *
289133808Spjd * FUNCTION:    DtDetectAllLabels
290133808Spjd *
291133808Spjd * PARAMETERS:  FieldList           - Field object at start of generic list
292133808Spjd *
293133808Spjd * RETURN:      None
294133808Spjd *
295133808Spjd * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as
296133808Spjd *              a UEFI table.) and insert them into the global label list.
297133808Spjd *
298139295Spjd *****************************************************************************/
299139295Spjd
300139295Spjdvoid
301139295SpjdDtDetectAllLabels (
302139295Spjd    DT_FIELD                *FieldList)
303139295Spjd{
304139295Spjd    ACPI_DMTABLE_INFO       *Info;
305139295Spjd    DT_FIELD                *GenericField;
306142727Spjd    UINT32                  TableOffset;
307133808Spjd
308142727Spjd
309133808Spjd    TableOffset = Gbl_CurrentTableOffset;
310142727Spjd    GenericField = FieldList;
311133808Spjd
312133808Spjd    /*
313139295Spjd     * Process all "Label:" fields within the parse tree. We need
314133808Spjd     * to know the offsets for all labels before we can compile
315133808Spjd     * the parse tree in order to handle forward references. Traverse
316133808Spjd     * tree and get/set all field lengths of all operators in order to
317133808Spjd     * determine the label offsets.
318133808Spjd     */
319133808Spjd    while (GenericField)
320133808Spjd    {
321133808Spjd        Info = DtGetGenericTableInfo (GenericField->Name);
322133808Spjd        if (Info)
323133808Spjd        {
324133808Spjd            /* Maintain table offsets */
325133808Spjd
326133808Spjd            GenericField->TableOffset = TableOffset;
327133808Spjd            TableOffset += DtGetFieldLength (GenericField, Info);
328133808Spjd
329133808Spjd            /* Insert all labels in the global label list */
330133808Spjd
331133808Spjd            if (Info->Opcode == ACPI_DMT_LABEL)
332133808Spjd            {
333133808Spjd                DtInsertLabelField (GenericField);
334142727Spjd            }
335142727Spjd        }
336142727Spjd
337142727Spjd        GenericField = GenericField->Next;
338142727Spjd    }
339133808Spjd}
340133808Spjd
341139295Spjd
342139295Spjd/******************************************************************************
343139295Spjd *
344139295Spjd * FUNCTION:    DtInsertLabelField
345133808Spjd *
346139295Spjd * PARAMETERS:  Field               - Field object with Label to be inserted
347139295Spjd *
348139295Spjd * RETURN:      None
349139295Spjd *
350139295Spjd * DESCRIPTION: Insert a label field into the global label list
351139295Spjd *
352139295Spjd *****************************************************************************/
353139295Spjd
354139295Spjdstatic void
355139295SpjdDtInsertLabelField (
356139295Spjd    DT_FIELD                *Field)
357139295Spjd{
358139295Spjd
359139295Spjd    DbgPrint (ASL_DEBUG_OUTPUT,
360139295Spjd        "DtInsertLabelField: Found Label : %s at output table offset %X\n",
361139295Spjd        Field->Value, Field->TableOffset);
362139295Spjd
363139295Spjd    Field->NextLabel = Gbl_LabelList;
364142727Spjd    Gbl_LabelList = Field;
365142727Spjd}
366142727Spjd
367142727Spjd
368139295Spjd/******************************************************************************
369139295Spjd *
370139295Spjd * FUNCTION:    DtLookupLabel
371163888Spjd *
372142727Spjd * PARAMETERS:  Name                - Label to be resolved
373142727Spjd *
374142727Spjd * RETURN:      Field object associated with the label
375142727Spjd *
376142727Spjd * DESCRIPTION: Lookup a label in the global label list. Used during the
377142727Spjd *              resolution of integer expressions.
378142727Spjd *
379142727Spjd *****************************************************************************/
380142727Spjd
381142727Spjdstatic DT_FIELD *
382142727SpjdDtLookupLabel (
383142727Spjd    char                    *Name)
384142727Spjd{
385142727Spjd    DT_FIELD                *LabelField;
386142727Spjd
387142727Spjd
388142727Spjd    /* Skip a leading $ */
389142727Spjd
390142727Spjd    if (*Name == '$')
391142727Spjd    {
392142727Spjd        Name++;
393142727Spjd    }
394142727Spjd
395142727Spjd    /* Search global list */
396142727Spjd
397139295Spjd    LabelField = Gbl_LabelList;
398139295Spjd    while (LabelField)
399139295Spjd    {
400155174Spjd        if (!ACPI_STRCMP (Name, LabelField->Value))
401139295Spjd        {
402139295Spjd            return (LabelField);
403139295Spjd        }
404139295Spjd        LabelField = LabelField->NextLabel;
405139295Spjd    }
406139295Spjd
407139295Spjd    return (NULL);
408139295Spjd}
409139295Spjd