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