xref: /titanic_51/usr/src/uts/intel/io/acpica/executer/exmisc.c (revision 45e662eb8429b38c18931ebeed30f2e5287ae51b)
1 
2 /******************************************************************************
3  *
4  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2011, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #define __EXMISC_C__
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acinterp.h"
50 #include "amlcode.h"
51 #include "amlresrc.h"
52 
53 
54 #define _COMPONENT          ACPI_EXECUTER
55         ACPI_MODULE_NAME    ("exmisc")
56 
57 
58 /*******************************************************************************
59  *
60  * FUNCTION:    AcpiExGetObjectReference
61  *
62  * PARAMETERS:  ObjDesc             - Create a reference to this object
63  *              ReturnDesc          - Where to store the reference
64  *              WalkState           - Current state
65  *
66  * RETURN:      Status
67  *
68  * DESCRIPTION: Obtain and return a "reference" to the target object
69  *              Common code for the RefOfOp and the CondRefOfOp.
70  *
71  ******************************************************************************/
72 
73 ACPI_STATUS
74 AcpiExGetObjectReference (
75     ACPI_OPERAND_OBJECT     *ObjDesc,
76     ACPI_OPERAND_OBJECT     **ReturnDesc,
77     ACPI_WALK_STATE         *WalkState)
78 {
79     ACPI_OPERAND_OBJECT     *ReferenceObj;
80     ACPI_OPERAND_OBJECT     *ReferencedObj;
81 
82 
83     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
84 
85 
86     *ReturnDesc = NULL;
87 
88     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
89     {
90     case ACPI_DESC_TYPE_OPERAND:
91 
92         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
93         {
94             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
95         }
96 
97         /*
98          * Must be a reference to a Local or Arg
99          */
100         switch (ObjDesc->Reference.Class)
101         {
102         case ACPI_REFCLASS_LOCAL:
103         case ACPI_REFCLASS_ARG:
104         case ACPI_REFCLASS_DEBUG:
105 
106             /* The referenced object is the pseudo-node for the local/arg */
107 
108             ReferencedObj = ObjDesc->Reference.Object;
109             break;
110 
111         default:
112 
113             ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
114                 ObjDesc->Reference.Class));
115             return_ACPI_STATUS (AE_AML_INTERNAL);
116         }
117         break;
118 
119 
120     case ACPI_DESC_TYPE_NAMED:
121 
122         /*
123          * A named reference that has already been resolved to a Node
124          */
125         ReferencedObj = ObjDesc;
126         break;
127 
128 
129     default:
130 
131         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
132             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
133         return_ACPI_STATUS (AE_TYPE);
134     }
135 
136 
137     /* Create a new reference object */
138 
139     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
140     if (!ReferenceObj)
141     {
142         return_ACPI_STATUS (AE_NO_MEMORY);
143     }
144 
145     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
146     ReferenceObj->Reference.Object = ReferencedObj;
147     *ReturnDesc = ReferenceObj;
148 
149     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
150         "Object %p Type [%s], returning Reference %p\n",
151         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
152 
153     return_ACPI_STATUS (AE_OK);
154 }
155 
156 
157 /*******************************************************************************
158  *
159  * FUNCTION:    AcpiExConcatTemplate
160  *
161  * PARAMETERS:  Operand0            - First source object
162  *              Operand1            - Second source object
163  *              ActualReturnDesc    - Where to place the return object
164  *              WalkState           - Current walk state
165  *
166  * RETURN:      Status
167  *
168  * DESCRIPTION: Concatenate two resource templates
169  *
170  ******************************************************************************/
171 
172 ACPI_STATUS
173 AcpiExConcatTemplate (
174     ACPI_OPERAND_OBJECT     *Operand0,
175     ACPI_OPERAND_OBJECT     *Operand1,
176     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
177     ACPI_WALK_STATE         *WalkState)
178 {
179     ACPI_STATUS             Status;
180     ACPI_OPERAND_OBJECT     *ReturnDesc;
181     UINT8                   *NewBuf;
182     UINT8                   *EndTag;
183     ACPI_SIZE               Length0;
184     ACPI_SIZE               Length1;
185     ACPI_SIZE               NewLength;
186 
187 
188     ACPI_FUNCTION_TRACE (ExConcatTemplate);
189 
190 
191     /*
192      * Find the EndTag descriptor in each resource template.
193      * Note1: returned pointers point TO the EndTag, not past it.
194      * Note2: zero-length buffers are allowed; treated like one EndTag
195      */
196 
197     /* Get the length of the first resource template */
198 
199     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
200     if (ACPI_FAILURE (Status))
201     {
202         return_ACPI_STATUS (Status);
203     }
204 
205     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
206 
207     /* Get the length of the second resource template */
208 
209     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
210     if (ACPI_FAILURE (Status))
211     {
212         return_ACPI_STATUS (Status);
213     }
214 
215     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
216 
217     /* Combine both lengths, minimum size will be 2 for EndTag */
218 
219     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
220 
221     /* Create a new buffer object for the result (with one EndTag) */
222 
223     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
224     if (!ReturnDesc)
225     {
226         return_ACPI_STATUS (AE_NO_MEMORY);
227     }
228 
229     /*
230      * Copy the templates to the new buffer, 0 first, then 1 follows. One
231      * EndTag descriptor is copied from Operand1.
232      */
233     NewBuf = ReturnDesc->Buffer.Pointer;
234     ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
235     ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
236 
237     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
238 
239     NewBuf[NewLength - 1] = 0;
240     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
241 
242     /* Return the completed resource template */
243 
244     *ActualReturnDesc = ReturnDesc;
245     return_ACPI_STATUS (AE_OK);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    AcpiExDoConcatenate
252  *
253  * PARAMETERS:  Operand0            - First source object
254  *              Operand1            - Second source object
255  *              ActualReturnDesc    - Where to place the return object
256  *              WalkState           - Current walk state
257  *
258  * RETURN:      Status
259  *
260  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
261  *
262  ******************************************************************************/
263 
264 ACPI_STATUS
265 AcpiExDoConcatenate (
266     ACPI_OPERAND_OBJECT     *Operand0,
267     ACPI_OPERAND_OBJECT     *Operand1,
268     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
269     ACPI_WALK_STATE         *WalkState)
270 {
271     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
272     ACPI_OPERAND_OBJECT     *ReturnDesc;
273     char                    *NewBuf;
274     ACPI_STATUS             Status;
275 
276 
277     ACPI_FUNCTION_TRACE (ExDoConcatenate);
278 
279 
280     /*
281      * Convert the second operand if necessary.  The first operand
282      * determines the type of the second operand, (See the Data Types
283      * section of the ACPI specification.)  Both object types are
284      * guaranteed to be either Integer/String/Buffer by the operand
285      * resolution mechanism.
286      */
287     switch (Operand0->Common.Type)
288     {
289     case ACPI_TYPE_INTEGER:
290         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
291         break;
292 
293     case ACPI_TYPE_STRING:
294         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
295                     ACPI_IMPLICIT_CONVERT_HEX);
296         break;
297 
298     case ACPI_TYPE_BUFFER:
299         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
300         break;
301 
302     default:
303         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
304             Operand0->Common.Type));
305         Status = AE_AML_INTERNAL;
306     }
307 
308     if (ACPI_FAILURE (Status))
309     {
310         goto Cleanup;
311     }
312 
313     /*
314      * Both operands are now known to be the same object type
315      * (Both are Integer, String, or Buffer), and we can now perform the
316      * concatenation.
317      */
318 
319     /*
320      * There are three cases to handle:
321      *
322      * 1) Two Integers concatenated to produce a new Buffer
323      * 2) Two Strings concatenated to produce a new String
324      * 3) Two Buffers concatenated to produce a new Buffer
325      */
326     switch (Operand0->Common.Type)
327     {
328     case ACPI_TYPE_INTEGER:
329 
330         /* Result of two Integers is a Buffer */
331         /* Need enough buffer space for two integers */
332 
333         ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
334                             ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
335         if (!ReturnDesc)
336         {
337             Status = AE_NO_MEMORY;
338             goto Cleanup;
339         }
340 
341         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
342 
343         /* Copy the first integer, LSB first */
344 
345         ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
346                         AcpiGbl_IntegerByteWidth);
347 
348         /* Copy the second integer (LSB first) after the first */
349 
350         ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
351                         &LocalOperand1->Integer.Value,
352                         AcpiGbl_IntegerByteWidth);
353         break;
354 
355     case ACPI_TYPE_STRING:
356 
357         /* Result of two Strings is a String */
358 
359         ReturnDesc = AcpiUtCreateStringObject (
360                         ((ACPI_SIZE) Operand0->String.Length +
361                         LocalOperand1->String.Length));
362         if (!ReturnDesc)
363         {
364             Status = AE_NO_MEMORY;
365             goto Cleanup;
366         }
367 
368         NewBuf = ReturnDesc->String.Pointer;
369 
370         /* Concatenate the strings */
371 
372         ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
373         ACPI_STRCPY (NewBuf + Operand0->String.Length,
374                         LocalOperand1->String.Pointer);
375         break;
376 
377     case ACPI_TYPE_BUFFER:
378 
379         /* Result of two Buffers is a Buffer */
380 
381         ReturnDesc = AcpiUtCreateBufferObject (
382                         ((ACPI_SIZE) Operand0->Buffer.Length +
383                         LocalOperand1->Buffer.Length));
384         if (!ReturnDesc)
385         {
386             Status = AE_NO_MEMORY;
387             goto Cleanup;
388         }
389 
390         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
391 
392         /* Concatenate the buffers */
393 
394         ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
395                         Operand0->Buffer.Length);
396         ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
397                         LocalOperand1->Buffer.Pointer,
398                         LocalOperand1->Buffer.Length);
399         break;
400 
401     default:
402 
403         /* Invalid object type, should not happen here */
404 
405         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
406             Operand0->Common.Type));
407         Status =AE_AML_INTERNAL;
408         goto Cleanup;
409     }
410 
411     *ActualReturnDesc = ReturnDesc;
412 
413 Cleanup:
414     if (LocalOperand1 != Operand1)
415     {
416         AcpiUtRemoveReference (LocalOperand1);
417     }
418     return_ACPI_STATUS (Status);
419 }
420 
421 
422 /*******************************************************************************
423  *
424  * FUNCTION:    AcpiExDoMathOp
425  *
426  * PARAMETERS:  Opcode              - AML opcode
427  *              Integer0            - Integer operand #0
428  *              Integer1            - Integer operand #1
429  *
430  * RETURN:      Integer result of the operation
431  *
432  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
433  *              math functions here is to prevent a lot of pointer dereferencing
434  *              to obtain the operands.
435  *
436  ******************************************************************************/
437 
438 UINT64
439 AcpiExDoMathOp (
440     UINT16                  Opcode,
441     UINT64                  Integer0,
442     UINT64                  Integer1)
443 {
444 
445     ACPI_FUNCTION_ENTRY ();
446 
447 
448     switch (Opcode)
449     {
450     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
451 
452         return (Integer0 + Integer1);
453 
454 
455     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
456 
457         return (Integer0 & Integer1);
458 
459 
460     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
461 
462         return (~(Integer0 & Integer1));
463 
464 
465     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
466 
467         return (Integer0 | Integer1);
468 
469 
470     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
471 
472         return (~(Integer0 | Integer1));
473 
474 
475     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
476 
477         return (Integer0 ^ Integer1);
478 
479 
480     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
481 
482         return (Integer0 * Integer1);
483 
484 
485     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
486 
487         /*
488          * We need to check if the shiftcount is larger than the integer bit
489          * width since the behavior of this is not well-defined in the C language.
490          */
491         if (Integer1 >= AcpiGbl_IntegerBitWidth)
492         {
493             return (0);
494         }
495         return (Integer0 << Integer1);
496 
497 
498     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
499 
500         /*
501          * We need to check if the shiftcount is larger than the integer bit
502          * width since the behavior of this is not well-defined in the C language.
503          */
504         if (Integer1 >= AcpiGbl_IntegerBitWidth)
505         {
506             return (0);
507         }
508         return (Integer0 >> Integer1);
509 
510 
511     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
512 
513         return (Integer0 - Integer1);
514 
515     default:
516 
517         return (0);
518     }
519 }
520 
521 
522 /*******************************************************************************
523  *
524  * FUNCTION:    AcpiExDoLogicalNumericOp
525  *
526  * PARAMETERS:  Opcode              - AML opcode
527  *              Integer0            - Integer operand #0
528  *              Integer1            - Integer operand #1
529  *              LogicalResult       - TRUE/FALSE result of the operation
530  *
531  * RETURN:      Status
532  *
533  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
534  *              operators (LAnd and LOr), both operands must be integers.
535  *
536  *              Note: cleanest machine code seems to be produced by the code
537  *              below, rather than using statements of the form:
538  *                  Result = (Integer0 && Integer1);
539  *
540  ******************************************************************************/
541 
542 ACPI_STATUS
543 AcpiExDoLogicalNumericOp (
544     UINT16                  Opcode,
545     UINT64                  Integer0,
546     UINT64                  Integer1,
547     BOOLEAN                 *LogicalResult)
548 {
549     ACPI_STATUS             Status = AE_OK;
550     BOOLEAN                 LocalResult = FALSE;
551 
552 
553     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
554 
555 
556     switch (Opcode)
557     {
558     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
559 
560         if (Integer0 && Integer1)
561         {
562             LocalResult = TRUE;
563         }
564         break;
565 
566     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
567 
568         if (Integer0 || Integer1)
569         {
570             LocalResult = TRUE;
571         }
572         break;
573 
574     default:
575         Status = AE_AML_INTERNAL;
576         break;
577     }
578 
579     /* Return the logical result and status */
580 
581     *LogicalResult = LocalResult;
582     return_ACPI_STATUS (Status);
583 }
584 
585 
586 /*******************************************************************************
587  *
588  * FUNCTION:    AcpiExDoLogicalOp
589  *
590  * PARAMETERS:  Opcode              - AML opcode
591  *              Operand0            - operand #0
592  *              Operand1            - operand #1
593  *              LogicalResult       - TRUE/FALSE result of the operation
594  *
595  * RETURN:      Status
596  *
597  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
598  *              functions here is to prevent a lot of pointer dereferencing
599  *              to obtain the operands and to simplify the generation of the
600  *              logical value. For the Numeric operators (LAnd and LOr), both
601  *              operands must be integers. For the other logical operators,
602  *              operands can be any combination of Integer/String/Buffer. The
603  *              first operand determines the type to which the second operand
604  *              will be converted.
605  *
606  *              Note: cleanest machine code seems to be produced by the code
607  *              below, rather than using statements of the form:
608  *                  Result = (Operand0 == Operand1);
609  *
610  ******************************************************************************/
611 
612 ACPI_STATUS
613 AcpiExDoLogicalOp (
614     UINT16                  Opcode,
615     ACPI_OPERAND_OBJECT     *Operand0,
616     ACPI_OPERAND_OBJECT     *Operand1,
617     BOOLEAN                 *LogicalResult)
618 {
619     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
620     UINT64                  Integer0;
621     UINT64                  Integer1;
622     UINT32                  Length0;
623     UINT32                  Length1;
624     ACPI_STATUS             Status = AE_OK;
625     BOOLEAN                 LocalResult = FALSE;
626     int                     Compare;
627 
628 
629     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
630 
631 
632     /*
633      * Convert the second operand if necessary.  The first operand
634      * determines the type of the second operand, (See the Data Types
635      * section of the ACPI 3.0+ specification.)  Both object types are
636      * guaranteed to be either Integer/String/Buffer by the operand
637      * resolution mechanism.
638      */
639     switch (Operand0->Common.Type)
640     {
641     case ACPI_TYPE_INTEGER:
642         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
643         break;
644 
645     case ACPI_TYPE_STRING:
646         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
647                     ACPI_IMPLICIT_CONVERT_HEX);
648         break;
649 
650     case ACPI_TYPE_BUFFER:
651         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
652         break;
653 
654     default:
655         Status = AE_AML_INTERNAL;
656         break;
657     }
658 
659     if (ACPI_FAILURE (Status))
660     {
661         goto Cleanup;
662     }
663 
664     /*
665      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
666      */
667     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
668     {
669         /*
670          * 1) Both operands are of type integer
671          *    Note: LocalOperand1 may have changed above
672          */
673         Integer0 = Operand0->Integer.Value;
674         Integer1 = LocalOperand1->Integer.Value;
675 
676         switch (Opcode)
677         {
678         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
679 
680             if (Integer0 == Integer1)
681             {
682                 LocalResult = TRUE;
683             }
684             break;
685 
686         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
687 
688             if (Integer0 > Integer1)
689             {
690                 LocalResult = TRUE;
691             }
692             break;
693 
694         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
695 
696             if (Integer0 < Integer1)
697             {
698                 LocalResult = TRUE;
699             }
700             break;
701 
702         default:
703             Status = AE_AML_INTERNAL;
704             break;
705         }
706     }
707     else
708     {
709         /*
710          * 2) Both operands are Strings or both are Buffers
711          *    Note: Code below takes advantage of common Buffer/String
712          *          object fields. LocalOperand1 may have changed above. Use
713          *          memcmp to handle nulls in buffers.
714          */
715         Length0 = Operand0->Buffer.Length;
716         Length1 = LocalOperand1->Buffer.Length;
717 
718         /* Lexicographic compare: compare the data bytes */
719 
720         Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
721                     LocalOperand1->Buffer.Pointer,
722                     (Length0 > Length1) ? Length1 : Length0);
723 
724         switch (Opcode)
725         {
726         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
727 
728             /* Length and all bytes must be equal */
729 
730             if ((Length0 == Length1) &&
731                 (Compare == 0))
732             {
733                 /* Length and all bytes match ==> TRUE */
734 
735                 LocalResult = TRUE;
736             }
737             break;
738 
739         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
740 
741             if (Compare > 0)
742             {
743                 LocalResult = TRUE;
744                 goto Cleanup;   /* TRUE */
745             }
746             if (Compare < 0)
747             {
748                 goto Cleanup;   /* FALSE */
749             }
750 
751             /* Bytes match (to shortest length), compare lengths */
752 
753             if (Length0 > Length1)
754             {
755                 LocalResult = TRUE;
756             }
757             break;
758 
759         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
760 
761             if (Compare > 0)
762             {
763                 goto Cleanup;   /* FALSE */
764             }
765             if (Compare < 0)
766             {
767                 LocalResult = TRUE;
768                 goto Cleanup;   /* TRUE */
769             }
770 
771             /* Bytes match (to shortest length), compare lengths */
772 
773             if (Length0 < Length1)
774             {
775                 LocalResult = TRUE;
776             }
777             break;
778 
779         default:
780             Status = AE_AML_INTERNAL;
781             break;
782         }
783     }
784 
785 Cleanup:
786 
787     /* New object was created if implicit conversion performed - delete */
788 
789     if (LocalOperand1 != Operand1)
790     {
791         AcpiUtRemoveReference (LocalOperand1);
792     }
793 
794     /* Return the logical result and status */
795 
796     *LogicalResult = LocalResult;
797     return_ACPI_STATUS (Status);
798 }
799 
800 
801