1274357Sjkim/******************************************************************************* 2274357Sjkim * 3274357Sjkim * Module Name: dmcstyle - Support for C-style operator disassembly 4274357Sjkim * 5274357Sjkim ******************************************************************************/ 6274357Sjkim 7274357Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9274357Sjkim * All rights reserved. 10274357Sjkim * 11274357Sjkim * Redistribution and use in source and binary forms, with or without 12274357Sjkim * modification, are permitted provided that the following conditions 13274357Sjkim * are met: 14274357Sjkim * 1. Redistributions of source code must retain the above copyright 15274357Sjkim * notice, this list of conditions, and the following disclaimer, 16274357Sjkim * without modification. 17274357Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18274357Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19274357Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20274357Sjkim * including a substantially similar Disclaimer requirement for further 21274357Sjkim * binary redistribution. 22274357Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23274357Sjkim * of any contributors may be used to endorse or promote products derived 24274357Sjkim * from this software without specific prior written permission. 25274357Sjkim * 26274357Sjkim * Alternatively, this software may be distributed under the terms of the 27274357Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28274357Sjkim * Software Foundation. 29274357Sjkim * 30274357Sjkim * NO WARRANTY 31274357Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32274357Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33274357Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34274357Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35274357Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36274357Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37274357Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38274357Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39274357Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40274357Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41274357Sjkim * POSSIBILITY OF SUCH DAMAGES. 42274357Sjkim */ 43274357Sjkim 44278970Sjkim#include <contrib/dev/acpica/include/acpi.h> 45278970Sjkim#include <contrib/dev/acpica/include/accommon.h> 46278970Sjkim#include <contrib/dev/acpica/include/acparser.h> 47278970Sjkim#include <contrib/dev/acpica/include/amlcode.h> 48278970Sjkim#include <contrib/dev/acpica/include/acdebug.h> 49274357Sjkim 50274357Sjkim 51274357Sjkim#define _COMPONENT ACPI_CA_DEBUGGER 52274357Sjkim ACPI_MODULE_NAME ("dmcstyle") 53274357Sjkim 54274357Sjkim 55274357Sjkim/* Local prototypes */ 56274357Sjkim 57274357Sjkimstatic char * 58274357SjkimAcpiDmGetCompoundSymbol ( 59274357Sjkim UINT16 AslOpcode); 60274357Sjkim 61274357Sjkimstatic void 62274357SjkimAcpiDmPromoteTarget ( 63274357Sjkim ACPI_PARSE_OBJECT *Op, 64274357Sjkim ACPI_PARSE_OBJECT *Target); 65274357Sjkim 66274357Sjkimstatic BOOLEAN 67274357SjkimAcpiDmIsValidTarget ( 68274357Sjkim ACPI_PARSE_OBJECT *Op); 69274357Sjkim 70274357Sjkimstatic BOOLEAN 71274357SjkimAcpiDmIsTargetAnOperand ( 72274357Sjkim ACPI_PARSE_OBJECT *Target, 73274357Sjkim ACPI_PARSE_OBJECT *Operand, 74274357Sjkim BOOLEAN TopLevel); 75274357Sjkim 76274357Sjkim 77274357Sjkim/******************************************************************************* 78274357Sjkim * 79274357Sjkim * FUNCTION: AcpiDmCheckForSymbolicOpcode 80274357Sjkim * 81274357Sjkim * PARAMETERS: Op - Current parse object 82274357Sjkim * Walk - Current parse tree walk info 83274357Sjkim * 84274357Sjkim * RETURN: TRUE if opcode can be converted to symbolic, FALSE otherwise 85274357Sjkim * 86274357Sjkim * DESCRIPTION: This is the main code that implements disassembly of AML code 87274357Sjkim * to C-style operators. Called during descending phase of the 88274357Sjkim * parse tree walk. 89274357Sjkim * 90274357Sjkim ******************************************************************************/ 91274357Sjkim 92274357SjkimBOOLEAN 93274357SjkimAcpiDmCheckForSymbolicOpcode ( 94274357Sjkim ACPI_PARSE_OBJECT *Op, 95274357Sjkim ACPI_OP_WALK_INFO *Info) 96274357Sjkim{ 97274357Sjkim char *OperatorSymbol = NULL; 98274357Sjkim ACPI_PARSE_OBJECT *Child1; 99274357Sjkim ACPI_PARSE_OBJECT *Child2; 100274357Sjkim ACPI_PARSE_OBJECT *Target; 101274357Sjkim 102274357Sjkim 103274357Sjkim /* Exit immediately if ASL+ not enabled */ 104274357Sjkim 105274357Sjkim if (!AcpiGbl_CstyleDisassembly) 106274357Sjkim { 107274357Sjkim return (FALSE); 108274357Sjkim } 109274357Sjkim 110274357Sjkim /* Get the first operand */ 111274357Sjkim 112274357Sjkim Child1 = AcpiPsGetArg (Op, 0); 113274357Sjkim if (!Child1) 114274357Sjkim { 115274357Sjkim return (FALSE); 116274357Sjkim } 117274357Sjkim 118274357Sjkim /* Get the second operand */ 119274357Sjkim 120274357Sjkim Child2 = Child1->Common.Next; 121274357Sjkim 122274357Sjkim /* Setup the operator string for this opcode */ 123274357Sjkim 124274357Sjkim switch (Op->Common.AmlOpcode) 125274357Sjkim { 126274357Sjkim case AML_ADD_OP: 127274357Sjkim OperatorSymbol = " + "; 128274357Sjkim break; 129274357Sjkim 130274357Sjkim case AML_SUBTRACT_OP: 131274357Sjkim OperatorSymbol = " - "; 132274357Sjkim break; 133274357Sjkim 134274357Sjkim case AML_MULTIPLY_OP: 135274357Sjkim OperatorSymbol = " * "; 136274357Sjkim break; 137274357Sjkim 138274357Sjkim case AML_DIVIDE_OP: 139274357Sjkim OperatorSymbol = " / "; 140274357Sjkim break; 141274357Sjkim 142274357Sjkim case AML_MOD_OP: 143274357Sjkim OperatorSymbol = " % "; 144274357Sjkim break; 145274357Sjkim 146274357Sjkim case AML_SHIFT_LEFT_OP: 147274357Sjkim OperatorSymbol = " << "; 148274357Sjkim break; 149274357Sjkim 150274357Sjkim case AML_SHIFT_RIGHT_OP: 151274357Sjkim OperatorSymbol = " >> "; 152274357Sjkim break; 153274357Sjkim 154274357Sjkim case AML_BIT_AND_OP: 155274357Sjkim OperatorSymbol = " & "; 156274357Sjkim break; 157274357Sjkim 158274357Sjkim case AML_BIT_OR_OP: 159274357Sjkim OperatorSymbol = " | "; 160274357Sjkim break; 161274357Sjkim 162274357Sjkim case AML_BIT_XOR_OP: 163274357Sjkim OperatorSymbol = " ^ "; 164274357Sjkim break; 165274357Sjkim 166274357Sjkim /* Logical operators, no target */ 167274357Sjkim 168274357Sjkim case AML_LAND_OP: 169274357Sjkim OperatorSymbol = " && "; 170274357Sjkim break; 171274357Sjkim 172274357Sjkim case AML_LEQUAL_OP: 173274357Sjkim OperatorSymbol = " == "; 174274357Sjkim break; 175274357Sjkim 176274357Sjkim case AML_LGREATER_OP: 177274357Sjkim OperatorSymbol = " > "; 178274357Sjkim break; 179274357Sjkim 180274357Sjkim case AML_LLESS_OP: 181274357Sjkim OperatorSymbol = " < "; 182274357Sjkim break; 183274357Sjkim 184274357Sjkim case AML_LOR_OP: 185274357Sjkim OperatorSymbol = " || "; 186274357Sjkim break; 187274357Sjkim 188274357Sjkim case AML_LNOT_OP: 189274357Sjkim /* 190274357Sjkim * Check for the LNOT sub-opcodes. These correspond to 191274357Sjkim * LNotEqual, LLessEqual, and LGreaterEqual. There are 192274357Sjkim * no actual AML opcodes for these operators. 193274357Sjkim */ 194274357Sjkim switch (Child1->Common.AmlOpcode) 195274357Sjkim { 196274357Sjkim case AML_LEQUAL_OP: 197274357Sjkim OperatorSymbol = " != "; 198274357Sjkim break; 199274357Sjkim 200274357Sjkim case AML_LGREATER_OP: 201274357Sjkim OperatorSymbol = " <= "; 202274357Sjkim break; 203274357Sjkim 204274357Sjkim case AML_LLESS_OP: 205274357Sjkim OperatorSymbol = " >= "; 206274357Sjkim break; 207274357Sjkim 208274357Sjkim default: 209274357Sjkim 210274357Sjkim /* Unary LNOT case, emit "!" immediately */ 211274357Sjkim 212274357Sjkim AcpiOsPrintf ("!"); 213274357Sjkim return (TRUE); 214274357Sjkim } 215274357Sjkim 216274357Sjkim Child1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX; 217274357Sjkim Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX; 218306536Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; 219274357Sjkim 220274357Sjkim /* Save symbol string in the next child (not peer) */ 221274357Sjkim 222274357Sjkim Child2 = AcpiPsGetArg (Child1, 0); 223274357Sjkim if (!Child2) 224274357Sjkim { 225274357Sjkim return (FALSE); 226274357Sjkim } 227274357Sjkim 228274357Sjkim Child2->Common.OperatorSymbol = OperatorSymbol; 229274357Sjkim return (TRUE); 230274357Sjkim 231274357Sjkim case AML_INDEX_OP: 232306536Sjkim /* 233306536Sjkim * Check for constant source operand. Note: although technically 234306536Sjkim * legal syntax, the iASL compiler does not support this with 235306536Sjkim * the symbolic operators for Index(). It doesn't make sense to 236306536Sjkim * use Index() with a constant anyway. 237306536Sjkim */ 238306536Sjkim if ((Child1->Common.AmlOpcode == AML_STRING_OP) || 239306536Sjkim (Child1->Common.AmlOpcode == AML_BUFFER_OP) || 240306536Sjkim (Child1->Common.AmlOpcode == AML_PACKAGE_OP) || 241306536Sjkim (Child1->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) 242306536Sjkim { 243306536Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN; 244306536Sjkim return (FALSE); 245306536Sjkim } 246306536Sjkim 247306536Sjkim /* Index operator is [] */ 248306536Sjkim 249274357Sjkim Child1->Common.OperatorSymbol = " ["; 250274357Sjkim Child2->Common.OperatorSymbol = "]"; 251274357Sjkim break; 252274357Sjkim 253274357Sjkim /* Unary operators */ 254274357Sjkim 255274357Sjkim case AML_DECREMENT_OP: 256274357Sjkim OperatorSymbol = "--"; 257274357Sjkim break; 258274357Sjkim 259274357Sjkim case AML_INCREMENT_OP: 260274357Sjkim OperatorSymbol = "++"; 261274357Sjkim break; 262274357Sjkim 263274357Sjkim case AML_BIT_NOT_OP: 264274357Sjkim case AML_STORE_OP: 265274357Sjkim OperatorSymbol = NULL; 266274357Sjkim break; 267274357Sjkim 268274357Sjkim default: 269274357Sjkim return (FALSE); 270274357Sjkim } 271274357Sjkim 272274357Sjkim if (Child1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX) 273274357Sjkim { 274274357Sjkim return (TRUE); 275274357Sjkim } 276274357Sjkim 277274357Sjkim /* 278274357Sjkim * This is the key to how the disassembly of the C-style operators 279274357Sjkim * works. We save the operator symbol in the first child, thus 280274357Sjkim * deferring symbol output until after the first operand has been 281274357Sjkim * emitted. 282274357Sjkim */ 283274357Sjkim if (!Child1->Common.OperatorSymbol) 284274357Sjkim { 285274357Sjkim Child1->Common.OperatorSymbol = OperatorSymbol; 286274357Sjkim } 287274357Sjkim 288274357Sjkim /* 289274357Sjkim * Check for a valid target as the 3rd (or sometimes 2nd) operand 290274357Sjkim * 291274357Sjkim * Compound assignment operator support: 292274357Sjkim * Attempt to optimize constructs of the form: 293274357Sjkim * Add (Local1, 0xFF, Local1) 294274357Sjkim * to: 295274357Sjkim * Local1 += 0xFF 296274357Sjkim * 297274357Sjkim * Only the math operators and Store() have a target. 298274357Sjkim * Logicals have no target. 299274357Sjkim */ 300274357Sjkim switch (Op->Common.AmlOpcode) 301274357Sjkim { 302274357Sjkim case AML_ADD_OP: 303274357Sjkim case AML_SUBTRACT_OP: 304274357Sjkim case AML_MULTIPLY_OP: 305274357Sjkim case AML_DIVIDE_OP: 306274357Sjkim case AML_MOD_OP: 307274357Sjkim case AML_SHIFT_LEFT_OP: 308274357Sjkim case AML_SHIFT_RIGHT_OP: 309274357Sjkim case AML_BIT_AND_OP: 310274357Sjkim case AML_BIT_OR_OP: 311274357Sjkim case AML_BIT_XOR_OP: 312274357Sjkim 313274357Sjkim /* Target is 3rd operand */ 314274357Sjkim 315274357Sjkim Target = Child2->Common.Next; 316274357Sjkim if (Op->Common.AmlOpcode == AML_DIVIDE_OP) 317274357Sjkim { 318274357Sjkim /* 319274357Sjkim * Divide has an extra target operand (Remainder). 320274357Sjkim * If this extra target is specified, it cannot be converted 321274357Sjkim * to a C-style operator 322274357Sjkim */ 323274357Sjkim if (AcpiDmIsValidTarget (Target)) 324274357Sjkim { 325274357Sjkim Child1->Common.OperatorSymbol = NULL; 326274357Sjkim return (FALSE); 327274357Sjkim } 328274357Sjkim 329274357Sjkim Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 330274357Sjkim Target = Target->Common.Next; 331274357Sjkim } 332274357Sjkim 333274357Sjkim /* Parser should ensure there is at least a placeholder target */ 334274357Sjkim 335274357Sjkim if (!Target) 336274357Sjkim { 337274357Sjkim return (FALSE); 338274357Sjkim } 339274357Sjkim 340274357Sjkim if (!AcpiDmIsValidTarget (Target)) 341274357Sjkim { 342274357Sjkim /* Not a valid target (placeholder only, from parser) */ 343274357Sjkim break; 344274357Sjkim } 345274357Sjkim 346274357Sjkim /* 347274357Sjkim * Promote the target up to the first child in the parse 348274357Sjkim * tree. This is done because the target will be output 349274357Sjkim * first, in the form: 350274357Sjkim * <Target> = Operands... 351274357Sjkim */ 352274357Sjkim AcpiDmPromoteTarget (Op, Target); 353274357Sjkim 354306536Sjkim /* Check operands for conversion to a "Compound Assignment" */ 355306536Sjkim 356306536Sjkim switch (Op->Common.AmlOpcode) 357274357Sjkim { 358306536Sjkim /* Commutative operators */ 359274357Sjkim 360306536Sjkim case AML_ADD_OP: 361306536Sjkim case AML_MULTIPLY_OP: 362306536Sjkim case AML_BIT_AND_OP: 363306536Sjkim case AML_BIT_OR_OP: 364306536Sjkim case AML_BIT_XOR_OP: 365306536Sjkim /* 366306536Sjkim * For the commutative operators, we can convert to a 367306536Sjkim * compound statement only if at least one (either) operand 368306536Sjkim * is the same as the target. 369306536Sjkim * 370306536Sjkim * Add (A, B, A) --> A += B 371306536Sjkim * Add (B, A, A) --> A += B 372306536Sjkim * Add (B, C, A) --> A = (B + C) 373306536Sjkim */ 374306536Sjkim if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE)) || 375306536Sjkim (AcpiDmIsTargetAnOperand (Target, Child2, TRUE))) 376306536Sjkim { 377306536Sjkim Target->Common.OperatorSymbol = 378306536Sjkim AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); 379274357Sjkim 380306536Sjkim /* Convert operator to compound assignment */ 381306536Sjkim 382306536Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; 383306536Sjkim Child1->Common.OperatorSymbol = NULL; 384306536Sjkim return (TRUE); 385306536Sjkim } 386306536Sjkim break; 387306536Sjkim 388306536Sjkim /* Non-commutative operators */ 389306536Sjkim 390306536Sjkim case AML_SUBTRACT_OP: 391306536Sjkim case AML_DIVIDE_OP: 392306536Sjkim case AML_MOD_OP: 393306536Sjkim case AML_SHIFT_LEFT_OP: 394306536Sjkim case AML_SHIFT_RIGHT_OP: 395306536Sjkim /* 396306536Sjkim * For the non-commutative operators, we can convert to a 397306536Sjkim * compound statement only if the target is the same as the 398306536Sjkim * first operand. 399306536Sjkim * 400306536Sjkim * Subtract (A, B, A) --> A -= B 401306536Sjkim * Subtract (B, A, A) --> A = (B - A) 402306536Sjkim */ 403306536Sjkim if ((AcpiDmIsTargetAnOperand (Target, Child1, TRUE))) 404306536Sjkim { 405306536Sjkim Target->Common.OperatorSymbol = 406306536Sjkim AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode); 407306536Sjkim 408306536Sjkim /* Convert operator to compound assignment */ 409306536Sjkim 410306536Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT; 411306536Sjkim Child1->Common.OperatorSymbol = NULL; 412306536Sjkim return (TRUE); 413306536Sjkim } 414306536Sjkim break; 415306536Sjkim 416306536Sjkim default: 417306536Sjkim break; 418274357Sjkim } 419274357Sjkim 420274357Sjkim /* 421274357Sjkim * If we are within a C-style expression, emit an extra open 422274357Sjkim * paren. Implemented by examining the parent op. 423274357Sjkim */ 424274357Sjkim switch (Op->Common.Parent->Common.AmlOpcode) 425274357Sjkim { 426274357Sjkim case AML_ADD_OP: 427274357Sjkim case AML_SUBTRACT_OP: 428274357Sjkim case AML_MULTIPLY_OP: 429274357Sjkim case AML_DIVIDE_OP: 430274357Sjkim case AML_MOD_OP: 431274357Sjkim case AML_SHIFT_LEFT_OP: 432274357Sjkim case AML_SHIFT_RIGHT_OP: 433274357Sjkim case AML_BIT_AND_OP: 434274357Sjkim case AML_BIT_OR_OP: 435274357Sjkim case AML_BIT_XOR_OP: 436274357Sjkim case AML_LAND_OP: 437274357Sjkim case AML_LEQUAL_OP: 438274357Sjkim case AML_LGREATER_OP: 439274357Sjkim case AML_LLESS_OP: 440274357Sjkim case AML_LOR_OP: 441274357Sjkim 442274357Sjkim Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT; 443274357Sjkim AcpiOsPrintf ("("); 444274357Sjkim break; 445274357Sjkim 446274357Sjkim default: 447274357Sjkim break; 448274357Sjkim } 449274357Sjkim 450274357Sjkim /* Normal output for ASL/AML operators with a target operand */ 451274357Sjkim 452274357Sjkim Target->Common.OperatorSymbol = " = ("; 453274357Sjkim return (TRUE); 454274357Sjkim 455274357Sjkim /* Binary operators, no parens */ 456274357Sjkim 457274357Sjkim case AML_DECREMENT_OP: 458274357Sjkim case AML_INCREMENT_OP: 459274357Sjkim return (TRUE); 460274357Sjkim 461274357Sjkim case AML_INDEX_OP: 462274357Sjkim 463274357Sjkim /* Target is optional, 3rd operand */ 464274357Sjkim 465274357Sjkim Target = Child2->Common.Next; 466274357Sjkim if (AcpiDmIsValidTarget (Target)) 467274357Sjkim { 468274357Sjkim AcpiDmPromoteTarget (Op, Target); 469274357Sjkim 470274357Sjkim if (!Target->Common.OperatorSymbol) 471274357Sjkim { 472274357Sjkim Target->Common.OperatorSymbol = " = "; 473274357Sjkim } 474274357Sjkim } 475274357Sjkim return (TRUE); 476274357Sjkim 477274357Sjkim case AML_STORE_OP: 478274357Sjkim /* 479274357Sjkim * Target is the 2nd operand. 480274357Sjkim * We know the target is valid, it is not optional. 481274357Sjkim * In the parse tree, simply swap the target with the 482274357Sjkim * source so that the target is processed first. 483274357Sjkim */ 484274357Sjkim Target = Child1->Common.Next; 485306536Sjkim if (!Target) 486306536Sjkim { 487306536Sjkim return (FALSE); 488306536Sjkim } 489306536Sjkim 490274357Sjkim AcpiDmPromoteTarget (Op, Target); 491274357Sjkim if (!Target->Common.OperatorSymbol) 492274357Sjkim { 493274357Sjkim Target->Common.OperatorSymbol = " = "; 494274357Sjkim } 495274357Sjkim return (TRUE); 496274357Sjkim 497274357Sjkim case AML_BIT_NOT_OP: 498274357Sjkim 499274357Sjkim /* Target is optional, 2nd operand */ 500274357Sjkim 501274357Sjkim Target = Child1->Common.Next; 502274357Sjkim if (!Target) 503274357Sjkim { 504274357Sjkim return (FALSE); 505274357Sjkim } 506274357Sjkim 507274357Sjkim if (AcpiDmIsValidTarget (Target)) 508274357Sjkim { 509274357Sjkim /* Valid target, not a placeholder */ 510274357Sjkim 511274357Sjkim AcpiDmPromoteTarget (Op, Target); 512274357Sjkim Target->Common.OperatorSymbol = " = ~"; 513274357Sjkim } 514274357Sjkim else 515274357Sjkim { 516274357Sjkim /* No target. Emit this prefix operator immediately */ 517274357Sjkim 518274357Sjkim AcpiOsPrintf ("~"); 519274357Sjkim } 520274357Sjkim return (TRUE); 521274357Sjkim 522274357Sjkim default: 523274357Sjkim break; 524274357Sjkim } 525274357Sjkim 526306536Sjkim /* 527306536Sjkim * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens 528306536Sjkim * output here. We also need to check the parent to see if this op 529306536Sjkim * is part of a compound test (!=, >=, <=). 530306536Sjkim */ 531306536Sjkim if ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) || 532306536Sjkim ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) && 533306536Sjkim (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX))) 534306536Sjkim { 535306536Sjkim /* Do Nothing. Paren already generated */ 536306536Sjkim return (TRUE); 537306536Sjkim } 538306536Sjkim 539274357Sjkim /* All other operators, emit an open paren */ 540274357Sjkim 541274357Sjkim AcpiOsPrintf ("("); 542274357Sjkim return (TRUE); 543274357Sjkim} 544274357Sjkim 545274357Sjkim 546274357Sjkim/******************************************************************************* 547274357Sjkim * 548274357Sjkim * FUNCTION: AcpiDmCloseOperator 549274357Sjkim * 550274357Sjkim * PARAMETERS: Op - Current parse object 551274357Sjkim * 552274357Sjkim * RETURN: None 553274357Sjkim * 554274357Sjkim * DESCRIPTION: Closes an operator by adding a closing parentheses if and 555274357Sjkim * when necessary. Called during ascending phase of the 556274357Sjkim * parse tree walk. 557274357Sjkim * 558274357Sjkim ******************************************************************************/ 559274357Sjkim 560274357Sjkimvoid 561274357SjkimAcpiDmCloseOperator ( 562274357Sjkim ACPI_PARSE_OBJECT *Op) 563274357Sjkim{ 564306536Sjkim BOOLEAN IsCStyleOp = FALSE; 565274357Sjkim 566274357Sjkim /* Always emit paren if ASL+ disassembly disabled */ 567274357Sjkim 568274357Sjkim if (!AcpiGbl_CstyleDisassembly) 569274357Sjkim { 570274357Sjkim AcpiOsPrintf (")"); 571274357Sjkim return; 572274357Sjkim } 573274357Sjkim 574274357Sjkim /* Check if we need to add an additional closing paren */ 575274357Sjkim 576274357Sjkim switch (Op->Common.AmlOpcode) 577274357Sjkim { 578274357Sjkim case AML_ADD_OP: 579274357Sjkim case AML_SUBTRACT_OP: 580274357Sjkim case AML_MULTIPLY_OP: 581274357Sjkim case AML_DIVIDE_OP: 582274357Sjkim case AML_MOD_OP: 583274357Sjkim case AML_SHIFT_LEFT_OP: 584274357Sjkim case AML_SHIFT_RIGHT_OP: 585274357Sjkim case AML_BIT_AND_OP: 586274357Sjkim case AML_BIT_OR_OP: 587274357Sjkim case AML_BIT_XOR_OP: 588274357Sjkim case AML_LAND_OP: 589274357Sjkim case AML_LEQUAL_OP: 590274357Sjkim case AML_LGREATER_OP: 591274357Sjkim case AML_LLESS_OP: 592274357Sjkim case AML_LOR_OP: 593274357Sjkim 594274357Sjkim /* Emit paren only if this is not a compound assignment */ 595274357Sjkim 596306536Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND_ASSIGNMENT) 597274357Sjkim { 598274357Sjkim return; 599274357Sjkim } 600274357Sjkim 601274357Sjkim /* Emit extra close paren for assignment within an expression */ 602274357Sjkim 603274357Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT) 604274357Sjkim { 605274357Sjkim AcpiOsPrintf (")"); 606274357Sjkim } 607306536Sjkim 608306536Sjkim IsCStyleOp = TRUE; 609274357Sjkim break; 610274357Sjkim 611306536Sjkim case AML_INDEX_OP: 612274357Sjkim 613306536Sjkim /* This is case for unsupported Index() source constants */ 614306536Sjkim 615306536Sjkim if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN) 616306536Sjkim { 617306536Sjkim AcpiOsPrintf (")"); 618306536Sjkim } 619306536Sjkim return; 620306536Sjkim 621274357Sjkim /* No need for parens for these */ 622274357Sjkim 623274357Sjkim case AML_DECREMENT_OP: 624274357Sjkim case AML_INCREMENT_OP: 625274357Sjkim case AML_LNOT_OP: 626274357Sjkim case AML_BIT_NOT_OP: 627274357Sjkim case AML_STORE_OP: 628274357Sjkim return; 629274357Sjkim 630274357Sjkim default: 631274357Sjkim 632274357Sjkim /* Always emit paren for non-ASL+ operators */ 633274357Sjkim break; 634274357Sjkim } 635274357Sjkim 636306536Sjkim /* 637306536Sjkim * Nodes marked with ACPI_PARSEOP_PARAMLIST don't need a parens 638306536Sjkim * output here. We also need to check the parent to see if this op 639306536Sjkim * is part of a compound test (!=, >=, <=). 640306536Sjkim */ 641306536Sjkim if (IsCStyleOp && 642306536Sjkim ((Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) || 643306536Sjkim ((Op->Common.Parent->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST) && 644306536Sjkim (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)))) 645306536Sjkim { 646306536Sjkim return; 647306536Sjkim } 648306536Sjkim 649274357Sjkim AcpiOsPrintf (")"); 650306536Sjkim return; 651274357Sjkim} 652274357Sjkim 653274357Sjkim 654274357Sjkim/******************************************************************************* 655274357Sjkim * 656274357Sjkim * FUNCTION: AcpiDmGetCompoundSymbol 657274357Sjkim * 658274357Sjkim * PARAMETERS: AslOpcode 659274357Sjkim * 660274357Sjkim * RETURN: String containing the compound assignment symbol 661274357Sjkim * 662274357Sjkim * DESCRIPTION: Detect opcodes that can be converted to compound assignment, 663274357Sjkim * return the appropriate operator string. 664274357Sjkim * 665274357Sjkim ******************************************************************************/ 666274357Sjkim 667274357Sjkimstatic char * 668274357SjkimAcpiDmGetCompoundSymbol ( 669274357Sjkim UINT16 AmlOpcode) 670274357Sjkim{ 671274357Sjkim char *Symbol; 672274357Sjkim 673274357Sjkim 674274357Sjkim switch (AmlOpcode) 675274357Sjkim { 676274357Sjkim case AML_ADD_OP: 677274357Sjkim Symbol = " += "; 678274357Sjkim break; 679274357Sjkim 680274357Sjkim case AML_SUBTRACT_OP: 681274357Sjkim Symbol = " -= "; 682274357Sjkim break; 683274357Sjkim 684274357Sjkim case AML_MULTIPLY_OP: 685274357Sjkim Symbol = " *= "; 686274357Sjkim break; 687274357Sjkim 688274357Sjkim case AML_DIVIDE_OP: 689274357Sjkim Symbol = " /= "; 690274357Sjkim break; 691274357Sjkim 692274357Sjkim case AML_MOD_OP: 693274357Sjkim Symbol = " %= "; 694274357Sjkim break; 695274357Sjkim 696274357Sjkim case AML_SHIFT_LEFT_OP: 697274357Sjkim Symbol = " <<= "; 698274357Sjkim break; 699274357Sjkim 700274357Sjkim case AML_SHIFT_RIGHT_OP: 701274357Sjkim Symbol = " >>= "; 702274357Sjkim break; 703274357Sjkim 704274357Sjkim case AML_BIT_AND_OP: 705274357Sjkim Symbol = " &= "; 706274357Sjkim break; 707274357Sjkim 708274357Sjkim case AML_BIT_OR_OP: 709274357Sjkim Symbol = " |= "; 710274357Sjkim break; 711274357Sjkim 712274357Sjkim case AML_BIT_XOR_OP: 713274357Sjkim Symbol = " ^= "; 714274357Sjkim break; 715274357Sjkim 716274357Sjkim default: 717274357Sjkim 718274357Sjkim /* No operator string for all other opcodes */ 719306536Sjkim 720274357Sjkim return (NULL); 721274357Sjkim } 722274357Sjkim 723274357Sjkim return (Symbol); 724274357Sjkim} 725274357Sjkim 726274357Sjkim 727274357Sjkim/******************************************************************************* 728274357Sjkim * 729274357Sjkim * FUNCTION: AcpiDmPromoteTarget 730274357Sjkim * 731274357Sjkim * PARAMETERS: Op - Operator parse object 732274357Sjkim * Target - Target associate with the Op 733274357Sjkim * 734274357Sjkim * RETURN: None 735274357Sjkim * 736274357Sjkim * DESCRIPTION: Transform the parse tree by moving the target up to the first 737274357Sjkim * child of the Op. 738274357Sjkim * 739274357Sjkim ******************************************************************************/ 740274357Sjkim 741274357Sjkimstatic void 742274357SjkimAcpiDmPromoteTarget ( 743274357Sjkim ACPI_PARSE_OBJECT *Op, 744274357Sjkim ACPI_PARSE_OBJECT *Target) 745274357Sjkim{ 746274357Sjkim ACPI_PARSE_OBJECT *Child; 747274357Sjkim 748274357Sjkim 749274357Sjkim /* Link target directly to the Op as first child */ 750274357Sjkim 751274357Sjkim Child = Op->Common.Value.Arg; 752274357Sjkim Op->Common.Value.Arg = Target; 753274357Sjkim Target->Common.Next = Child; 754274357Sjkim 755274357Sjkim /* Find the last peer, it is linked to the target. Unlink it. */ 756274357Sjkim 757274357Sjkim while (Child->Common.Next != Target) 758274357Sjkim { 759274357Sjkim Child = Child->Common.Next; 760274357Sjkim } 761274357Sjkim 762274357Sjkim Child->Common.Next = NULL; 763274357Sjkim} 764274357Sjkim 765274357Sjkim 766274357Sjkim/******************************************************************************* 767274357Sjkim * 768274357Sjkim * FUNCTION: AcpiDmIsValidTarget 769274357Sjkim * 770274357Sjkim * PARAMETERS: Target - Target Op from the parse tree 771274357Sjkim * 772274357Sjkim * RETURN: TRUE if the Target is real. FALSE if it is just a placeholder 773274357Sjkim * Op that was inserted by the parser. 774274357Sjkim * 775274357Sjkim * DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target. 776274357Sjkim * In other words, determine if the optional target is used or 777306536Sjkim * not. Note: If Target is NULL, something is seriously wrong, 778306536Sjkim * probably with the parse tree. 779274357Sjkim * 780274357Sjkim ******************************************************************************/ 781274357Sjkim 782274357Sjkimstatic BOOLEAN 783274357SjkimAcpiDmIsValidTarget ( 784274357Sjkim ACPI_PARSE_OBJECT *Target) 785274357Sjkim{ 786274357Sjkim 787306536Sjkim if (!Target) 788306536Sjkim { 789306536Sjkim return (FALSE); 790306536Sjkim } 791306536Sjkim 792274357Sjkim if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 793274357Sjkim (Target->Common.Value.Arg == NULL)) 794274357Sjkim { 795274357Sjkim return (FALSE); 796274357Sjkim } 797274357Sjkim 798274357Sjkim return (TRUE); 799274357Sjkim} 800274357Sjkim 801274357Sjkim 802274357Sjkim/******************************************************************************* 803274357Sjkim * 804274357Sjkim * FUNCTION: AcpiDmIsTargetAnOperand 805274357Sjkim * 806274357Sjkim * PARAMETERS: Target - Target associated with the expression 807274357Sjkim * Operand - An operand associated with expression 808274357Sjkim * 809274357Sjkim * RETURN: TRUE if expression can be converted to a compound assignment. 810274357Sjkim * FALSE otherwise. 811274357Sjkim * 812274357Sjkim * DESCRIPTION: Determine if the Target duplicates the operand, in order to 813274357Sjkim * detect if the expression can be converted to a compound 814274357Sjkim * assigment. (+=, *=, etc.) 815274357Sjkim * 816274357Sjkim ******************************************************************************/ 817274357Sjkim 818274357Sjkimstatic BOOLEAN 819274357SjkimAcpiDmIsTargetAnOperand ( 820274357Sjkim ACPI_PARSE_OBJECT *Target, 821274357Sjkim ACPI_PARSE_OBJECT *Operand, 822274357Sjkim BOOLEAN TopLevel) 823274357Sjkim{ 824274357Sjkim const ACPI_OPCODE_INFO *OpInfo; 825274357Sjkim BOOLEAN Same; 826274357Sjkim 827274357Sjkim 828274357Sjkim /* 829274357Sjkim * Opcodes must match. Note: ignoring the difference between nameseg 830274357Sjkim * and namepath for now. May be needed later. 831274357Sjkim */ 832274357Sjkim if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode) 833274357Sjkim { 834274357Sjkim return (FALSE); 835274357Sjkim } 836274357Sjkim 837274357Sjkim /* Nodes should match, even if they are NULL */ 838274357Sjkim 839274357Sjkim if (Target->Common.Node != Operand->Common.Node) 840274357Sjkim { 841274357Sjkim return (FALSE); 842274357Sjkim } 843274357Sjkim 844274357Sjkim /* Determine if a child exists */ 845274357Sjkim 846274357Sjkim OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode); 847274357Sjkim if (OpInfo->Flags & AML_HAS_ARGS) 848274357Sjkim { 849274357Sjkim Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg, 850274357Sjkim Operand->Common.Value.Arg, FALSE); 851274357Sjkim if (!Same) 852274357Sjkim { 853274357Sjkim return (FALSE); 854274357Sjkim } 855274357Sjkim } 856274357Sjkim 857274357Sjkim /* Check the next peer, as long as we are not at the top level */ 858274357Sjkim 859274357Sjkim if ((!TopLevel) && 860274357Sjkim Target->Common.Next) 861274357Sjkim { 862274357Sjkim Same = AcpiDmIsTargetAnOperand (Target->Common.Next, 863274357Sjkim Operand->Common.Next, FALSE); 864274357Sjkim if (!Same) 865274357Sjkim { 866274357Sjkim return (FALSE); 867274357Sjkim } 868274357Sjkim } 869274357Sjkim 870274357Sjkim /* Supress the duplicate operand at the top-level */ 871274357Sjkim 872274357Sjkim if (TopLevel) 873274357Sjkim { 874274357Sjkim Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 875274357Sjkim } 876274357Sjkim return (TRUE); 877274357Sjkim} 878