dtexpress.c revision 250838
1210284Sjmallett/****************************************************************************** 2215990Sjmallett * 3215990Sjmallett * Module Name: dtexpress.c - Support for integer expressions and labels 4210284Sjmallett * 5210284Sjmallett *****************************************************************************/ 6215990Sjmallett 7215990Sjmallett/* 8215990Sjmallett * Copyright (C) 2000 - 2013, Intel Corp. 9210284Sjmallett * All rights reserved. 10215990Sjmallett * 11215990Sjmallett * Redistribution and use in source and binary forms, with or without 12210284Sjmallett * modification, are permitted provided that the following conditions 13215990Sjmallett * are met: 14215990Sjmallett * 1. Redistributions of source code must retain the above copyright 15215990Sjmallett * notice, this list of conditions, and the following disclaimer, 16215990Sjmallett * without modification. 17215990Sjmallett * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18215990Sjmallett * substantially similar to the "NO WARRANTY" disclaimer below 19215990Sjmallett * ("Disclaimer") and any redistribution must be conditioned upon 20215990Sjmallett * including a substantially similar Disclaimer requirement for further 21215990Sjmallett * binary redistribution. 22215990Sjmallett * 3. Neither the names of the above-listed copyright holders nor the names 23215990Sjmallett * of any contributors may be used to endorse or promote products derived 24215990Sjmallett * from this software without specific prior written permission. 25215990Sjmallett * 26215990Sjmallett * Alternatively, this software may be distributed under the terms of the 27215990Sjmallett * GNU General Public License ("GPL") version 2 as published by the Free 28215990Sjmallett * Software Foundation. 29215990Sjmallett * 30215990Sjmallett * NO WARRANTY 31215990Sjmallett * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32215990Sjmallett * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33215990Sjmallett * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34215990Sjmallett * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35215990Sjmallett * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36215990Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37215990Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38210284Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39210284Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40210284Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41210284Sjmallett * POSSIBILITY OF SUCH DAMAGES. 42210284Sjmallett */ 43210284Sjmallett 44210284Sjmallett#define __DTEXPRESS_C__ 45215990Sjmallett 46210284Sjmallett#include <contrib/dev/acpica/compiler/aslcompiler.h> 47210284Sjmallett#include <contrib/dev/acpica/compiler/dtcompiler.h> 48210284Sjmallett#include "dtparser.y.h" 49210284Sjmallett 50210284Sjmallett#define _COMPONENT DT_COMPILER 51210284Sjmallett ACPI_MODULE_NAME ("dtexpress") 52215990Sjmallett 53210284Sjmallett 54210284Sjmallett/* Local prototypes */ 55210284Sjmallett 56210284Sjmallettstatic void 57210284SjmallettDtInsertLabelField ( 58210284Sjmallett DT_FIELD *Field); 59210284Sjmallett 60210284Sjmallettstatic DT_FIELD * 61210284SjmallettDtLookupLabel ( 62210284Sjmallett char *Name); 63210284Sjmallett 64210284Sjmallett/* Global used for errors during parse and related functions */ 65210284Sjmallett 66210284SjmallettDT_FIELD *Gbl_CurrentField; 67210284Sjmallett 68210284Sjmallett 69210284Sjmallett/****************************************************************************** 70210284Sjmallett * 71210284Sjmallett * FUNCTION: DtResolveIntegerExpression 72210284Sjmallett * 73210284Sjmallett * PARAMETERS: Field - Field object with Integer expression 74210284Sjmallett * ReturnValue - Where the integer is returned 75210284Sjmallett * 76210284Sjmallett * RETURN: Status, and the resolved 64-bit integer value 77210284Sjmallett * 78210284Sjmallett * DESCRIPTION: Resolve an integer expression to a single value. Supports 79210284Sjmallett * both integer constants and labels. 80210284Sjmallett * 81210284Sjmallett *****************************************************************************/ 82210284Sjmallett 83210284SjmallettACPI_STATUS 84210284SjmallettDtResolveIntegerExpression ( 85210284Sjmallett DT_FIELD *Field, 86210284Sjmallett UINT64 *ReturnValue) 87210284Sjmallett{ 88210284Sjmallett UINT64 Result; 89210284Sjmallett 90210284Sjmallett 91210284Sjmallett DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", 92210284Sjmallett Field->Value); 93210284Sjmallett 94210284Sjmallett Gbl_CurrentField = Field; 95210284Sjmallett 96210284Sjmallett Result = DtEvaluateExpression (Field->Value); 97210284Sjmallett *ReturnValue = Result; 98210284Sjmallett return (AE_OK); 99210284Sjmallett} 100210284Sjmallett 101210284Sjmallett 102210284Sjmallett/****************************************************************************** 103210284Sjmallett * 104210284Sjmallett * FUNCTION: DtDoOperator 105210284Sjmallett * 106210284Sjmallett * PARAMETERS: LeftValue - First 64-bit operand 107210284Sjmallett * Operator - Parse token for the operator (EXPOP_*) 108210284Sjmallett * RightValue - Second 64-bit operand 109210284Sjmallett * 110210284Sjmallett * RETURN: 64-bit result of the requested operation 111210284Sjmallett * 112210284Sjmallett * DESCRIPTION: Perform the various 64-bit integer math functions 113210284Sjmallett * 114210284Sjmallett *****************************************************************************/ 115210284Sjmallett 116210284SjmallettUINT64 117210284SjmallettDtDoOperator ( 118210284Sjmallett UINT64 LeftValue, 119210284Sjmallett UINT32 Operator, 120210284Sjmallett UINT64 RightValue) 121210284Sjmallett{ 122210284Sjmallett UINT64 Result; 123210284Sjmallett 124210284Sjmallett 125210284Sjmallett /* Perform the requested operation */ 126210284Sjmallett 127210284Sjmallett switch (Operator) 128210284Sjmallett { 129210284Sjmallett case EXPOP_ONES_COMPLIMENT: 130210284Sjmallett 131210284Sjmallett Result = ~RightValue; 132210284Sjmallett break; 133210284Sjmallett 134210284Sjmallett case EXPOP_LOGICAL_NOT: 135210284Sjmallett 136210284Sjmallett Result = !RightValue; 137210284Sjmallett break; 138210284Sjmallett 139210284Sjmallett case EXPOP_MULTIPLY: 140210284Sjmallett 141210284Sjmallett Result = LeftValue * RightValue; 142210284Sjmallett break; 143210284Sjmallett 144210284Sjmallett case EXPOP_DIVIDE: 145210284Sjmallett 146210284Sjmallett if (!RightValue) 147210284Sjmallett { 148210284Sjmallett DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 149210284Sjmallett Gbl_CurrentField, NULL); 150210284Sjmallett return (0); 151210284Sjmallett } 152210284Sjmallett Result = LeftValue / RightValue; 153210284Sjmallett break; 154210284Sjmallett 155210284Sjmallett case EXPOP_MODULO: 156210284Sjmallett 157210284Sjmallett if (!RightValue) 158210284Sjmallett { 159210284Sjmallett DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 160210284Sjmallett Gbl_CurrentField, NULL); 161210284Sjmallett return (0); 162210284Sjmallett } 163210284Sjmallett Result = LeftValue % RightValue; 164210284Sjmallett break; 165210284Sjmallett 166210284Sjmallett case EXPOP_ADD: 167210284Sjmallett Result = LeftValue + RightValue; 168210284Sjmallett break; 169210284Sjmallett 170210284Sjmallett case EXPOP_SUBTRACT: 171210284Sjmallett 172210284Sjmallett Result = LeftValue - RightValue; 173210284Sjmallett break; 174210284Sjmallett 175210284Sjmallett case EXPOP_SHIFT_RIGHT: 176210284Sjmallett 177210284Sjmallett Result = LeftValue >> RightValue; 178210284Sjmallett break; 179210284Sjmallett 180210284Sjmallett case EXPOP_SHIFT_LEFT: 181210284Sjmallett 182215990Sjmallett Result = LeftValue << RightValue; 183215990Sjmallett break; 184215990Sjmallett 185215990Sjmallett case EXPOP_LESS: 186215990Sjmallett 187215990Sjmallett Result = LeftValue < RightValue; 188215990Sjmallett break; 189215990Sjmallett 190215990Sjmallett case EXPOP_GREATER: 191215990Sjmallett 192215990Sjmallett Result = LeftValue > RightValue; 193215990Sjmallett break; 194215990Sjmallett 195215990Sjmallett case EXPOP_LESS_EQUAL: 196215990Sjmallett 197215990Sjmallett Result = LeftValue <= RightValue; 198215990Sjmallett break; 199215990Sjmallett 200215990Sjmallett case EXPOP_GREATER_EQUAL: 201215990Sjmallett 202215990Sjmallett Result = LeftValue >= RightValue; 203215990Sjmallett break; 204215990Sjmallett 205215990Sjmallett case EXPOP_EQUAL: 206215990Sjmallett 207215990Sjmallett Result = LeftValue == RightValue; 208215990Sjmallett break; 209215990Sjmallett 210215990Sjmallett case EXPOP_NOT_EQUAL: 211215990Sjmallett 212215990Sjmallett Result = LeftValue != RightValue; 213215990Sjmallett break; 214215990Sjmallett 215215990Sjmallett case EXPOP_AND: 216215990Sjmallett 217215990Sjmallett Result = LeftValue & RightValue; 218215990Sjmallett break; 219215990Sjmallett 220215990Sjmallett case EXPOP_XOR: 221215990Sjmallett 222215990Sjmallett Result = LeftValue ^ RightValue; 223215990Sjmallett break; 224215990Sjmallett 225215990Sjmallett case EXPOP_OR: 226215990Sjmallett 227215990Sjmallett Result = LeftValue | RightValue; 228215990Sjmallett break; 229215990Sjmallett 230215990Sjmallett case EXPOP_LOGICAL_AND: 231215990Sjmallett 232215990Sjmallett Result = LeftValue && RightValue; 233215990Sjmallett break; 234215990Sjmallett 235215990Sjmallett case EXPOP_LOGICAL_OR: 236215990Sjmallett 237215990Sjmallett Result = LeftValue || RightValue; 238215990Sjmallett break; 239215990Sjmallett 240215990Sjmallett default: 241215990Sjmallett 242215990Sjmallett /* Unknown operator */ 243215990Sjmallett 244215990Sjmallett DtFatal (ASL_MSG_INVALID_EXPRESSION, 245215990Sjmallett Gbl_CurrentField, NULL); 246215990Sjmallett return (0); 247215990Sjmallett } 248215990Sjmallett 249215990Sjmallett DbgPrint (ASL_DEBUG_OUTPUT, 250215990Sjmallett "IntegerEval: (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", 251215990Sjmallett ACPI_FORMAT_UINT64 (LeftValue), 252215990Sjmallett DtGetOpName (Operator), 253215990Sjmallett ACPI_FORMAT_UINT64 (RightValue), 254215990Sjmallett ACPI_FORMAT_UINT64 (Result)); 255215990Sjmallett 256215990Sjmallett return (Result); 257215990Sjmallett} 258215990Sjmallett 259215990Sjmallett 260215990Sjmallett/****************************************************************************** 261215990Sjmallett * 262215990Sjmallett * FUNCTION: DtResolveLabel 263215990Sjmallett * 264215990Sjmallett * PARAMETERS: LabelString - Contains the label 265215990Sjmallett * 266215990Sjmallett * RETURN: Table offset associated with the label 267215990Sjmallett * 268215990Sjmallett * DESCRIPTION: Lookup a lable and return its value. 269215990Sjmallett * 270215990Sjmallett *****************************************************************************/ 271215990Sjmallett 272215990SjmallettUINT64 273215990SjmallettDtResolveLabel ( 274215990Sjmallett char *LabelString) 275215990Sjmallett{ 276215990Sjmallett DT_FIELD *LabelField; 277215990Sjmallett 278215990Sjmallett 279215990Sjmallett DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); 280215990Sjmallett 281215990Sjmallett /* Resolve a label reference to an integer (table offset) */ 282215990Sjmallett 283215990Sjmallett if (*LabelString != '$') 284215990Sjmallett { 285215990Sjmallett return (0); 286215990Sjmallett } 287215990Sjmallett 288215990Sjmallett LabelField = DtLookupLabel (LabelString); 289215990Sjmallett if (!LabelField) 290215990Sjmallett { 291215990Sjmallett DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, 292215990Sjmallett Gbl_CurrentField, LabelString); 293215990Sjmallett return (0); 294215990Sjmallett } 295215990Sjmallett 296215990Sjmallett /* All we need from the label is the offset in the table */ 297215990Sjmallett 298215990Sjmallett DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", 299215990Sjmallett LabelField->TableOffset); 300215990Sjmallett 301215990Sjmallett return (LabelField->TableOffset); 302215990Sjmallett} 303215990Sjmallett 304210284Sjmallett 305215990Sjmallett/****************************************************************************** 306210284Sjmallett * 307210284Sjmallett * FUNCTION: DtDetectAllLabels 308210284Sjmallett * 309210284Sjmallett * PARAMETERS: FieldList - Field object at start of generic list 310210284Sjmallett * 311210284Sjmallett * RETURN: None 312210284Sjmallett * 313210284Sjmallett * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 314210284Sjmallett * a UEFI table.) and insert them into the global label list. 315210284Sjmallett * 316210284Sjmallett *****************************************************************************/ 317210284Sjmallett 318210284Sjmallettvoid 319210284SjmallettDtDetectAllLabels ( 320210284Sjmallett DT_FIELD *FieldList) 321210284Sjmallett{ 322210284Sjmallett ACPI_DMTABLE_INFO *Info; 323210284Sjmallett DT_FIELD *GenericField; 324210284Sjmallett UINT32 TableOffset; 325210284Sjmallett 326210284Sjmallett 327210284Sjmallett TableOffset = Gbl_CurrentTableOffset; 328210284Sjmallett GenericField = FieldList; 329210284Sjmallett 330210284Sjmallett /* 331210284Sjmallett * Process all "Label:" fields within the parse tree. We need 332210284Sjmallett * to know the offsets for all labels before we can compile 333210284Sjmallett * the parse tree in order to handle forward references. Traverse 334210284Sjmallett * tree and get/set all field lengths of all operators in order to 335210284Sjmallett * determine the label offsets. 336210284Sjmallett */ 337210284Sjmallett while (GenericField) 338210284Sjmallett { 339210284Sjmallett Info = DtGetGenericTableInfo (GenericField->Name); 340210284Sjmallett if (Info) 341210284Sjmallett { 342210284Sjmallett /* Maintain table offsets */ 343210284Sjmallett 344210284Sjmallett GenericField->TableOffset = TableOffset; 345210284Sjmallett TableOffset += DtGetFieldLength (GenericField, Info); 346210284Sjmallett 347210284Sjmallett /* Insert all labels in the global label list */ 348210284Sjmallett 349210284Sjmallett if (Info->Opcode == ACPI_DMT_LABEL) 350210284Sjmallett { 351210284Sjmallett DtInsertLabelField (GenericField); 352210284Sjmallett } 353210284Sjmallett } 354210284Sjmallett 355210284Sjmallett GenericField = GenericField->Next; 356210284Sjmallett } 357210284Sjmallett} 358210284Sjmallett 359210284Sjmallett 360210284Sjmallett/****************************************************************************** 361210284Sjmallett * 362210284Sjmallett * FUNCTION: DtInsertLabelField 363210284Sjmallett * 364210284Sjmallett * PARAMETERS: Field - Field object with Label to be inserted 365210284Sjmallett * 366210284Sjmallett * RETURN: None 367210284Sjmallett * 368210284Sjmallett * DESCRIPTION: Insert a label field into the global label list 369210284Sjmallett * 370210284Sjmallett *****************************************************************************/ 371210284Sjmallett 372210284Sjmallettstatic void 373210284SjmallettDtInsertLabelField ( 374210284Sjmallett DT_FIELD *Field) 375210284Sjmallett{ 376210284Sjmallett 377210284Sjmallett DbgPrint (ASL_DEBUG_OUTPUT, 378210284Sjmallett "DtInsertLabelField: Found Label : %s at output table offset %X\n", 379210284Sjmallett Field->Value, Field->TableOffset); 380210284Sjmallett 381210284Sjmallett Field->NextLabel = Gbl_LabelList; 382210284Sjmallett Gbl_LabelList = Field; 383210284Sjmallett} 384210284Sjmallett 385210284Sjmallett 386210284Sjmallett/****************************************************************************** 387210284Sjmallett * 388210284Sjmallett * FUNCTION: DtLookupLabel 389210284Sjmallett * 390210284Sjmallett * PARAMETERS: Name - Label to be resolved 391210284Sjmallett * 392210284Sjmallett * RETURN: Field object associated with the label 393210284Sjmallett * 394210284Sjmallett * DESCRIPTION: Lookup a label in the global label list. Used during the 395210284Sjmallett * resolution of integer expressions. 396210284Sjmallett * 397210284Sjmallett *****************************************************************************/ 398210284Sjmallett 399210284Sjmallettstatic DT_FIELD * 400210284SjmallettDtLookupLabel ( 401210284Sjmallett char *Name) 402210284Sjmallett{ 403210284Sjmallett DT_FIELD *LabelField; 404210284Sjmallett 405210284Sjmallett 406210284Sjmallett /* Skip a leading $ */ 407210284Sjmallett 408210284Sjmallett if (*Name == '$') 409 { 410 Name++; 411 } 412 413 /* Search global list */ 414 415 LabelField = Gbl_LabelList; 416 while (LabelField) 417 { 418 if (!ACPI_STRCMP (Name, LabelField->Value)) 419 { 420 return (LabelField); 421 } 422 LabelField = LabelField->NextLabel; 423 } 424 425 return (NULL); 426} 427