File: /usr/src/linux/drivers/acpi/executer/exdyadic.c

1     /******************************************************************************
2      *
3      * Module Name: exdyadic - ACPI AML execution for dyadic (2-operand) operators
4      *              $Revision: 88 $
5      *
6      *****************************************************************************/
7     
8     /*
9      *  Copyright (C) 2000, 2001 R. Byron Moore
10      *
11      *  This program is free software; you can redistribute it and/or modify
12      *  it under the terms of the GNU General Public License as published by
13      *  the Free Software Foundation; either version 2 of the License, or
14      *  (at your option) any later version.
15      *
16      *  This program is distributed in the hope that it will be useful,
17      *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18      *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19      *  GNU General Public License for more details.
20      *
21      *  You should have received a copy of the GNU General Public License
22      *  along with this program; if not, write to the Free Software
23      *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24      */
25     
26     
27     #include "acpi.h"
28     #include "acparser.h"
29     #include "acnamesp.h"
30     #include "acinterp.h"
31     #include "acevents.h"
32     #include "amlcode.h"
33     #include "acdispat.h"
34     
35     
36     #define _COMPONENT          ACPI_EXECUTER
37     	 MODULE_NAME         ("exdyadic")
38     
39     
40     /*******************************************************************************
41      *
42      * FUNCTION:    Acpi_ex_do_concatenate
43      *
44      * PARAMETERS:  *Obj_desc           - Object to be converted.  Must be an
45      *                                    Integer, Buffer, or String
46      *              Walk_state          - Current walk state
47      *
48      * RETURN:      Status
49      *
50      * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
51      *
52      ******************************************************************************/
53     
54     acpi_status
55     acpi_ex_do_concatenate (
56     	acpi_operand_object     *obj_desc,
57     	acpi_operand_object     *obj_desc2,
58     	acpi_operand_object     **actual_ret_desc,
59     	acpi_walk_state         *walk_state)
60     {
61     	acpi_status             status;
62     	u32                     i;
63     	acpi_integer            this_integer;
64     	acpi_operand_object     *ret_desc;
65     	NATIVE_CHAR             *new_buf;
66     	u32                     integer_size = sizeof (acpi_integer);
67     
68     
69     	FUNCTION_ENTRY ();
70     
71     
72     	/*
73     	 * There are three cases to handle:
74     	 * 1) Two Integers concatenated to produce a buffer
75     	 * 2) Two Strings concatenated to produce a string
76     	 * 3) Two Buffers concatenated to produce a buffer
77     	 */
78     	switch (obj_desc->common.type) {
79     	case ACPI_TYPE_INTEGER:
80     
81     		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
82     
83     		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
84     			/*
85     			 * We are running a method that exists in a 32-bit ACPI table.
86     			 * Truncate the value to 32 bits by zeroing out the upper
87     			 * 32-bit field
88     			 */
89     			integer_size = sizeof (u32);
90     		}
91     
92     		/* Result of two integers is a buffer */
93     
94     		ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
95     		if (!ret_desc) {
96     			return (AE_NO_MEMORY);
97     		}
98     
99     		/* Need enough space for two integers */
100     
101     		ret_desc->buffer.length = integer_size * 2;
102     		new_buf = ACPI_MEM_CALLOCATE (ret_desc->buffer.length);
103     		if (!new_buf) {
104     			REPORT_ERROR
105     				(("Ex_do_concatenate: Buffer allocation failure\n"));
106     			status = AE_NO_MEMORY;
107     			goto cleanup;
108     		}
109     
110     		ret_desc->buffer.pointer = (u8 *) new_buf;
111     
112     		/* Convert the first integer */
113     
114     		this_integer = obj_desc->integer.value;
115     		for (i = 0; i < integer_size; i++) {
116     			new_buf[i] = (u8) this_integer;
117     			this_integer >>= 8;
118     		}
119     
120     		/* Convert the second integer */
121     
122     		this_integer = obj_desc2->integer.value;
123     		for (; i < (integer_size * 2); i++) {
124     			new_buf[i] = (u8) this_integer;
125     			this_integer >>= 8;
126     		}
127     
128     		break;
129     
130     
131     	case ACPI_TYPE_STRING:
132     
133     		ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
134     		if (!ret_desc) {
135     			return (AE_NO_MEMORY);
136     		}
137     
138     		/* Operand1 is string  */
139     
140     		new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length +
141     				  obj_desc2->string.length + 1);
142     		if (!new_buf) {
143     			REPORT_ERROR
144     				(("Ex_do_concatenate: String allocation failure\n"));
145     			status = AE_NO_MEMORY;
146     			goto cleanup;
147     		}
148     
149     		STRCPY (new_buf, obj_desc->string.pointer);
150     		STRCPY (new_buf + obj_desc->string.length,
151     				  obj_desc2->string.pointer);
152     
153     		/* Point the return object to the new string */
154     
155     		ret_desc->string.pointer = new_buf;
156     		ret_desc->string.length = obj_desc->string.length +=
157     				  obj_desc2->string.length;
158     		break;
159     
160     
161     	case ACPI_TYPE_BUFFER:
162     
163     		/* Operand1 is a buffer */
164     
165     		ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
166     		if (!ret_desc) {
167     			return (AE_NO_MEMORY);
168     		}
169     
170     		new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length +
171     				  obj_desc2->buffer.length);
172     		if (!new_buf) {
173     			REPORT_ERROR
174     				(("Ex_do_concatenate: Buffer allocation failure\n"));
175     			status = AE_NO_MEMORY;
176     			goto cleanup;
177     		}
178     
179     		MEMCPY (new_buf, obj_desc->buffer.pointer,
180     				  obj_desc->buffer.length);
181     		MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
182     				  obj_desc2->buffer.length);
183     
184     		/*
185     		 * Point the return object to the new buffer
186     		 */
187     
188     		ret_desc->buffer.pointer    = (u8 *) new_buf;
189     		ret_desc->buffer.length     = obj_desc->buffer.length +
190     				 obj_desc2->buffer.length;
191     		break;
192     
193     	default:
194     		status = AE_AML_INTERNAL;
195     		ret_desc = NULL;
196     	}
197     
198     
199     	*actual_ret_desc = ret_desc;
200     	return (AE_OK);
201     
202     
203     cleanup:
204     
205     	acpi_ut_remove_reference (ret_desc);
206     	return (status);
207     }
208     
209     
210     /*******************************************************************************
211      *
212      * FUNCTION:    Acpi_ex_dyadic1
213      *
214      * PARAMETERS:  Opcode              - The opcode to be executed
215      *              Walk_state          - Current walk state
216      *
217      * RETURN:      Status
218      *
219      * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands:
220      *              Notify_op
221      *
222      * ALLOCATION:  Deletes both operands
223      *
224      ******************************************************************************/
225     
226     acpi_status
227     acpi_ex_dyadic1 (
228     	u16                     opcode,
229     	acpi_walk_state         *walk_state)
230     {
231     	acpi_operand_object     **operand = &walk_state->operands[0];
232     	acpi_namespace_node     *node;
233     	acpi_status             status = AE_OK;
234     
235     
236     	FUNCTION_TRACE_PTR ("Ex_dyadic1", WALK_OPERANDS);
237     
238     
239     	/* Examine the opcode */
240     
241     	switch (opcode) {
242     
243     	/* Def_notify  :=  Notify_op   (0)Notify_object   (1)Notify_value */
244     
245     	case AML_NOTIFY_OP:
246     
247     		/* The Obj_desc is actually an Node */
248     
249     		node = (acpi_namespace_node *) operand[0];
250     		operand[0] = NULL;
251     
252     		/* Object must be a device or thermal zone */
253     
254     		if (node && operand[1]) {
255     			switch (node->type) {
256     			case ACPI_TYPE_DEVICE:
257     			case ACPI_TYPE_THERMAL:
258     
259     				/*
260     				 * Dispatch the notify to the appropriate handler
261     				 * NOTE: the request is queued for execution after this method
262     				 * completes.  The notify handlers are NOT invoked synchronously
263     				 * from this thread -- because handlers may in turn run other
264     				 * control methods.
265     				 */
266     				status = acpi_ev_queue_notify_request (node,
267     						 (u32) operand[1]->integer.value);
268     				break;
269     
270     			default:
271     				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type %X\n",
272     					operand[0]->common.type));
273     
274     				status = AE_AML_OPERAND_TYPE;
275     				break;
276     			}
277     		}
278     		break;
279     
280     	default:
281     
282     		REPORT_ERROR (("Acpi_ex_dyadic1: Unknown dyadic opcode %X\n", opcode));
283     		status = AE_AML_BAD_OPCODE;
284     	}
285     
286     
287     	/* Always delete both operands */
288     
289     	acpi_ut_remove_reference (operand[1]);
290     	acpi_ut_remove_reference (operand[0]);
291     
292     
293     	return_ACPI_STATUS (status);
294     }
295     
296     
297     /*******************************************************************************
298      *
299      * FUNCTION:    Acpi_ex_dyadic2_r
300      *
301      * PARAMETERS:  Opcode              - The opcode to be executed
302      *              Walk_state          - Current walk state
303      *              Return_desc         - Where to store the return object
304      *
305      * RETURN:      Status
306      *
307      * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and
308      *              one or two result operands.
309      *
310      * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
311      *
312      ******************************************************************************/
313     
314     acpi_status
315     acpi_ex_dyadic2_r (
316     	u16                     opcode,
317     	acpi_walk_state         *walk_state,
318     	acpi_operand_object     **return_desc)
319     {
320     	acpi_operand_object     **operand = &walk_state->operands[0];
321     	acpi_operand_object     *ret_desc   = NULL;
322     	acpi_operand_object     *ret_desc2  = NULL;
323     	acpi_status             status      = AE_OK;
324     
325     
326     	FUNCTION_TRACE_U32 ("Ex_dyadic2_r", opcode);
327     
328     
329     	/* Create an internal return object if necessary */
330     
331     	switch (opcode) {
332     	case AML_ADD_OP:
333     	case AML_BIT_AND_OP:
334     	case AML_BIT_NAND_OP:
335     	case AML_BIT_OR_OP:
336     	case AML_BIT_NOR_OP:
337     	case AML_BIT_XOR_OP:
338     	case AML_DIVIDE_OP:
339     	case AML_MOD_OP:
340     	case AML_MULTIPLY_OP:
341     	case AML_SHIFT_LEFT_OP:
342     	case AML_SHIFT_RIGHT_OP:
343     	case AML_SUBTRACT_OP:
344     
345     		ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
346     		if (!ret_desc) {
347     			status = AE_NO_MEMORY;
348     			goto cleanup;
349     		}
350     
351     		break;
352     	}
353     
354     
355     	/*
356     	 * Execute the opcode
357     	 */
358     	switch (opcode) {
359     
360     	/* Def_add :=  Add_op  Operand1    Operand2    Result  */
361     
362     	case AML_ADD_OP:
363     
364     		ret_desc->integer.value = operand[0]->integer.value +
365     				  operand[1]->integer.value;
366     		break;
367     
368     
369     	/* Def_and :=  And_op  Operand1    Operand2    Result  */
370     
371     	case AML_BIT_AND_OP:
372     
373     		ret_desc->integer.value = operand[0]->integer.value &
374     				  operand[1]->integer.value;
375     		break;
376     
377     
378     	/* Def_nAnd := NAnd_op Operand1    Operand2    Result  */
379     
380     	case AML_BIT_NAND_OP:
381     
382     		ret_desc->integer.value = ~(operand[0]->integer.value &
383     				 operand[1]->integer.value);
384     		break;
385     
386     
387     	/* Def_or  :=  Or_op   Operand1    Operand2    Result  */
388     
389     	case AML_BIT_OR_OP:
390     
391     		ret_desc->integer.value = operand[0]->integer.value |
392     				  operand[1]->integer.value;
393     		break;
394     
395     
396     	/* Def_nOr :=  NOr_op  Operand1    Operand2    Result  */
397     
398     	case AML_BIT_NOR_OP:
399     
400     		ret_desc->integer.value = ~(operand[0]->integer.value |
401     				 operand[1]->integer.value);
402     		break;
403     
404     
405     	/* Def_xOr :=  XOr_op  Operand1    Operand2    Result  */
406     
407     	case AML_BIT_XOR_OP:
408     
409     		ret_desc->integer.value = operand[0]->integer.value ^
410     				  operand[1]->integer.value;
411     		break;
412     
413     
414     	/* Def_divide  :=  Divide_op Dividend Divisor Remainder Quotient */
415     
416     	case AML_DIVIDE_OP:
417     
418     		if (!operand[1]->integer.value) {
419     			REPORT_ERROR
420     				(("Divide_op: Divide by zero\n"));
421     
422     			status = AE_AML_DIVIDE_BY_ZERO;
423     			goto cleanup;
424     		}
425     
426     		ret_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
427     		if (!ret_desc2) {
428     			status = AE_NO_MEMORY;
429     			goto cleanup;
430     		}
431     
432     		/* Remainder (modulo) */
433     
434     		ret_desc->integer.value  = ACPI_MODULO (operand[0]->integer.value,
435     				  operand[1]->integer.value);
436     
437     		/* Result (what we used to call the quotient) */
438     
439     		ret_desc2->integer.value = ACPI_DIVIDE (operand[0]->integer.value,
440     				  operand[1]->integer.value);
441     		break;
442     
443     
444     	/* Def_mod  :=  Mod_op Dividend Divisor Remainder */
445     
446     	case AML_MOD_OP:    /* ACPI 2.0 */
447     
448     		if (!operand[1]->integer.value) {
449     			REPORT_ERROR
450     				(("Mod_op: Divide by zero\n"));
451     
452     			status = AE_AML_DIVIDE_BY_ZERO;
453     			goto cleanup;
454     		}
455     
456     		/* Remainder (modulo) */
457     
458     		ret_desc->integer.value  = ACPI_MODULO (operand[0]->integer.value,
459     				  operand[1]->integer.value);
460     		break;
461     
462     
463     	/* Def_multiply := Multiply_op Operand1    Operand2    Result  */
464     
465     	case AML_MULTIPLY_OP:
466     
467     		ret_desc->integer.value = operand[0]->integer.value *
468     				  operand[1]->integer.value;
469     		break;
470     
471     
472     	/* Def_shift_left  :=  Shift_left_op Operand Shift_count Result */
473     
474     	case AML_SHIFT_LEFT_OP:
475     
476     		ret_desc->integer.value = operand[0]->integer.value <<
477     				  operand[1]->integer.value;
478     		break;
479     
480     
481     	/* Def_shift_right :=  Shift_right_op  Operand Shift_count Result  */
482     
483     	case AML_SHIFT_RIGHT_OP:
484     
485     		ret_desc->integer.value = operand[0]->integer.value >>
486     				  operand[1]->integer.value;
487     		break;
488     
489     
490     	/* Def_subtract := Subtract_op Operand1    Operand2    Result  */
491     
492     	case AML_SUBTRACT_OP:
493     
494     		ret_desc->integer.value = operand[0]->integer.value -
495     				  operand[1]->integer.value;
496     		break;
497     
498     
499     	/* Def_concat  :=  Concat_op   Data1   Data2   Result  */
500     
501     	case AML_CONCAT_OP:
502     
503     		/*
504     		 * Convert the second operand if necessary.  The first operand
505     		 * determines the type of the second operand, (See the Data Types
506     		 * section of the ACPI specification.)  Both object types are
507     		 * guaranteed to be either Integer/String/Buffer by the operand
508     		 * resolution mechanism above.
509     		 */
510     		switch (operand[0]->common.type) {
511     		case ACPI_TYPE_INTEGER:
512     			status = acpi_ex_convert_to_integer (operand[1], &operand[1], walk_state);
513     			break;
514     
515     		case ACPI_TYPE_STRING:
516     			status = acpi_ex_convert_to_string (operand[1], &operand[1], 16, ACPI_UINT32_MAX, walk_state);
517     			break;
518     
519     		case ACPI_TYPE_BUFFER:
520     			status = acpi_ex_convert_to_buffer (operand[1], &operand[1], walk_state);
521     			break;
522     
523     		default:
524     			status = AE_AML_INTERNAL;
525     		}
526     
527     		if (ACPI_FAILURE (status)) {
528     			goto cleanup;
529     		}
530     
531     
532     		/*
533     		 * Both operands are now known to be the same object type
534     		 * (Both are Integer, String, or Buffer), and we can now perform the
535     		 * concatenation.
536     		 */
537     		status = acpi_ex_do_concatenate (operand[0], operand[1], &ret_desc, walk_state);
538     		if (ACPI_FAILURE (status)) {
539     			goto cleanup;
540     		}
541     		break;
542     
543     
544     	/* Def_to_string := Buffer, Length, Result */
545     
546     	case AML_TO_STRING_OP:  /* ACPI 2.0 */
547     
548     		status = acpi_ex_convert_to_string (operand[0], &ret_desc, 16,
549     				  (u32) operand[1]->integer.value, walk_state);
550     		break;
551     
552     
553     	/* Def_concat_res := Buffer, Buffer, Result */
554     
555     	case AML_CONCAT_RES_OP:  /* ACPI 2.0 */
556     
557     		status = AE_NOT_IMPLEMENTED;
558     		goto cleanup;
559     		break;
560     
561     
562     	default:
563     
564     		REPORT_ERROR (("Acpi_ex_dyadic2_r: Unknown dyadic opcode %X\n",
565     				opcode));
566     		status = AE_AML_BAD_OPCODE;
567     		goto cleanup;
568     	}
569     
570     
571     	/*
572     	 * Store the result of the operation (which is now in Operand[0]) into
573     	 * the result descriptor, or the location pointed to by the result
574     	 * descriptor (Operand[2]).
575     	 */
576     	status = acpi_ex_store (ret_desc, operand[2], walk_state);
577     	if (ACPI_FAILURE (status)) {
578     		goto cleanup;
579     	}
580     
581     	if (AML_DIVIDE_OP == opcode) {
582     		status = acpi_ex_store (ret_desc2, operand[3], walk_state);
583     
584     		/*
585     		 * Since the remainder is not returned, remove a reference to
586     		 * the object we created earlier
587     		 */
588     		acpi_ut_remove_reference (ret_desc);
589     		*return_desc = ret_desc2;
590     	}
591     
592     	else {
593     		*return_desc = ret_desc;
594     	}
595     
596     
597     cleanup:
598     
599     	/* Always delete the operands */
600     
601     	acpi_ut_remove_reference (operand[0]);
602     	acpi_ut_remove_reference (operand[1]);
603     
604     
605     	/* Delete return object on error */
606     
607     	if (ACPI_FAILURE (status)) {
608     		/* On failure, delete the result ops */
609     
610     		acpi_ut_remove_reference (operand[2]);
611     		acpi_ut_remove_reference (operand[3]);
612     
613     		if (ret_desc) {
614     			/* And delete the internal return object */
615     
616     			acpi_ut_remove_reference (ret_desc);
617     			ret_desc = NULL;
618     		}
619     	}
620     
621     	/* Set the return object and exit */
622     
623     	return_ACPI_STATUS (status);
624     }
625     
626     
627     /*******************************************************************************
628      *
629      * FUNCTION:    Acpi_ex_dyadic2_s
630      *
631      * PARAMETERS:  Opcode              - The opcode to be executed
632      *              Walk_state          - Current walk state
633      *              Return_desc         - Where to store the return object
634      *
635      * RETURN:      Status
636      *
637      * DESCRIPTION: Execute Type 2 dyadic synchronization operator
638      *
639      * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
640      *
641      ******************************************************************************/
642     
643     acpi_status
644     acpi_ex_dyadic2_s (
645     	u16                     opcode,
646     	acpi_walk_state         *walk_state,
647     	acpi_operand_object     **return_desc)
648     {
649     	acpi_operand_object     **operand = &walk_state->operands[0];
650     	acpi_operand_object     *ret_desc = NULL;
651     	acpi_status             status;
652     
653     
654     	FUNCTION_TRACE_PTR ("Ex_dyadic2_s", WALK_OPERANDS);
655     
656     
657     	/* Create the internal return object */
658     
659     	ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
660     	if (!ret_desc) {
661     		status = AE_NO_MEMORY;
662     		goto cleanup;
663     	}
664     
665     	/* Default return value is FALSE, operation did not time out */
666     
667     	ret_desc->integer.value = 0;
668     
669     
670     	/* Examine the opcode */
671     
672     	switch (opcode) {
673     
674     	/* Def_acquire :=  Acquire_op  Mutex_object Timeout */
675     
676     	case AML_ACQUIRE_OP:
677     
678     		status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
679     		break;
680     
681     
682     	/* Def_wait := Wait_op Acpi_event_object Timeout */
683     
684     	case AML_WAIT_OP:
685     
686     		status = acpi_ex_system_wait_event (operand[1], operand[0]);
687     		break;
688     
689     
690     	default:
691     
692     		REPORT_ERROR (("Acpi_ex_dyadic2_s: Unknown dyadic synchronization opcode %X\n", opcode));
693     		status = AE_AML_BAD_OPCODE;
694     		goto cleanup;
695     	}
696     
697     
698     	/*
699     	 * Return a boolean indicating if operation timed out
700     	 * (TRUE) or not (FALSE)
701     	 */
702     	if (status == AE_TIME) {
703     		ret_desc->integer.value = ACPI_INTEGER_MAX;  /* TRUE, op timed out */
704     		status = AE_OK;
705     	}
706     
707     
708     cleanup:
709     
710     	/* Delete params */
711     
712     	acpi_ut_remove_reference (operand[1]);
713     	acpi_ut_remove_reference (operand[0]);
714     
715     	/* Delete return object on error */
716     
717     	if (ACPI_FAILURE (status) &&
718     		(ret_desc)) {
719     		acpi_ut_remove_reference (ret_desc);
720     		ret_desc = NULL;
721     	}
722     
723     
724     	/* Set the return object and exit */
725     
726     	*return_desc = ret_desc;
727     	return_ACPI_STATUS (status);
728     }
729     
730     
731     /*******************************************************************************
732      *
733      * FUNCTION:    Acpi_ex_dyadic2
734      *
735      * PARAMETERS:  Opcode              - The opcode to be executed
736      *              Walk_state          - Current walk state
737      *              Return_desc         - Where to store the return object
738      *
739      * RETURN:      Status
740      *
741      * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and
742      *              no result operands
743      *
744      * ALLOCATION:  Deletes one operand descriptor -- other remains on stack
745      *              containing result value
746      *
747      ******************************************************************************/
748     
749     acpi_status
750     acpi_ex_dyadic2 (
751     	u16                     opcode,
752     	acpi_walk_state         *walk_state,
753     	acpi_operand_object     **return_desc)
754     {
755     	acpi_operand_object     **operand = &walk_state->operands[0];
756     	acpi_operand_object     *ret_desc = NULL;
757     	acpi_status             status = AE_OK;
758     	u8                      lboolean;
759     
760     
761     	FUNCTION_TRACE_PTR ("Ex_dyadic2", WALK_OPERANDS);
762     
763     
764     	/* Create the internal return object */
765     
766     	ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
767     	if (!ret_desc) {
768     		status = AE_NO_MEMORY;
769     		goto cleanup;
770     	}
771     
772     	/*
773     	 * Execute the Opcode
774     	 */
775     	lboolean = FALSE;
776     	switch (opcode) {
777     
778     	/* Def_lAnd := LAnd_op Operand1    Operand2    */
779     
780     	case AML_LAND_OP:
781     
782     		lboolean = (u8) (operand[0]->integer.value &&
783     				  operand[1]->integer.value);
784     		break;
785     
786     
787     	/* Def_lEqual  :=  LEqual_op   Operand1    Operand2    */
788     
789     	case AML_LEQUAL_OP:
790     
791     		lboolean = (u8) (operand[0]->integer.value ==
792     				  operand[1]->integer.value);
793     		break;
794     
795     
796     	/* Def_lGreater := LGreater_op Operand1    Operand2    */
797     
798     	case AML_LGREATER_OP:
799     
800     		lboolean = (u8) (operand[0]->integer.value >
801     				  operand[1]->integer.value);
802     		break;
803     
804     
805     	/* Def_lLess   :=  LLess_op Operand1   Operand2    */
806     
807     	case AML_LLESS_OP:
808     
809     		lboolean = (u8) (operand[0]->integer.value <
810     				  operand[1]->integer.value);
811     		break;
812     
813     
814     	/* Def_lOr :=  LOr_op  Operand1    Operand2    */
815     
816     	case AML_LOR_OP:
817     
818     		lboolean = (u8) (operand[0]->integer.value ||
819     				  operand[1]->integer.value);
820     		break;
821     
822     
823     	/* Def_copy := Source, Destination */
824     
825     	case AML_COPY_OP:   /* ACPI 2.0 */
826     
827     		status = AE_NOT_IMPLEMENTED;
828     		goto cleanup;
829     		break;
830     
831     
832     	default:
833     
834     		REPORT_ERROR (("Acpi_ex_dyadic2: Unknown dyadic opcode %X\n", opcode));
835     		status = AE_AML_BAD_OPCODE;
836     		goto cleanup;
837     		break;
838     	}
839     
840     
841     	/* Set return value to logical TRUE (all ones) or FALSE (zero) */
842     
843     	if (lboolean) {
844     		ret_desc->integer.value = ACPI_INTEGER_MAX;
845     	}
846     	else {
847     		ret_desc->integer.value = 0;
848     	}
849     
850     
851     cleanup:
852     
853     	/* Always delete operands */
854     
855     	acpi_ut_remove_reference (operand[0]);
856     	acpi_ut_remove_reference (operand[1]);
857     
858     
859     	/* Delete return object on error */
860     
861     	if (ACPI_FAILURE (status) &&
862     		(ret_desc)) {
863     		acpi_ut_remove_reference (ret_desc);
864     		ret_desc = NULL;
865     	}
866     
867     
868     	/* Set the return object and exit */
869     
870     	*return_desc = ret_desc;
871     	return_ACPI_STATUS (status);
872     }
873     
874     
875