167754Smsmith 267754Smsmith/****************************************************************************** 367754Smsmith * 477424Smsmith * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 567754Smsmith * 667754Smsmith *****************************************************************************/ 767754Smsmith 8217365Sjkim/* 9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 1070243Smsmith * All rights reserved. 1167754Smsmith * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 2667754Smsmith * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 3067754Smsmith * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 4467754Smsmith 4577424Smsmith#define __EXMISC_C__ 4667754Smsmith 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 50193341Sjkim#include <contrib/dev/acpica/include/amlcode.h> 51193341Sjkim#include <contrib/dev/acpica/include/amlresrc.h> 5267754Smsmith 5367754Smsmith 5477424Smsmith#define _COMPONENT ACPI_EXECUTER 5591116Smsmith ACPI_MODULE_NAME ("exmisc") 5667754Smsmith 5767754Smsmith 5867754Smsmith/******************************************************************************* 5967754Smsmith * 6085756Smsmith * FUNCTION: AcpiExGetObjectReference 6167754Smsmith * 62100966Siwasaki * PARAMETERS: ObjDesc - Create a reference to this object 63100966Siwasaki * ReturnDesc - Where to store the reference 64100966Siwasaki * WalkState - Current state 6567754Smsmith * 6667754Smsmith * RETURN: Status 6767754Smsmith * 6885756Smsmith * DESCRIPTION: Obtain and return a "reference" to the target object 6985756Smsmith * Common code for the RefOfOp and the CondRefOfOp. 7067754Smsmith * 7167754Smsmith ******************************************************************************/ 7267754Smsmith 7367754SmsmithACPI_STATUS 7485756SmsmithAcpiExGetObjectReference ( 7585756Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 7685756Smsmith ACPI_OPERAND_OBJECT **ReturnDesc, 7784491Smsmith ACPI_WALK_STATE *WalkState) 7867754Smsmith{ 79100966Siwasaki ACPI_OPERAND_OBJECT *ReferenceObj; 80100966Siwasaki ACPI_OPERAND_OBJECT *ReferencedObj; 8167754Smsmith 8267754Smsmith 83167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc); 8467754Smsmith 8580062Smsmith 86100966Siwasaki *ReturnDesc = NULL; 87100966Siwasaki 8891116Smsmith switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) 8985756Smsmith { 9099679Siwasaki case ACPI_DESC_TYPE_OPERAND: 9191116Smsmith 92193267Sjkim if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) 9385756Smsmith { 94100966Siwasaki return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 9585756Smsmith } 9667754Smsmith 9785756Smsmith /* 98100966Siwasaki * Must be a reference to a Local or Arg 9985756Smsmith */ 100193267Sjkim switch (ObjDesc->Reference.Class) 10185756Smsmith { 102193267Sjkim case ACPI_REFCLASS_LOCAL: 103193267Sjkim case ACPI_REFCLASS_ARG: 104193267Sjkim case ACPI_REFCLASS_DEBUG: 10567754Smsmith 106100966Siwasaki /* The referenced object is the pseudo-node for the local/arg */ 107100966Siwasaki 108100966Siwasaki ReferencedObj = ObjDesc->Reference.Object; 10985756Smsmith break; 11085756Smsmith 11185756Smsmith default: 11285756Smsmith 113204773Sjkim ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", 114193267Sjkim ObjDesc->Reference.Class)); 115100966Siwasaki return_ACPI_STATUS (AE_AML_INTERNAL); 11685756Smsmith } 11791116Smsmith break; 11885756Smsmith 11985756Smsmith 12091116Smsmith case ACPI_DESC_TYPE_NAMED: 12191116Smsmith 122102550Siwasaki /* 123100966Siwasaki * A named reference that has already been resolved to a Node 124100966Siwasaki */ 125100966Siwasaki ReferencedObj = ObjDesc; 12691116Smsmith break; 12767754Smsmith 12891116Smsmith 12991116Smsmith default: 13091116Smsmith 131204773Sjkim ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X", 132167802Sjkim ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))); 133100966Siwasaki return_ACPI_STATUS (AE_TYPE); 13485756Smsmith } 13567754Smsmith 13667754Smsmith 137100966Siwasaki /* Create a new reference object */ 13880062Smsmith 139107325Siwasaki ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 140100966Siwasaki if (!ReferenceObj) 141100966Siwasaki { 142100966Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 143100966Siwasaki } 144100966Siwasaki 145193267Sjkim ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF; 146100966Siwasaki ReferenceObj->Reference.Object = ReferencedObj; 147100966Siwasaki *ReturnDesc = ReferenceObj; 148100966Siwasaki 149151937Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 150151937Sjkim "Object %p Type [%s], returning Reference %p\n", 151151937Sjkim ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc)); 152100966Siwasaki 153100966Siwasaki return_ACPI_STATUS (AE_OK); 15485756Smsmith} 15580062Smsmith 15680062Smsmith 15785756Smsmith/******************************************************************************* 15885756Smsmith * 15991116Smsmith * FUNCTION: AcpiExConcatTemplate 16085756Smsmith * 161138287Smarks * PARAMETERS: Operand0 - First source object 162138287Smarks * Operand1 - Second source object 163138287Smarks * ActualReturnDesc - Where to place the return object 16485756Smsmith * WalkState - Current walk state 16585756Smsmith * 16685756Smsmith * RETURN: Status 16785756Smsmith * 16891116Smsmith * DESCRIPTION: Concatenate two resource templates 16991116Smsmith * 17091116Smsmith ******************************************************************************/ 17191116Smsmith 17291116SmsmithACPI_STATUS 17391116SmsmithAcpiExConcatTemplate ( 174138287Smarks ACPI_OPERAND_OBJECT *Operand0, 175138287Smarks ACPI_OPERAND_OBJECT *Operand1, 17691116Smsmith ACPI_OPERAND_OBJECT **ActualReturnDesc, 17791116Smsmith ACPI_WALK_STATE *WalkState) 17891116Smsmith{ 179167802Sjkim ACPI_STATUS Status; 18091116Smsmith ACPI_OPERAND_OBJECT *ReturnDesc; 181107325Siwasaki UINT8 *NewBuf; 182167802Sjkim UINT8 *EndTag; 183167802Sjkim ACPI_SIZE Length0; 18491116Smsmith ACPI_SIZE Length1; 185167802Sjkim ACPI_SIZE NewLength; 18691116Smsmith 18791116Smsmith 188167802Sjkim ACPI_FUNCTION_TRACE (ExConcatTemplate); 18991116Smsmith 19091116Smsmith 191167802Sjkim /* 192167802Sjkim * Find the EndTag descriptor in each resource template. 193167802Sjkim * Note1: returned pointers point TO the EndTag, not past it. 194167802Sjkim * Note2: zero-length buffers are allowed; treated like one EndTag 195167802Sjkim */ 19691116Smsmith 197167802Sjkim /* Get the length of the first resource template */ 198167802Sjkim 199167802Sjkim Status = AcpiUtGetResourceEndTag (Operand0, &EndTag); 200167802Sjkim if (ACPI_FAILURE (Status)) 20191116Smsmith { 202167802Sjkim return_ACPI_STATUS (Status); 20391116Smsmith } 20491116Smsmith 205167802Sjkim Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer); 20691116Smsmith 207167802Sjkim /* Get the length of the second resource template */ 20891116Smsmith 209167802Sjkim Status = AcpiUtGetResourceEndTag (Operand1, &EndTag); 210167802Sjkim if (ACPI_FAILURE (Status)) 211167802Sjkim { 212167802Sjkim return_ACPI_STATUS (Status); 213167802Sjkim } 214107325Siwasaki 215167802Sjkim Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer); 216167802Sjkim 217167802Sjkim /* Combine both lengths, minimum size will be 2 for EndTag */ 218167802Sjkim 219167802Sjkim NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG); 220167802Sjkim 221167802Sjkim /* Create a new buffer object for the result (with one EndTag) */ 222167802Sjkim 223167802Sjkim ReturnDesc = AcpiUtCreateBufferObject (NewLength); 224107325Siwasaki if (!ReturnDesc) 22591116Smsmith { 226107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 22791116Smsmith } 22891116Smsmith 229167802Sjkim /* 230167802Sjkim * Copy the templates to the new buffer, 0 first, then 1 follows. One 231167802Sjkim * EndTag descriptor is copied from Operand1. 232167802Sjkim */ 233107325Siwasaki NewBuf = ReturnDesc->Buffer.Pointer; 234167802Sjkim ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0); 235167802Sjkim ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); 23691116Smsmith 237167802Sjkim /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ 23891116Smsmith 239167802Sjkim NewBuf[NewLength - 1] = 0; 240167802Sjkim NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; 24191116Smsmith 242167802Sjkim /* Return the completed resource template */ 24391116Smsmith 24491116Smsmith *ActualReturnDesc = ReturnDesc; 24591116Smsmith return_ACPI_STATUS (AE_OK); 24691116Smsmith} 24791116Smsmith 24891116Smsmith 24991116Smsmith/******************************************************************************* 25091116Smsmith * 25191116Smsmith * FUNCTION: AcpiExDoConcatenate 25291116Smsmith * 253138287Smarks * PARAMETERS: Operand0 - First source object 254138287Smarks * Operand1 - Second source object 25591116Smsmith * ActualReturnDesc - Where to place the return object 25691116Smsmith * WalkState - Current walk state 25791116Smsmith * 25891116Smsmith * RETURN: Status 25991116Smsmith * 26085756Smsmith * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 26185756Smsmith * 26285756Smsmith ******************************************************************************/ 26380062Smsmith 26485756SmsmithACPI_STATUS 26585756SmsmithAcpiExDoConcatenate ( 266138287Smarks ACPI_OPERAND_OBJECT *Operand0, 267138287Smarks ACPI_OPERAND_OBJECT *Operand1, 26885756Smsmith ACPI_OPERAND_OBJECT **ActualReturnDesc, 26985756Smsmith ACPI_WALK_STATE *WalkState) 27085756Smsmith{ 271138287Smarks ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 27285756Smsmith ACPI_OPERAND_OBJECT *ReturnDesc; 273114237Snjl char *NewBuf; 274138287Smarks ACPI_STATUS Status; 27580062Smsmith 27680062Smsmith 277167802Sjkim ACPI_FUNCTION_TRACE (ExDoConcatenate); 27880062Smsmith 27980062Smsmith 28085756Smsmith /* 281138287Smarks * Convert the second operand if necessary. The first operand 282138287Smarks * determines the type of the second operand, (See the Data Types 283138287Smarks * section of the ACPI specification.) Both object types are 284138287Smarks * guaranteed to be either Integer/String/Buffer by the operand 285138287Smarks * resolution mechanism. 286138287Smarks */ 287193267Sjkim switch (Operand0->Common.Type) 288138287Smarks { 289138287Smarks case ACPI_TYPE_INTEGER: 290138287Smarks Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 291138287Smarks break; 292138287Smarks 293138287Smarks case ACPI_TYPE_STRING: 294138287Smarks Status = AcpiExConvertToString (Operand1, &LocalOperand1, 295138287Smarks ACPI_IMPLICIT_CONVERT_HEX); 296138287Smarks break; 297138287Smarks 298138287Smarks case ACPI_TYPE_BUFFER: 299138287Smarks Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 300138287Smarks break; 301138287Smarks 302138287Smarks default: 303204773Sjkim ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 304193267Sjkim Operand0->Common.Type)); 305138287Smarks Status = AE_AML_INTERNAL; 306138287Smarks } 307138287Smarks 308138287Smarks if (ACPI_FAILURE (Status)) 309138287Smarks { 310138287Smarks goto Cleanup; 311138287Smarks } 312138287Smarks 313138287Smarks /* 314138287Smarks * Both operands are now known to be the same object type 315138287Smarks * (Both are Integer, String, or Buffer), and we can now perform the 316138287Smarks * concatenation. 317138287Smarks */ 318138287Smarks 319138287Smarks /* 32085756Smsmith * There are three cases to handle: 321102550Siwasaki * 32299679Siwasaki * 1) Two Integers concatenated to produce a new Buffer 32399679Siwasaki * 2) Two Strings concatenated to produce a new String 32499679Siwasaki * 3) Two Buffers concatenated to produce a new Buffer 32585756Smsmith */ 326193267Sjkim switch (Operand0->Common.Type) 32785756Smsmith { 32885756Smsmith case ACPI_TYPE_INTEGER: 32985756Smsmith 33099679Siwasaki /* Result of two Integers is a Buffer */ 331107325Siwasaki /* Need enough buffer space for two integers */ 33285756Smsmith 333151937Sjkim ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) 334138287Smarks ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); 33585756Smsmith if (!ReturnDesc) 33684491Smsmith { 337138287Smarks Status = AE_NO_MEMORY; 338138287Smarks goto Cleanup; 33985756Smsmith } 34084491Smsmith 341114237Snjl NewBuf = (char *) ReturnDesc->Buffer.Pointer; 34284491Smsmith 343138287Smarks /* Copy the first integer, LSB first */ 34484491Smsmith 345167802Sjkim ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, 346138287Smarks AcpiGbl_IntegerByteWidth); 34784491Smsmith 348138287Smarks /* Copy the second integer (LSB first) after the first */ 34984491Smsmith 350138287Smarks ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, 351138287Smarks &LocalOperand1->Integer.Value, 352138287Smarks AcpiGbl_IntegerByteWidth); 35380062Smsmith break; 35480062Smsmith 35585756Smsmith case ACPI_TYPE_STRING: 35680062Smsmith 35799679Siwasaki /* Result of two Strings is a String */ 35899679Siwasaki 359193267Sjkim ReturnDesc = AcpiUtCreateStringObject ( 360193267Sjkim ((ACPI_SIZE) Operand0->String.Length + 361167802Sjkim LocalOperand1->String.Length)); 362138287Smarks if (!ReturnDesc) 36380062Smsmith { 36480062Smsmith Status = AE_NO_MEMORY; 36567754Smsmith goto Cleanup; 36667754Smsmith } 36783174Smsmith 368138287Smarks NewBuf = ReturnDesc->String.Pointer; 369138287Smarks 37099679Siwasaki /* Concatenate the strings */ 37199679Siwasaki 372167802Sjkim ACPI_STRCPY (NewBuf, Operand0->String.Pointer); 373138287Smarks ACPI_STRCPY (NewBuf + Operand0->String.Length, 374138287Smarks LocalOperand1->String.Pointer); 37585756Smsmith break; 37680062Smsmith 37785756Smsmith case ACPI_TYPE_BUFFER: 37880062Smsmith 37999679Siwasaki /* Result of two Buffers is a Buffer */ 38085756Smsmith 381193267Sjkim ReturnDesc = AcpiUtCreateBufferObject ( 382193267Sjkim ((ACPI_SIZE) Operand0->Buffer.Length + 383167802Sjkim LocalOperand1->Buffer.Length)); 38485756Smsmith if (!ReturnDesc) 38585756Smsmith { 386138287Smarks Status = AE_NO_MEMORY; 387138287Smarks goto Cleanup; 38867754Smsmith } 38967754Smsmith 390114237Snjl NewBuf = (char *) ReturnDesc->Buffer.Pointer; 39167754Smsmith 39299679Siwasaki /* Concatenate the buffers */ 39399679Siwasaki 394167802Sjkim ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, 395138287Smarks Operand0->Buffer.Length); 396138287Smarks ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, 397138287Smarks LocalOperand1->Buffer.Pointer, 398138287Smarks LocalOperand1->Buffer.Length); 39980062Smsmith break; 40067754Smsmith 40185756Smsmith default: 40299679Siwasaki 40399679Siwasaki /* Invalid object type, should not happen here */ 40499679Siwasaki 405204773Sjkim ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 406193267Sjkim Operand0->Common.Type)); 407138287Smarks Status =AE_AML_INTERNAL; 408138287Smarks goto Cleanup; 40985756Smsmith } 41067754Smsmith 41185756Smsmith *ActualReturnDesc = ReturnDesc; 41267754Smsmith 41385756SmsmithCleanup: 414138287Smarks if (LocalOperand1 != Operand1) 415138287Smarks { 416138287Smarks AcpiUtRemoveReference (LocalOperand1); 417138287Smarks } 418151937Sjkim return_ACPI_STATUS (Status); 41967754Smsmith} 42067754Smsmith 42167754Smsmith 42267754Smsmith/******************************************************************************* 42367754Smsmith * 42485756Smsmith * FUNCTION: AcpiExDoMathOp 42567754Smsmith * 42685756Smsmith * PARAMETERS: Opcode - AML opcode 427138287Smarks * Integer0 - Integer operand #0 428138287Smarks * Integer1 - Integer operand #1 42967754Smsmith * 43085756Smsmith * RETURN: Integer result of the operation 43167754Smsmith * 43285756Smsmith * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 43385756Smsmith * math functions here is to prevent a lot of pointer dereferencing 43485756Smsmith * to obtain the operands. 43567754Smsmith * 43667754Smsmith ******************************************************************************/ 43767754Smsmith 438202771SjkimUINT64 43985756SmsmithAcpiExDoMathOp ( 44085756Smsmith UINT16 Opcode, 441202771Sjkim UINT64 Integer0, 442202771Sjkim UINT64 Integer1) 44367754Smsmith{ 44467754Smsmith 445138287Smarks ACPI_FUNCTION_ENTRY (); 44667754Smsmith 447138287Smarks 44885756Smsmith switch (Opcode) 44967754Smsmith { 450138287Smarks case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 45167754Smsmith 452138287Smarks return (Integer0 + Integer1); 45367754Smsmith 45467754Smsmith 455138287Smarks case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 45667754Smsmith 457138287Smarks return (Integer0 & Integer1); 45867754Smsmith 45980062Smsmith 460138287Smarks case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 46167754Smsmith 462138287Smarks return (~(Integer0 & Integer1)); 46367754Smsmith 46467754Smsmith 465138287Smarks case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 46667754Smsmith 467138287Smarks return (Integer0 | Integer1); 46867754Smsmith 46967754Smsmith 470138287Smarks case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 47167754Smsmith 472138287Smarks return (~(Integer0 | Integer1)); 47367754Smsmith 47467754Smsmith 475138287Smarks case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 47667754Smsmith 477138287Smarks return (Integer0 ^ Integer1); 47867754Smsmith 47967754Smsmith 480138287Smarks case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 48167754Smsmith 482138287Smarks return (Integer0 * Integer1); 48367754Smsmith 48467754Smsmith 485151937Sjkim case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/ 48667754Smsmith 487167802Sjkim /* 488167802Sjkim * We need to check if the shiftcount is larger than the integer bit 489167802Sjkim * width since the behavior of this is not well-defined in the C language. 490167802Sjkim */ 491167802Sjkim if (Integer1 >= AcpiGbl_IntegerBitWidth) 492167802Sjkim { 493167802Sjkim return (0); 494167802Sjkim } 495138287Smarks return (Integer0 << Integer1); 49667754Smsmith 49780062Smsmith 49885756Smsmith case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */ 49980062Smsmith 500167802Sjkim /* 501167802Sjkim * We need to check if the shiftcount is larger than the integer bit 502167802Sjkim * width since the behavior of this is not well-defined in the C language. 503167802Sjkim */ 504167802Sjkim if (Integer1 >= AcpiGbl_IntegerBitWidth) 505167802Sjkim { 506167802Sjkim return (0); 507167802Sjkim } 508138287Smarks return (Integer0 >> Integer1); 50980062Smsmith 51080062Smsmith 511138287Smarks case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 51267754Smsmith 513138287Smarks return (Integer0 - Integer1); 51467754Smsmith 51585756Smsmith default: 51667754Smsmith 51785756Smsmith return (0); 51885756Smsmith } 51985756Smsmith} 52067754Smsmith 52167754Smsmith 52285756Smsmith/******************************************************************************* 52385756Smsmith * 524138287Smarks * FUNCTION: AcpiExDoLogicalNumericOp 525138287Smarks * 526138287Smarks * PARAMETERS: Opcode - AML opcode 527138287Smarks * Integer0 - Integer operand #0 528138287Smarks * Integer1 - Integer operand #1 529138287Smarks * LogicalResult - TRUE/FALSE result of the operation 530138287Smarks * 531138287Smarks * RETURN: Status 532138287Smarks * 533138287Smarks * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 534138287Smarks * operators (LAnd and LOr), both operands must be integers. 535138287Smarks * 536138287Smarks * Note: cleanest machine code seems to be produced by the code 537138287Smarks * below, rather than using statements of the form: 538138287Smarks * Result = (Integer0 && Integer1); 539138287Smarks * 540138287Smarks ******************************************************************************/ 541138287Smarks 542138287SmarksACPI_STATUS 543138287SmarksAcpiExDoLogicalNumericOp ( 544138287Smarks UINT16 Opcode, 545202771Sjkim UINT64 Integer0, 546202771Sjkim UINT64 Integer1, 547138287Smarks BOOLEAN *LogicalResult) 548138287Smarks{ 549138287Smarks ACPI_STATUS Status = AE_OK; 550138287Smarks BOOLEAN LocalResult = FALSE; 551138287Smarks 552138287Smarks 553167802Sjkim ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp); 554138287Smarks 555138287Smarks 556138287Smarks switch (Opcode) 557138287Smarks { 558138287Smarks case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 559138287Smarks 560138287Smarks if (Integer0 && Integer1) 561138287Smarks { 562138287Smarks LocalResult = TRUE; 563138287Smarks } 564138287Smarks break; 565138287Smarks 566138287Smarks case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 567138287Smarks 568138287Smarks if (Integer0 || Integer1) 569138287Smarks { 570138287Smarks LocalResult = TRUE; 571138287Smarks } 572138287Smarks break; 573138287Smarks 574138287Smarks default: 575138287Smarks Status = AE_AML_INTERNAL; 576138287Smarks break; 577138287Smarks } 578138287Smarks 579138287Smarks /* Return the logical result and status */ 580138287Smarks 581138287Smarks *LogicalResult = LocalResult; 582138287Smarks return_ACPI_STATUS (Status); 583138287Smarks} 584138287Smarks 585138287Smarks 586138287Smarks/******************************************************************************* 587138287Smarks * 58885756Smsmith * FUNCTION: AcpiExDoLogicalOp 58985756Smsmith * 59085756Smsmith * PARAMETERS: Opcode - AML opcode 591138287Smarks * Operand0 - operand #0 592138287Smarks * Operand1 - operand #1 593138287Smarks * LogicalResult - TRUE/FALSE result of the operation 59485756Smsmith * 595138287Smarks * RETURN: Status 59685756Smsmith * 59785756Smsmith * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 59885756Smsmith * functions here is to prevent a lot of pointer dereferencing 59985756Smsmith * to obtain the operands and to simplify the generation of the 600138287Smarks * logical value. For the Numeric operators (LAnd and LOr), both 601138287Smarks * operands must be integers. For the other logical operators, 602138287Smarks * operands can be any combination of Integer/String/Buffer. The 603138287Smarks * first operand determines the type to which the second operand 604138287Smarks * will be converted. 60585756Smsmith * 60685756Smsmith * Note: cleanest machine code seems to be produced by the code 60785756Smsmith * below, rather than using statements of the form: 60885756Smsmith * Result = (Operand0 == Operand1); 60985756Smsmith * 61085756Smsmith ******************************************************************************/ 61167754Smsmith 612138287SmarksACPI_STATUS 61385756SmsmithAcpiExDoLogicalOp ( 61485756Smsmith UINT16 Opcode, 615138287Smarks ACPI_OPERAND_OBJECT *Operand0, 616138287Smarks ACPI_OPERAND_OBJECT *Operand1, 617138287Smarks BOOLEAN *LogicalResult) 61885756Smsmith{ 619138287Smarks ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 620202771Sjkim UINT64 Integer0; 621202771Sjkim UINT64 Integer1; 622138287Smarks UINT32 Length0; 623138287Smarks UINT32 Length1; 624138287Smarks ACPI_STATUS Status = AE_OK; 625138287Smarks BOOLEAN LocalResult = FALSE; 626138287Smarks int Compare; 62767754Smsmith 62867754Smsmith 629167802Sjkim ACPI_FUNCTION_TRACE (ExDoLogicalOp); 630138287Smarks 631138287Smarks 632138287Smarks /* 633138287Smarks * Convert the second operand if necessary. The first operand 634138287Smarks * determines the type of the second operand, (See the Data Types 635138287Smarks * section of the ACPI 3.0+ specification.) Both object types are 636138287Smarks * guaranteed to be either Integer/String/Buffer by the operand 637138287Smarks * resolution mechanism. 638138287Smarks */ 639193267Sjkim switch (Operand0->Common.Type) 64085756Smsmith { 641138287Smarks case ACPI_TYPE_INTEGER: 642138287Smarks Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 643138287Smarks break; 64467754Smsmith 645138287Smarks case ACPI_TYPE_STRING: 646138287Smarks Status = AcpiExConvertToString (Operand1, &LocalOperand1, 647138287Smarks ACPI_IMPLICIT_CONVERT_HEX); 648138287Smarks break; 64967754Smsmith 650138287Smarks case ACPI_TYPE_BUFFER: 651138287Smarks Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 65285756Smsmith break; 65367754Smsmith 654138287Smarks default: 655138287Smarks Status = AE_AML_INTERNAL; 656138287Smarks break; 657138287Smarks } 65867754Smsmith 659138287Smarks if (ACPI_FAILURE (Status)) 660138287Smarks { 661138287Smarks goto Cleanup; 662138287Smarks } 66367754Smsmith 664138287Smarks /* 665138287Smarks * Two cases: 1) Both Integers, 2) Both Strings or Buffers 666138287Smarks */ 667193267Sjkim if (Operand0->Common.Type == ACPI_TYPE_INTEGER) 668138287Smarks { 669138287Smarks /* 670138287Smarks * 1) Both operands are of type integer 671138287Smarks * Note: LocalOperand1 may have changed above 672138287Smarks */ 673138287Smarks Integer0 = Operand0->Integer.Value; 674138287Smarks Integer1 = LocalOperand1->Integer.Value; 675138287Smarks 676138287Smarks switch (Opcode) 67785756Smsmith { 678138287Smarks case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 67967754Smsmith 680138287Smarks if (Integer0 == Integer1) 681138287Smarks { 682138287Smarks LocalResult = TRUE; 683138287Smarks } 684138287Smarks break; 68567754Smsmith 686138287Smarks case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 68767754Smsmith 688138287Smarks if (Integer0 > Integer1) 689138287Smarks { 690138287Smarks LocalResult = TRUE; 691138287Smarks } 692138287Smarks break; 693138287Smarks 694138287Smarks case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 695138287Smarks 696138287Smarks if (Integer0 < Integer1) 697138287Smarks { 698138287Smarks LocalResult = TRUE; 699138287Smarks } 700138287Smarks break; 701138287Smarks 702138287Smarks default: 703138287Smarks Status = AE_AML_INTERNAL; 704138287Smarks break; 70585756Smsmith } 706138287Smarks } 707138287Smarks else 708138287Smarks { 709138287Smarks /* 710138287Smarks * 2) Both operands are Strings or both are Buffers 711138287Smarks * Note: Code below takes advantage of common Buffer/String 712138287Smarks * object fields. LocalOperand1 may have changed above. Use 713138287Smarks * memcmp to handle nulls in buffers. 714138287Smarks */ 715138287Smarks Length0 = Operand0->Buffer.Length; 716138287Smarks Length1 = LocalOperand1->Buffer.Length; 71767754Smsmith 718138287Smarks /* Lexicographic compare: compare the data bytes */ 71967754Smsmith 720151937Sjkim Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer, 721151937Sjkim LocalOperand1->Buffer.Pointer, 722138287Smarks (Length0 > Length1) ? Length1 : Length0); 72367754Smsmith 724138287Smarks switch (Opcode) 72585756Smsmith { 726138287Smarks case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 72767754Smsmith 728138287Smarks /* Length and all bytes must be equal */ 72967754Smsmith 730138287Smarks if ((Length0 == Length1) && 731138287Smarks (Compare == 0)) 732138287Smarks { 733138287Smarks /* Length and all bytes match ==> TRUE */ 73467754Smsmith 735138287Smarks LocalResult = TRUE; 736138287Smarks } 737138287Smarks break; 738138287Smarks 739138287Smarks case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 740138287Smarks 741138287Smarks if (Compare > 0) 742138287Smarks { 743138287Smarks LocalResult = TRUE; 744138287Smarks goto Cleanup; /* TRUE */ 745138287Smarks } 746138287Smarks if (Compare < 0) 747138287Smarks { 748138287Smarks goto Cleanup; /* FALSE */ 749138287Smarks } 750138287Smarks 751138287Smarks /* Bytes match (to shortest length), compare lengths */ 752138287Smarks 753138287Smarks if (Length0 > Length1) 754138287Smarks { 755138287Smarks LocalResult = TRUE; 756138287Smarks } 757138287Smarks break; 758138287Smarks 759138287Smarks case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 760138287Smarks 761138287Smarks if (Compare > 0) 762138287Smarks { 763138287Smarks goto Cleanup; /* FALSE */ 764138287Smarks } 765138287Smarks if (Compare < 0) 766138287Smarks { 767138287Smarks LocalResult = TRUE; 768138287Smarks goto Cleanup; /* TRUE */ 769138287Smarks } 770138287Smarks 771138287Smarks /* Bytes match (to shortest length), compare lengths */ 772138287Smarks 773138287Smarks if (Length0 < Length1) 774138287Smarks { 775138287Smarks LocalResult = TRUE; 776138287Smarks } 777138287Smarks break; 778138287Smarks 779138287Smarks default: 780138287Smarks Status = AE_AML_INTERNAL; 781138287Smarks break; 78267754Smsmith } 783138287Smarks } 78499679Siwasaki 785138287SmarksCleanup: 786138287Smarks 787138287Smarks /* New object was created if implicit conversion performed - delete */ 788138287Smarks 789138287Smarks if (LocalOperand1 != Operand1) 790138287Smarks { 791138287Smarks AcpiUtRemoveReference (LocalOperand1); 79267754Smsmith } 79367754Smsmith 794138287Smarks /* Return the logical result and status */ 795138287Smarks 796138287Smarks *LogicalResult = LocalResult; 797138287Smarks return_ACPI_STATUS (Status); 79885756Smsmith} 79967754Smsmith 80067754Smsmith 801