1 /****************************************************************************** 2 * 3 * Module Name: dtexpress.c - Support for integer expressions and labels 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #define __DTEXPRESS_C__ 45 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include <contrib/dev/acpica/compiler/dtcompiler.h> 48 #include "dtparser.y.h" 49 50 #define _COMPONENT DT_COMPILER 51 ACPI_MODULE_NAME ("dtexpress") 52 53 54 /* Local prototypes */ 55 56 static void 57 DtInsertLabelField ( 58 DT_FIELD *Field); 59 60 static DT_FIELD * 61 DtLookupLabel ( 62 char *Name); 63 64 /* Global used for errors during parse and related functions */ 65 66 DT_FIELD *Gbl_CurrentField; 67 68 69 /****************************************************************************** 70 * 71 * FUNCTION: DtResolveIntegerExpression 72 * 73 * PARAMETERS: Field - Field object with Integer expression 74 * ReturnValue - Where the integer is returned 75 * 76 * RETURN: Status, and the resolved 64-bit integer value 77 * 78 * DESCRIPTION: Resolve an integer expression to a single value. Supports 79 * both integer constants and labels. 80 * 81 *****************************************************************************/ 82 83 ACPI_STATUS 84 DtResolveIntegerExpression ( 85 DT_FIELD *Field, 86 UINT64 *ReturnValue) 87 { 88 UINT64 Result; 89 90 91 DbgPrint (ASL_DEBUG_OUTPUT, "Full Integer expression: %s\n", 92 Field->Value); 93 94 Gbl_CurrentField = Field; 95 96 Result = DtEvaluateExpression (Field->Value); 97 *ReturnValue = Result; 98 return (AE_OK); 99 } 100 101 102 /****************************************************************************** 103 * 104 * FUNCTION: DtDoOperator 105 * 106 * PARAMETERS: LeftValue - First 64-bit operand 107 * Operator - Parse token for the operator (EXPOP_*) 108 * RightValue - Second 64-bit operand 109 * 110 * RETURN: 64-bit result of the requested operation 111 * 112 * DESCRIPTION: Perform the various 64-bit integer math functions 113 * 114 *****************************************************************************/ 115 116 UINT64 117 DtDoOperator ( 118 UINT64 LeftValue, 119 UINT32 Operator, 120 UINT64 RightValue) 121 { 122 UINT64 Result; 123 124 125 /* Perform the requested operation */ 126 127 switch (Operator) 128 { 129 case EXPOP_ONES_COMPLIMENT: 130 Result = ~RightValue; 131 break; 132 133 case EXPOP_LOGICAL_NOT: 134 Result = !RightValue; 135 break; 136 137 case EXPOP_MULTIPLY: 138 Result = LeftValue * RightValue; 139 break; 140 141 case EXPOP_DIVIDE: 142 if (!RightValue) 143 { 144 DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 145 Gbl_CurrentField, NULL); 146 return (0); 147 } 148 Result = LeftValue / RightValue; 149 break; 150 151 case EXPOP_MODULO: 152 if (!RightValue) 153 { 154 DtError (ASL_ERROR, ASL_MSG_DIVIDE_BY_ZERO, 155 Gbl_CurrentField, NULL); 156 return (0); 157 } 158 Result = LeftValue % RightValue; 159 break; 160 161 case EXPOP_ADD: 162 Result = LeftValue + RightValue; 163 break; 164 165 case EXPOP_SUBTRACT: 166 Result = LeftValue - RightValue; 167 break; 168 169 case EXPOP_SHIFT_RIGHT: 170 Result = LeftValue >> RightValue; 171 break; 172 173 case EXPOP_SHIFT_LEFT: 174 Result = LeftValue << RightValue; 175 break; 176 177 case EXPOP_LESS: 178 Result = LeftValue < RightValue; 179 break; 180 181 case EXPOP_GREATER: 182 Result = LeftValue > RightValue; 183 break; 184 185 case EXPOP_LESS_EQUAL: 186 Result = LeftValue <= RightValue; 187 break; 188 189 case EXPOP_GREATER_EQUAL: 190 Result = LeftValue >= RightValue; 191 break; 192 193 case EXPOP_EQUAL: 194 Result = LeftValue == RightValue; 195 break; 196 197 case EXPOP_NOT_EQUAL: 198 Result = LeftValue != RightValue; 199 break; 200 201 case EXPOP_AND: 202 Result = LeftValue & RightValue; 203 break; 204 205 case EXPOP_XOR: 206 Result = LeftValue ^ RightValue; 207 break; 208 209 case EXPOP_OR: 210 Result = LeftValue | RightValue; 211 break; 212 213 case EXPOP_LOGICAL_AND: 214 Result = LeftValue && RightValue; 215 break; 216 217 case EXPOP_LOGICAL_OR: 218 Result = LeftValue || RightValue; 219 break; 220 221 default: 222 223 /* Unknown operator */ 224 225 DtFatal (ASL_MSG_INVALID_EXPRESSION, 226 Gbl_CurrentField, NULL); 227 return (0); 228 } 229 230 DbgPrint (ASL_DEBUG_OUTPUT, 231 "IntegerEval: (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", 232 ACPI_FORMAT_UINT64 (LeftValue), 233 DtGetOpName (Operator), 234 ACPI_FORMAT_UINT64 (RightValue), 235 ACPI_FORMAT_UINT64 (Result)); 236 237 return (Result); 238 } 239 240 241 /****************************************************************************** 242 * 243 * FUNCTION: DtResolveLabel 244 * 245 * PARAMETERS: LabelString - Contains the label 246 * 247 * RETURN: Table offset associated with the label 248 * 249 * DESCRIPTION: Lookup a lable and return its value. 250 * 251 *****************************************************************************/ 252 253 UINT64 254 DtResolveLabel ( 255 char *LabelString) 256 { 257 DT_FIELD *LabelField; 258 259 260 DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); 261 262 /* Resolve a label reference to an integer (table offset) */ 263 264 if (*LabelString != '$') 265 { 266 return (0); 267 } 268 269 LabelField = DtLookupLabel (LabelString); 270 if (!LabelField) 271 { 272 DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, 273 Gbl_CurrentField, LabelString); 274 return (0); 275 } 276 277 /* All we need from the label is the offset in the table */ 278 279 DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", 280 LabelField->TableOffset); 281 282 return (LabelField->TableOffset); 283 } 284 285 286 /****************************************************************************** 287 * 288 * FUNCTION: DtDetectAllLabels 289 * 290 * PARAMETERS: FieldList - Field object at start of generic list 291 * 292 * RETURN: None 293 * 294 * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 295 * a UEFI table.) and insert them into the global label list. 296 * 297 *****************************************************************************/ 298 299 void 300 DtDetectAllLabels ( 301 DT_FIELD *FieldList) 302 { 303 ACPI_DMTABLE_INFO *Info; 304 DT_FIELD *GenericField; 305 UINT32 TableOffset; 306 307 308 TableOffset = Gbl_CurrentTableOffset; 309 GenericField = FieldList; 310 311 /* 312 * Process all "Label:" fields within the parse tree. We need 313 * to know the offsets for all labels before we can compile 314 * the parse tree in order to handle forward references. Traverse 315 * tree and get/set all field lengths of all operators in order to 316 * determine the label offsets. 317 */ 318 while (GenericField) 319 { 320 Info = DtGetGenericTableInfo (GenericField->Name); 321 if (Info) 322 { 323 /* Maintain table offsets */ 324 325 GenericField->TableOffset = TableOffset; 326 TableOffset += DtGetFieldLength (GenericField, Info); 327 328 /* Insert all labels in the global label list */ 329 330 if (Info->Opcode == ACPI_DMT_LABEL) 331 { 332 DtInsertLabelField (GenericField); 333 } 334 } 335 336 GenericField = GenericField->Next; 337 } 338 } 339 340 341 /****************************************************************************** 342 * 343 * FUNCTION: DtInsertLabelField 344 * 345 * PARAMETERS: Field - Field object with Label to be inserted 346 * 347 * RETURN: None 348 * 349 * DESCRIPTION: Insert a label field into the global label list 350 * 351 *****************************************************************************/ 352 353 static void 354 DtInsertLabelField ( 355 DT_FIELD *Field) 356 { 357 358 DbgPrint (ASL_DEBUG_OUTPUT, 359 "DtInsertLabelField: Found Label : %s at output table offset %X\n", 360 Field->Value, Field->TableOffset); 361 362 Field->NextLabel = Gbl_LabelList; 363 Gbl_LabelList = Field; 364 } 365 366 367 /****************************************************************************** 368 * 369 * FUNCTION: DtLookupLabel 370 * 371 * PARAMETERS: Name - Label to be resolved 372 * 373 * RETURN: Field object associated with the label 374 * 375 * DESCRIPTION: Lookup a label in the global label list. Used during the 376 * resolution of integer expressions. 377 * 378 *****************************************************************************/ 379 380 static DT_FIELD * 381 DtLookupLabel ( 382 char *Name) 383 { 384 DT_FIELD *LabelField; 385 386 387 /* Skip a leading $ */ 388 389 if (*Name == '$') 390 { 391 Name++; 392 } 393 394 /* Search global list */ 395 396 LabelField = Gbl_LabelList; 397 while (LabelField) 398 { 399 if (!ACPI_STRCMP (Name, LabelField->Value)) 400 { 401 return (LabelField); 402 } 403 LabelField = LabelField->NextLabel; 404 } 405 406 return (NULL); 407 } 408