1218585Sjkim/****************************************************************************** 2218585Sjkim * 3218585Sjkim * Module Name: dtexpress.c - Support for integer expressions and labels 4218585Sjkim * 5218585Sjkim *****************************************************************************/ 6218585Sjkim 7218585Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9218585Sjkim * All rights reserved. 10218585Sjkim * 11218585Sjkim * Redistribution and use in source and binary forms, with or without 12218585Sjkim * modification, are permitted provided that the following conditions 13218585Sjkim * are met: 14218585Sjkim * 1. Redistributions of source code must retain the above copyright 15218585Sjkim * notice, this list of conditions, and the following disclaimer, 16218585Sjkim * without modification. 17218585Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18218585Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19218585Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20218585Sjkim * including a substantially similar Disclaimer requirement for further 21218585Sjkim * binary redistribution. 22218585Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23218585Sjkim * of any contributors may be used to endorse or promote products derived 24218585Sjkim * from this software without specific prior written permission. 25218585Sjkim * 26218585Sjkim * Alternatively, this software may be distributed under the terms of the 27218585Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28218585Sjkim * Software Foundation. 29218585Sjkim * 30218585Sjkim * NO WARRANTY 31218585Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32218585Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33218585Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34218585Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35218585Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36218585Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37218585Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38218585Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39218585Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40218585Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41218585Sjkim * POSSIBILITY OF SUCH DAMAGES. 42218585Sjkim */ 43218585Sjkim 44218590Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45218590Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h> 46220663Sjkim#include "dtparser.y.h" 47218585Sjkim 48218585Sjkim#define _COMPONENT DT_COMPILER 49218585Sjkim ACPI_MODULE_NAME ("dtexpress") 50218585Sjkim 51218585Sjkim 52218585Sjkim/* Local prototypes */ 53218585Sjkim 54218585Sjkimstatic void 55218585SjkimDtInsertLabelField ( 56218585Sjkim DT_FIELD *Field); 57218585Sjkim 58218585Sjkimstatic DT_FIELD * 59218585SjkimDtLookupLabel ( 60218585Sjkim char *Name); 61218585Sjkim 62220663Sjkim/* Global used for errors during parse and related functions */ 63218585Sjkim 64220663SjkimDT_FIELD *Gbl_CurrentField; 65220663Sjkim 66220663Sjkim 67218585Sjkim/****************************************************************************** 68218585Sjkim * 69218585Sjkim * FUNCTION: DtResolveIntegerExpression 70218585Sjkim * 71218585Sjkim * PARAMETERS: Field - Field object with Integer expression 72220663Sjkim * ReturnValue - Where the integer is returned 73218585Sjkim * 74220663Sjkim * RETURN: Status, and the resolved 64-bit integer value 75218585Sjkim * 76218585Sjkim * DESCRIPTION: Resolve an integer expression to a single value. Supports 77220663Sjkim * both integer constants and labels. 78218585Sjkim * 79218585Sjkim *****************************************************************************/ 80218585Sjkim 81220663SjkimACPI_STATUS 82218585SjkimDtResolveIntegerExpression ( 83220663Sjkim DT_FIELD *Field, 84220663Sjkim UINT64 *ReturnValue) 85218585Sjkim{ 86220663Sjkim UINT64 Result; 87218585Sjkim 88218585Sjkim 89218585Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", 90218585Sjkim Field->Value); 91218585Sjkim 92220663Sjkim Gbl_CurrentField = Field; 93218585Sjkim 94220663Sjkim Result = DtEvaluateExpression (Field->Value); 95220663Sjkim *ReturnValue = Result; 96220663Sjkim return (AE_OK); 97220663Sjkim} 98218585Sjkim 99218585Sjkim 100220663Sjkim/****************************************************************************** 101220663Sjkim * 102220663Sjkim * FUNCTION: DtDoOperator 103220663Sjkim * 104220663Sjkim * PARAMETERS: LeftValue - First 64-bit operand 105220663Sjkim * Operator - Parse token for the operator (EXPOP_*) 106220663Sjkim * RightValue - Second 64-bit operand 107220663Sjkim * 108220663Sjkim * RETURN: 64-bit result of the requested operation 109220663Sjkim * 110220663Sjkim * DESCRIPTION: Perform the various 64-bit integer math functions 111220663Sjkim * 112220663Sjkim *****************************************************************************/ 113218585Sjkim 114220663SjkimUINT64 115220663SjkimDtDoOperator ( 116220663Sjkim UINT64 LeftValue, 117220663Sjkim UINT32 Operator, 118220663Sjkim UINT64 RightValue) 119220663Sjkim{ 120220663Sjkim UINT64 Result; 121220663Sjkim 122220663Sjkim 123220663Sjkim /* Perform the requested operation */ 124220663Sjkim 125220663Sjkim switch (Operator) 126218585Sjkim { 127220663Sjkim case EXPOP_ONES_COMPLIMENT: 128250838Sjkim 129220663Sjkim Result = ~RightValue; 130220663Sjkim break; 131218585Sjkim 132220663Sjkim case EXPOP_LOGICAL_NOT: 133250838Sjkim 134220663Sjkim Result = !RightValue; 135220663Sjkim break; 136218585Sjkim 137220663Sjkim case EXPOP_MULTIPLY: 138250838Sjkim 139220663Sjkim Result = LeftValue * RightValue; 140220663Sjkim break; 141220663Sjkim 142220663Sjkim case EXPOP_DIVIDE: 143250838Sjkim 144220663Sjkim if (!RightValue) 145220663Sjkim { 146220663Sjkim DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 147233250Sjkim Gbl_CurrentField, NULL); 148220663Sjkim return (0); 149218585Sjkim } 150306536Sjkim 151220663Sjkim Result = LeftValue / RightValue; 152220663Sjkim break; 153218585Sjkim 154220663Sjkim case EXPOP_MODULO: 155250838Sjkim 156220663Sjkim if (!RightValue) 157218585Sjkim { 158220663Sjkim DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 159233250Sjkim Gbl_CurrentField, NULL); 160218585Sjkim return (0); 161218585Sjkim } 162306536Sjkim 163220663Sjkim Result = LeftValue % RightValue; 164220663Sjkim break; 165218585Sjkim 166220663Sjkim case EXPOP_ADD: 167220663Sjkim Result = LeftValue + RightValue; 168220663Sjkim break; 169218585Sjkim 170220663Sjkim case EXPOP_SUBTRACT: 171250838Sjkim 172220663Sjkim Result = LeftValue - RightValue; 173220663Sjkim break; 174218585Sjkim 175220663Sjkim case EXPOP_SHIFT_RIGHT: 176250838Sjkim 177220663Sjkim Result = LeftValue >> RightValue; 178220663Sjkim break; 179218585Sjkim 180220663Sjkim case EXPOP_SHIFT_LEFT: 181250838Sjkim 182220663Sjkim Result = LeftValue << RightValue; 183220663Sjkim break; 184218585Sjkim 185220663Sjkim case EXPOP_LESS: 186250838Sjkim 187220663Sjkim Result = LeftValue < RightValue; 188220663Sjkim break; 189218585Sjkim 190220663Sjkim case EXPOP_GREATER: 191250838Sjkim 192220663Sjkim Result = LeftValue > RightValue; 193220663Sjkim break; 194218585Sjkim 195220663Sjkim case EXPOP_LESS_EQUAL: 196250838Sjkim 197220663Sjkim Result = LeftValue <= RightValue; 198220663Sjkim break; 199218585Sjkim 200220663Sjkim case EXPOP_GREATER_EQUAL: 201250838Sjkim 202220663Sjkim Result = LeftValue >= RightValue; 203220663Sjkim break; 204218585Sjkim 205220663Sjkim case EXPOP_EQUAL: 206250838Sjkim 207233250Sjkim Result = LeftValue == RightValue; 208220663Sjkim break; 209218585Sjkim 210220663Sjkim case EXPOP_NOT_EQUAL: 211250838Sjkim 212220663Sjkim Result = LeftValue != RightValue; 213220663Sjkim break; 214218585Sjkim 215220663Sjkim case EXPOP_AND: 216250838Sjkim 217220663Sjkim Result = LeftValue & RightValue; 218220663Sjkim break; 219218585Sjkim 220220663Sjkim case EXPOP_XOR: 221250838Sjkim 222220663Sjkim Result = LeftValue ^ RightValue; 223220663Sjkim break; 224218585Sjkim 225220663Sjkim case EXPOP_OR: 226250838Sjkim 227220663Sjkim Result = LeftValue | RightValue; 228220663Sjkim break; 229220663Sjkim 230220663Sjkim case EXPOP_LOGICAL_AND: 231250838Sjkim 232220663Sjkim Result = LeftValue && RightValue; 233220663Sjkim break; 234220663Sjkim 235220663Sjkim case EXPOP_LOGICAL_OR: 236250838Sjkim 237220663Sjkim Result = LeftValue || RightValue; 238220663Sjkim break; 239220663Sjkim 240220663Sjkim default: 241220663Sjkim 242220663Sjkim /* Unknown operator */ 243220663Sjkim 244220663Sjkim DtFatal (ASL_MSG_INVALID_EXPRESSION, 245233250Sjkim Gbl_CurrentField, NULL); 246220663Sjkim return (0); 247218585Sjkim } 248218585Sjkim 249220663Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 250233250Sjkim "IntegerEval: (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", 251220663Sjkim ACPI_FORMAT_UINT64 (LeftValue), 252220663Sjkim DtGetOpName (Operator), 253220663Sjkim ACPI_FORMAT_UINT64 (RightValue), 254220663Sjkim ACPI_FORMAT_UINT64 (Result)); 255220663Sjkim 256220663Sjkim return (Result); 257218585Sjkim} 258218585Sjkim 259218585Sjkim 260218585Sjkim/****************************************************************************** 261218585Sjkim * 262220663Sjkim * FUNCTION: DtResolveLabel 263218585Sjkim * 264220663Sjkim * PARAMETERS: LabelString - Contains the label 265218585Sjkim * 266220663Sjkim * RETURN: Table offset associated with the label 267218585Sjkim * 268220663Sjkim * DESCRIPTION: Lookup a lable and return its value. 269218585Sjkim * 270218585Sjkim *****************************************************************************/ 271218585Sjkim 272220663SjkimUINT64 273220663SjkimDtResolveLabel ( 274220663Sjkim char *LabelString) 275218585Sjkim{ 276218585Sjkim DT_FIELD *LabelField; 277218585Sjkim 278218585Sjkim 279220663Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); 280218585Sjkim 281218585Sjkim /* Resolve a label reference to an integer (table offset) */ 282218585Sjkim 283220663Sjkim if (*LabelString != '$') 284218585Sjkim { 285220663Sjkim return (0); 286220663Sjkim } 287218585Sjkim 288220663Sjkim LabelField = DtLookupLabel (LabelString); 289220663Sjkim if (!LabelField) 290220663Sjkim { 291220663Sjkim DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, 292220663Sjkim Gbl_CurrentField, LabelString); 293220663Sjkim return (0); 294218585Sjkim } 295218585Sjkim 296220663Sjkim /* All we need from the label is the offset in the table */ 297218585Sjkim 298220663Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", 299220663Sjkim LabelField->TableOffset); 300218585Sjkim 301220663Sjkim return (LabelField->TableOffset); 302218585Sjkim} 303218585Sjkim 304218585Sjkim 305218585Sjkim/****************************************************************************** 306218585Sjkim * 307218585Sjkim * FUNCTION: DtDetectAllLabels 308218585Sjkim * 309218585Sjkim * PARAMETERS: FieldList - Field object at start of generic list 310218585Sjkim * 311218585Sjkim * RETURN: None 312218585Sjkim * 313218585Sjkim * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 314218585Sjkim * a UEFI table.) and insert them into the global label list. 315218585Sjkim * 316218585Sjkim *****************************************************************************/ 317218585Sjkim 318218585Sjkimvoid 319218585SjkimDtDetectAllLabels ( 320218585Sjkim DT_FIELD *FieldList) 321218585Sjkim{ 322218585Sjkim ACPI_DMTABLE_INFO *Info; 323218585Sjkim DT_FIELD *GenericField; 324218585Sjkim UINT32 TableOffset; 325218585Sjkim 326218585Sjkim 327218585Sjkim TableOffset = Gbl_CurrentTableOffset; 328218585Sjkim GenericField = FieldList; 329218585Sjkim 330218585Sjkim /* 331218585Sjkim * Process all "Label:" fields within the parse tree. We need 332218585Sjkim * to know the offsets for all labels before we can compile 333218585Sjkim * the parse tree in order to handle forward references. Traverse 334218585Sjkim * tree and get/set all field lengths of all operators in order to 335218585Sjkim * determine the label offsets. 336218585Sjkim */ 337218585Sjkim while (GenericField) 338218585Sjkim { 339218585Sjkim Info = DtGetGenericTableInfo (GenericField->Name); 340218585Sjkim if (Info) 341218585Sjkim { 342218585Sjkim /* Maintain table offsets */ 343218585Sjkim 344218585Sjkim GenericField->TableOffset = TableOffset; 345218585Sjkim TableOffset += DtGetFieldLength (GenericField, Info); 346218585Sjkim 347218585Sjkim /* Insert all labels in the global label list */ 348218585Sjkim 349218585Sjkim if (Info->Opcode == ACPI_DMT_LABEL) 350218585Sjkim { 351218585Sjkim DtInsertLabelField (GenericField); 352218585Sjkim } 353218585Sjkim } 354218585Sjkim 355218585Sjkim GenericField = GenericField->Next; 356218585Sjkim } 357218585Sjkim} 358218585Sjkim 359218585Sjkim 360218585Sjkim/****************************************************************************** 361218585Sjkim * 362218585Sjkim * FUNCTION: DtInsertLabelField 363218585Sjkim * 364218585Sjkim * PARAMETERS: Field - Field object with Label to be inserted 365218585Sjkim * 366218585Sjkim * RETURN: None 367218585Sjkim * 368218585Sjkim * DESCRIPTION: Insert a label field into the global label list 369218585Sjkim * 370218585Sjkim *****************************************************************************/ 371218585Sjkim 372218585Sjkimstatic void 373218585SjkimDtInsertLabelField ( 374218585Sjkim DT_FIELD *Field) 375218585Sjkim{ 376218585Sjkim 377218585Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 378218585Sjkim "DtInsertLabelField: Found Label : %s at output table offset %X\n", 379218585Sjkim Field->Value, Field->TableOffset); 380218585Sjkim 381218585Sjkim Field->NextLabel = Gbl_LabelList; 382218585Sjkim Gbl_LabelList = Field; 383218585Sjkim} 384218585Sjkim 385218585Sjkim 386218585Sjkim/****************************************************************************** 387218585Sjkim * 388218585Sjkim * FUNCTION: DtLookupLabel 389218585Sjkim * 390218585Sjkim * PARAMETERS: Name - Label to be resolved 391218585Sjkim * 392218585Sjkim * RETURN: Field object associated with the label 393218585Sjkim * 394218585Sjkim * DESCRIPTION: Lookup a label in the global label list. Used during the 395218585Sjkim * resolution of integer expressions. 396218585Sjkim * 397218585Sjkim *****************************************************************************/ 398218585Sjkim 399218585Sjkimstatic DT_FIELD * 400218585SjkimDtLookupLabel ( 401218585Sjkim char *Name) 402218585Sjkim{ 403218585Sjkim DT_FIELD *LabelField; 404218585Sjkim 405218585Sjkim 406218585Sjkim /* Skip a leading $ */ 407218585Sjkim 408218585Sjkim if (*Name == '$') 409218585Sjkim { 410218585Sjkim Name++; 411218585Sjkim } 412218585Sjkim 413218585Sjkim /* Search global list */ 414218585Sjkim 415218585Sjkim LabelField = Gbl_LabelList; 416218585Sjkim while (LabelField) 417218585Sjkim { 418306536Sjkim if (!strcmp (Name, LabelField->Value)) 419218585Sjkim { 420218585Sjkim return (LabelField); 421218585Sjkim } 422306536Sjkim 423218585Sjkim LabelField = LabelField->NextLabel; 424218585Sjkim } 425218585Sjkim 426218585Sjkim return (NULL); 427218585Sjkim} 428