162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acinterp.h" 1362306a36Sopenharmony_ci#include "amlcode.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define _COMPONENT ACPI_EXECUTER 1662306a36Sopenharmony_ciACPI_MODULE_NAME("exmisc") 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/******************************************************************************* 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * FUNCTION: acpi_ex_get_object_reference 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * PARAMETERS: obj_desc - Create a reference to this object 2362306a36Sopenharmony_ci * return_desc - Where to store the reference 2462306a36Sopenharmony_ci * walk_state - Current state 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * RETURN: Status 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * DESCRIPTION: Obtain and return a "reference" to the target object 2962306a36Sopenharmony_ci * Common code for the ref_of_op and the cond_ref_of_op. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci ******************************************************************************/ 3262306a36Sopenharmony_ciacpi_status 3362306a36Sopenharmony_ciacpi_ex_get_object_reference(union acpi_operand_object *obj_desc, 3462306a36Sopenharmony_ci union acpi_operand_object **return_desc, 3562306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci union acpi_operand_object *reference_obj; 3862306a36Sopenharmony_ci union acpi_operand_object *referenced_obj; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci *return_desc = NULL; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { 4562306a36Sopenharmony_ci case ACPI_DESC_TYPE_OPERAND: 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) { 4862306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* 5262306a36Sopenharmony_ci * Must be a reference to a Local or Arg 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_ci switch (obj_desc->reference.class) { 5562306a36Sopenharmony_ci case ACPI_REFCLASS_LOCAL: 5662306a36Sopenharmony_ci case ACPI_REFCLASS_ARG: 5762306a36Sopenharmony_ci case ACPI_REFCLASS_DEBUG: 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* The referenced object is the pseudo-node for the local/arg */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci referenced_obj = obj_desc->reference.object; 6262306a36Sopenharmony_ci break; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci default: 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X", 6762306a36Sopenharmony_ci obj_desc->reference.class)); 6862306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci break; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci case ACPI_DESC_TYPE_NAMED: 7362306a36Sopenharmony_ci /* 7462306a36Sopenharmony_ci * A named reference that has already been resolved to a Node 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci referenced_obj = obj_desc; 7762306a36Sopenharmony_ci break; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci default: 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Invalid descriptor type 0x%X", 8262306a36Sopenharmony_ci ACPI_GET_DESCRIPTOR_TYPE(obj_desc))); 8362306a36Sopenharmony_ci return_ACPI_STATUS(AE_TYPE); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* Create a new reference object */ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci reference_obj = 8962306a36Sopenharmony_ci acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); 9062306a36Sopenharmony_ci if (!reference_obj) { 9162306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci reference_obj->reference.class = ACPI_REFCLASS_REFOF; 9562306a36Sopenharmony_ci reference_obj->reference.object = referenced_obj; 9662306a36Sopenharmony_ci *return_desc = reference_obj; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 9962306a36Sopenharmony_ci "Object %p Type [%s], returning Reference %p\n", 10062306a36Sopenharmony_ci obj_desc, acpi_ut_get_object_type_name(obj_desc), 10162306a36Sopenharmony_ci *return_desc)); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/******************************************************************************* 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * FUNCTION: acpi_ex_do_math_op 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * PARAMETERS: opcode - AML opcode 11162306a36Sopenharmony_ci * integer0 - Integer operand #0 11262306a36Sopenharmony_ci * integer1 - Integer operand #1 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * RETURN: Integer result of the operation 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 11762306a36Sopenharmony_ci * math functions here is to prevent a lot of pointer dereferencing 11862306a36Sopenharmony_ci * to obtain the operands. 11962306a36Sopenharmony_ci * 12062306a36Sopenharmony_ci ******************************************************************************/ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciu64 acpi_ex_do_math_op(u16 opcode, u64 integer0, u64 integer1) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci ACPI_FUNCTION_ENTRY(); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci switch (opcode) { 12862306a36Sopenharmony_ci case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return (integer0 + integer1); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return (integer0 & integer1); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return (~(integer0 & integer1)); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return (integer0 | integer1); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci return (~(integer0 | integer1)); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return (integer0 ^ integer1); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return (integer0 * integer1); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * We need to check if the shiftcount is larger than the integer bit 16062306a36Sopenharmony_ci * width since the behavior of this is not well-defined in the C language. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_ci if (integer1 >= acpi_gbl_integer_bit_width) { 16362306a36Sopenharmony_ci return (0); 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci return (integer0 << integer1); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* 17062306a36Sopenharmony_ci * We need to check if the shiftcount is larger than the integer bit 17162306a36Sopenharmony_ci * width since the behavior of this is not well-defined in the C language. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ci if (integer1 >= acpi_gbl_integer_bit_width) { 17462306a36Sopenharmony_ci return (0); 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci return (integer0 >> integer1); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return (integer0 - integer1); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci default: 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return (0); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/******************************************************************************* 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * FUNCTION: acpi_ex_do_logical_numeric_op 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * PARAMETERS: opcode - AML opcode 19362306a36Sopenharmony_ci * integer0 - Integer operand #0 19462306a36Sopenharmony_ci * integer1 - Integer operand #1 19562306a36Sopenharmony_ci * logical_result - TRUE/FALSE result of the operation 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * RETURN: Status 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 20062306a36Sopenharmony_ci * operators (LAnd and LOr), both operands must be integers. 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * Note: cleanest machine code seems to be produced by the code 20362306a36Sopenharmony_ci * below, rather than using statements of the form: 20462306a36Sopenharmony_ci * Result = (Integer0 && Integer1); 20562306a36Sopenharmony_ci * 20662306a36Sopenharmony_ci ******************************************************************************/ 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ciacpi_status 20962306a36Sopenharmony_ciacpi_ex_do_logical_numeric_op(u16 opcode, 21062306a36Sopenharmony_ci u64 integer0, u64 integer1, u8 *logical_result) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci acpi_status status = AE_OK; 21362306a36Sopenharmony_ci u8 local_result = FALSE; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci switch (opcode) { 21862306a36Sopenharmony_ci case AML_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (integer0 && integer1) { 22162306a36Sopenharmony_ci local_result = TRUE; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (integer0 || integer1) { 22862306a36Sopenharmony_ci local_result = TRUE; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci break; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci default: 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 23562306a36Sopenharmony_ci "Invalid numeric logical opcode: %X", opcode)); 23662306a36Sopenharmony_ci status = AE_AML_INTERNAL; 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Return the logical result and status */ 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci *logical_result = local_result; 24362306a36Sopenharmony_ci return_ACPI_STATUS(status); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/******************************************************************************* 24762306a36Sopenharmony_ci * 24862306a36Sopenharmony_ci * FUNCTION: acpi_ex_do_logical_op 24962306a36Sopenharmony_ci * 25062306a36Sopenharmony_ci * PARAMETERS: opcode - AML opcode 25162306a36Sopenharmony_ci * operand0 - operand #0 25262306a36Sopenharmony_ci * operand1 - operand #1 25362306a36Sopenharmony_ci * logical_result - TRUE/FALSE result of the operation 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * RETURN: Status 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 25862306a36Sopenharmony_ci * functions here is to prevent a lot of pointer dereferencing 25962306a36Sopenharmony_ci * to obtain the operands and to simplify the generation of the 26062306a36Sopenharmony_ci * logical value. For the Numeric operators (LAnd and LOr), both 26162306a36Sopenharmony_ci * operands must be integers. For the other logical operators, 26262306a36Sopenharmony_ci * operands can be any combination of Integer/String/Buffer. The 26362306a36Sopenharmony_ci * first operand determines the type to which the second operand 26462306a36Sopenharmony_ci * will be converted. 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * Note: cleanest machine code seems to be produced by the code 26762306a36Sopenharmony_ci * below, rather than using statements of the form: 26862306a36Sopenharmony_ci * Result = (Operand0 == Operand1); 26962306a36Sopenharmony_ci * 27062306a36Sopenharmony_ci ******************************************************************************/ 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ciacpi_status 27362306a36Sopenharmony_ciacpi_ex_do_logical_op(u16 opcode, 27462306a36Sopenharmony_ci union acpi_operand_object *operand0, 27562306a36Sopenharmony_ci union acpi_operand_object *operand1, u8 * logical_result) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci union acpi_operand_object *local_operand1 = operand1; 27862306a36Sopenharmony_ci u64 integer0; 27962306a36Sopenharmony_ci u64 integer1; 28062306a36Sopenharmony_ci u32 length0; 28162306a36Sopenharmony_ci u32 length1; 28262306a36Sopenharmony_ci acpi_status status = AE_OK; 28362306a36Sopenharmony_ci u8 local_result = FALSE; 28462306a36Sopenharmony_ci int compare; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ex_do_logical_op); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* 28962306a36Sopenharmony_ci * Convert the second operand if necessary. The first operand 29062306a36Sopenharmony_ci * determines the type of the second operand, (See the Data Types 29162306a36Sopenharmony_ci * section of the ACPI 3.0+ specification.) Both object types are 29262306a36Sopenharmony_ci * guaranteed to be either Integer/String/Buffer by the operand 29362306a36Sopenharmony_ci * resolution mechanism. 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci switch (operand0->common.type) { 29662306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci status = acpi_ex_convert_to_integer(operand1, &local_operand1, 29962306a36Sopenharmony_ci ACPI_IMPLICIT_CONVERSION); 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci case ACPI_TYPE_STRING: 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci status = 30562306a36Sopenharmony_ci acpi_ex_convert_to_string(operand1, &local_operand1, 30662306a36Sopenharmony_ci ACPI_IMPLICIT_CONVERT_HEX); 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci status = acpi_ex_convert_to_buffer(operand1, &local_operand1); 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci default: 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 31762306a36Sopenharmony_ci "Invalid object type for logical operator: %X", 31862306a36Sopenharmony_ci operand0->common.type)); 31962306a36Sopenharmony_ci status = AE_AML_INTERNAL; 32062306a36Sopenharmony_ci break; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 32462306a36Sopenharmony_ci goto cleanup; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* 32862306a36Sopenharmony_ci * Two cases: 1) Both Integers, 2) Both Strings or Buffers 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci if (operand0->common.type == ACPI_TYPE_INTEGER) { 33162306a36Sopenharmony_ci /* 33262306a36Sopenharmony_ci * 1) Both operands are of type integer 33362306a36Sopenharmony_ci * Note: local_operand1 may have changed above 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci integer0 = operand0->integer.value; 33662306a36Sopenharmony_ci integer1 = local_operand1->integer.value; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci switch (opcode) { 33962306a36Sopenharmony_ci case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */ 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (integer0 == integer1) { 34262306a36Sopenharmony_ci local_result = TRUE; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */ 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if (integer0 > integer1) { 34962306a36Sopenharmony_ci local_result = TRUE; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */ 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (integer0 < integer1) { 35662306a36Sopenharmony_ci local_result = TRUE; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci break; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci default: 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 36362306a36Sopenharmony_ci "Invalid comparison opcode: %X", opcode)); 36462306a36Sopenharmony_ci status = AE_AML_INTERNAL; 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci } else { 36862306a36Sopenharmony_ci /* 36962306a36Sopenharmony_ci * 2) Both operands are Strings or both are Buffers 37062306a36Sopenharmony_ci * Note: Code below takes advantage of common Buffer/String 37162306a36Sopenharmony_ci * object fields. local_operand1 may have changed above. Use 37262306a36Sopenharmony_ci * memcmp to handle nulls in buffers. 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ci length0 = operand0->buffer.length; 37562306a36Sopenharmony_ci length1 = local_operand1->buffer.length; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Lexicographic compare: compare the data bytes */ 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci compare = memcmp(operand0->buffer.pointer, 38062306a36Sopenharmony_ci local_operand1->buffer.pointer, 38162306a36Sopenharmony_ci (length0 > length1) ? length1 : length0); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci switch (opcode) { 38462306a36Sopenharmony_ci case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */ 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* Length and all bytes must be equal */ 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if ((length0 == length1) && (compare == 0)) { 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* Length and all bytes match ==> TRUE */ 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci local_result = TRUE; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */ 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (compare > 0) { 39962306a36Sopenharmony_ci local_result = TRUE; 40062306a36Sopenharmony_ci goto cleanup; /* TRUE */ 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci if (compare < 0) { 40362306a36Sopenharmony_ci goto cleanup; /* FALSE */ 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* Bytes match (to shortest length), compare lengths */ 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (length0 > length1) { 40962306a36Sopenharmony_ci local_result = TRUE; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci break; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */ 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci if (compare > 0) { 41662306a36Sopenharmony_ci goto cleanup; /* FALSE */ 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci if (compare < 0) { 41962306a36Sopenharmony_ci local_result = TRUE; 42062306a36Sopenharmony_ci goto cleanup; /* TRUE */ 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* Bytes match (to shortest length), compare lengths */ 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (length0 < length1) { 42662306a36Sopenharmony_ci local_result = TRUE; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci default: 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 43362306a36Sopenharmony_ci "Invalid comparison opcode: %X", opcode)); 43462306a36Sopenharmony_ci status = AE_AML_INTERNAL; 43562306a36Sopenharmony_ci break; 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cicleanup: 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci /* New object was created if implicit conversion performed - delete */ 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (local_operand1 != operand1) { 44462306a36Sopenharmony_ci acpi_ut_remove_reference(local_operand1); 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* Return the logical result and status */ 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci *logical_result = local_result; 45062306a36Sopenharmony_ci return_ACPI_STATUS(status); 45162306a36Sopenharmony_ci} 452