1 /****************************************************************************** 2 * 3 * Module Name: dtexpress.c - Support for integer expressions and labels 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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, Gbl_CurrentField->Value); 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, Gbl_CurrentField->Value); 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, Gbl_CurrentField->Value); 227 return (0); 228 } 229 230 DbgPrint (ASL_DEBUG_OUTPUT, 231 "IntegerEval: %s (%8.8X%8.8X %s %8.8X%8.8X) = %8.8X%8.8X\n", 232 Gbl_CurrentField->Value, 233 ACPI_FORMAT_UINT64 (LeftValue), 234 DtGetOpName (Operator), 235 ACPI_FORMAT_UINT64 (RightValue), 236 ACPI_FORMAT_UINT64 (Result)); 237 238 return (Result); 239 } 240 241 242 /****************************************************************************** 243 * 244 * FUNCTION: DtResolveLabel 245 * 246 * PARAMETERS: LabelString - Contains the label 247 * 248 * RETURN: Table offset associated with the label 249 * 250 * DESCRIPTION: Lookup a lable and return its value. 251 * 252 *****************************************************************************/ 253 254 UINT64 255 DtResolveLabel ( 256 char *LabelString) 257 { 258 DT_FIELD *LabelField; 259 260 261 DbgPrint (ASL_DEBUG_OUTPUT, "Resolve Label: %s\n", LabelString); 262 263 /* Resolve a label reference to an integer (table offset) */ 264 265 if (*LabelString != '$') 266 { 267 return (0); 268 } 269 270 LabelField = DtLookupLabel (LabelString); 271 if (!LabelField) 272 { 273 DtError (ASL_ERROR, ASL_MSG_UNKNOWN_LABEL, 274 Gbl_CurrentField, LabelString); 275 return (0); 276 } 277 278 /* All we need from the label is the offset in the table */ 279 280 DbgPrint (ASL_DEBUG_OUTPUT, "Resolved Label: 0x%8.8X\n", 281 LabelField->TableOffset); 282 283 return (LabelField->TableOffset); 284 } 285 286 287 /****************************************************************************** 288 * 289 * FUNCTION: DtDetectAllLabels 290 * 291 * PARAMETERS: FieldList - Field object at start of generic list 292 * 293 * RETURN: None 294 * 295 * DESCRIPTION: Detect all labels in a list of "generic" opcodes (such as 296 * a UEFI table.) and insert them into the global label list. 297 * 298 *****************************************************************************/ 299 300 void 301 DtDetectAllLabels ( 302 DT_FIELD *FieldList) 303 { 304 ACPI_DMTABLE_INFO *Info; 305 DT_FIELD *GenericField; 306 UINT32 TableOffset; 307 308 309 TableOffset = Gbl_CurrentTableOffset; 310 GenericField = FieldList; 311 312 /* 313 * Process all "Label:" fields within the parse tree. We need 314 * to know the offsets for all labels before we can compile 315 * the parse tree in order to handle forward references. Traverse 316 * tree and get/set all field lengths of all operators in order to 317 * determine the label offsets. 318 */ 319 while (GenericField) 320 { 321 Info = DtGetGenericTableInfo (GenericField->Name); 322 if (Info) 323 { 324 /* Maintain table offsets */ 325 326 GenericField->TableOffset = TableOffset; 327 TableOffset += DtGetFieldLength (GenericField, Info); 328 329 /* Insert all labels in the global label list */ 330 331 if (Info->Opcode == ACPI_DMT_LABEL) 332 { 333 DtInsertLabelField (GenericField); 334 } 335 } 336 337 GenericField = GenericField->Next; 338 } 339 } 340 341 342 /****************************************************************************** 343 * 344 * FUNCTION: DtInsertLabelField 345 * 346 * PARAMETERS: Field - Field object with Label to be inserted 347 * 348 * RETURN: None 349 * 350 * DESCRIPTION: Insert a label field into the global label list 351 * 352 *****************************************************************************/ 353 354 static void 355 DtInsertLabelField ( 356 DT_FIELD *Field) 357 { 358 359 DbgPrint (ASL_DEBUG_OUTPUT, 360 "DtInsertLabelField: Found Label : %s at output table offset %X\n", 361 Field->Value, Field->TableOffset); 362 363 Field->NextLabel = Gbl_LabelList; 364 Gbl_LabelList = Field; 365 } 366 367 368 /****************************************************************************** 369 * 370 * FUNCTION: DtLookupLabel 371 * 372 * PARAMETERS: Name - Label to be resolved 373 * 374 * RETURN: Field object associated with the label 375 * 376 * DESCRIPTION: Lookup a label in the global label list. Used during the 377 * resolution of integer expressions. 378 * 379 *****************************************************************************/ 380 381 static DT_FIELD * 382 DtLookupLabel ( 383 char *Name) 384 { 385 DT_FIELD *LabelField; 386 387 388 /* Skip a leading $ */ 389 390 if (*Name == '$') 391 { 392 Name++; 393 } 394 395 /* Search global list */ 396 397 LabelField = Gbl_LabelList; 398 while (LabelField) 399 { 400 if (!ACPI_STRCMP (Name, LabelField->Value)) 401 { 402 return (LabelField); 403 } 404 LabelField = LabelField->NextLabel; 405 } 406 407 return (NULL); 408 } 409