Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/disassembler/dmcstyle.c
48524 views
1
/*******************************************************************************
2
*
3
* Module Name: dmcstyle - Support for C-style operator disassembly
4
*
5
******************************************************************************/
6
7
/******************************************************************************
8
*
9
* 1. Copyright Notice
10
*
11
* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
12
* All rights reserved.
13
*
14
* 2. License
15
*
16
* 2.1. This is your license from Intel Corp. under its intellectual property
17
* rights. You may have additional license terms from the party that provided
18
* you this software, covering your right to use that party's intellectual
19
* property rights.
20
*
21
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
* copy of the source code appearing in this file ("Covered Code") an
23
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
* base code distributed originally by Intel ("Original Intel Code") to copy,
25
* make derivatives, distribute, use and display any portion of the Covered
26
* Code in any form, with the right to sublicense such rights; and
27
*
28
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
* license (with the right to sublicense), under only those claims of Intel
30
* patents that are infringed by the Original Intel Code, to make, use, sell,
31
* offer to sell, and import the Covered Code and derivative works thereof
32
* solely to the minimum extent necessary to exercise the above copyright
33
* license, and in no event shall the patent license extend to any additions
34
* to or modifications of the Original Intel Code. No other license or right
35
* is granted directly or by implication, estoppel or otherwise;
36
*
37
* The above copyright and patent license is granted only if the following
38
* conditions are met:
39
*
40
* 3. Conditions
41
*
42
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
* Redistribution of source code of any substantial portion of the Covered
44
* Code or modification with rights to further distribute source must include
45
* the above Copyright Notice, the above License, this list of Conditions,
46
* and the following Disclaimer and Export Compliance provision. In addition,
47
* Licensee must cause all Covered Code to which Licensee contributes to
48
* contain a file documenting the changes Licensee made to create that Covered
49
* Code and the date of any change. Licensee must include in that file the
50
* documentation of any changes made by any predecessor Licensee. Licensee
51
* must include a prominent statement that the modification is derived,
52
* directly or indirectly, from Original Intel Code.
53
*
54
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
* Redistribution of source code of any substantial portion of the Covered
56
* Code or modification without rights to further distribute source must
57
* include the following Disclaimer and Export Compliance provision in the
58
* documentation and/or other materials provided with distribution. In
59
* addition, Licensee may not authorize further sublicense of source of any
60
* portion of the Covered Code, and must include terms to the effect that the
61
* license from Licensee to its licensee is limited to the intellectual
62
* property embodied in the software Licensee provides to its licensee, and
63
* not to intellectual property embodied in modifications its licensee may
64
* make.
65
*
66
* 3.3. Redistribution of Executable. Redistribution in executable form of any
67
* substantial portion of the Covered Code or modification must reproduce the
68
* above Copyright Notice, and the following Disclaimer and Export Compliance
69
* provision in the documentation and/or other materials provided with the
70
* distribution.
71
*
72
* 3.4. Intel retains all right, title, and interest in and to the Original
73
* Intel Code.
74
*
75
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
* Intel shall be used in advertising or otherwise to promote the sale, use or
77
* other dealings in products derived from or relating to the Covered Code
78
* without prior written authorization from Intel.
79
*
80
* 4. Disclaimer and Export Compliance
81
*
82
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
* PARTICULAR PURPOSE.
89
*
90
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
* LIMITED REMEDY.
98
*
99
* 4.3. Licensee shall not export, either directly or indirectly, any of this
100
* software or system incorporating such software without first obtaining any
101
* required license or other approval from the U. S. Department of Commerce or
102
* any other agency or department of the United States Government. In the
103
* event Licensee exports any such software from the United States or
104
* re-exports any such software from a foreign destination, Licensee shall
105
* ensure that the distribution and export/re-export of the software is in
106
* compliance with all laws, regulations, orders, or other restrictions of the
107
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
* any of its subsidiaries will export/re-export any technical data, process,
109
* software, or service, directly or indirectly, to any country for which the
110
* United States government or any agency thereof requires an export license,
111
* other governmental approval, or letter of assurance, without first obtaining
112
* such license, approval or letter.
113
*
114
*****************************************************************************
115
*
116
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acparser.h>
155
#include <contrib/dev/acpica/include/amlcode.h>
156
#include <contrib/dev/acpica/include/acdebug.h>
157
#include <contrib/dev/acpica/include/acconvert.h>
158
159
160
#define _COMPONENT ACPI_CA_DEBUGGER
161
ACPI_MODULE_NAME ("dmcstyle")
162
163
164
/* Local prototypes */
165
166
static char *
167
AcpiDmGetCompoundSymbol (
168
UINT16 AslOpcode);
169
170
static void
171
AcpiDmPromoteTarget (
172
ACPI_PARSE_OBJECT *Op,
173
ACPI_PARSE_OBJECT *Target);
174
175
static BOOLEAN
176
AcpiDmIsValidTarget (
177
ACPI_PARSE_OBJECT *Op);
178
179
static BOOLEAN
180
AcpiDmIsTargetAnOperand (
181
ACPI_PARSE_OBJECT *Target,
182
ACPI_PARSE_OBJECT *Operand,
183
BOOLEAN TopLevel);
184
185
static BOOLEAN
186
AcpiDmIsOptimizationIgnored (
187
ACPI_PARSE_OBJECT *StoreOp,
188
ACPI_PARSE_OBJECT *StoreArgument);
189
190
191
/*******************************************************************************
192
*
193
* FUNCTION: AcpiDmCheckForSymbolicOpcode
194
*
195
* PARAMETERS: Op - Current parse object
196
* Walk - Current parse tree walk info
197
*
198
* RETURN: TRUE if opcode can be converted to symbolic, FALSE otherwise
199
*
200
* DESCRIPTION: This is the main code that implements disassembly of AML code
201
* to C-style operators. Called during descending phase of the
202
* parse tree walk.
203
*
204
******************************************************************************/
205
206
BOOLEAN
207
AcpiDmCheckForSymbolicOpcode (
208
ACPI_PARSE_OBJECT *Op,
209
ACPI_OP_WALK_INFO *Info)
210
{
211
char *OperatorSymbol = NULL;
212
ACPI_PARSE_OBJECT *Argument1;
213
ACPI_PARSE_OBJECT *Argument2;
214
ACPI_PARSE_OBJECT *Target;
215
ACPI_PARSE_OBJECT *Target2;
216
217
218
/* Exit immediately if ASL+ not enabled */
219
220
if (!AcpiGbl_CstyleDisassembly)
221
{
222
return (FALSE);
223
}
224
225
/* Get the first operand */
226
227
Argument1 = AcpiPsGetArg (Op, 0);
228
if (!Argument1)
229
{
230
return (FALSE);
231
}
232
233
/* Get the second operand */
234
235
Argument2 = Argument1->Common.Next;
236
237
/* Setup the operator string for this opcode */
238
239
switch (Op->Common.AmlOpcode)
240
{
241
case AML_ADD_OP:
242
OperatorSymbol = " + ";
243
break;
244
245
case AML_SUBTRACT_OP:
246
OperatorSymbol = " - ";
247
break;
248
249
case AML_MULTIPLY_OP:
250
OperatorSymbol = " * ";
251
break;
252
253
case AML_DIVIDE_OP:
254
OperatorSymbol = " / ";
255
break;
256
257
case AML_MOD_OP:
258
OperatorSymbol = " % ";
259
break;
260
261
case AML_SHIFT_LEFT_OP:
262
OperatorSymbol = " << ";
263
break;
264
265
case AML_SHIFT_RIGHT_OP:
266
OperatorSymbol = " >> ";
267
break;
268
269
case AML_BIT_AND_OP:
270
OperatorSymbol = " & ";
271
break;
272
273
case AML_BIT_OR_OP:
274
OperatorSymbol = " | ";
275
break;
276
277
case AML_BIT_XOR_OP:
278
OperatorSymbol = " ^ ";
279
break;
280
281
/* Logical operators, no target */
282
283
case AML_LOGICAL_AND_OP:
284
OperatorSymbol = " && ";
285
break;
286
287
case AML_LOGICAL_EQUAL_OP:
288
OperatorSymbol = " == ";
289
break;
290
291
case AML_LOGICAL_GREATER_OP:
292
OperatorSymbol = " > ";
293
break;
294
295
case AML_LOGICAL_LESS_OP:
296
OperatorSymbol = " < ";
297
break;
298
299
case AML_LOGICAL_OR_OP:
300
OperatorSymbol = " || ";
301
break;
302
303
case AML_LOGICAL_NOT_OP:
304
/*
305
* Check for the LNOT sub-opcodes. These correspond to
306
* LNotEqual, LLessEqual, and LGreaterEqual. There are
307
* no actual AML opcodes for these operators.
308
*/
309
switch (Argument1->Common.AmlOpcode)
310
{
311
case AML_LOGICAL_EQUAL_OP:
312
OperatorSymbol = " != ";
313
break;
314
315
case AML_LOGICAL_GREATER_OP:
316
OperatorSymbol = " <= ";
317
break;
318
319
case AML_LOGICAL_LESS_OP:
320
OperatorSymbol = " >= ";
321
break;
322
323
default:
324
325
/* Unary LNOT case, emit "!" immediately */
326
327
AcpiOsPrintf ("!");
328
return (TRUE);
329
}
330
331
Argument1->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
332
Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
333
334
/* Save symbol string in the next child (not peer) */
335
336
Argument2 = AcpiPsGetArg (Argument1, 0);
337
if (!Argument2)
338
{
339
return (FALSE);
340
}
341
342
Argument2->Common.OperatorSymbol = OperatorSymbol;
343
return (TRUE);
344
345
case AML_INDEX_OP:
346
/*
347
* Check for constant source operand. Note: although technically
348
* legal syntax, the iASL compiler does not support this with
349
* the symbolic operators for Index(). It doesn't make sense to
350
* use Index() with a constant anyway.
351
*/
352
if ((Argument1->Common.AmlOpcode == AML_STRING_OP) ||
353
(Argument1->Common.AmlOpcode == AML_BUFFER_OP) ||
354
(Argument1->Common.AmlOpcode == AML_PACKAGE_OP) ||
355
(Argument1->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
356
{
357
Op->Common.DisasmFlags |= ACPI_PARSEOP_CLOSING_PAREN;
358
return (FALSE);
359
}
360
361
/* Index operator is [] */
362
363
Argument1->Common.OperatorSymbol = " [";
364
Argument2->Common.OperatorSymbol = "]";
365
break;
366
367
/* Unary operators */
368
369
case AML_DECREMENT_OP:
370
OperatorSymbol = "--";
371
break;
372
373
case AML_INCREMENT_OP:
374
OperatorSymbol = "++";
375
break;
376
377
case AML_BIT_NOT_OP:
378
case AML_STORE_OP:
379
OperatorSymbol = NULL;
380
break;
381
382
default:
383
return (FALSE);
384
}
385
386
if (Argument1->Common.DisasmOpcode == ACPI_DASM_LNOT_SUFFIX)
387
{
388
return (TRUE);
389
}
390
391
/*
392
* This is the key to how the disassembly of the C-style operators
393
* works. We save the operator symbol in the first child, thus
394
* deferring symbol output until after the first operand has been
395
* emitted.
396
*/
397
if (!Argument1->Common.OperatorSymbol)
398
{
399
Argument1->Common.OperatorSymbol = OperatorSymbol;
400
}
401
402
/*
403
* Check for a valid target as the 3rd (or sometimes 2nd) operand
404
*
405
* Compound assignment operator support:
406
* Attempt to optimize constructs of the form:
407
* Add (Local1, 0xFF, Local1)
408
* to:
409
* Local1 += 0xFF
410
*
411
* Only the math operators and Store() have a target.
412
* Logicals have no target.
413
*/
414
switch (Op->Common.AmlOpcode)
415
{
416
case AML_ADD_OP:
417
case AML_SUBTRACT_OP:
418
case AML_MULTIPLY_OP:
419
case AML_DIVIDE_OP:
420
case AML_MOD_OP:
421
case AML_SHIFT_LEFT_OP:
422
case AML_SHIFT_RIGHT_OP:
423
case AML_BIT_AND_OP:
424
case AML_BIT_OR_OP:
425
case AML_BIT_XOR_OP:
426
427
/* Target is 3rd operand */
428
429
Target = Argument2->Common.Next;
430
if (Op->Common.AmlOpcode == AML_DIVIDE_OP)
431
{
432
Target2 = Target->Common.Next;
433
434
/*
435
* Divide has an extra target operand (Remainder).
436
* Default behavior is to simply ignore ASL+ conversion
437
* if the remainder target (modulo) is specified.
438
*/
439
if (!AcpiGbl_DoDisassemblerOptimizations)
440
{
441
if (AcpiDmIsValidTarget (Target))
442
{
443
Argument1->Common.OperatorSymbol = NULL;
444
Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
445
return (FALSE);
446
}
447
448
Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
449
Target = Target2;
450
}
451
else
452
{
453
/*
454
* Divide has an extra target operand (Remainder).
455
* If both targets are specified, it cannot be converted
456
* to a C-style operator.
457
*/
458
if (AcpiDmIsValidTarget (Target) &&
459
AcpiDmIsValidTarget (Target2))
460
{
461
Argument1->Common.OperatorSymbol = NULL;
462
Op->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
463
return (FALSE);
464
}
465
466
if (AcpiDmIsValidTarget (Target)) /* Only first Target is valid (remainder) */
467
{
468
/* Convert the Divide to Modulo */
469
470
Op->Common.AmlOpcode = AML_MOD_OP;
471
472
Argument1->Common.OperatorSymbol = " % ";
473
Target2->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
474
}
475
else /* Only second Target (quotient) is valid */
476
{
477
Target->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
478
Target = Target2;
479
}
480
}
481
}
482
483
/* Parser should ensure there is at least a placeholder target */
484
485
if (!Target)
486
{
487
return (FALSE);
488
}
489
490
if (!AcpiDmIsValidTarget (Target))
491
{
492
/* Not a valid target (placeholder only, from parser) */
493
break;
494
}
495
496
/*
497
* Promote the target up to the first child in the parse
498
* tree. This is done because the target will be output
499
* first, in the form:
500
* <Target> = Operands...
501
*/
502
AcpiDmPromoteTarget (Op, Target);
503
504
/* Check operands for conversion to a "Compound Assignment" */
505
506
switch (Op->Common.AmlOpcode)
507
{
508
/* Commutative operators */
509
510
case AML_ADD_OP:
511
case AML_MULTIPLY_OP:
512
case AML_BIT_AND_OP:
513
case AML_BIT_OR_OP:
514
case AML_BIT_XOR_OP:
515
/*
516
* For the commutative operators, we can convert to a
517
* compound statement only if at least one (either) operand
518
* is the same as the target.
519
*
520
* Add (A, B, A) --> A += B
521
* Add (B, A, A) --> A += B
522
* Add (B, C, A) --> A = (B + C)
523
*/
524
if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)) ||
525
(AcpiDmIsTargetAnOperand (Target, Argument2, TRUE)))
526
{
527
Target->Common.OperatorSymbol =
528
AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
529
530
/* Convert operator to compound assignment */
531
532
Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
533
Argument1->Common.OperatorSymbol = NULL;
534
return (TRUE);
535
}
536
break;
537
538
/* Non-commutative operators */
539
540
case AML_SUBTRACT_OP:
541
case AML_DIVIDE_OP:
542
case AML_MOD_OP:
543
case AML_SHIFT_LEFT_OP:
544
case AML_SHIFT_RIGHT_OP:
545
/*
546
* For the non-commutative operators, we can convert to a
547
* compound statement only if the target is the same as the
548
* first operand.
549
*
550
* Subtract (A, B, A) --> A -= B
551
* Subtract (B, A, A) --> A = (B - A)
552
*/
553
if ((AcpiDmIsTargetAnOperand (Target, Argument1, TRUE)))
554
{
555
Target->Common.OperatorSymbol =
556
AcpiDmGetCompoundSymbol (Op->Common.AmlOpcode);
557
558
/* Convert operator to compound assignment */
559
560
Op->Common.DisasmFlags |= ACPI_PARSEOP_COMPOUND_ASSIGNMENT;
561
Argument1->Common.OperatorSymbol = NULL;
562
return (TRUE);
563
}
564
break;
565
566
default:
567
break;
568
}
569
570
/*
571
* If we are within a C-style expression, emit an extra open
572
* paren. Implemented by examining the parent op.
573
*/
574
switch (Op->Common.Parent->Common.AmlOpcode)
575
{
576
case AML_ADD_OP:
577
case AML_SUBTRACT_OP:
578
case AML_MULTIPLY_OP:
579
case AML_DIVIDE_OP:
580
case AML_MOD_OP:
581
case AML_SHIFT_LEFT_OP:
582
case AML_SHIFT_RIGHT_OP:
583
case AML_BIT_AND_OP:
584
case AML_BIT_OR_OP:
585
case AML_BIT_XOR_OP:
586
case AML_LOGICAL_AND_OP:
587
case AML_LOGICAL_EQUAL_OP:
588
case AML_LOGICAL_GREATER_OP:
589
case AML_LOGICAL_LESS_OP:
590
case AML_LOGICAL_OR_OP:
591
592
Op->Common.DisasmFlags |= ACPI_PARSEOP_ASSIGNMENT;
593
AcpiOsPrintf ("(");
594
break;
595
596
default:
597
break;
598
}
599
600
/* Normal output for ASL/AML operators with a target operand */
601
602
Target->Common.OperatorSymbol = " = (";
603
return (TRUE);
604
605
/* Binary operators, no parens */
606
607
case AML_DECREMENT_OP:
608
case AML_INCREMENT_OP:
609
return (TRUE);
610
611
case AML_INDEX_OP:
612
613
/* Target is optional, 3rd operand */
614
615
Target = Argument2->Common.Next;
616
if (AcpiDmIsValidTarget (Target))
617
{
618
AcpiDmPromoteTarget (Op, Target);
619
620
if (!Target->Common.OperatorSymbol)
621
{
622
Target->Common.OperatorSymbol = " = ";
623
}
624
}
625
return (TRUE);
626
627
case AML_STORE_OP:
628
/*
629
* For Store, the Target is the 2nd operand. We know the target
630
* is valid, because it is not optional.
631
*
632
* Ignore any optimizations/folding if flag is set.
633
* Used for iASL/disassembler test suite only.
634
*/
635
if (AcpiDmIsOptimizationIgnored (Op, Argument1))
636
{
637
return (FALSE);
638
}
639
640
/*
641
* Perform conversion.
642
* In the parse tree, simply swap the target with the
643
* source so that the target is processed first.
644
*/
645
Target = Argument1->Common.Next;
646
if (!Target)
647
{
648
return (FALSE);
649
}
650
651
AcpiDmPromoteTarget (Op, Target);
652
if (!Target->Common.OperatorSymbol)
653
{
654
Target->Common.OperatorSymbol = " = ";
655
}
656
return (TRUE);
657
658
case AML_BIT_NOT_OP:
659
660
/* Target is optional, 2nd operand */
661
662
Target = Argument1->Common.Next;
663
if (!Target)
664
{
665
return (FALSE);
666
}
667
668
if (AcpiDmIsValidTarget (Target))
669
{
670
/* Valid target, not a placeholder */
671
672
AcpiDmPromoteTarget (Op, Target);
673
Target->Common.OperatorSymbol = " = ~";
674
}
675
else
676
{
677
/* No target. Emit this prefix operator immediately */
678
679
AcpiOsPrintf ("~");
680
}
681
return (TRUE);
682
683
default:
684
break;
685
}
686
687
/* All other operators, emit an open paren */
688
689
AcpiOsPrintf ("(");
690
return (TRUE);
691
}
692
693
694
/*******************************************************************************
695
*
696
* FUNCTION: AcpiDmIsOptimizationIgnored
697
*
698
* PARAMETERS: StoreOp - Store operator parse object
699
* StoreArgument - Target associate with the Op
700
*
701
* RETURN: TRUE if this Store operator should not be converted/removed.
702
*
703
* DESCRIPTION: The following function implements "Do not optimize if a
704
* store is immediately followed by a math/bit operator that
705
* has no target".
706
*
707
* Function is ignored if DoDisassemblerOptimizations is TRUE.
708
* This is the default, ignore this function.
709
*
710
* Disables these types of optimizations, and simply emits
711
* legacy ASL code:
712
* Store (Add (INT1, 4), INT2) --> Add (INT1, 4, INT2)
713
* --> INT2 = INT1 + 4
714
*
715
* Store (Not (INT1), INT2) --> Not (INT1, INT2)
716
* --> INT2 = ~INT1
717
*
718
* Used only for the ASL test suite. For the test suite, we
719
* don't want to perform some optimizations to ensure binary
720
* compatibility with the generation of the legacy ASL->AML.
721
* In other words, for all test modules we want exactly:
722
* (ASL+ -> AML) == (ASL- -> AML)
723
*
724
******************************************************************************/
725
726
static BOOLEAN
727
AcpiDmIsOptimizationIgnored (
728
ACPI_PARSE_OBJECT *StoreOp,
729
ACPI_PARSE_OBJECT *StoreArgument)
730
{
731
ACPI_PARSE_OBJECT *Argument1;
732
ACPI_PARSE_OBJECT *Argument2;
733
ACPI_PARSE_OBJECT *Target;
734
735
736
/* No optimizations/folding for the typical case */
737
738
if (AcpiGbl_DoDisassemblerOptimizations)
739
{
740
return (FALSE);
741
}
742
743
/*
744
* Only a small subset of ASL/AML operators can be optimized.
745
* Can only optimize/fold if there is no target (or targets)
746
* specified for the operator. And of course, the operator
747
* is surrounded by a Store() operator.
748
*/
749
switch (StoreArgument->Common.AmlOpcode)
750
{
751
case AML_ADD_OP:
752
case AML_SUBTRACT_OP:
753
case AML_MULTIPLY_OP:
754
case AML_MOD_OP:
755
case AML_SHIFT_LEFT_OP:
756
case AML_SHIFT_RIGHT_OP:
757
case AML_BIT_AND_OP:
758
case AML_BIT_OR_OP:
759
case AML_BIT_XOR_OP:
760
case AML_INDEX_OP:
761
762
/* These operators have two arguments and one target */
763
764
Argument1 = StoreArgument->Common.Value.Arg;
765
Argument2 = Argument1->Common.Next;
766
Target = Argument2->Common.Next;
767
768
if (!AcpiDmIsValidTarget (Target))
769
{
770
StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
771
return (TRUE);
772
}
773
break;
774
775
case AML_DIVIDE_OP:
776
777
/* This operator has two arguments and two targets */
778
779
Argument1 = StoreArgument->Common.Value.Arg;
780
Argument2 = Argument1->Common.Next;
781
Target = Argument2->Common.Next;
782
783
if (!AcpiDmIsValidTarget (Target) ||
784
!AcpiDmIsValidTarget (Target->Common.Next))
785
{
786
StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
787
return (TRUE);
788
}
789
break;
790
791
case AML_BIT_NOT_OP:
792
793
/* This operator has one operand and one target */
794
795
Argument1 = StoreArgument->Common.Value.Arg;
796
Target = Argument1->Common.Next;
797
798
if (!AcpiDmIsValidTarget (Target))
799
{
800
StoreOp->Common.DisasmFlags |= ACPI_PARSEOP_LEGACY_ASL_ONLY;
801
return (TRUE);
802
}
803
break;
804
805
default:
806
break;
807
}
808
809
return (FALSE);
810
}
811
812
813
/*******************************************************************************
814
*
815
* FUNCTION: AcpiDmCloseOperator
816
*
817
* PARAMETERS: Op - Current parse object
818
*
819
* RETURN: None
820
*
821
* DESCRIPTION: Closes an operator by adding a closing parentheses if and
822
* when necessary. Called during ascending phase of the
823
* parse tree walk.
824
*
825
******************************************************************************/
826
827
void
828
AcpiDmCloseOperator (
829
ACPI_PARSE_OBJECT *Op)
830
{
831
832
/* Always emit paren if ASL+ disassembly disabled */
833
834
if (!AcpiGbl_CstyleDisassembly)
835
{
836
AcpiOsPrintf (")");
837
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
838
return;
839
}
840
841
if (Op->Common.DisasmFlags & ACPI_PARSEOP_LEGACY_ASL_ONLY)
842
{
843
AcpiOsPrintf (")");
844
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
845
return;
846
}
847
848
/* Check if we need to add an additional closing paren */
849
850
switch (Op->Common.AmlOpcode)
851
{
852
case AML_ADD_OP:
853
case AML_SUBTRACT_OP:
854
case AML_MULTIPLY_OP:
855
case AML_DIVIDE_OP:
856
case AML_MOD_OP:
857
case AML_SHIFT_LEFT_OP:
858
case AML_SHIFT_RIGHT_OP:
859
case AML_BIT_AND_OP:
860
case AML_BIT_OR_OP:
861
case AML_BIT_XOR_OP:
862
case AML_LOGICAL_AND_OP:
863
case AML_LOGICAL_EQUAL_OP:
864
case AML_LOGICAL_GREATER_OP:
865
case AML_LOGICAL_LESS_OP:
866
case AML_LOGICAL_OR_OP:
867
868
/* Emit paren only if this is not a compound assignment */
869
870
if (Op->Common.DisasmFlags & ACPI_PARSEOP_COMPOUND_ASSIGNMENT)
871
{
872
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
873
return;
874
}
875
876
/* Emit extra close paren for assignment within an expression */
877
878
if (Op->Common.DisasmFlags & ACPI_PARSEOP_ASSIGNMENT)
879
{
880
AcpiOsPrintf (")");
881
}
882
break;
883
884
case AML_INDEX_OP:
885
886
/* This is case for unsupported Index() source constants */
887
888
if (Op->Common.DisasmFlags & ACPI_PARSEOP_CLOSING_PAREN)
889
{
890
AcpiOsPrintf (")");
891
}
892
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
893
return;
894
895
/* No need for parens for these */
896
897
case AML_DECREMENT_OP:
898
case AML_INCREMENT_OP:
899
case AML_LOGICAL_NOT_OP:
900
case AML_BIT_NOT_OP:
901
case AML_STORE_OP:
902
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
903
return;
904
905
default:
906
907
/* Always emit paren for non-ASL+ operators */
908
break;
909
}
910
911
AcpiOsPrintf (")");
912
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
913
914
return;
915
}
916
917
918
/*******************************************************************************
919
*
920
* FUNCTION: AcpiDmGetCompoundSymbol
921
*
922
* PARAMETERS: AslOpcode
923
*
924
* RETURN: String containing the compound assignment symbol
925
*
926
* DESCRIPTION: Detect opcodes that can be converted to compound assignment,
927
* return the appropriate operator string.
928
*
929
******************************************************************************/
930
931
static char *
932
AcpiDmGetCompoundSymbol (
933
UINT16 AmlOpcode)
934
{
935
char *Symbol;
936
937
938
switch (AmlOpcode)
939
{
940
case AML_ADD_OP:
941
Symbol = " += ";
942
break;
943
944
case AML_SUBTRACT_OP:
945
Symbol = " -= ";
946
break;
947
948
case AML_MULTIPLY_OP:
949
Symbol = " *= ";
950
break;
951
952
case AML_DIVIDE_OP:
953
Symbol = " /= ";
954
break;
955
956
case AML_MOD_OP:
957
Symbol = " %= ";
958
break;
959
960
case AML_SHIFT_LEFT_OP:
961
Symbol = " <<= ";
962
break;
963
964
case AML_SHIFT_RIGHT_OP:
965
Symbol = " >>= ";
966
break;
967
968
case AML_BIT_AND_OP:
969
Symbol = " &= ";
970
break;
971
972
case AML_BIT_OR_OP:
973
Symbol = " |= ";
974
break;
975
976
case AML_BIT_XOR_OP:
977
Symbol = " ^= ";
978
break;
979
980
default:
981
982
/* No operator string for all other opcodes */
983
984
return (NULL);
985
}
986
987
return (Symbol);
988
}
989
990
991
/*******************************************************************************
992
*
993
* FUNCTION: AcpiDmPromoteTarget
994
*
995
* PARAMETERS: Op - Operator parse object
996
* Target - Target associate with the Op
997
*
998
* RETURN: None
999
*
1000
* DESCRIPTION: Transform the parse tree by moving the target up to the first
1001
* child of the Op.
1002
*
1003
******************************************************************************/
1004
1005
static void
1006
AcpiDmPromoteTarget (
1007
ACPI_PARSE_OBJECT *Op,
1008
ACPI_PARSE_OBJECT *Target)
1009
{
1010
ACPI_PARSE_OBJECT *Child;
1011
1012
1013
/* Link target directly to the Op as first child */
1014
1015
Child = Op->Common.Value.Arg;
1016
Op->Common.Value.Arg = Target;
1017
Target->Common.Next = Child;
1018
1019
/* Find the last peer, it is linked to the target. Unlink it. */
1020
1021
while (Child->Common.Next != Target)
1022
{
1023
Child = Child->Common.Next;
1024
}
1025
1026
Child->Common.Next = NULL;
1027
}
1028
1029
1030
/*******************************************************************************
1031
*
1032
* FUNCTION: AcpiDmIsValidTarget
1033
*
1034
* PARAMETERS: Target - Target Op from the parse tree
1035
*
1036
* RETURN: TRUE if the Target is real. FALSE if it is just a placeholder
1037
* Op that was inserted by the parser.
1038
*
1039
* DESCRIPTION: Determine if a Target Op is a placeholder Op or a real Target.
1040
* In other words, determine if the optional target is used or
1041
* not. Note: If Target is NULL, something is seriously wrong,
1042
* probably with the parse tree.
1043
*
1044
******************************************************************************/
1045
1046
static BOOLEAN
1047
AcpiDmIsValidTarget (
1048
ACPI_PARSE_OBJECT *Target)
1049
{
1050
1051
if (!Target)
1052
{
1053
return (FALSE);
1054
}
1055
1056
if ((Target->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
1057
(Target->Common.Value.Arg == NULL))
1058
{
1059
return (FALSE);
1060
}
1061
1062
return (TRUE);
1063
}
1064
1065
1066
/*******************************************************************************
1067
*
1068
* FUNCTION: AcpiDmIsTargetAnOperand
1069
*
1070
* PARAMETERS: Target - Target associated with the expression
1071
* Operand - An operand associated with expression
1072
*
1073
* RETURN: TRUE if expression can be converted to a compound assignment.
1074
* FALSE otherwise.
1075
*
1076
* DESCRIPTION: Determine if the Target duplicates the operand, in order to
1077
* detect if the expression can be converted to a compound
1078
* assignment. (+=, *=, etc.)
1079
*
1080
******************************************************************************/
1081
1082
static BOOLEAN
1083
AcpiDmIsTargetAnOperand (
1084
ACPI_PARSE_OBJECT *Target,
1085
ACPI_PARSE_OBJECT *Operand,
1086
BOOLEAN TopLevel)
1087
{
1088
const ACPI_OPCODE_INFO *OpInfo;
1089
BOOLEAN Same;
1090
1091
1092
/*
1093
* Opcodes must match. Note: ignoring the difference between nameseg
1094
* and namepath for now. May be needed later.
1095
*/
1096
if (Target->Common.AmlOpcode != Operand->Common.AmlOpcode)
1097
{
1098
return (FALSE);
1099
}
1100
1101
/* Nodes should match, even if they are NULL */
1102
1103
if (Target->Common.Node != Operand->Common.Node)
1104
{
1105
return (FALSE);
1106
}
1107
1108
/* Determine if a child exists */
1109
1110
OpInfo = AcpiPsGetOpcodeInfo (Operand->Common.AmlOpcode);
1111
if (OpInfo->Flags & AML_HAS_ARGS)
1112
{
1113
Same = AcpiDmIsTargetAnOperand (Target->Common.Value.Arg,
1114
Operand->Common.Value.Arg, FALSE);
1115
if (!Same)
1116
{
1117
return (FALSE);
1118
}
1119
}
1120
1121
/* Check the next peer, as long as we are not at the top level */
1122
1123
if ((!TopLevel) &&
1124
Target->Common.Next)
1125
{
1126
Same = AcpiDmIsTargetAnOperand (Target->Common.Next,
1127
Operand->Common.Next, FALSE);
1128
if (!Same)
1129
{
1130
return (FALSE);
1131
}
1132
}
1133
1134
/* Suppress the duplicate operand at the top-level */
1135
1136
if (TopLevel)
1137
{
1138
Operand->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1139
}
1140
return (TRUE);
1141
}
1142
1143