1149703c7Sjruoho /******************************************************************************
2149703c7Sjruoho  *
3149703c7Sjruoho  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4149703c7Sjruoho  *
5149703c7Sjruoho  *****************************************************************************/
6149703c7Sjruoho 
768471b32Sjruoho /*
8*e5631441Schristos  * Copyright (C) 2000 - 2022, Intel Corp.
9149703c7Sjruoho  * All rights reserved.
10149703c7Sjruoho  *
1168471b32Sjruoho  * Redistribution and use in source and binary forms, with or without
1268471b32Sjruoho  * modification, are permitted provided that the following conditions
1368471b32Sjruoho  * are met:
1468471b32Sjruoho  * 1. Redistributions of source code must retain the above copyright
1568471b32Sjruoho  *    notice, this list of conditions, and the following disclaimer,
1668471b32Sjruoho  *    without modification.
1768471b32Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1868471b32Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
1968471b32Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
2068471b32Sjruoho  *    including a substantially similar Disclaimer requirement for further
2168471b32Sjruoho  *    binary redistribution.
2268471b32Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
2368471b32Sjruoho  *    of any contributors may be used to endorse or promote products derived
2468471b32Sjruoho  *    from this software without specific prior written permission.
25149703c7Sjruoho  *
2668471b32Sjruoho  * Alternatively, this software may be distributed under the terms of the
2768471b32Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
2868471b32Sjruoho  * Software Foundation.
29149703c7Sjruoho  *
3068471b32Sjruoho  * NO WARRANTY
3168471b32Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3268471b32Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33d4291bf2Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3468471b32Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3568471b32Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3668471b32Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3768471b32Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3868471b32Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3968471b32Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4068471b32Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4168471b32Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
4268471b32Sjruoho  */
43149703c7Sjruoho 
44149703c7Sjruoho #include "acpi.h"
45149703c7Sjruoho #include "accommon.h"
46149703c7Sjruoho #include "acinterp.h"
47149703c7Sjruoho #include "amlcode.h"
48149703c7Sjruoho 
49149703c7Sjruoho 
50149703c7Sjruoho #define _COMPONENT          ACPI_EXECUTER
51149703c7Sjruoho         ACPI_MODULE_NAME    ("exmisc")
52149703c7Sjruoho 
53149703c7Sjruoho 
54149703c7Sjruoho /*******************************************************************************
55149703c7Sjruoho  *
56149703c7Sjruoho  * FUNCTION:    AcpiExGetObjectReference
57149703c7Sjruoho  *
58149703c7Sjruoho  * PARAMETERS:  ObjDesc             - Create a reference to this object
59149703c7Sjruoho  *              ReturnDesc          - Where to store the reference
60149703c7Sjruoho  *              WalkState           - Current state
61149703c7Sjruoho  *
62149703c7Sjruoho  * RETURN:      Status
63149703c7Sjruoho  *
64149703c7Sjruoho  * DESCRIPTION: Obtain and return a "reference" to the target object
65149703c7Sjruoho  *              Common code for the RefOfOp and the CondRefOfOp.
66149703c7Sjruoho  *
67149703c7Sjruoho  ******************************************************************************/
68149703c7Sjruoho 
69149703c7Sjruoho ACPI_STATUS
AcpiExGetObjectReference(ACPI_OPERAND_OBJECT * ObjDesc,ACPI_OPERAND_OBJECT ** ReturnDesc,ACPI_WALK_STATE * WalkState)70149703c7Sjruoho AcpiExGetObjectReference (
71149703c7Sjruoho     ACPI_OPERAND_OBJECT     *ObjDesc,
72149703c7Sjruoho     ACPI_OPERAND_OBJECT     **ReturnDesc,
73149703c7Sjruoho     ACPI_WALK_STATE         *WalkState)
74149703c7Sjruoho {
75149703c7Sjruoho     ACPI_OPERAND_OBJECT     *ReferenceObj;
76149703c7Sjruoho     ACPI_OPERAND_OBJECT     *ReferencedObj;
77149703c7Sjruoho 
78149703c7Sjruoho 
79149703c7Sjruoho     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
80149703c7Sjruoho 
81149703c7Sjruoho 
82149703c7Sjruoho     *ReturnDesc = NULL;
83149703c7Sjruoho 
84149703c7Sjruoho     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
85149703c7Sjruoho     {
86149703c7Sjruoho     case ACPI_DESC_TYPE_OPERAND:
87149703c7Sjruoho 
88149703c7Sjruoho         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
89149703c7Sjruoho         {
90149703c7Sjruoho             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
91149703c7Sjruoho         }
92149703c7Sjruoho 
93149703c7Sjruoho         /*
94149703c7Sjruoho          * Must be a reference to a Local or Arg
95149703c7Sjruoho          */
96149703c7Sjruoho         switch (ObjDesc->Reference.Class)
97149703c7Sjruoho         {
98149703c7Sjruoho         case ACPI_REFCLASS_LOCAL:
99149703c7Sjruoho         case ACPI_REFCLASS_ARG:
100149703c7Sjruoho         case ACPI_REFCLASS_DEBUG:
101149703c7Sjruoho 
102149703c7Sjruoho             /* The referenced object is the pseudo-node for the local/arg */
103149703c7Sjruoho 
104149703c7Sjruoho             ReferencedObj = ObjDesc->Reference.Object;
105149703c7Sjruoho             break;
106149703c7Sjruoho 
107149703c7Sjruoho         default:
108149703c7Sjruoho 
1095fe1040dSchristos             ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
110149703c7Sjruoho                 ObjDesc->Reference.Class));
1115fe1040dSchristos             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
112149703c7Sjruoho         }
113149703c7Sjruoho         break;
114149703c7Sjruoho 
115149703c7Sjruoho     case ACPI_DESC_TYPE_NAMED:
116149703c7Sjruoho         /*
117149703c7Sjruoho          * A named reference that has already been resolved to a Node
118149703c7Sjruoho          */
119149703c7Sjruoho         ReferencedObj = ObjDesc;
120149703c7Sjruoho         break;
121149703c7Sjruoho 
122149703c7Sjruoho     default:
123149703c7Sjruoho 
124149703c7Sjruoho         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
125149703c7Sjruoho             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
126149703c7Sjruoho         return_ACPI_STATUS (AE_TYPE);
127149703c7Sjruoho     }
128149703c7Sjruoho 
129149703c7Sjruoho 
130149703c7Sjruoho     /* Create a new reference object */
131149703c7Sjruoho 
132149703c7Sjruoho     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
133149703c7Sjruoho     if (!ReferenceObj)
134149703c7Sjruoho     {
135149703c7Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
136149703c7Sjruoho     }
137149703c7Sjruoho 
138149703c7Sjruoho     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
139149703c7Sjruoho     ReferenceObj->Reference.Object = ReferencedObj;
140149703c7Sjruoho     *ReturnDesc = ReferenceObj;
141149703c7Sjruoho 
142149703c7Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
143149703c7Sjruoho         "Object %p Type [%s], returning Reference %p\n",
144149703c7Sjruoho         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
145149703c7Sjruoho 
146149703c7Sjruoho     return_ACPI_STATUS (AE_OK);
147149703c7Sjruoho }
148149703c7Sjruoho 
149149703c7Sjruoho 
150149703c7Sjruoho /*******************************************************************************
151149703c7Sjruoho  *
152149703c7Sjruoho  * FUNCTION:    AcpiExDoMathOp
153149703c7Sjruoho  *
154149703c7Sjruoho  * PARAMETERS:  Opcode              - AML opcode
155149703c7Sjruoho  *              Integer0            - Integer operand #0
156149703c7Sjruoho  *              Integer1            - Integer operand #1
157149703c7Sjruoho  *
158149703c7Sjruoho  * RETURN:      Integer result of the operation
159149703c7Sjruoho  *
160149703c7Sjruoho  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
161149703c7Sjruoho  *              math functions here is to prevent a lot of pointer dereferencing
162149703c7Sjruoho  *              to obtain the operands.
163149703c7Sjruoho  *
164149703c7Sjruoho  ******************************************************************************/
165149703c7Sjruoho 
166149703c7Sjruoho UINT64
AcpiExDoMathOp(UINT16 Opcode,UINT64 Integer0,UINT64 Integer1)167149703c7Sjruoho AcpiExDoMathOp (
168149703c7Sjruoho     UINT16                  Opcode,
169149703c7Sjruoho     UINT64                  Integer0,
170149703c7Sjruoho     UINT64                  Integer1)
171149703c7Sjruoho {
172149703c7Sjruoho 
173149703c7Sjruoho     ACPI_FUNCTION_ENTRY ();
174149703c7Sjruoho 
175149703c7Sjruoho 
176149703c7Sjruoho     switch (Opcode)
177149703c7Sjruoho     {
178149703c7Sjruoho     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
179149703c7Sjruoho 
180149703c7Sjruoho         return (Integer0 + Integer1);
181149703c7Sjruoho 
182149703c7Sjruoho     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
183149703c7Sjruoho 
184149703c7Sjruoho         return (Integer0 & Integer1);
185149703c7Sjruoho 
186149703c7Sjruoho     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
187149703c7Sjruoho 
188149703c7Sjruoho         return (~(Integer0 & Integer1));
189149703c7Sjruoho 
190149703c7Sjruoho     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
191149703c7Sjruoho 
192149703c7Sjruoho         return (Integer0 | Integer1);
193149703c7Sjruoho 
194149703c7Sjruoho     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
195149703c7Sjruoho 
196149703c7Sjruoho         return (~(Integer0 | Integer1));
197149703c7Sjruoho 
198149703c7Sjruoho     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
199149703c7Sjruoho 
200149703c7Sjruoho         return (Integer0 ^ Integer1);
201149703c7Sjruoho 
202149703c7Sjruoho     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
203149703c7Sjruoho 
204149703c7Sjruoho         return (Integer0 * Integer1);
205149703c7Sjruoho 
206149703c7Sjruoho     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
207149703c7Sjruoho 
208149703c7Sjruoho         /*
209149703c7Sjruoho          * We need to check if the shiftcount is larger than the integer bit
210149703c7Sjruoho          * width since the behavior of this is not well-defined in the C language.
211149703c7Sjruoho          */
212149703c7Sjruoho         if (Integer1 >= AcpiGbl_IntegerBitWidth)
213149703c7Sjruoho         {
214149703c7Sjruoho             return (0);
215149703c7Sjruoho         }
216149703c7Sjruoho         return (Integer0 << Integer1);
217149703c7Sjruoho 
218149703c7Sjruoho     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
219149703c7Sjruoho 
220149703c7Sjruoho         /*
221149703c7Sjruoho          * We need to check if the shiftcount is larger than the integer bit
222149703c7Sjruoho          * width since the behavior of this is not well-defined in the C language.
223149703c7Sjruoho          */
224149703c7Sjruoho         if (Integer1 >= AcpiGbl_IntegerBitWidth)
225149703c7Sjruoho         {
226149703c7Sjruoho             return (0);
227149703c7Sjruoho         }
228149703c7Sjruoho         return (Integer0 >> Integer1);
229149703c7Sjruoho 
230149703c7Sjruoho     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
231149703c7Sjruoho 
232149703c7Sjruoho         return (Integer0 - Integer1);
233149703c7Sjruoho 
234149703c7Sjruoho     default:
235149703c7Sjruoho 
236149703c7Sjruoho         return (0);
237149703c7Sjruoho     }
238149703c7Sjruoho }
239149703c7Sjruoho 
240149703c7Sjruoho 
241149703c7Sjruoho /*******************************************************************************
242149703c7Sjruoho  *
243149703c7Sjruoho  * FUNCTION:    AcpiExDoLogicalNumericOp
244149703c7Sjruoho  *
245149703c7Sjruoho  * PARAMETERS:  Opcode              - AML opcode
246149703c7Sjruoho  *              Integer0            - Integer operand #0
247149703c7Sjruoho  *              Integer1            - Integer operand #1
248149703c7Sjruoho  *              LogicalResult       - TRUE/FALSE result of the operation
249149703c7Sjruoho  *
250149703c7Sjruoho  * RETURN:      Status
251149703c7Sjruoho  *
252149703c7Sjruoho  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
253149703c7Sjruoho  *              operators (LAnd and LOr), both operands must be integers.
254149703c7Sjruoho  *
255149703c7Sjruoho  *              Note: cleanest machine code seems to be produced by the code
256149703c7Sjruoho  *              below, rather than using statements of the form:
257149703c7Sjruoho  *                  Result = (Integer0 && Integer1);
258149703c7Sjruoho  *
259149703c7Sjruoho  ******************************************************************************/
260149703c7Sjruoho 
261149703c7Sjruoho ACPI_STATUS
AcpiExDoLogicalNumericOp(UINT16 Opcode,UINT64 Integer0,UINT64 Integer1,BOOLEAN * LogicalResult)262149703c7Sjruoho AcpiExDoLogicalNumericOp (
263149703c7Sjruoho     UINT16                  Opcode,
264149703c7Sjruoho     UINT64                  Integer0,
265149703c7Sjruoho     UINT64                  Integer1,
266149703c7Sjruoho     BOOLEAN                 *LogicalResult)
267149703c7Sjruoho {
268149703c7Sjruoho     ACPI_STATUS             Status = AE_OK;
269149703c7Sjruoho     BOOLEAN                 LocalResult = FALSE;
270149703c7Sjruoho 
271149703c7Sjruoho 
272149703c7Sjruoho     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
273149703c7Sjruoho 
274149703c7Sjruoho 
275149703c7Sjruoho     switch (Opcode)
276149703c7Sjruoho     {
2771a3716ccSchristos     case AML_LOGICAL_AND_OP:        /* LAnd (Integer0, Integer1) */
278149703c7Sjruoho 
279149703c7Sjruoho         if (Integer0 && Integer1)
280149703c7Sjruoho         {
281149703c7Sjruoho             LocalResult = TRUE;
282149703c7Sjruoho         }
283149703c7Sjruoho         break;
284149703c7Sjruoho 
2851a3716ccSchristos     case AML_LOGICAL_OR_OP:         /* LOr (Integer0, Integer1) */
286149703c7Sjruoho 
287149703c7Sjruoho         if (Integer0 || Integer1)
288149703c7Sjruoho         {
289149703c7Sjruoho             LocalResult = TRUE;
290149703c7Sjruoho         }
291149703c7Sjruoho         break;
292149703c7Sjruoho 
293149703c7Sjruoho     default:
29473d4e80bSchristos 
295d382fe7fSchristos         ACPI_ERROR ((AE_INFO,
296d382fe7fSchristos             "Invalid numeric logical opcode: %X", Opcode));
297149703c7Sjruoho         Status = AE_AML_INTERNAL;
298149703c7Sjruoho         break;
299149703c7Sjruoho     }
300149703c7Sjruoho 
301149703c7Sjruoho     /* Return the logical result and status */
302149703c7Sjruoho 
303149703c7Sjruoho     *LogicalResult = LocalResult;
304149703c7Sjruoho     return_ACPI_STATUS (Status);
305149703c7Sjruoho }
306149703c7Sjruoho 
307149703c7Sjruoho 
308149703c7Sjruoho /*******************************************************************************
309149703c7Sjruoho  *
310149703c7Sjruoho  * FUNCTION:    AcpiExDoLogicalOp
311149703c7Sjruoho  *
312149703c7Sjruoho  * PARAMETERS:  Opcode              - AML opcode
313149703c7Sjruoho  *              Operand0            - operand #0
314149703c7Sjruoho  *              Operand1            - operand #1
315149703c7Sjruoho  *              LogicalResult       - TRUE/FALSE result of the operation
316149703c7Sjruoho  *
317149703c7Sjruoho  * RETURN:      Status
318149703c7Sjruoho  *
319149703c7Sjruoho  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
320149703c7Sjruoho  *              functions here is to prevent a lot of pointer dereferencing
321149703c7Sjruoho  *              to obtain the operands and to simplify the generation of the
322149703c7Sjruoho  *              logical value. For the Numeric operators (LAnd and LOr), both
323149703c7Sjruoho  *              operands must be integers. For the other logical operators,
324149703c7Sjruoho  *              operands can be any combination of Integer/String/Buffer. The
325149703c7Sjruoho  *              first operand determines the type to which the second operand
326149703c7Sjruoho  *              will be converted.
327149703c7Sjruoho  *
328149703c7Sjruoho  *              Note: cleanest machine code seems to be produced by the code
329149703c7Sjruoho  *              below, rather than using statements of the form:
330149703c7Sjruoho  *                  Result = (Operand0 == Operand1);
331149703c7Sjruoho  *
332149703c7Sjruoho  ******************************************************************************/
333149703c7Sjruoho 
334149703c7Sjruoho ACPI_STATUS
AcpiExDoLogicalOp(UINT16 Opcode,ACPI_OPERAND_OBJECT * Operand0,ACPI_OPERAND_OBJECT * Operand1,BOOLEAN * LogicalResult)335149703c7Sjruoho AcpiExDoLogicalOp (
336149703c7Sjruoho     UINT16                  Opcode,
337149703c7Sjruoho     ACPI_OPERAND_OBJECT     *Operand0,
338149703c7Sjruoho     ACPI_OPERAND_OBJECT     *Operand1,
339149703c7Sjruoho     BOOLEAN                 *LogicalResult)
340149703c7Sjruoho {
341149703c7Sjruoho     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
342149703c7Sjruoho     UINT64                  Integer0;
343149703c7Sjruoho     UINT64                  Integer1;
344149703c7Sjruoho     UINT32                  Length0;
345149703c7Sjruoho     UINT32                  Length1;
346149703c7Sjruoho     ACPI_STATUS             Status = AE_OK;
347149703c7Sjruoho     BOOLEAN                 LocalResult = FALSE;
348149703c7Sjruoho     int                     Compare;
349149703c7Sjruoho 
350149703c7Sjruoho 
351149703c7Sjruoho     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
352149703c7Sjruoho 
353149703c7Sjruoho 
354149703c7Sjruoho     /*
355149703c7Sjruoho      * Convert the second operand if necessary. The first operand
356149703c7Sjruoho      * determines the type of the second operand, (See the Data Types
357149703c7Sjruoho      * section of the ACPI 3.0+ specification.)  Both object types are
358149703c7Sjruoho      * guaranteed to be either Integer/String/Buffer by the operand
359149703c7Sjruoho      * resolution mechanism.
360149703c7Sjruoho      */
361149703c7Sjruoho     switch (Operand0->Common.Type)
362149703c7Sjruoho     {
363149703c7Sjruoho     case ACPI_TYPE_INTEGER:
36473d4e80bSchristos 
3655b9576aaSchristos         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1,
366d382fe7fSchristos             ACPI_IMPLICIT_CONVERSION);
367149703c7Sjruoho         break;
368149703c7Sjruoho 
369149703c7Sjruoho     case ACPI_TYPE_STRING:
37073d4e80bSchristos 
3715fe1040dSchristos         Status = AcpiExConvertToString (
3725fe1040dSchristos             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
373149703c7Sjruoho         break;
374149703c7Sjruoho 
375149703c7Sjruoho     case ACPI_TYPE_BUFFER:
37673d4e80bSchristos 
377149703c7Sjruoho         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
378149703c7Sjruoho         break;
379149703c7Sjruoho 
380149703c7Sjruoho     default:
38173d4e80bSchristos 
382d382fe7fSchristos         ACPI_ERROR ((AE_INFO,
383d382fe7fSchristos             "Invalid object type for logical operator: %X",
384d382fe7fSchristos             Operand0->Common.Type));
385149703c7Sjruoho         Status = AE_AML_INTERNAL;
386149703c7Sjruoho         break;
387149703c7Sjruoho     }
388149703c7Sjruoho 
389149703c7Sjruoho     if (ACPI_FAILURE (Status))
390149703c7Sjruoho     {
391149703c7Sjruoho         goto Cleanup;
392149703c7Sjruoho     }
393149703c7Sjruoho 
394149703c7Sjruoho     /*
395149703c7Sjruoho      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
396149703c7Sjruoho      */
397149703c7Sjruoho     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
398149703c7Sjruoho     {
399149703c7Sjruoho         /*
400149703c7Sjruoho          * 1) Both operands are of type integer
401149703c7Sjruoho          *    Note: LocalOperand1 may have changed above
402149703c7Sjruoho          */
403149703c7Sjruoho         Integer0 = Operand0->Integer.Value;
404149703c7Sjruoho         Integer1 = LocalOperand1->Integer.Value;
405149703c7Sjruoho 
406149703c7Sjruoho         switch (Opcode)
407149703c7Sjruoho         {
4081a3716ccSchristos         case AML_LOGICAL_EQUAL_OP:          /* LEqual (Operand0, Operand1) */
409149703c7Sjruoho 
410149703c7Sjruoho             if (Integer0 == Integer1)
411149703c7Sjruoho             {
412149703c7Sjruoho                 LocalResult = TRUE;
413149703c7Sjruoho             }
414149703c7Sjruoho             break;
415149703c7Sjruoho 
4161a3716ccSchristos         case AML_LOGICAL_GREATER_OP:        /* LGreater (Operand0, Operand1) */
417149703c7Sjruoho 
418149703c7Sjruoho             if (Integer0 > Integer1)
419149703c7Sjruoho             {
420149703c7Sjruoho                 LocalResult = TRUE;
421149703c7Sjruoho             }
422149703c7Sjruoho             break;
423149703c7Sjruoho 
4241a3716ccSchristos         case AML_LOGICAL_LESS_OP:           /* LLess (Operand0, Operand1) */
425149703c7Sjruoho 
426149703c7Sjruoho             if (Integer0 < Integer1)
427149703c7Sjruoho             {
428149703c7Sjruoho                 LocalResult = TRUE;
429149703c7Sjruoho             }
430149703c7Sjruoho             break;
431149703c7Sjruoho 
432149703c7Sjruoho         default:
43373d4e80bSchristos 
434d382fe7fSchristos             ACPI_ERROR ((AE_INFO,
435d382fe7fSchristos                 "Invalid comparison opcode: %X", Opcode));
436149703c7Sjruoho             Status = AE_AML_INTERNAL;
437149703c7Sjruoho             break;
438149703c7Sjruoho         }
439149703c7Sjruoho     }
440149703c7Sjruoho     else
441149703c7Sjruoho     {
442149703c7Sjruoho         /*
443149703c7Sjruoho          * 2) Both operands are Strings or both are Buffers
444149703c7Sjruoho          *    Note: Code below takes advantage of common Buffer/String
445149703c7Sjruoho          *          object fields. LocalOperand1 may have changed above. Use
446149703c7Sjruoho          *          memcmp to handle nulls in buffers.
447149703c7Sjruoho          */
448149703c7Sjruoho         Length0 = Operand0->Buffer.Length;
449149703c7Sjruoho         Length1 = LocalOperand1->Buffer.Length;
450149703c7Sjruoho 
451149703c7Sjruoho         /* Lexicographic compare: compare the data bytes */
452149703c7Sjruoho 
453db5c6ae1Schristos         Compare = memcmp (Operand0->Buffer.Pointer,
454149703c7Sjruoho             LocalOperand1->Buffer.Pointer,
455149703c7Sjruoho             (Length0 > Length1) ? Length1 : Length0);
456149703c7Sjruoho 
457149703c7Sjruoho         switch (Opcode)
458149703c7Sjruoho         {
4591a3716ccSchristos         case AML_LOGICAL_EQUAL_OP:      /* LEqual (Operand0, Operand1) */
460149703c7Sjruoho 
461149703c7Sjruoho             /* Length and all bytes must be equal */
462149703c7Sjruoho 
463149703c7Sjruoho             if ((Length0 == Length1) &&
464149703c7Sjruoho                 (Compare == 0))
465149703c7Sjruoho             {
466149703c7Sjruoho                 /* Length and all bytes match ==> TRUE */
467149703c7Sjruoho 
468149703c7Sjruoho                 LocalResult = TRUE;
469149703c7Sjruoho             }
470149703c7Sjruoho             break;
471149703c7Sjruoho 
4721a3716ccSchristos         case AML_LOGICAL_GREATER_OP:    /* LGreater (Operand0, Operand1) */
473149703c7Sjruoho 
474149703c7Sjruoho             if (Compare > 0)
475149703c7Sjruoho             {
476149703c7Sjruoho                 LocalResult = TRUE;
477149703c7Sjruoho                 goto Cleanup;   /* TRUE */
478149703c7Sjruoho             }
479149703c7Sjruoho             if (Compare < 0)
480149703c7Sjruoho             {
481149703c7Sjruoho                 goto Cleanup;   /* FALSE */
482149703c7Sjruoho             }
483149703c7Sjruoho 
484149703c7Sjruoho             /* Bytes match (to shortest length), compare lengths */
485149703c7Sjruoho 
486149703c7Sjruoho             if (Length0 > Length1)
487149703c7Sjruoho             {
488149703c7Sjruoho                 LocalResult = TRUE;
489149703c7Sjruoho             }
490149703c7Sjruoho             break;
491149703c7Sjruoho 
4921a3716ccSchristos         case AML_LOGICAL_LESS_OP:       /* LLess (Operand0, Operand1) */
493149703c7Sjruoho 
494149703c7Sjruoho             if (Compare > 0)
495149703c7Sjruoho             {
496149703c7Sjruoho                 goto Cleanup;   /* FALSE */
497149703c7Sjruoho             }
498149703c7Sjruoho             if (Compare < 0)
499149703c7Sjruoho             {
500149703c7Sjruoho                 LocalResult = TRUE;
501149703c7Sjruoho                 goto Cleanup;   /* TRUE */
502149703c7Sjruoho             }
503149703c7Sjruoho 
504149703c7Sjruoho             /* Bytes match (to shortest length), compare lengths */
505149703c7Sjruoho 
506149703c7Sjruoho             if (Length0 < Length1)
507149703c7Sjruoho             {
508149703c7Sjruoho                 LocalResult = TRUE;
509149703c7Sjruoho             }
510149703c7Sjruoho             break;
511149703c7Sjruoho 
512149703c7Sjruoho         default:
51373d4e80bSchristos 
514d382fe7fSchristos             ACPI_ERROR ((AE_INFO,
515d382fe7fSchristos                 "Invalid comparison opcode: %X", Opcode));
516149703c7Sjruoho             Status = AE_AML_INTERNAL;
517149703c7Sjruoho             break;
518149703c7Sjruoho         }
519149703c7Sjruoho     }
520149703c7Sjruoho 
521149703c7Sjruoho Cleanup:
522149703c7Sjruoho 
523149703c7Sjruoho     /* New object was created if implicit conversion performed - delete */
524149703c7Sjruoho 
525149703c7Sjruoho     if (LocalOperand1 != Operand1)
526149703c7Sjruoho     {
527149703c7Sjruoho         AcpiUtRemoveReference (LocalOperand1);
528149703c7Sjruoho     }
529149703c7Sjruoho 
530149703c7Sjruoho     /* Return the logical result and status */
531149703c7Sjruoho 
532149703c7Sjruoho     *LogicalResult = LocalResult;
533149703c7Sjruoho     return_ACPI_STATUS (Status);
534149703c7Sjruoho }
535