00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "tm_p.h"
00033 #include "regs.h"
00034 #include "hard-reg-set.h"
00035 #include "real.h"
00036 #include "insn-config.h"
00037 #include "conditions.h"
00038 #include "output.h"
00039 #include "insn-codes.h"
00040 #include "insn-attr.h"
00041 #include "flags.h"
00042 #include "except.h"
00043 #include "function.h"
00044 #include "recog.h"
00045 #include "expr.h"
00046 #include "optabs.h"
00047 #include "toplev.h"
00048 #include "basic-block.h"
00049 #include "ggc.h"
00050 #include "target.h"
00051 #include "target-def.h"
00052 #include "langhooks.h"
00053 #include "cgraph.h"
00054 #include "tree-gimple.h"
00055 #include "dwarf2.h"
00056 #include "tm-constrs.h"
00057
00058 #ifndef CHECK_STACK_LIMIT
00059 #define CHECK_STACK_LIMIT (-1)
00060 #endif
00061
00062
00063 #define MODE_INDEX(mode) \
00064 ((mode) == QImode ? 0 \
00065 : (mode) == HImode ? 1 \
00066 : (mode) == SImode ? 2 \
00067 : (mode) == DImode ? 3 \
00068 : 4)
00069
00070
00071
00072 #define COSTS_N_BYTES(N) ((N) * 2)
00073
00074 static const
00075 struct processor_costs size_cost = {
00076 COSTS_N_BYTES (2),
00077 COSTS_N_BYTES (3),
00078 COSTS_N_BYTES (2),
00079 COSTS_N_BYTES (3),
00080 {COSTS_N_BYTES (3),
00081 COSTS_N_BYTES (3),
00082 COSTS_N_BYTES (3),
00083 COSTS_N_BYTES (3),
00084 COSTS_N_BYTES (5)},
00085 0,
00086 {COSTS_N_BYTES (3),
00087 COSTS_N_BYTES (3),
00088 COSTS_N_BYTES (3),
00089 COSTS_N_BYTES (3),
00090 COSTS_N_BYTES (5)},
00091 COSTS_N_BYTES (3),
00092 COSTS_N_BYTES (3),
00093 0,
00094 2,
00095 2,
00096 {2, 2, 2},
00097
00098
00099 {2, 2, 2},
00100 2,
00101 {2, 2, 2},
00102
00103 {2, 2, 2},
00104
00105 3,
00106 {3, 3},
00107
00108 {3, 3},
00109
00110 3,
00111 {3, 3, 3},
00112
00113 {3, 3, 3},
00114
00115 3,
00116 0,
00117 0,
00118 2,
00119 COSTS_N_BYTES (2),
00120 COSTS_N_BYTES (2),
00121 COSTS_N_BYTES (2),
00122 COSTS_N_BYTES (2),
00123 COSTS_N_BYTES (2),
00124 COSTS_N_BYTES (2),
00125 };
00126
00127
00128 static const
00129 struct processor_costs i386_cost = {
00130 COSTS_N_INSNS (1),
00131 COSTS_N_INSNS (1),
00132 COSTS_N_INSNS (3),
00133 COSTS_N_INSNS (2),
00134 {COSTS_N_INSNS (6),
00135 COSTS_N_INSNS (6),
00136 COSTS_N_INSNS (6),
00137 COSTS_N_INSNS (6),
00138 COSTS_N_INSNS (6)},
00139 COSTS_N_INSNS (1),
00140 {COSTS_N_INSNS (23),
00141 COSTS_N_INSNS (23),
00142 COSTS_N_INSNS (23),
00143 COSTS_N_INSNS (23),
00144 COSTS_N_INSNS (23)},
00145 COSTS_N_INSNS (3),
00146 COSTS_N_INSNS (2),
00147 15,
00148 3,
00149 4,
00150 {2, 4, 2},
00151
00152
00153 {2, 4, 2},
00154 2,
00155 {8, 8, 8},
00156
00157 {8, 8, 8},
00158
00159 2,
00160 {4, 8},
00161
00162 {4, 8},
00163
00164 2,
00165 {4, 8, 16},
00166
00167 {4, 8, 16},
00168
00169 3,
00170 0,
00171 0,
00172 1,
00173 COSTS_N_INSNS (23),
00174 COSTS_N_INSNS (27),
00175 COSTS_N_INSNS (88),
00176 COSTS_N_INSNS (22),
00177 COSTS_N_INSNS (24),
00178 COSTS_N_INSNS (122),
00179 };
00180
00181 static const
00182 struct processor_costs i486_cost = {
00183 COSTS_N_INSNS (1),
00184 COSTS_N_INSNS (1),
00185 COSTS_N_INSNS (3),
00186 COSTS_N_INSNS (2),
00187 {COSTS_N_INSNS (12),
00188 COSTS_N_INSNS (12),
00189 COSTS_N_INSNS (12),
00190 COSTS_N_INSNS (12),
00191 COSTS_N_INSNS (12)},
00192 1,
00193 {COSTS_N_INSNS (40),
00194 COSTS_N_INSNS (40),
00195 COSTS_N_INSNS (40),
00196 COSTS_N_INSNS (40),
00197 COSTS_N_INSNS (40)},
00198 COSTS_N_INSNS (3),
00199 COSTS_N_INSNS (2),
00200 15,
00201 3,
00202 4,
00203 {2, 4, 2},
00204
00205
00206 {2, 4, 2},
00207 2,
00208 {8, 8, 8},
00209
00210 {8, 8, 8},
00211
00212 2,
00213 {4, 8},
00214
00215 {4, 8},
00216
00217 2,
00218 {4, 8, 16},
00219
00220 {4, 8, 16},
00221
00222 3,
00223 0,
00224 0,
00225 1,
00226 COSTS_N_INSNS (8),
00227 COSTS_N_INSNS (16),
00228 COSTS_N_INSNS (73),
00229 COSTS_N_INSNS (3),
00230 COSTS_N_INSNS (3),
00231 COSTS_N_INSNS (83),
00232 };
00233
00234 static const
00235 struct processor_costs pentium_cost = {
00236 COSTS_N_INSNS (1),
00237 COSTS_N_INSNS (1),
00238 COSTS_N_INSNS (4),
00239 COSTS_N_INSNS (1),
00240 {COSTS_N_INSNS (11),
00241 COSTS_N_INSNS (11),
00242 COSTS_N_INSNS (11),
00243 COSTS_N_INSNS (11),
00244 COSTS_N_INSNS (11)},
00245 0,
00246 {COSTS_N_INSNS (25),
00247 COSTS_N_INSNS (25),
00248 COSTS_N_INSNS (25),
00249 COSTS_N_INSNS (25),
00250 COSTS_N_INSNS (25)},
00251 COSTS_N_INSNS (3),
00252 COSTS_N_INSNS (2),
00253 8,
00254 6,
00255 6,
00256 {2, 4, 2},
00257
00258
00259 {2, 4, 2},
00260 2,
00261 {2, 2, 6},
00262
00263 {4, 4, 6},
00264
00265 8,
00266 {8, 8},
00267
00268 {8, 8},
00269
00270 2,
00271 {4, 8, 16},
00272
00273 {4, 8, 16},
00274
00275 3,
00276 0,
00277 0,
00278 2,
00279 COSTS_N_INSNS (3),
00280 COSTS_N_INSNS (3),
00281 COSTS_N_INSNS (39),
00282 COSTS_N_INSNS (1),
00283 COSTS_N_INSNS (1),
00284 COSTS_N_INSNS (70),
00285 };
00286
00287 static const
00288 struct processor_costs pentiumpro_cost = {
00289 COSTS_N_INSNS (1),
00290 COSTS_N_INSNS (1),
00291 COSTS_N_INSNS (1),
00292 COSTS_N_INSNS (1),
00293 {COSTS_N_INSNS (4),
00294 COSTS_N_INSNS (4),
00295 COSTS_N_INSNS (4),
00296 COSTS_N_INSNS (4),
00297 COSTS_N_INSNS (4)},
00298 0,
00299 {COSTS_N_INSNS (17),
00300 COSTS_N_INSNS (17),
00301 COSTS_N_INSNS (17),
00302 COSTS_N_INSNS (17),
00303 COSTS_N_INSNS (17)},
00304 COSTS_N_INSNS (1),
00305 COSTS_N_INSNS (1),
00306 8,
00307 6,
00308 2,
00309 {4, 4, 4},
00310
00311
00312 {2, 2, 2},
00313 2,
00314 {2, 2, 6},
00315
00316 {4, 4, 6},
00317
00318 2,
00319 {2, 2},
00320
00321 {2, 2},
00322
00323 2,
00324 {2, 2, 8},
00325
00326 {2, 2, 8},
00327
00328 3,
00329 32,
00330 6,
00331 2,
00332 COSTS_N_INSNS (3),
00333 COSTS_N_INSNS (5),
00334 COSTS_N_INSNS (56),
00335 COSTS_N_INSNS (2),
00336 COSTS_N_INSNS (2),
00337 COSTS_N_INSNS (56),
00338 };
00339
00340 static const
00341 struct processor_costs k6_cost = {
00342 COSTS_N_INSNS (1),
00343 COSTS_N_INSNS (2),
00344 COSTS_N_INSNS (1),
00345 COSTS_N_INSNS (1),
00346 {COSTS_N_INSNS (3),
00347 COSTS_N_INSNS (3),
00348 COSTS_N_INSNS (3),
00349 COSTS_N_INSNS (3),
00350 COSTS_N_INSNS (3)},
00351 0,
00352 {COSTS_N_INSNS (18),
00353 COSTS_N_INSNS (18),
00354 COSTS_N_INSNS (18),
00355 COSTS_N_INSNS (18),
00356 COSTS_N_INSNS (18)},
00357 COSTS_N_INSNS (2),
00358 COSTS_N_INSNS (2),
00359 8,
00360 4,
00361 3,
00362 {4, 5, 4},
00363
00364
00365 {2, 3, 2},
00366 4,
00367 {6, 6, 6},
00368
00369 {4, 4, 4},
00370
00371 2,
00372 {2, 2},
00373
00374 {2, 2},
00375
00376 2,
00377 {2, 2, 8},
00378
00379 {2, 2, 8},
00380
00381 6,
00382 32,
00383 1,
00384 1,
00385 COSTS_N_INSNS (2),
00386 COSTS_N_INSNS (2),
00387 COSTS_N_INSNS (56),
00388 COSTS_N_INSNS (2),
00389 COSTS_N_INSNS (2),
00390 COSTS_N_INSNS (56),
00391 };
00392
00393 static const
00394 struct processor_costs athlon_cost = {
00395 COSTS_N_INSNS (1),
00396 COSTS_N_INSNS (2),
00397 COSTS_N_INSNS (1),
00398 COSTS_N_INSNS (1),
00399 {COSTS_N_INSNS (5),
00400 COSTS_N_INSNS (5),
00401 COSTS_N_INSNS (5),
00402 COSTS_N_INSNS (5),
00403 COSTS_N_INSNS (5)},
00404 0,
00405 {COSTS_N_INSNS (18),
00406 COSTS_N_INSNS (26),
00407 COSTS_N_INSNS (42),
00408 COSTS_N_INSNS (74),
00409 COSTS_N_INSNS (74)},
00410 COSTS_N_INSNS (1),
00411 COSTS_N_INSNS (1),
00412 8,
00413 9,
00414 4,
00415 {3, 4, 3},
00416
00417
00418 {3, 4, 3},
00419 4,
00420 {4, 4, 12},
00421
00422 {6, 6, 8},
00423
00424 2,
00425 {4, 4},
00426
00427 {4, 4},
00428
00429 2,
00430 {4, 4, 6},
00431
00432 {4, 4, 5},
00433
00434 5,
00435 64,
00436 6,
00437 5,
00438 COSTS_N_INSNS (4),
00439 COSTS_N_INSNS (4),
00440 COSTS_N_INSNS (24),
00441 COSTS_N_INSNS (2),
00442 COSTS_N_INSNS (2),
00443 COSTS_N_INSNS (35),
00444 };
00445
00446 static const
00447 struct processor_costs k8_cost = {
00448 COSTS_N_INSNS (1),
00449 COSTS_N_INSNS (2),
00450 COSTS_N_INSNS (1),
00451 COSTS_N_INSNS (1),
00452 {COSTS_N_INSNS (3),
00453 COSTS_N_INSNS (4),
00454 COSTS_N_INSNS (3),
00455 COSTS_N_INSNS (4),
00456 COSTS_N_INSNS (5)},
00457 0,
00458 {COSTS_N_INSNS (18),
00459 COSTS_N_INSNS (26),
00460 COSTS_N_INSNS (42),
00461 COSTS_N_INSNS (74),
00462 COSTS_N_INSNS (74)},
00463 COSTS_N_INSNS (1),
00464 COSTS_N_INSNS (1),
00465 8,
00466 9,
00467 4,
00468 {3, 4, 3},
00469
00470
00471 {3, 4, 3},
00472 4,
00473 {4, 4, 12},
00474
00475 {6, 6, 8},
00476
00477 2,
00478 {3, 3},
00479
00480 {4, 4},
00481
00482 2,
00483 {4, 3, 6},
00484
00485 {4, 4, 5},
00486
00487 5,
00488 64,
00489 6,
00490 5,
00491 COSTS_N_INSNS (4),
00492 COSTS_N_INSNS (4),
00493 COSTS_N_INSNS (19),
00494 COSTS_N_INSNS (2),
00495 COSTS_N_INSNS (2),
00496 COSTS_N_INSNS (35),
00497 };
00498
00499 struct processor_costs amdfam10_cost = {
00500 COSTS_N_INSNS (1),
00501 COSTS_N_INSNS (2),
00502 COSTS_N_INSNS (1),
00503 COSTS_N_INSNS (1),
00504 {COSTS_N_INSNS (3),
00505 COSTS_N_INSNS (4),
00506 COSTS_N_INSNS (3),
00507 COSTS_N_INSNS (4),
00508 COSTS_N_INSNS (5)},
00509 0,
00510 {COSTS_N_INSNS (19),
00511 COSTS_N_INSNS (35),
00512 COSTS_N_INSNS (51),
00513 COSTS_N_INSNS (83),
00514 COSTS_N_INSNS (83)},
00515 COSTS_N_INSNS (1),
00516 COSTS_N_INSNS (1),
00517 8,
00518 9,
00519 4,
00520 {3, 4, 3},
00521
00522
00523 {3, 4, 3},
00524 4,
00525 {4, 4, 12},
00526
00527 {6, 6, 8},
00528
00529 2,
00530 {3, 3},
00531
00532 {4, 4},
00533
00534 2,
00535 {4, 4, 3},
00536
00537 {4, 4, 5},
00538
00539 3,
00540
00541
00542
00543
00544
00545
00546
00547
00548 64,
00549
00550
00551
00552
00553
00554 100,
00555 5,
00556 COSTS_N_INSNS (4),
00557 COSTS_N_INSNS (4),
00558 COSTS_N_INSNS (19),
00559 COSTS_N_INSNS (2),
00560 COSTS_N_INSNS (2),
00561 COSTS_N_INSNS (35),
00562 };
00563
00564
00565
00566
00567 static const
00568 struct processor_costs pentium4_cost = {
00569 COSTS_N_INSNS (1),
00570 COSTS_N_INSNS (3),
00571 COSTS_N_INSNS (4),
00572 COSTS_N_INSNS (4),
00573 {COSTS_N_INSNS (15),
00574 COSTS_N_INSNS (15),
00575 COSTS_N_INSNS (15),
00576 COSTS_N_INSNS (15),
00577 COSTS_N_INSNS (15)},
00578 0,
00579 {COSTS_N_INSNS (56),
00580 COSTS_N_INSNS (56),
00581 COSTS_N_INSNS (56),
00582 COSTS_N_INSNS (56),
00583 COSTS_N_INSNS (56)},
00584 COSTS_N_INSNS (1),
00585 COSTS_N_INSNS (1),
00586 16,
00587 6,
00588 2,
00589 {4, 5, 4},
00590
00591
00592 {2, 3, 2},
00593 2,
00594 {2, 2, 6},
00595
00596 {4, 4, 6},
00597
00598 2,
00599 {2, 2},
00600
00601 {2, 2},
00602
00603 12,
00604 {12, 12, 12},
00605
00606 {2, 2, 8},
00607
00608 10,
00609 64,
00610 6,
00611 2,
00612 COSTS_N_INSNS (5),
00613 COSTS_N_INSNS (7),
00614 COSTS_N_INSNS (43),
00615 COSTS_N_INSNS (2),
00616 COSTS_N_INSNS (2),
00617 COSTS_N_INSNS (43),
00618 };
00619
00620 static const
00621 struct processor_costs nocona_cost = {
00622 COSTS_N_INSNS (1),
00623 COSTS_N_INSNS (1),
00624 COSTS_N_INSNS (1),
00625 COSTS_N_INSNS (1),
00626 {COSTS_N_INSNS (10),
00627 COSTS_N_INSNS (10),
00628 COSTS_N_INSNS (10),
00629 COSTS_N_INSNS (10),
00630 COSTS_N_INSNS (10)},
00631 0,
00632 {COSTS_N_INSNS (66),
00633 COSTS_N_INSNS (66),
00634 COSTS_N_INSNS (66),
00635 COSTS_N_INSNS (66),
00636 COSTS_N_INSNS (66)},
00637 COSTS_N_INSNS (1),
00638 COSTS_N_INSNS (1),
00639 16,
00640 17,
00641 4,
00642 {4, 4, 4},
00643
00644
00645 {4, 4, 4},
00646 3,
00647 {12, 12, 12},
00648
00649 {4, 4, 4},
00650
00651 6,
00652 {12, 12},
00653
00654 {12, 12},
00655
00656 6,
00657 {12, 12, 12},
00658
00659 {12, 12, 12},
00660
00661 8,
00662 128,
00663 8,
00664 1,
00665 COSTS_N_INSNS (6),
00666 COSTS_N_INSNS (8),
00667 COSTS_N_INSNS (40),
00668 COSTS_N_INSNS (3),
00669 COSTS_N_INSNS (3),
00670 COSTS_N_INSNS (44),
00671 };
00672
00673
00674 static const
00675 struct processor_costs generic64_cost = {
00676 COSTS_N_INSNS (1),
00677
00678
00679
00680
00681 COSTS_N_INSNS (1) + 1,
00682 COSTS_N_INSNS (1),
00683 COSTS_N_INSNS (1),
00684 {COSTS_N_INSNS (3),
00685 COSTS_N_INSNS (4),
00686 COSTS_N_INSNS (3),
00687 COSTS_N_INSNS (4),
00688 COSTS_N_INSNS (2)},
00689 0,
00690 {COSTS_N_INSNS (18),
00691 COSTS_N_INSNS (26),
00692 COSTS_N_INSNS (42),
00693 COSTS_N_INSNS (74),
00694 COSTS_N_INSNS (74)},
00695 COSTS_N_INSNS (1),
00696 COSTS_N_INSNS (1),
00697 8,
00698 17,
00699 4,
00700 {4, 4, 4},
00701
00702
00703 {4, 4, 4},
00704 4,
00705 {12, 12, 12},
00706
00707 {6, 6, 8},
00708
00709 2,
00710 {8, 8},
00711
00712 {8, 8},
00713
00714 2,
00715 {8, 8, 8},
00716
00717 {8, 8, 8},
00718
00719 5,
00720 64,
00721 6,
00722
00723
00724 3,
00725 COSTS_N_INSNS (8),
00726 COSTS_N_INSNS (8),
00727 COSTS_N_INSNS (20),
00728 COSTS_N_INSNS (8),
00729 COSTS_N_INSNS (8),
00730 COSTS_N_INSNS (40),
00731 };
00732
00733
00734 static const
00735 struct processor_costs generic32_cost = {
00736 COSTS_N_INSNS (1),
00737 COSTS_N_INSNS (1) + 1,
00738 COSTS_N_INSNS (1),
00739 COSTS_N_INSNS (1),
00740 {COSTS_N_INSNS (3),
00741 COSTS_N_INSNS (4),
00742 COSTS_N_INSNS (3),
00743 COSTS_N_INSNS (4),
00744 COSTS_N_INSNS (2)},
00745 0,
00746 {COSTS_N_INSNS (18),
00747 COSTS_N_INSNS (26),
00748 COSTS_N_INSNS (42),
00749 COSTS_N_INSNS (74),
00750 COSTS_N_INSNS (74)},
00751 COSTS_N_INSNS (1),
00752 COSTS_N_INSNS (1),
00753 8,
00754 17,
00755 4,
00756 {4, 4, 4},
00757
00758
00759 {4, 4, 4},
00760 4,
00761 {12, 12, 12},
00762
00763 {6, 6, 8},
00764
00765 2,
00766 {8, 8},
00767
00768 {8, 8},
00769
00770 2,
00771 {8, 8, 8},
00772
00773 {8, 8, 8},
00774
00775 5,
00776 64,
00777 6,
00778 3,
00779 COSTS_N_INSNS (8),
00780 COSTS_N_INSNS (8),
00781 COSTS_N_INSNS (20),
00782 COSTS_N_INSNS (8),
00783 COSTS_N_INSNS (8),
00784 COSTS_N_INSNS (40),
00785 };
00786
00787 const struct processor_costs *ix86_cost = &pentium_cost;
00788
00789
00790 #define m_386 (1<<PROCESSOR_I386)
00791 #define m_486 (1<<PROCESSOR_I486)
00792 #define m_PENT (1<<PROCESSOR_PENTIUM)
00793 #define m_PPRO (1<<PROCESSOR_PENTIUMPRO)
00794 #define m_K6 (1<<PROCESSOR_K6)
00795 #define m_ATHLON (1<<PROCESSOR_ATHLON)
00796 #define m_PENT4 (1<<PROCESSOR_PENTIUM4)
00797 #define m_K8 (1<<PROCESSOR_K8)
00798 #define m_ATHLON_K8 (m_K8 | m_ATHLON)
00799 #define m_AMDFAM10 (1<<PROCESSOR_AMDFAM10)
00800 #define m_NOCONA (1<<PROCESSOR_NOCONA)
00801 #define m_GENERIC32 (1<<PROCESSOR_GENERIC32)
00802 #define m_GENERIC64 (1<<PROCESSOR_GENERIC64)
00803 #define m_GENERIC (m_GENERIC32 | m_GENERIC64)
00804 #define m_ATHLON_K8_AMDFAM10 (m_K8 | m_ATHLON | m_AMDFAM10)
00805
00806
00807
00808
00809
00810
00811
00812 const int x86_use_leave = m_386 | m_K6 | m_GENERIC64 | m_ATHLON_K8_AMDFAM10;
00813 const int x86_push_memory = m_386 | m_K6 | m_PENT4 | m_NOCONA | m_GENERIC | m_ATHLON_K8_AMDFAM10;
00814 const int x86_zero_extend_with_and = m_486 | m_PENT;
00815 const int x86_movx = m_ATHLON_K8_AMDFAM10 | m_PPRO | m_PENT4 | m_NOCONA | m_GENERIC ;
00816 const int x86_double_with_add = ~m_386;
00817 const int x86_use_bit_test = m_386;
00818 const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON_K8_AMDFAM10 | m_K6 | m_GENERIC;
00819 const int x86_cmove = m_PPRO | m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA;
00820 const int x86_3dnow_a = m_ATHLON_K8_AMDFAM10;
00821 const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_GENERIC;
00822
00823
00824
00825
00826 const int x86_branch_hints = 0;
00827 const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4 | m_NOCONA | m_GENERIC32;
00828
00829
00830
00831
00832
00833
00834
00835
00836 const int x86_partial_reg_stall = m_PPRO;
00837 const int x86_partial_flag_reg_stall = m_GENERIC;
00838 const int x86_use_himode_fiop = m_386 | m_486 | m_K6;
00839 const int x86_use_simode_fiop = ~(m_PPRO | m_ATHLON_K8_AMDFAM10 | m_PENT | m_GENERIC);
00840 const int x86_use_mov0 = m_K6;
00841 const int x86_use_cltd = ~(m_PENT | m_K6 | m_GENERIC);
00842 const int x86_read_modify_write = ~m_PENT;
00843 const int x86_read_modify = ~(m_PENT | m_PPRO);
00844 const int x86_split_long_moves = m_PPRO;
00845 const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON_K8_AMDFAM10 | m_GENERIC;
00846 const int x86_fast_prefix = ~(m_PENT | m_486 | m_386);
00847 const int x86_single_stringop = m_386 | m_PENT4 | m_NOCONA;
00848 const int x86_qimode_math = ~(0);
00849 const int x86_promote_qi_regs = 0;
00850
00851
00852
00853 const int x86_himode_math = ~(m_PPRO);
00854 const int x86_promote_hi_regs = m_PPRO;
00855 const int x86_sub_esp_4 = m_ATHLON_K8_AMDFAM10 | m_PPRO | m_PENT4 | m_NOCONA | m_GENERIC;
00856 const int x86_sub_esp_8 = m_ATHLON_K8_AMDFAM10 | m_PPRO | m_386 | m_486 | m_PENT4 | m_NOCONA | m_GENERIC;
00857 const int x86_add_esp_4 = m_ATHLON_K8_AMDFAM10 | m_K6 | m_PENT4 | m_NOCONA | m_GENERIC;
00858 const int x86_add_esp_8 = m_ATHLON_K8_AMDFAM10 | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4 | m_NOCONA | m_GENERIC;
00859
00860 const int x86_integer_DFmode_moves = ~(m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_PPRO | m_GENERIC);
00861 const int x86_partial_reg_dependency = m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_GENERIC;
00862 const int x86_memory_mismatch_stall = m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_GENERIC;
00863
00864
00865
00866
00867
00868
00869 const int x86_accumulate_outgoing_args = m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_PPRO | m_GENERIC;
00870 const int x86_prologue_using_move = m_ATHLON_K8 | m_PPRO | m_GENERIC;
00871 const int x86_epilogue_using_move = m_ATHLON_K8 | m_PPRO | m_GENERIC;
00872 const int x86_shift1 = ~m_486;
00873 const int x86_arch_always_fancy_math_387 = m_PENT | m_PPRO | m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_GENERIC;
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883 const int x86_sse_partial_reg_dependency = m_PENT4 | m_NOCONA | m_PPRO | m_GENERIC | m_AMDFAM10;
00884
00885
00886
00887
00888 const int x86_sse_split_regs = m_ATHLON_K8;
00889 const int x86_sse_unaligned_move_optimal = m_AMDFAM10;
00890 const int x86_sse_typeless_stores = m_ATHLON_K8;
00891 const int x86_sse_load0_by_pxor = m_PPRO | m_PENT4 | m_NOCONA;
00892 const int x86_use_ffreep = m_ATHLON_K8_AMDFAM10;
00893 const int x86_rep_movl_optimal = m_386 | m_PENT | m_PPRO | m_K6;
00894 const int x86_use_incdec = ~(m_PENT4 | m_NOCONA | m_GENERIC);
00895
00896
00897
00898 const int x86_inter_unit_moves = 0 ;
00899
00900 const int x86_ext_80387_constants = m_K6 | m_ATHLON | m_PENT4 | m_NOCONA | m_PPRO | m_GENERIC32;
00901
00902
00903 const int x86_four_jump_limit = m_PPRO | m_ATHLON_K8_AMDFAM10 | m_PENT4 | m_NOCONA | m_GENERIC;
00904 const int x86_schedule = m_PPRO | m_ATHLON_K8_AMDFAM10 | m_K6 | m_PENT | m_GENERIC;
00905 const int x86_use_bt = m_ATHLON_K8_AMDFAM10;
00906
00907 const int x86_cmpxchg = ~m_386;
00908
00909 const int x86_cmpxchg8b = ~(m_386 | m_486);
00910
00911 const int x86_cmpxchg16b = m_NOCONA;
00912
00913 const int x86_xadd = ~m_386;
00914 const int x86_pad_returns = m_ATHLON_K8_AMDFAM10 | m_GENERIC;
00915
00916
00917
00918 #define FAST_PROLOGUE_INSN_COUNT 20
00919
00920
00921 static const char *const qi_reg_name[] = QI_REGISTER_NAMES;
00922 static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
00923 static const char *const hi_reg_name[] = HI_REGISTER_NAMES;
00924
00925
00926
00927
00928 enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
00929 {
00930
00931 AREG, DREG, CREG, BREG,
00932
00933 SIREG, DIREG, NON_Q_REGS, NON_Q_REGS,
00934
00935 FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
00936 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
00937
00938 NON_Q_REGS,
00939
00940 NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS,
00941 SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
00942 SSE_REGS, SSE_REGS,
00943 MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
00944 MMX_REGS, MMX_REGS,
00945 NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
00946 NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
00947 SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
00948 SSE_REGS, SSE_REGS,
00949 };
00950
00951
00952
00953 int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
00954 {
00955 0, 2, 1, 3, 6, 7, 4, 5,
00956 12, 13, 14, 15, 16, 17, 18, 19,
00957 -1, -1, -1, -1, -1,
00958 21, 22, 23, 24, 25, 26, 27, 28,
00959 29, 30, 31, 32, 33, 34, 35, 36,
00960 -1, -1, -1, -1, -1, -1, -1, -1,
00961 -1, -1, -1, -1, -1, -1, -1, -1,
00962 };
00963
00964 static int const x86_64_int_parameter_registers[6] =
00965 {
00966 5 , 4 , 1 , 2 ,
00967 FIRST_REX_INT_REG , FIRST_REX_INT_REG + 1
00968 };
00969
00970 static int const x86_64_int_return_registers[4] =
00971 {
00972 0 , 1 , 5 , 4
00973 };
00974
00975
00976 int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
00977 {
00978 0, 1, 2, 3, 4, 5, 6, 7,
00979 33, 34, 35, 36, 37, 38, 39, 40,
00980 -1, -1, -1, -1, -1,
00981 17, 18, 19, 20, 21, 22, 23, 24,
00982 41, 42, 43, 44, 45, 46, 47, 48,
00983 8,9,10,11,12,13,14,15,
00984 25, 26, 27, 28, 29, 30, 31, 32,
00985 };
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
01042 {
01043 0, 2, 1, 3, 6, 7, 5, 4,
01044 11, 12, 13, 14, 15, 16, 17, 18,
01045 -1, 9, -1, -1, -1,
01046 21, 22, 23, 24, 25, 26, 27, 28,
01047 29, 30, 31, 32, 33, 34, 35, 36,
01048 -1, -1, -1, -1, -1, -1, -1, -1,
01049 -1, -1, -1, -1, -1, -1, -1, -1,
01050 };
01051
01052
01053
01054
01055 rtx ix86_compare_op0 = NULL_RTX;
01056 rtx ix86_compare_op1 = NULL_RTX;
01057 rtx ix86_compare_emitted = NULL_RTX;
01058
01059
01060 #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
01061
01062
01063
01064 struct stack_local_entry GTY(())
01065 {
01066 unsigned short mode;
01067 unsigned short n;
01068 rtx rtl;
01069 struct stack_local_entry *next;
01070 };
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 struct ix86_frame
01092 {
01093 int nregs;
01094 int padding1;
01095 int va_arg_size;
01096 HOST_WIDE_INT frame;
01097 int padding2;
01098 int outgoing_arguments_size;
01099 int red_zone_size;
01100
01101 HOST_WIDE_INT to_allocate;
01102
01103 HOST_WIDE_INT frame_pointer_offset;
01104 HOST_WIDE_INT hard_frame_pointer_offset;
01105 HOST_WIDE_INT stack_pointer_offset;
01106
01107
01108
01109 bool save_regs_using_mov;
01110 };
01111
01112
01113 enum cmodel ix86_cmodel;
01114
01115 enum asm_dialect ix86_asm_dialect = ASM_ATT;
01116
01117 enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
01118
01119
01120 enum fpmath_unit ix86_fpmath;
01121
01122
01123 enum processor_type ix86_tune;
01124
01125 enum processor_type ix86_arch;
01126
01127
01128 int x86_prefetch_sse;
01129
01130
01131 static int ix86_regparm;
01132
01133
01134 extern int ix86_force_align_arg_pointer;
01135 static const char ix86_force_align_arg_pointer_string[] = "force_align_arg_pointer";
01136
01137
01138 unsigned int ix86_preferred_stack_boundary;
01139
01140
01141 int ix86_branch_cost;
01142
01143
01144
01145
01146 int ix86_section_threshold = 65536;
01147
01148
01149 char internal_label_prefix[16];
01150 int internal_label_prefix_len;
01151
01152 static bool ix86_handle_option (size_t, const char *, int);
01153 static void output_pic_addr_const (FILE *, rtx, int);
01154 static void put_condition_code (enum rtx_code, enum machine_mode,
01155 int, int, FILE *);
01156 static const char *get_some_local_dynamic_name (void);
01157 static int get_some_local_dynamic_name_1 (rtx *, void *);
01158 static rtx ix86_expand_int_compare (enum rtx_code, rtx, rtx);
01159 static enum rtx_code ix86_prepare_fp_compare_args (enum rtx_code, rtx *,
01160 rtx *);
01161 static bool ix86_fixed_condition_code_regs (unsigned int *, unsigned int *);
01162 static enum machine_mode ix86_cc_modes_compatible (enum machine_mode,
01163 enum machine_mode);
01164 static rtx get_thread_pointer (int);
01165 static rtx legitimize_tls_address (rtx, enum tls_model, int);
01166 static void get_pc_thunk_name (char [32], unsigned int);
01167 static rtx gen_push (rtx);
01168 static int ix86_flags_dependent (rtx, rtx, enum attr_type);
01169 static int ix86_agi_dependent (rtx, rtx, enum attr_type);
01170 static struct machine_function * ix86_init_machine_status (void);
01171 static int ix86_split_to_parts (rtx, rtx *, enum machine_mode);
01172 static int ix86_nsaved_regs (void);
01173 static void ix86_emit_save_regs (void);
01174 static void ix86_emit_save_regs_using_mov (rtx, HOST_WIDE_INT);
01175 static void ix86_emit_restore_regs_using_mov (rtx, HOST_WIDE_INT, int);
01176 static void ix86_output_function_epilogue (FILE *, HOST_WIDE_INT);
01177 static HOST_WIDE_INT ix86_GOT_alias_set (void);
01178 static void ix86_adjust_counter (rtx, HOST_WIDE_INT);
01179 static rtx ix86_expand_aligntest (rtx, int);
01180 static void ix86_expand_strlensi_unroll_1 (rtx, rtx, rtx);
01181 static int ix86_issue_rate (void);
01182 static int ix86_adjust_cost (rtx, rtx, rtx, int);
01183 static int ia32_multipass_dfa_lookahead (void);
01184 static void ix86_init_mmx_sse_builtins (void);
01185 static rtx x86_this_parameter (tree);
01186 static void x86_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
01187 HOST_WIDE_INT, tree);
01188 static bool x86_can_output_mi_thunk (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
01189 static void x86_file_start (void);
01190 static void ix86_reorg (void);
01191 static bool ix86_expand_carry_flag_compare (enum rtx_code, rtx, rtx, rtx*);
01192 static tree ix86_build_builtin_va_list (void);
01193 static void ix86_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
01194 tree, int *, int);
01195 static tree ix86_gimplify_va_arg (tree, tree, tree *, tree *);
01196 static bool ix86_scalar_mode_supported_p (enum machine_mode);
01197 static bool ix86_vector_mode_supported_p (enum machine_mode);
01198
01199 static int ix86_address_cost (rtx);
01200 static bool ix86_cannot_force_const_mem (rtx);
01201 static rtx ix86_delegitimize_address (rtx);
01202
01203 static void i386_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
01204
01205 struct builtin_description;
01206 static rtx ix86_expand_sse_comi (const struct builtin_description *,
01207 tree, rtx);
01208 static rtx ix86_expand_sse_compare (const struct builtin_description *,
01209 tree, rtx);
01210 static rtx ix86_expand_unop1_builtin (enum insn_code, tree, rtx);
01211 static rtx ix86_expand_unop_builtin (enum insn_code, tree, rtx, int);
01212 static rtx ix86_expand_binop_builtin (enum insn_code, tree, rtx);
01213 static rtx ix86_expand_store_builtin (enum insn_code, tree);
01214 static rtx safe_vector_operand (rtx, enum machine_mode);
01215 static rtx ix86_expand_fp_compare (enum rtx_code, rtx, rtx, rtx, rtx *, rtx *);
01216 static int ix86_fp_comparison_arithmetics_cost (enum rtx_code code);
01217 static int ix86_fp_comparison_fcomi_cost (enum rtx_code code);
01218 static int ix86_fp_comparison_sahf_cost (enum rtx_code code);
01219 static int ix86_fp_comparison_cost (enum rtx_code code);
01220 static unsigned int ix86_select_alt_pic_regnum (void);
01221 static int ix86_save_reg (unsigned int, int);
01222 static void ix86_compute_frame_layout (struct ix86_frame *);
01223 static int ix86_comp_type_attributes (tree, tree);
01224 static int ix86_function_regparm (tree, tree);
01225 const struct attribute_spec ix86_attribute_table[];
01226 static bool ix86_function_ok_for_sibcall (tree, tree);
01227 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
01228 static int ix86_value_regno (enum machine_mode, tree, tree);
01229 static bool contains_128bit_aligned_vector_p (tree);
01230 static rtx ix86_struct_value_rtx (tree, int);
01231 static bool ix86_ms_bitfield_layout_p (tree);
01232 static tree ix86_handle_struct_attribute (tree *, tree, tree, int, bool *);
01233 static int extended_reg_mentioned_1 (rtx *, void *);
01234 static bool ix86_rtx_costs (rtx, int, int, int *);
01235 static int min_insn_size (rtx);
01236 static tree ix86_md_asm_clobbers (tree outputs, tree inputs, tree clobbers);
01237 static bool ix86_must_pass_in_stack (enum machine_mode mode, tree type);
01238 static bool ix86_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
01239 tree, bool);
01240 static void ix86_init_builtins (void);
01241 static rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
01242 static const char *ix86_mangle_fundamental_type (tree);
01243 static tree ix86_stack_protect_fail (void);
01244 static rtx ix86_internal_arg_pointer (void);
01245 static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
01246
01247
01248 static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
01249 ATTRIBUTE_UNUSED;
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 enum x86_64_reg_class
01260 {
01261 X86_64_NO_CLASS,
01262 X86_64_INTEGER_CLASS,
01263 X86_64_INTEGERSI_CLASS,
01264 X86_64_SSE_CLASS,
01265 X86_64_SSESF_CLASS,
01266 X86_64_SSEDF_CLASS,
01267 X86_64_SSEUP_CLASS,
01268 X86_64_X87_CLASS,
01269 X86_64_X87UP_CLASS,
01270 X86_64_COMPLEX_X87_CLASS,
01271 X86_64_MEMORY_CLASS
01272 };
01273 static const char * const x86_64_reg_class_name[] = {
01274 "no", "integer", "integerSI", "sse", "sseSF", "sseDF",
01275 "sseup", "x87", "x87up", "cplx87", "no"
01276 };
01277
01278 #define MAX_CLASSES 4
01279
01280
01281 static REAL_VALUE_TYPE ext_80387_constants_table [5];
01282 static bool ext_80387_constants_init = 0;
01283 static void init_ext_80387_constants (void);
01284 static bool ix86_in_large_data_p (tree) ATTRIBUTE_UNUSED;
01285 static void ix86_encode_section_info (tree, rtx, int) ATTRIBUTE_UNUSED;
01286 static void x86_64_elf_unique_section (tree decl, int reloc) ATTRIBUTE_UNUSED;
01287 static section *x86_64_elf_select_section (tree decl, int reloc,
01288 unsigned HOST_WIDE_INT align)
01289 ATTRIBUTE_UNUSED;
01290
01291
01292 #undef TARGET_ATTRIBUTE_TABLE
01293 #define TARGET_ATTRIBUTE_TABLE ix86_attribute_table
01294 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
01295 # undef TARGET_MERGE_DECL_ATTRIBUTES
01296 # define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
01297 #endif
01298
01299 #undef TARGET_COMP_TYPE_ATTRIBUTES
01300 #define TARGET_COMP_TYPE_ATTRIBUTES ix86_comp_type_attributes
01301
01302 #undef TARGET_INIT_BUILTINS
01303 #define TARGET_INIT_BUILTINS ix86_init_builtins
01304 #undef TARGET_EXPAND_BUILTIN
01305 #define TARGET_EXPAND_BUILTIN ix86_expand_builtin
01306
01307 #undef TARGET_ASM_FUNCTION_EPILOGUE
01308 #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
01309
01310 #undef TARGET_ENCODE_SECTION_INFO
01311 #ifndef SUBTARGET_ENCODE_SECTION_INFO
01312 #define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
01313 #else
01314 #define TARGET_ENCODE_SECTION_INFO SUBTARGET_ENCODE_SECTION_INFO
01315 #endif
01316
01317 #undef TARGET_ASM_OPEN_PAREN
01318 #define TARGET_ASM_OPEN_PAREN ""
01319 #undef TARGET_ASM_CLOSE_PAREN
01320 #define TARGET_ASM_CLOSE_PAREN ""
01321
01322 #undef TARGET_ASM_ALIGNED_HI_OP
01323 #define TARGET_ASM_ALIGNED_HI_OP ASM_SHORT
01324 #undef TARGET_ASM_ALIGNED_SI_OP
01325 #define TARGET_ASM_ALIGNED_SI_OP ASM_LONG
01326 #ifdef ASM_QUAD
01327 #undef TARGET_ASM_ALIGNED_DI_OP
01328 #define TARGET_ASM_ALIGNED_DI_OP ASM_QUAD
01329 #endif
01330
01331 #undef TARGET_ASM_UNALIGNED_HI_OP
01332 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
01333 #undef TARGET_ASM_UNALIGNED_SI_OP
01334 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
01335 #undef TARGET_ASM_UNALIGNED_DI_OP
01336 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
01337
01338 #undef TARGET_SCHED_ADJUST_COST
01339 #define TARGET_SCHED_ADJUST_COST ix86_adjust_cost
01340 #undef TARGET_SCHED_ISSUE_RATE
01341 #define TARGET_SCHED_ISSUE_RATE ix86_issue_rate
01342 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
01343 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
01344 ia32_multipass_dfa_lookahead
01345
01346 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
01347 #define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
01348
01349 #ifdef HAVE_AS_TLS
01350 #undef TARGET_HAVE_TLS
01351 #define TARGET_HAVE_TLS true
01352 #endif
01353 #undef TARGET_CANNOT_FORCE_CONST_MEM
01354 #define TARGET_CANNOT_FORCE_CONST_MEM ix86_cannot_force_const_mem
01355 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
01356 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_rtx_true
01357
01358 #undef TARGET_DELEGITIMIZE_ADDRESS
01359 #define TARGET_DELEGITIMIZE_ADDRESS ix86_delegitimize_address
01360
01361 #undef TARGET_MS_BITFIELD_LAYOUT_P
01362 #define TARGET_MS_BITFIELD_LAYOUT_P ix86_ms_bitfield_layout_p
01363
01364 #if TARGET_MACHO
01365 #undef TARGET_BINDS_LOCAL_P
01366 #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
01367 #endif
01368
01369 #undef TARGET_ASM_OUTPUT_MI_THUNK
01370 #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
01371 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
01372 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
01373
01374 #undef TARGET_ASM_FILE_START
01375 #define TARGET_ASM_FILE_START x86_file_start
01376
01377 #undef TARGET_DEFAULT_TARGET_FLAGS
01378 #define TARGET_DEFAULT_TARGET_FLAGS \
01379 (TARGET_DEFAULT \
01380 | TARGET_64BIT_DEFAULT \
01381 | TARGET_SUBTARGET_DEFAULT \
01382 | TARGET_TLS_DIRECT_SEG_REFS_DEFAULT)
01383
01384 #undef TARGET_HANDLE_OPTION
01385 #define TARGET_HANDLE_OPTION ix86_handle_option
01386
01387 #undef TARGET_RTX_COSTS
01388 #define TARGET_RTX_COSTS ix86_rtx_costs
01389 #undef TARGET_ADDRESS_COST
01390 #define TARGET_ADDRESS_COST ix86_address_cost
01391
01392 #undef TARGET_FIXED_CONDITION_CODE_REGS
01393 #define TARGET_FIXED_CONDITION_CODE_REGS ix86_fixed_condition_code_regs
01394 #undef TARGET_CC_MODES_COMPATIBLE
01395 #define TARGET_CC_MODES_COMPATIBLE ix86_cc_modes_compatible
01396
01397 #undef TARGET_MACHINE_DEPENDENT_REORG
01398 #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg
01399
01400 #undef TARGET_BUILD_BUILTIN_VA_LIST
01401 #define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list
01402
01403 #undef TARGET_MD_ASM_CLOBBERS
01404 #define TARGET_MD_ASM_CLOBBERS ix86_md_asm_clobbers
01405
01406 #undef TARGET_PROMOTE_PROTOTYPES
01407 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
01408 #undef TARGET_STRUCT_VALUE_RTX
01409 #define TARGET_STRUCT_VALUE_RTX ix86_struct_value_rtx
01410 #undef TARGET_SETUP_INCOMING_VARARGS
01411 #define TARGET_SETUP_INCOMING_VARARGS ix86_setup_incoming_varargs
01412 #undef TARGET_MUST_PASS_IN_STACK
01413 #define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack
01414 #undef TARGET_PASS_BY_REFERENCE
01415 #define TARGET_PASS_BY_REFERENCE ix86_pass_by_reference
01416 #undef TARGET_INTERNAL_ARG_POINTER
01417 #define TARGET_INTERNAL_ARG_POINTER ix86_internal_arg_pointer
01418 #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
01419 #define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
01420
01421 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
01422 #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
01423
01424 #undef TARGET_SCALAR_MODE_SUPPORTED_P
01425 #define TARGET_SCALAR_MODE_SUPPORTED_P ix86_scalar_mode_supported_p
01426
01427 #undef TARGET_VECTOR_MODE_SUPPORTED_P
01428 #define TARGET_VECTOR_MODE_SUPPORTED_P ix86_vector_mode_supported_p
01429
01430 #ifdef HAVE_AS_TLS
01431 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
01432 #define TARGET_ASM_OUTPUT_DWARF_DTPREL i386_output_dwarf_dtprel
01433 #endif
01434
01435 #ifdef SUBTARGET_INSERT_ATTRIBUTES
01436 #undef TARGET_INSERT_ATTRIBUTES
01437 #define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
01438 #endif
01439
01440 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
01441 #define TARGET_MANGLE_FUNDAMENTAL_TYPE ix86_mangle_fundamental_type
01442
01443 #undef TARGET_STACK_PROTECT_FAIL
01444 #define TARGET_STACK_PROTECT_FAIL ix86_stack_protect_fail
01445
01446 #undef TARGET_FUNCTION_VALUE
01447 #define TARGET_FUNCTION_VALUE ix86_function_value
01448
01449 struct gcc_target targetm = TARGET_INITIALIZER;
01450
01451
01452
01453
01454 #ifndef DEFAULT_PCC_STRUCT_RETURN
01455 #define DEFAULT_PCC_STRUCT_RETURN 1
01456 #endif
01457
01458
01459
01460 static bool
01461 ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
01462 {
01463 switch (code)
01464 {
01465 case OPT_m3dnow:
01466 if (!value)
01467 {
01468 target_flags &= ~MASK_3DNOW_A;
01469 target_flags_explicit |= MASK_3DNOW_A;
01470 }
01471 return true;
01472
01473 case OPT_mmmx:
01474 if (!value)
01475 {
01476 target_flags &= ~(MASK_3DNOW | MASK_3DNOW_A);
01477 target_flags_explicit |= MASK_3DNOW | MASK_3DNOW_A;
01478 }
01479 return true;
01480
01481 case OPT_msse:
01482 if (!value)
01483 {
01484 target_flags &= ~(MASK_SSE2 | MASK_SSE3 | MASK_SSE4A);
01485 target_flags_explicit |= MASK_SSE2 | MASK_SSE3 | MASK_SSE4A;
01486 }
01487 return true;
01488
01489 case OPT_msse2:
01490 if (!value)
01491 {
01492 target_flags &= ~(MASK_SSE3 | MASK_SSE4A);
01493 target_flags_explicit |= MASK_SSE3 | MASK_SSE4A;
01494 }
01495 return true;
01496
01497 case OPT_msse3:
01498 if (!value)
01499 {
01500 target_flags &= ~MASK_SSE4A;
01501 target_flags_explicit |= MASK_SSE4A;
01502 }
01503 return true;
01504
01505
01506 default:
01507 return true;
01508 }
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 void
01521 override_options (void)
01522 {
01523 int i;
01524 int ix86_tune_defaulted = 0;
01525
01526
01527 #define MAX_CODE_ALIGN 16
01528
01529 static struct ptt
01530 {
01531 const struct processor_costs *cost;
01532 const int target_enable;
01533 const int target_disable;
01534 const int align_loop;
01535 const int align_loop_max_skip;
01536 const int align_jump;
01537 const int align_jump_max_skip;
01538 const int align_func;
01539 }
01540 const processor_target_table[PROCESSOR_max] =
01541 {
01542 {&i386_cost, 0, 0, 4, 3, 4, 3, 4},
01543 {&i486_cost, 0, 0, 16, 15, 16, 15, 16},
01544 {&pentium_cost, 0, 0, 16, 7, 16, 7, 16},
01545 {&pentiumpro_cost, 0, 0, 16, 15, 16, 7, 16},
01546 {&k6_cost, 0, 0, 32, 7, 32, 7, 32},
01547 {&athlon_cost, 0, 0, 16, 7, 16, 7, 16},
01548 {&pentium4_cost, 0, 0, 0, 0, 0, 0, 0},
01549 {&k8_cost, 0, 0, 16, 7, 16, 7, 16},
01550 {&nocona_cost, 0, 0, 0, 0, 0, 0, 0},
01551 {&generic32_cost, 0, 0, 16, 7, 16, 7, 16},
01552 {&generic64_cost, 0, 0, 16, 7, 16, 7, 16},
01553 {&amdfam10_cost, 0, 0, 32, 24, 32, 7, 32}
01554 };
01555
01556 static const char * const cpu_names[] = TARGET_CPU_DEFAULT_NAMES;
01557 static struct pta
01558 {
01559 const char *const name;
01560 const enum processor_type processor;
01561 const enum pta_flags
01562 {
01563 PTA_SSE = 1,
01564 PTA_SSE2 = 2,
01565 PTA_SSE3 = 4,
01566 PTA_MMX = 8,
01567 PTA_PREFETCH_SSE = 16,
01568 PTA_3DNOW = 32,
01569 PTA_3DNOW_A = 64,
01570 PTA_64BIT = 128,
01571 PTA_CX16 = 256,
01572 PTA_POPCNT = 512,
01573 PTA_ABM = 1024,
01574 PTA_SSE4A = 2048
01575 } flags;
01576 }
01577 const processor_alias_table[] =
01578 {
01579 {"i386", PROCESSOR_I386, 0},
01580 {"i486", PROCESSOR_I486, 0},
01581 {"i586", PROCESSOR_PENTIUM, 0},
01582 {"pentium", PROCESSOR_PENTIUM, 0},
01583 {"pentium-mmx", PROCESSOR_PENTIUM, PTA_MMX},
01584 {"winchip-c6", PROCESSOR_I486, PTA_MMX},
01585 {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
01586 {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
01587 {"c3-2", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_PREFETCH_SSE | PTA_SSE},
01588 {"i686", PROCESSOR_PENTIUMPRO, 0},
01589 {"pentiumpro", PROCESSOR_PENTIUMPRO, 0},
01590 {"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX},
01591 {"pentium3", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE | PTA_PREFETCH_SSE},
01592 {"pentium3m", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE | PTA_PREFETCH_SSE},
01593 {"pentium-m", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE | PTA_PREFETCH_SSE | PTA_SSE2},
01594 {"pentium4", PROCESSOR_PENTIUM4, PTA_SSE | PTA_SSE2
01595 | PTA_MMX | PTA_PREFETCH_SSE},
01596 {"pentium4m", PROCESSOR_PENTIUM4, PTA_SSE | PTA_SSE2
01597 | PTA_MMX | PTA_PREFETCH_SSE},
01598 {"prescott", PROCESSOR_NOCONA, PTA_SSE | PTA_SSE2 | PTA_SSE3
01599 | PTA_MMX | PTA_PREFETCH_SSE},
01600 {"nocona", PROCESSOR_NOCONA, PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_64BIT
01601 | PTA_MMX | PTA_PREFETCH_SSE},
01602 {"k6", PROCESSOR_K6, PTA_MMX},
01603 {"k6-2", PROCESSOR_K6, PTA_MMX | PTA_3DNOW},
01604 {"k6-3", PROCESSOR_K6, PTA_MMX | PTA_3DNOW},
01605 {"athlon", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01606 | PTA_3DNOW_A},
01607 {"athlon-tbird", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE
01608 | PTA_3DNOW | PTA_3DNOW_A},
01609 {"athlon-4", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01610 | PTA_3DNOW_A | PTA_SSE},
01611 {"athlon-xp", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01612 | PTA_3DNOW_A | PTA_SSE},
01613 {"athlon-mp", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01614 | PTA_3DNOW_A | PTA_SSE},
01615 {"x86-64", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_64BIT
01616 | PTA_SSE | PTA_SSE2 },
01617 {"k8", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW | PTA_64BIT
01618 | PTA_3DNOW_A | PTA_SSE | PTA_SSE2},
01619 {"opteron", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW | PTA_64BIT
01620 | PTA_3DNOW_A | PTA_SSE | PTA_SSE2},
01621 {"athlon64", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW | PTA_64BIT
01622 | PTA_3DNOW_A | PTA_SSE | PTA_SSE2},
01623 {"athlon-fx", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW | PTA_64BIT
01624 | PTA_3DNOW_A | PTA_SSE | PTA_SSE2},
01625 {"amdfam10", PROCESSOR_AMDFAM10, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01626 | PTA_64BIT | PTA_3DNOW_A | PTA_SSE
01627 | PTA_SSE2 | PTA_SSE3 | PTA_POPCNT
01628 | PTA_ABM | PTA_SSE4A | PTA_CX16},
01629 {"barcelona", PROCESSOR_AMDFAM10, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01630 | PTA_64BIT | PTA_3DNOW_A | PTA_SSE
01631 | PTA_SSE2 | PTA_SSE3 | PTA_POPCNT
01632 | PTA_ABM | PTA_SSE4A | PTA_CX16},
01633 {"generic32", PROCESSOR_GENERIC32, 0 },
01634 {"generic64", PROCESSOR_GENERIC64, PTA_64BIT },
01635 };
01636
01637 int const pta_size = ARRAY_SIZE (processor_alias_table);
01638
01639 #ifdef SUBTARGET_OVERRIDE_OPTIONS
01640 SUBTARGET_OVERRIDE_OPTIONS;
01641 #endif
01642
01643 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
01644 SUBSUBTARGET_OVERRIDE_OPTIONS;
01645 #endif
01646
01647
01648 if (TARGET_MACHO && TARGET_64BIT)
01649 flag_pic = 2;
01650
01651
01652
01653 if (TARGET_64BIT)
01654 {
01655
01656 if (flag_omit_frame_pointer == 2)
01657 flag_omit_frame_pointer = (TARGET_MACHO ? 0 : 1);
01658 if (flag_asynchronous_unwind_tables == 2)
01659 flag_asynchronous_unwind_tables = 1;
01660 if (flag_pcc_struct_return == 2)
01661 flag_pcc_struct_return = 0;
01662 }
01663 else
01664 {
01665 if (flag_omit_frame_pointer == 2)
01666 flag_omit_frame_pointer = 0;
01667 if (flag_asynchronous_unwind_tables == 2)
01668 flag_asynchronous_unwind_tables = 0;
01669 if (flag_pcc_struct_return == 2)
01670 flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
01671 }
01672
01673
01674 if (ix86_tune_string)
01675 {
01676 if (!strcmp (ix86_tune_string, "generic")
01677 || !strcmp (ix86_tune_string, "i686")
01678
01679
01680
01681 || !strcmp (ix86_tune_string, "native"))
01682 {
01683 if (TARGET_64BIT)
01684 ix86_tune_string = "generic64";
01685 else
01686 ix86_tune_string = "generic32";
01687 }
01688 else if (!strncmp (ix86_tune_string, "generic", 7))
01689 error ("bad value (%s) for -mtune= switch", ix86_tune_string);
01690 }
01691 else
01692 {
01693 if (ix86_arch_string)
01694 ix86_tune_string = ix86_arch_string;
01695 if (!ix86_tune_string)
01696 {
01697 ix86_tune_string = cpu_names [TARGET_CPU_DEFAULT];
01698 ix86_tune_defaulted = 1;
01699 }
01700
01701
01702
01703 if (!strcmp (ix86_tune_string, "generic")
01704 || !strcmp (ix86_tune_string, "x86-64")
01705 || !strcmp (ix86_tune_string, "i686"))
01706 {
01707 if (TARGET_64BIT)
01708 ix86_tune_string = "generic64";
01709 else
01710 ix86_tune_string = "generic32";
01711 }
01712 }
01713 if (!strcmp (ix86_tune_string, "x86-64"))
01714 warning (OPT_Wdeprecated, "-mtune=x86-64 is deprecated. Use -mtune=k8 or "
01715 "-mtune=generic instead as appropriate.");
01716
01717 if (!ix86_arch_string)
01718 ix86_arch_string = TARGET_64BIT ? "x86-64" : "i386";
01719 if (!strcmp (ix86_arch_string, "generic"))
01720 error ("generic CPU can be used only for -mtune= switch");
01721 if (!strncmp (ix86_arch_string, "generic", 7))
01722 error ("bad value (%s) for -march= switch", ix86_arch_string);
01723
01724 if (ix86_cmodel_string != 0)
01725 {
01726 if (!strcmp (ix86_cmodel_string, "small"))
01727 ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
01728 else if (!strcmp (ix86_cmodel_string, "medium"))
01729 ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM;
01730 else if (flag_pic)
01731 sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
01732 else if (!strcmp (ix86_cmodel_string, "32"))
01733 ix86_cmodel = CM_32;
01734 else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
01735 ix86_cmodel = CM_KERNEL;
01736 else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
01737 ix86_cmodel = CM_LARGE;
01738 else
01739 error ("bad value (%s) for -mcmodel= switch", ix86_cmodel_string);
01740 }
01741 else
01742 {
01743 ix86_cmodel = CM_32;
01744 if (TARGET_64BIT)
01745 ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
01746 }
01747 if (ix86_asm_string != 0)
01748 {
01749 if (! TARGET_MACHO
01750 && !strcmp (ix86_asm_string, "intel"))
01751 ix86_asm_dialect = ASM_INTEL;
01752 else if (!strcmp (ix86_asm_string, "att"))
01753 ix86_asm_dialect = ASM_ATT;
01754 else
01755 error ("bad value (%s) for -masm= switch", ix86_asm_string);
01756 }
01757 if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
01758 error ("code model %qs not supported in the %s bit mode",
01759 ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
01760 if (ix86_cmodel == CM_LARGE)
01761 sorry ("code model %<large%> not supported yet");
01762 if ((TARGET_64BIT != 0) != ((target_flags & MASK_64BIT) != 0))
01763 sorry ("%i-bit mode not compiled in",
01764 (target_flags & MASK_64BIT) ? 64 : 32);
01765 for (i = 0; i < pta_size; i++)
01766 if (! strcmp (ix86_arch_string, processor_alias_table[i].name))
01767 {
01768 ix86_arch = processor_alias_table[i].processor;
01769
01770 ix86_tune = ix86_arch;
01771 if (processor_alias_table[i].flags & PTA_MMX
01772 && !(target_flags_explicit & MASK_MMX))
01773 target_flags |= MASK_MMX;
01774 if (processor_alias_table[i].flags & PTA_3DNOW
01775 && !(target_flags_explicit & MASK_3DNOW))
01776 target_flags |= MASK_3DNOW;
01777 if (processor_alias_table[i].flags & PTA_3DNOW_A
01778 && !(target_flags_explicit & MASK_3DNOW_A))
01779 target_flags |= MASK_3DNOW_A;
01780 if (processor_alias_table[i].flags & PTA_SSE
01781 && !(target_flags_explicit & MASK_SSE))
01782 target_flags |= MASK_SSE;
01783 if (processor_alias_table[i].flags & PTA_SSE2
01784 && !(target_flags_explicit & MASK_SSE2))
01785 target_flags |= MASK_SSE2;
01786 if (processor_alias_table[i].flags & PTA_SSE3
01787 && !(target_flags_explicit & MASK_SSE3))
01788 target_flags |= MASK_SSE3;
01789 if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
01790 x86_prefetch_sse = true;
01791 if (processor_alias_table[i].flags & PTA_SSE4A
01792 && !(target_flags_explicit & MASK_SSE4A))
01793 target_flags |= MASK_SSE4A;
01794
01795 if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
01796 error ("CPU you selected does not support x86-64 "
01797 "instruction set");
01798 break;
01799 }
01800 if (i == pta_size)
01801 error ("bad value (%s) for -march= switch", ix86_arch_string);
01802
01803 for (i = 0; i < pta_size; i++)
01804 if (! strcmp (ix86_tune_string, processor_alias_table[i].name))
01805 {
01806 ix86_tune = processor_alias_table[i].processor;
01807 if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
01808 {
01809 if (ix86_tune_defaulted)
01810 {
01811 ix86_tune_string = "x86-64";
01812 for (i = 0; i < pta_size; i++)
01813 if (! strcmp (ix86_tune_string,
01814 processor_alias_table[i].name))
01815 break;
01816 ix86_tune = processor_alias_table[i].processor;
01817 }
01818 else
01819 error ("CPU you selected does not support x86-64 "
01820 "instruction set");
01821 }
01822
01823
01824
01825
01826
01827 if (TARGET_CMOVE && (processor_alias_table[i].flags & PTA_PREFETCH_SSE))
01828 x86_prefetch_sse = true;
01829 break;
01830 }
01831 if (i == pta_size)
01832 error ("bad value (%s) for -mtune= switch", ix86_tune_string);
01833
01834 if (optimize_size)
01835 ix86_cost = &size_cost;
01836 else
01837 ix86_cost = processor_target_table[ix86_tune].cost;
01838 target_flags |= processor_target_table[ix86_tune].target_enable;
01839 target_flags &= ~processor_target_table[ix86_tune].target_disable;
01840
01841
01842 init_machine_status = ix86_init_machine_status;
01843
01844
01845 if (ix86_regparm_string)
01846 {
01847 i = atoi (ix86_regparm_string);
01848 if (i < 0 || i > REGPARM_MAX)
01849 error ("-mregparm=%d is not between 0 and %d", i, REGPARM_MAX);
01850 else
01851 ix86_regparm = i;
01852 }
01853 else
01854 if (TARGET_64BIT)
01855 ix86_regparm = REGPARM_MAX;
01856
01857
01858
01859
01860 if (ix86_align_loops_string)
01861 {
01862 warning (0, "-malign-loops is obsolete, use -falign-loops");
01863 if (align_loops == 0)
01864 {
01865 i = atoi (ix86_align_loops_string);
01866 if (i < 0 || i > MAX_CODE_ALIGN)
01867 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01868 else
01869 align_loops = 1 << i;
01870 }
01871 }
01872
01873 if (ix86_align_jumps_string)
01874 {
01875 warning (0, "-malign-jumps is obsolete, use -falign-jumps");
01876 if (align_jumps == 0)
01877 {
01878 i = atoi (ix86_align_jumps_string);
01879 if (i < 0 || i > MAX_CODE_ALIGN)
01880 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01881 else
01882 align_jumps = 1 << i;
01883 }
01884 }
01885
01886 if (ix86_align_funcs_string)
01887 {
01888 warning (0, "-malign-functions is obsolete, use -falign-functions");
01889 if (align_functions == 0)
01890 {
01891 i = atoi (ix86_align_funcs_string);
01892 if (i < 0 || i > MAX_CODE_ALIGN)
01893 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01894 else
01895 align_functions = 1 << i;
01896 }
01897 }
01898
01899
01900 if (align_loops == 0)
01901 {
01902 align_loops = processor_target_table[ix86_tune].align_loop;
01903 align_loops_max_skip = processor_target_table[ix86_tune].align_loop_max_skip;
01904 }
01905 if (align_jumps == 0)
01906 {
01907 align_jumps = processor_target_table[ix86_tune].align_jump;
01908 align_jumps_max_skip = processor_target_table[ix86_tune].align_jump_max_skip;
01909 }
01910 if (align_functions == 0)
01911 {
01912 align_functions = processor_target_table[ix86_tune].align_func;
01913 }
01914
01915
01916 ix86_branch_cost = ix86_cost->branch_cost;
01917 if (ix86_branch_cost_string)
01918 {
01919 i = atoi (ix86_branch_cost_string);
01920 if (i < 0 || i > 5)
01921 error ("-mbranch-cost=%d is not between 0 and 5", i);
01922 else
01923 ix86_branch_cost = i;
01924 }
01925 if (ix86_section_threshold_string)
01926 {
01927 i = atoi (ix86_section_threshold_string);
01928 if (i < 0)
01929 error ("-mlarge-data-threshold=%d is negative", i);
01930 else
01931 ix86_section_threshold = i;
01932 }
01933
01934 if (ix86_tls_dialect_string)
01935 {
01936 if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
01937 ix86_tls_dialect = TLS_DIALECT_GNU;
01938 else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0)
01939 ix86_tls_dialect = TLS_DIALECT_GNU2;
01940 else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
01941 ix86_tls_dialect = TLS_DIALECT_SUN;
01942 else
01943 error ("bad value (%s) for -mtls-dialect= switch",
01944 ix86_tls_dialect_string);
01945 }
01946
01947
01948 if (flag_omit_frame_pointer)
01949 target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER;
01950 else if (TARGET_OMIT_LEAF_FRAME_POINTER)
01951 flag_omit_frame_pointer = 1;
01952
01953
01954
01955 if (flag_finite_math_only)
01956 target_flags &= ~MASK_IEEE_FP;
01957
01958
01959
01960 if (x86_arch_always_fancy_math_387 & (1 << ix86_arch))
01961 target_flags &= ~MASK_NO_FANCY_MATH_387;
01962
01963
01964
01965 if (!TARGET_80387)
01966 target_flags |= MASK_NO_FANCY_MATH_387;
01967
01968
01969 if (TARGET_SSE4A)
01970 target_flags |= MASK_SSE3;
01971
01972
01973 if (TARGET_SSE3)
01974 target_flags |= MASK_SSE2;
01975
01976
01977 if (TARGET_SSE2)
01978 target_flags |= MASK_SSE;
01979
01980
01981 if (TARGET_SSE)
01982 {
01983 target_flags |= MASK_MMX & ~target_flags_explicit;
01984 x86_prefetch_sse = true;
01985 }
01986
01987
01988 if (TARGET_3DNOW)
01989 target_flags |= MASK_MMX;
01990
01991 if (TARGET_64BIT)
01992 {
01993 if (TARGET_ALIGN_DOUBLE)
01994 error ("-malign-double makes no sense in the 64bit mode");
01995 if (TARGET_RTD)
01996 error ("-mrtd calling convention not supported in the 64bit mode");
01997
01998
01999
02000
02001 target_flags
02002 |= ((MASK_SSE2 | MASK_SSE | MASK_MMX | MASK_128BIT_LONG_DOUBLE)
02003 & ~target_flags_explicit);
02004 }
02005 else
02006 {
02007
02008
02009 if (!(target_flags_explicit & MASK_NO_RED_ZONE))
02010 target_flags |= MASK_NO_RED_ZONE;
02011 }
02012
02013
02014
02015
02016
02017 ix86_preferred_stack_boundary = 128;
02018 if (ix86_preferred_stack_boundary_string)
02019 {
02020 i = atoi (ix86_preferred_stack_boundary_string);
02021 if (i < (TARGET_64BIT ? 4 : 2) || i > 12)
02022 error ("-mpreferred-stack-boundary=%d is not between %d and 12", i,
02023 TARGET_64BIT ? 4 : 2);
02024 else
02025 ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
02026 }
02027
02028
02029 if (TARGET_SSEREGPARM
02030 && ! TARGET_SSE)
02031 error ("-msseregparm used without SSE enabled");
02032
02033 ix86_fpmath = TARGET_FPMATH_DEFAULT;
02034
02035 if (ix86_fpmath_string != 0)
02036 {
02037 if (! strcmp (ix86_fpmath_string, "387"))
02038 ix86_fpmath = FPMATH_387;
02039 else if (! strcmp (ix86_fpmath_string, "sse"))
02040 {
02041 if (!TARGET_SSE)
02042 {
02043 warning (0, "SSE instruction set disabled, using 387 arithmetics");
02044 ix86_fpmath = FPMATH_387;
02045 }
02046 else
02047 ix86_fpmath = FPMATH_SSE;
02048 }
02049 else if (! strcmp (ix86_fpmath_string, "387,sse")
02050 || ! strcmp (ix86_fpmath_string, "sse,387"))
02051 {
02052 if (!TARGET_SSE)
02053 {
02054 warning (0, "SSE instruction set disabled, using 387 arithmetics");
02055 ix86_fpmath = FPMATH_387;
02056 }
02057 else if (!TARGET_80387)
02058 {
02059 warning (0, "387 instruction set disabled, using SSE arithmetics");
02060 ix86_fpmath = FPMATH_SSE;
02061 }
02062 else
02063 ix86_fpmath = FPMATH_SSE | FPMATH_387;
02064 }
02065 else
02066 error ("bad value (%s) for -mfpmath= switch", ix86_fpmath_string);
02067 }
02068
02069
02070 if (!TARGET_80387)
02071 target_flags &= ~MASK_FLOAT_RETURNS;
02072
02073 if ((x86_accumulate_outgoing_args & TUNEMASK)
02074 && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
02075 && !optimize_size)
02076 target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
02077
02078
02079
02080
02081
02082 if ((flag_unwind_tables || flag_asynchronous_unwind_tables
02083 || flag_exceptions || flag_non_call_exceptions)
02084 && flag_omit_frame_pointer
02085 && !(target_flags & MASK_ACCUMULATE_OUTGOING_ARGS))
02086 {
02087 if (target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
02088 warning (0, "unwind tables currently require either a frame pointer "
02089 "or -maccumulate-outgoing-args for correctness");
02090 target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
02091 }
02092
02093
02094 {
02095 char *p;
02096 ASM_GENERATE_INTERNAL_LABEL (internal_label_prefix, "LX", 0);
02097 p = strchr (internal_label_prefix, 'X');
02098 internal_label_prefix_len = p - internal_label_prefix;
02099 *p = '\0';
02100 }
02101
02102
02103
02104 if (!TARGET_SCHEDULE)
02105 flag_schedule_insns_after_reload = flag_schedule_insns = 0;
02106 }
02107
02108
02109
02110
02111
02112
02113 static section *
02114 x86_64_elf_select_section (tree decl, int reloc,
02115 unsigned HOST_WIDE_INT align)
02116 {
02117 if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
02118 && ix86_in_large_data_p (decl))
02119 {
02120 const char *sname = NULL;
02121 unsigned int flags = SECTION_WRITE;
02122 switch (categorize_decl_for_section (decl, reloc))
02123 {
02124 case SECCAT_DATA:
02125 sname = ".ldata";
02126 break;
02127 case SECCAT_DATA_REL:
02128 sname = ".ldata.rel";
02129 break;
02130 case SECCAT_DATA_REL_LOCAL:
02131 sname = ".ldata.rel.local";
02132 break;
02133 case SECCAT_DATA_REL_RO:
02134 sname = ".ldata.rel.ro";
02135 break;
02136 case SECCAT_DATA_REL_RO_LOCAL:
02137 sname = ".ldata.rel.ro.local";
02138 break;
02139 case SECCAT_BSS:
02140 sname = ".lbss";
02141 flags |= SECTION_BSS;
02142 break;
02143 case SECCAT_RODATA:
02144 case SECCAT_RODATA_MERGE_STR:
02145 case SECCAT_RODATA_MERGE_STR_INIT:
02146 case SECCAT_RODATA_MERGE_CONST:
02147 sname = ".lrodata";
02148 flags = 0;
02149 break;
02150 case SECCAT_SRODATA:
02151 case SECCAT_SDATA:
02152 case SECCAT_SBSS:
02153 gcc_unreachable ();
02154 case SECCAT_TEXT:
02155 case SECCAT_TDATA:
02156 case SECCAT_TBSS:
02157
02158
02159 break;
02160 }
02161 if (sname)
02162 {
02163
02164
02165
02166 if (!DECL_P (decl))
02167 return get_section (sname, flags, NULL);
02168 return get_named_section (decl, sname, reloc);
02169 }
02170 }
02171 return default_elf_select_section (decl, reloc, align);
02172 }
02173
02174
02175
02176
02177
02178
02179 static void
02180 x86_64_elf_unique_section (tree decl, int reloc)
02181 {
02182 if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
02183 && ix86_in_large_data_p (decl))
02184 {
02185 const char *prefix = NULL;
02186
02187 bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
02188
02189 switch (categorize_decl_for_section (decl, reloc))
02190 {
02191 case SECCAT_DATA:
02192 case SECCAT_DATA_REL:
02193 case SECCAT_DATA_REL_LOCAL:
02194 case SECCAT_DATA_REL_RO:
02195 case SECCAT_DATA_REL_RO_LOCAL:
02196 prefix = one_only ? ".gnu.linkonce.ld." : ".ldata.";
02197 break;
02198 case SECCAT_BSS:
02199 prefix = one_only ? ".gnu.linkonce.lb." : ".lbss.";
02200 break;
02201 case SECCAT_RODATA:
02202 case SECCAT_RODATA_MERGE_STR:
02203 case SECCAT_RODATA_MERGE_STR_INIT:
02204 case SECCAT_RODATA_MERGE_CONST:
02205 prefix = one_only ? ".gnu.linkonce.lr." : ".lrodata.";
02206 break;
02207 case SECCAT_SRODATA:
02208 case SECCAT_SDATA:
02209 case SECCAT_SBSS:
02210 gcc_unreachable ();
02211 case SECCAT_TEXT:
02212 case SECCAT_TDATA:
02213 case SECCAT_TBSS:
02214
02215
02216 break;
02217 }
02218 if (prefix)
02219 {
02220 const char *name;
02221 size_t nlen, plen;
02222 char *string;
02223 plen = strlen (prefix);
02224
02225 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
02226 name = targetm.strip_name_encoding (name);
02227 nlen = strlen (name);
02228
02229 string = alloca (nlen + plen + 1);
02230 memcpy (string, prefix, plen);
02231 memcpy (string + plen, name, nlen + 1);
02232
02233 DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
02234 return;
02235 }
02236 }
02237 default_unique_section (decl, reloc);
02238 }
02239
02240 #ifdef COMMON_ASM_OP
02241
02242
02243
02244
02245
02246 void
02247 x86_elf_aligned_common (FILE *file,
02248 const char *name, unsigned HOST_WIDE_INT size,
02249 int align)
02250 {
02251 if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
02252 && size > (unsigned int)ix86_section_threshold)
02253 fprintf (file, ".largecomm\t");
02254 else
02255 fprintf (file, "%s", COMMON_ASM_OP);
02256 assemble_name (file, name);
02257 fprintf (file, ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
02258 size, align / BITS_PER_UNIT);
02259 }
02260
02261
02262
02263
02264 void
02265 x86_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
02266 const char *name, unsigned HOST_WIDE_INT size,
02267 int align)
02268 {
02269 if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC)
02270 && size > (unsigned int)ix86_section_threshold)
02271 switch_to_section (get_named_section (decl, ".lbss", 0));
02272 else
02273 switch_to_section (bss_section);
02274 ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
02275 #ifdef ASM_DECLARE_OBJECT_NAME
02276 last_assemble_variable_decl = decl;
02277 ASM_DECLARE_OBJECT_NAME (file, name, decl);
02278 #else
02279
02280 ASM_OUTPUT_LABEL (file, name);
02281 #endif
02282 ASM_OUTPUT_SKIP (file, size ? size : 1);
02283 }
02284 #endif
02285
02286 void
02287 optimization_options (int level, int size ATTRIBUTE_UNUSED)
02288 {
02289
02290
02291 #ifdef INSN_SCHEDULING
02292 if (level > 1)
02293 flag_schedule_insns = 0;
02294 #endif
02295
02296 if (TARGET_MACHO)
02297
02298
02299 flag_errno_math = 0;
02300
02301
02302
02303
02304
02305 if (optimize >= 1)
02306 flag_omit_frame_pointer = 2;
02307 flag_pcc_struct_return = 2;
02308 flag_asynchronous_unwind_tables = 2;
02309 #ifdef SUBTARGET_OPTIMIZATION_OPTIONS
02310 SUBTARGET_OPTIMIZATION_OPTIONS;
02311 #endif
02312 }
02313
02314
02315 const struct attribute_spec ix86_attribute_table[] =
02316 {
02317
02318
02319
02320 { "stdcall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
02321
02322
02323 { "fastcall", 0, 0, false, true, true, ix86_handle_cconv_attribute },
02324
02325 { "cdecl", 0, 0, false, true, true, ix86_handle_cconv_attribute },
02326
02327
02328 { "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute },
02329
02330
02331 { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
02332
02333 { (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
02334 false, true, true, ix86_handle_cconv_attribute },
02335 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
02336 { "dllimport", 0, 0, false, false, false, handle_dll_attribute },
02337 { "dllexport", 0, 0, false, false, false, handle_dll_attribute },
02338 { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute },
02339 #endif
02340 { "ms_struct", 0, 0, false, false, false, ix86_handle_struct_attribute },
02341 { "gcc_struct", 0, 0, false, false, false, ix86_handle_struct_attribute },
02342 #ifdef SUBTARGET_ATTRIBUTE_TABLE
02343 SUBTARGET_ATTRIBUTE_TABLE,
02344 #endif
02345 { NULL, 0, 0, false, false, false, NULL }
02346 };
02347
02348
02349
02350
02351
02352 static bool
02353 ix86_function_ok_for_sibcall (tree decl, tree exp)
02354 {
02355 tree func;
02356 rtx a, b;
02357
02358
02359
02360
02361 if (!TARGET_64BIT && flag_pic && (!decl || !targetm.binds_local_p (decl)))
02362 return false;
02363
02364 if (decl)
02365 func = decl;
02366 else
02367 {
02368 func = TREE_TYPE (TREE_OPERAND (exp, 0));
02369 if (POINTER_TYPE_P (func))
02370 func = TREE_TYPE (func);
02371 }
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 a = ix86_function_value (TREE_TYPE (exp), func, false);
02383 b = ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
02384 cfun->decl, false);
02385 if (STACK_REG_P (a) || STACK_REG_P (b))
02386 {
02387 if (!rtx_equal_p (a, b))
02388 return false;
02389 }
02390 else if (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl))))
02391 ;
02392 else if (!rtx_equal_p (a, b))
02393 return false;
02394
02395
02396
02397
02398 if (!decl && !TARGET_64BIT)
02399 {
02400 tree type;
02401
02402
02403 type = TREE_OPERAND (exp, 0);
02404 type = TREE_TYPE (type);
02405 type = TREE_TYPE (type);
02406
02407 if (ix86_function_regparm (type, NULL) >= 3)
02408 {
02409
02410
02411 return false;
02412 }
02413 }
02414
02415 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
02416
02417 if (decl && DECL_DLLIMPORT_P (decl)
02418 && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
02419 return false;
02420 #endif
02421
02422
02423
02424 if (cfun->machine->force_align_arg_pointer)
02425 return false;
02426
02427
02428 return true;
02429 }
02430
02431
02432
02433
02434
02435 static tree
02436 ix86_handle_cconv_attribute (tree *node, tree name,
02437 tree args,
02438 int flags ATTRIBUTE_UNUSED,
02439 bool *no_add_attrs)
02440 {
02441 if (TREE_CODE (*node) != FUNCTION_TYPE
02442 && TREE_CODE (*node) != METHOD_TYPE
02443 && TREE_CODE (*node) != FIELD_DECL
02444 && TREE_CODE (*node) != TYPE_DECL)
02445 {
02446 warning (OPT_Wattributes, "%qs attribute only applies to functions",
02447 IDENTIFIER_POINTER (name));
02448 *no_add_attrs = true;
02449 return NULL_TREE;
02450 }
02451
02452
02453 if (is_attribute_p ("regparm", name))
02454 {
02455 tree cst;
02456
02457 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
02458 {
02459 error ("fastcall and regparm attributes are not compatible");
02460 }
02461
02462 cst = TREE_VALUE (args);
02463 if (TREE_CODE (cst) != INTEGER_CST)
02464 {
02465 warning (OPT_Wattributes,
02466 "%qs attribute requires an integer constant argument",
02467 IDENTIFIER_POINTER (name));
02468 *no_add_attrs = true;
02469 }
02470 else if (compare_tree_int (cst, REGPARM_MAX) > 0)
02471 {
02472 warning (OPT_Wattributes, "argument to %qs attribute larger than %d",
02473 IDENTIFIER_POINTER (name), REGPARM_MAX);
02474 *no_add_attrs = true;
02475 }
02476
02477 if (!TARGET_64BIT
02478 && lookup_attribute (ix86_force_align_arg_pointer_string,
02479 TYPE_ATTRIBUTES (*node))
02480 && compare_tree_int (cst, REGPARM_MAX-1))
02481 {
02482 error ("%s functions limited to %d register parameters",
02483 ix86_force_align_arg_pointer_string, REGPARM_MAX-1);
02484 }
02485
02486 return NULL_TREE;
02487 }
02488
02489 if (TARGET_64BIT)
02490 {
02491 warning (OPT_Wattributes, "%qs attribute ignored",
02492 IDENTIFIER_POINTER (name));
02493 *no_add_attrs = true;
02494 return NULL_TREE;
02495 }
02496
02497
02498 if (is_attribute_p ("fastcall", name))
02499 {
02500 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
02501 {
02502 error ("fastcall and cdecl attributes are not compatible");
02503 }
02504 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
02505 {
02506 error ("fastcall and stdcall attributes are not compatible");
02507 }
02508 if (lookup_attribute ("regparm", TYPE_ATTRIBUTES (*node)))
02509 {
02510 error ("fastcall and regparm attributes are not compatible");
02511 }
02512 }
02513
02514
02515
02516 else if (is_attribute_p ("stdcall", name))
02517 {
02518 if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
02519 {
02520 error ("stdcall and cdecl attributes are not compatible");
02521 }
02522 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
02523 {
02524 error ("stdcall and fastcall attributes are not compatible");
02525 }
02526 }
02527
02528
02529 else if (is_attribute_p ("cdecl", name))
02530 {
02531 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
02532 {
02533 error ("stdcall and cdecl attributes are not compatible");
02534 }
02535 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
02536 {
02537 error ("fastcall and cdecl attributes are not compatible");
02538 }
02539 }
02540
02541
02542
02543 return NULL_TREE;
02544 }
02545
02546
02547
02548
02549
02550 static int
02551 ix86_comp_type_attributes (tree type1, tree type2)
02552 {
02553
02554 const char *const rtdstr = TARGET_RTD ? "cdecl" : "stdcall";
02555
02556 if (TREE_CODE (type1) != FUNCTION_TYPE)
02557 return 1;
02558
02559
02560 if ((!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1))
02561 != !lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type2)))
02562 || (ix86_function_regparm (type1, NULL)
02563 != ix86_function_regparm (type2, NULL)))
02564 return 0;
02565
02566
02567 if (!lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type1))
02568 != !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
02569 return 0;
02570
02571
02572 if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
02573 != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
02574 return 0;
02575
02576 return 1;
02577 }
02578
02579
02580
02581
02582
02583 static int
02584 ix86_function_regparm (tree type, tree decl)
02585 {
02586 tree attr;
02587 int regparm = ix86_regparm;
02588 bool user_convention = false;
02589
02590 if (!TARGET_64BIT)
02591 {
02592 attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
02593 if (attr)
02594 {
02595 regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
02596 user_convention = true;
02597 }
02598
02599 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
02600 {
02601 regparm = 2;
02602 user_convention = true;
02603 }
02604
02605
02606 if (!TARGET_64BIT && !user_convention && decl
02607 && flag_unit_at_a_time && !profile_flag)
02608 {
02609 struct cgraph_local_info *i = cgraph_local_info (decl);
02610 if (i && i->local)
02611 {
02612 int local_regparm, globals = 0, regno;
02613
02614
02615
02616 for (local_regparm = 0; local_regparm < 3; local_regparm++)
02617 if (global_regs[local_regparm])
02618 break;
02619
02620
02621 if (local_regparm == 3
02622 && decl_function_context (decl)
02623 && !DECL_NO_STATIC_CHAIN (decl))
02624 local_regparm = 2;
02625
02626
02627
02628
02629
02630
02631 if ((DECL_STRUCT_FUNCTION (decl)
02632 && DECL_STRUCT_FUNCTION (decl)->machine->force_align_arg_pointer)
02633 || (!DECL_STRUCT_FUNCTION (decl)
02634 && lookup_attribute (ix86_force_align_arg_pointer_string,
02635 TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
02636 local_regparm = 2;
02637
02638
02639
02640 for (regno = 0; regno < 6; regno++)
02641 if (global_regs[regno])
02642 globals++;
02643 local_regparm
02644 = globals < local_regparm ? local_regparm - globals : 0;
02645
02646 if (local_regparm > regparm)
02647 regparm = local_regparm;
02648 }
02649 }
02650 }
02651 return regparm;
02652 }
02653
02654
02655
02656
02657
02658
02659 static int
02660 ix86_function_sseregparm (tree type, tree decl)
02661 {
02662
02663
02664 if (TARGET_SSEREGPARM
02665 || (type
02666 && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))))
02667 {
02668 if (!TARGET_SSE)
02669 {
02670 if (decl)
02671 error ("Calling %qD with attribute sseregparm without "
02672 "SSE/SSE2 enabled", decl);
02673 else
02674 error ("Calling %qT with attribute sseregparm without "
02675 "SSE/SSE2 enabled", type);
02676 return 0;
02677 }
02678
02679 return 2;
02680 }
02681
02682
02683
02684
02685 if (!TARGET_64BIT && decl
02686 && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
02687 {
02688 struct cgraph_local_info *i = cgraph_local_info (decl);
02689 if (i && i->local)
02690 return TARGET_SSE2 ? 2 : 1;
02691 }
02692
02693 return 0;
02694 }
02695
02696
02697
02698
02699
02700 static bool
02701 ix86_eax_live_at_start_p (void)
02702 {
02703
02704
02705
02706
02707
02708
02709 return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end, 0);
02710 }
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729 int
02730 ix86_return_pops_args (tree fundecl, tree funtype, int size)
02731 {
02732 int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
02733
02734
02735 if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
02736
02737
02738
02739 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
02740 || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
02741 rtd = 1;
02742
02743 if (rtd
02744 && (TYPE_ARG_TYPES (funtype) == NULL_TREE
02745 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))
02746 == void_type_node)))
02747 return size;
02748 }
02749
02750
02751 if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
02752 && !TARGET_64BIT
02753 && !KEEP_AGGREGATE_RETURN_POINTER)
02754 {
02755 int nregs = ix86_function_regparm (funtype, fundecl);
02756
02757 if (!nregs)
02758 return GET_MODE_SIZE (Pmode);
02759 }
02760
02761 return 0;
02762 }
02763
02764
02765
02766
02767 bool
02768 ix86_function_arg_regno_p (int regno)
02769 {
02770 int i;
02771 if (!TARGET_64BIT)
02772 {
02773 if (TARGET_MACHO)
02774 return (regno < REGPARM_MAX
02775 || (TARGET_SSE && SSE_REGNO_P (regno) && !fixed_regs[regno]));
02776 else
02777 return (regno < REGPARM_MAX
02778 || (TARGET_MMX && MMX_REGNO_P (regno)
02779 && (regno < FIRST_MMX_REG + MMX_REGPARM_MAX))
02780 || (TARGET_SSE && SSE_REGNO_P (regno)
02781 && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX)));
02782 }
02783
02784 if (TARGET_MACHO)
02785 {
02786 if (SSE_REGNO_P (regno) && TARGET_SSE)
02787 return true;
02788 }
02789 else
02790 {
02791 if (TARGET_SSE && SSE_REGNO_P (regno)
02792 && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX))
02793 return true;
02794 }
02795
02796 if (!regno)
02797 return true;
02798 for (i = 0; i < REGPARM_MAX; i++)
02799 if (regno == x86_64_int_parameter_registers[i])
02800 return true;
02801 return false;
02802 }
02803
02804
02805
02806 static bool
02807 ix86_must_pass_in_stack (enum machine_mode mode, tree type)
02808 {
02809 if (must_pass_in_stack_var_size_or_pad (mode, type))
02810 return true;
02811
02812
02813
02814
02815 return (!TARGET_64BIT && mode == TImode
02816 && type && TREE_CODE (type) != VECTOR_TYPE);
02817 }
02818
02819
02820
02821
02822
02823 void
02824 init_cumulative_args (CUMULATIVE_ARGS *cum,
02825 tree fntype,
02826 rtx libname,
02827 tree fndecl)
02828 {
02829 static CUMULATIVE_ARGS zero_cum;
02830 tree param, next_param;
02831
02832 if (TARGET_DEBUG_ARG)
02833 {
02834 fprintf (stderr, "\ninit_cumulative_args (");
02835 if (fntype)
02836 fprintf (stderr, "fntype code = %s, ret code = %s",
02837 tree_code_name[(int) TREE_CODE (fntype)],
02838 tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]);
02839 else
02840 fprintf (stderr, "no fntype");
02841
02842 if (libname)
02843 fprintf (stderr, ", libname = %s", XSTR (libname, 0));
02844 }
02845
02846 *cum = zero_cum;
02847
02848
02849 cum->nregs = ix86_regparm;
02850 if (TARGET_SSE)
02851 cum->sse_nregs = SSE_REGPARM_MAX;
02852 if (TARGET_MMX)
02853 cum->mmx_nregs = MMX_REGPARM_MAX;
02854 cum->warn_sse = true;
02855 cum->warn_mmx = true;
02856 cum->maybe_vaarg = false;
02857
02858
02859
02860 if (fntype && !TARGET_64BIT)
02861 {
02862 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
02863 {
02864 cum->nregs = 2;
02865 cum->fastcall = 1;
02866 }
02867 else
02868 cum->nregs = ix86_function_regparm (fntype, fndecl);
02869 }
02870
02871
02872
02873 cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
02874
02875
02876
02877
02878
02879
02880 if (cum->nregs || cum->mmx_nregs || cum->sse_nregs)
02881 {
02882 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
02883 param != 0; param = next_param)
02884 {
02885 next_param = TREE_CHAIN (param);
02886 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
02887 {
02888 if (!TARGET_64BIT)
02889 {
02890 cum->nregs = 0;
02891 cum->sse_nregs = 0;
02892 cum->mmx_nregs = 0;
02893 cum->warn_sse = 0;
02894 cum->warn_mmx = 0;
02895 cum->fastcall = 0;
02896 cum->float_in_sse = 0;
02897 }
02898 cum->maybe_vaarg = true;
02899 }
02900 }
02901 }
02902 if ((!fntype && !libname)
02903 || (fntype && !TYPE_ARG_TYPES (fntype)))
02904 cum->maybe_vaarg = true;
02905
02906 if (TARGET_DEBUG_ARG)
02907 fprintf (stderr, ", nregs=%d )\n", cum->nregs);
02908
02909 return;
02910 }
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922 static enum machine_mode
02923 type_natural_mode (tree type)
02924 {
02925 enum machine_mode mode = TYPE_MODE (type);
02926
02927 if (TREE_CODE (type) == VECTOR_TYPE && !VECTOR_MODE_P (mode))
02928 {
02929 HOST_WIDE_INT size = int_size_in_bytes (type);
02930 if ((size == 8 || size == 16)
02931
02932 && TYPE_VECTOR_SUBPARTS (type) > 1)
02933 {
02934 enum machine_mode innermode = TYPE_MODE (TREE_TYPE (type));
02935
02936 if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
02937 mode = MIN_MODE_VECTOR_FLOAT;
02938 else
02939 mode = MIN_MODE_VECTOR_INT;
02940
02941
02942 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
02943 if (GET_MODE_NUNITS (mode) == TYPE_VECTOR_SUBPARTS (type)
02944 && GET_MODE_INNER (mode) == innermode)
02945 return mode;
02946
02947 gcc_unreachable ();
02948 }
02949 }
02950
02951 return mode;
02952 }
02953
02954
02955
02956
02957
02958
02959 static rtx
02960 gen_reg_or_parallel (enum machine_mode mode, enum machine_mode orig_mode,
02961 unsigned int regno)
02962 {
02963 rtx tmp;
02964
02965 if (orig_mode != BLKmode)
02966 tmp = gen_rtx_REG (orig_mode, regno);
02967 else
02968 {
02969 tmp = gen_rtx_REG (mode, regno);
02970 tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
02971 tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (1, tmp));
02972 }
02973
02974 return tmp;
02975 }
02976
02977
02978
02979
02980
02981
02982
02983
02984 static enum x86_64_reg_class
02985 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
02986 {
02987
02988 if (class1 == class2)
02989 return class1;
02990
02991
02992
02993 if (class1 == X86_64_NO_CLASS)
02994 return class2;
02995 if (class2 == X86_64_NO_CLASS)
02996 return class1;
02997
02998
02999 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
03000 return X86_64_MEMORY_CLASS;
03001
03002
03003 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
03004 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
03005 return X86_64_INTEGERSI_CLASS;
03006 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
03007 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
03008 return X86_64_INTEGER_CLASS;
03009
03010
03011
03012 if (class1 == X86_64_X87_CLASS
03013 || class1 == X86_64_X87UP_CLASS
03014 || class1 == X86_64_COMPLEX_X87_CLASS
03015 || class2 == X86_64_X87_CLASS
03016 || class2 == X86_64_X87UP_CLASS
03017 || class2 == X86_64_COMPLEX_X87_CLASS)
03018 return X86_64_MEMORY_CLASS;
03019
03020
03021 return X86_64_SSE_CLASS;
03022 }
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036 static int
03037 classify_argument (enum machine_mode mode, tree type,
03038 enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset)
03039 {
03040 HOST_WIDE_INT bytes =
03041 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
03042 int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03043
03044
03045 if (bytes < 0)
03046 return 0;
03047
03048 if (mode != VOIDmode
03049 && targetm.calls.must_pass_in_stack (mode, type))
03050 return 0;
03051
03052 if (type && AGGREGATE_TYPE_P (type))
03053 {
03054 int i;
03055 tree field;
03056 enum x86_64_reg_class subclasses[MAX_CLASSES];
03057
03058
03059 if (bytes > 16)
03060 return 0;
03061
03062 for (i = 0; i < words; i++)
03063 classes[i] = X86_64_NO_CLASS;
03064
03065
03066
03067 if (!words)
03068 {
03069 classes[0] = X86_64_NO_CLASS;
03070 return 1;
03071 }
03072
03073
03074 switch (TREE_CODE (type))
03075 {
03076 case RECORD_TYPE:
03077
03078 if (TYPE_BINFO (type))
03079 {
03080 tree binfo, base_binfo;
03081 int basenum;
03082
03083 for (binfo = TYPE_BINFO (type), basenum = 0;
03084 BINFO_BASE_ITERATE (binfo, basenum, base_binfo); basenum++)
03085 {
03086 int num;
03087 int offset = tree_low_cst (BINFO_OFFSET (base_binfo), 0) * 8;
03088 tree type = BINFO_TYPE (base_binfo);
03089
03090 num = classify_argument (TYPE_MODE (type),
03091 type, subclasses,
03092 (offset + bit_offset) % 256);
03093 if (!num)
03094 return 0;
03095 for (i = 0; i < num; i++)
03096 {
03097 int pos = (offset + (bit_offset % 64)) / 8 / 8;
03098 classes[i + pos] =
03099 merge_classes (subclasses[i], classes[i + pos]);
03100 }
03101 }
03102 }
03103
03104 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
03105 {
03106 if (TREE_CODE (field) == FIELD_DECL)
03107 {
03108 int num;
03109
03110 if (TREE_TYPE (field) == error_mark_node)
03111 continue;
03112
03113
03114
03115
03116 if (DECL_BIT_FIELD (field))
03117 {
03118 for (i = (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
03119 i < ((int_bit_position (field) + (bit_offset % 64))
03120 + tree_low_cst (DECL_SIZE (field), 0)
03121 + 63) / 8 / 8; i++)
03122 classes[i] =
03123 merge_classes (X86_64_INTEGER_CLASS,
03124 classes[i]);
03125 }
03126 else
03127 {
03128 num = classify_argument (TYPE_MODE (TREE_TYPE (field)),
03129 TREE_TYPE (field), subclasses,
03130 (int_bit_position (field)
03131 + bit_offset) % 256);
03132 if (!num)
03133 return 0;
03134 for (i = 0; i < num; i++)
03135 {
03136 int pos =
03137 (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
03138 classes[i + pos] =
03139 merge_classes (subclasses[i], classes[i + pos]);
03140 }
03141 }
03142 }
03143 }
03144 break;
03145
03146 case ARRAY_TYPE:
03147
03148 {
03149 int num;
03150 num = classify_argument (TYPE_MODE (TREE_TYPE (type)),
03151 TREE_TYPE (type), subclasses, bit_offset);
03152 if (!num)
03153 return 0;
03154
03155
03156 if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4)
03157 subclasses[0] = X86_64_SSE_CLASS;
03158 if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4)
03159 subclasses[0] = X86_64_INTEGER_CLASS;
03160
03161 for (i = 0; i < words; i++)
03162 classes[i] = subclasses[i % num];
03163
03164 break;
03165 }
03166 case UNION_TYPE:
03167 case QUAL_UNION_TYPE:
03168
03169
03170
03171
03172 gcc_assert (!TYPE_BINFO (type)
03173 || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)));
03174 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
03175 {
03176 if (TREE_CODE (field) == FIELD_DECL)
03177 {
03178 int num;
03179
03180 if (TREE_TYPE (field) == error_mark_node)
03181 continue;
03182
03183 num = classify_argument (TYPE_MODE (TREE_TYPE (field)),
03184 TREE_TYPE (field), subclasses,
03185 bit_offset);
03186 if (!num)
03187 return 0;
03188 for (i = 0; i < num; i++)
03189 classes[i] = merge_classes (subclasses[i], classes[i]);
03190 }
03191 }
03192 break;
03193
03194 default:
03195 gcc_unreachable ();
03196 }
03197
03198
03199 for (i = 0; i < words; i++)
03200 {
03201
03202
03203 if (classes[i] == X86_64_MEMORY_CLASS)
03204 return 0;
03205
03206
03207
03208 if (classes[i] == X86_64_SSEUP_CLASS
03209 && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
03210 classes[i] = X86_64_SSE_CLASS;
03211
03212
03213 if (classes[i] == X86_64_X87UP_CLASS
03214 && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
03215 classes[i] = X86_64_SSE_CLASS;
03216 }
03217 return words;
03218 }
03219
03220
03221
03222 if (mode != VOIDmode && mode != BLKmode)
03223 {
03224 int mode_alignment = GET_MODE_BITSIZE (mode);
03225
03226 if (mode == XFmode)
03227 mode_alignment = 128;
03228 else if (mode == XCmode)
03229 mode_alignment = 256;
03230 if (COMPLEX_MODE_P (mode))
03231 mode_alignment /= 2;
03232
03233 if (bit_offset % mode_alignment)
03234 return 0;
03235 }
03236
03237
03238 if (VECTOR_MODE_P (mode)
03239 && GET_MODE_SIZE (GET_MODE_INNER (mode)) == bytes)
03240 mode = GET_MODE_INNER (mode);
03241
03242
03243 switch (mode)
03244 {
03245 case SDmode:
03246 case DDmode:
03247 classes[0] = X86_64_SSE_CLASS;
03248 return 1;
03249 case TDmode:
03250 classes[0] = X86_64_SSE_CLASS;
03251 classes[1] = X86_64_SSEUP_CLASS;
03252 return 2;
03253 case DImode:
03254 case SImode:
03255 case HImode:
03256 case QImode:
03257 case CSImode:
03258 case CHImode:
03259 case CQImode:
03260 if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
03261 classes[0] = X86_64_INTEGERSI_CLASS;
03262 else
03263 classes[0] = X86_64_INTEGER_CLASS;
03264 return 1;
03265 case CDImode:
03266 case TImode:
03267 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
03268 return 2;
03269 case CTImode:
03270 return 0;
03271 case SFmode:
03272 if (!(bit_offset % 64))
03273 classes[0] = X86_64_SSESF_CLASS;
03274 else
03275 classes[0] = X86_64_SSE_CLASS;
03276 return 1;
03277 case DFmode:
03278 classes[0] = X86_64_SSEDF_CLASS;
03279 return 1;
03280 case XFmode:
03281 classes[0] = X86_64_X87_CLASS;
03282 classes[1] = X86_64_X87UP_CLASS;
03283 return 2;
03284 case TFmode:
03285 classes[0] = X86_64_SSE_CLASS;
03286 classes[1] = X86_64_SSEUP_CLASS;
03287 return 2;
03288 case SCmode:
03289 classes[0] = X86_64_SSE_CLASS;
03290 return 1;
03291 case DCmode:
03292 classes[0] = X86_64_SSEDF_CLASS;
03293 classes[1] = X86_64_SSEDF_CLASS;
03294 return 2;
03295 case XCmode:
03296 classes[0] = X86_64_COMPLEX_X87_CLASS;
03297 return 1;
03298 case TCmode:
03299
03300 return 0;
03301 case V4SFmode:
03302 case V4SImode:
03303 case V16QImode:
03304 case V8HImode:
03305 case V2DFmode:
03306 case V2DImode:
03307 classes[0] = X86_64_SSE_CLASS;
03308 classes[1] = X86_64_SSEUP_CLASS;
03309 return 2;
03310 case V2SFmode:
03311 case V2SImode:
03312 case V4HImode:
03313 case V8QImode:
03314 classes[0] = X86_64_SSE_CLASS;
03315 return 1;
03316 case BLKmode:
03317 case VOIDmode:
03318 return 0;
03319 default:
03320 gcc_assert (VECTOR_MODE_P (mode));
03321
03322 if (bytes > 16)
03323 return 0;
03324
03325 gcc_assert (GET_MODE_CLASS (GET_MODE_INNER (mode)) == MODE_INT);
03326
03327 if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
03328 classes[0] = X86_64_INTEGERSI_CLASS;
03329 else
03330 classes[0] = X86_64_INTEGER_CLASS;
03331 classes[1] = X86_64_INTEGER_CLASS;
03332 return 1 + (bytes > 8);
03333 }
03334 }
03335
03336
03337
03338 static int
03339 examine_argument (enum machine_mode mode, tree type, int in_return,
03340 int *int_nregs, int *sse_nregs)
03341 {
03342 enum x86_64_reg_class class[MAX_CLASSES];
03343 int n = classify_argument (mode, type, class, 0);
03344
03345 *int_nregs = 0;
03346 *sse_nregs = 0;
03347 if (!n)
03348 return 0;
03349 for (n--; n >= 0; n--)
03350 switch (class[n])
03351 {
03352 case X86_64_INTEGER_CLASS:
03353 case X86_64_INTEGERSI_CLASS:
03354 (*int_nregs)++;
03355 break;
03356 case X86_64_SSE_CLASS:
03357 case X86_64_SSESF_CLASS:
03358 case X86_64_SSEDF_CLASS:
03359 (*sse_nregs)++;
03360 break;
03361 case X86_64_NO_CLASS:
03362 case X86_64_SSEUP_CLASS:
03363 break;
03364 case X86_64_X87_CLASS:
03365 case X86_64_X87UP_CLASS:
03366 if (!in_return)
03367 return 0;
03368 break;
03369 case X86_64_COMPLEX_X87_CLASS:
03370 return in_return ? 2 : 0;
03371 case X86_64_MEMORY_CLASS:
03372 gcc_unreachable ();
03373 }
03374 return 1;
03375 }
03376
03377
03378
03379
03380 static rtx
03381 construct_container (enum machine_mode mode, enum machine_mode orig_mode,
03382 tree type, int in_return, int nintregs, int nsseregs,
03383 const int *intreg, int sse_regno)
03384 {
03385
03386 static bool issued_sse_arg_error;
03387 static bool issued_sse_ret_error;
03388 static bool issued_x87_ret_error;
03389
03390 enum machine_mode tmpmode;
03391 int bytes =
03392 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
03393 enum x86_64_reg_class class[MAX_CLASSES];
03394 int n;
03395 int i;
03396 int nexps = 0;
03397 int needed_sseregs, needed_intregs;
03398 rtx exp[MAX_CLASSES];
03399 rtx ret;
03400
03401 n = classify_argument (mode, type, class, 0);
03402 if (TARGET_DEBUG_ARG)
03403 {
03404 if (!n)
03405 fprintf (stderr, "Memory class\n");
03406 else
03407 {
03408 fprintf (stderr, "Classes:");
03409 for (i = 0; i < n; i++)
03410 {
03411 fprintf (stderr, " %s", x86_64_reg_class_name[class[i]]);
03412 }
03413 fprintf (stderr, "\n");
03414 }
03415 }
03416 if (!n)
03417 return NULL;
03418 if (!examine_argument (mode, type, in_return, &needed_intregs,
03419 &needed_sseregs))
03420 return NULL;
03421 if (needed_intregs > nintregs || needed_sseregs > nsseregs)
03422 return NULL;
03423
03424
03425
03426 if (needed_sseregs && !TARGET_SSE)
03427 {
03428 if (in_return)
03429 {
03430 if (!issued_sse_ret_error)
03431 {
03432 error ("SSE register return with SSE disabled");
03433 issued_sse_ret_error = true;
03434 }
03435 }
03436 else if (!issued_sse_arg_error)
03437 {
03438 error ("SSE register argument with SSE disabled");
03439 issued_sse_arg_error = true;
03440 }
03441 return NULL;
03442 }
03443
03444
03445
03446 if (!TARGET_80387 && in_return)
03447 for (i = 0; i < n; i++)
03448 if (class[i] == X86_64_X87_CLASS
03449 || class[i] == X86_64_X87UP_CLASS
03450 || class[i] == X86_64_COMPLEX_X87_CLASS)
03451 {
03452 if (!issued_x87_ret_error)
03453 {
03454 error ("x87 register return with x87 disabled");
03455 issued_x87_ret_error = true;
03456 }
03457 return NULL;
03458 }
03459
03460
03461
03462 if (n == 1 && mode != SCmode)
03463 switch (class[0])
03464 {
03465 case X86_64_INTEGER_CLASS:
03466 case X86_64_INTEGERSI_CLASS:
03467 return gen_rtx_REG (mode, intreg[0]);
03468 case X86_64_SSE_CLASS:
03469 case X86_64_SSESF_CLASS:
03470 case X86_64_SSEDF_CLASS:
03471 return gen_reg_or_parallel (mode, orig_mode, SSE_REGNO (sse_regno));
03472 case X86_64_X87_CLASS:
03473 case X86_64_COMPLEX_X87_CLASS:
03474 return gen_rtx_REG (mode, FIRST_STACK_REG);
03475 case X86_64_NO_CLASS:
03476
03477 return NULL;
03478 default:
03479 gcc_unreachable ();
03480 }
03481 if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS
03482 && mode != BLKmode)
03483 return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
03484 if (n == 2
03485 && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
03486 return gen_rtx_REG (XFmode, FIRST_STACK_REG);
03487 if (n == 2 && class[0] == X86_64_INTEGER_CLASS
03488 && class[1] == X86_64_INTEGER_CLASS
03489 && (mode == CDImode || mode == TImode || mode == TFmode)
03490 && intreg[0] + 1 == intreg[1])
03491 return gen_rtx_REG (mode, intreg[0]);
03492
03493
03494 for (i = 0; i < n; i++)
03495 {
03496 switch (class[i])
03497 {
03498 case X86_64_NO_CLASS:
03499 break;
03500 case X86_64_INTEGER_CLASS:
03501 case X86_64_INTEGERSI_CLASS:
03502
03503 if (i * 8 + 8 > bytes)
03504 tmpmode = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
03505 else if (class[i] == X86_64_INTEGERSI_CLASS)
03506 tmpmode = SImode;
03507 else
03508 tmpmode = DImode;
03509
03510 if (tmpmode == BLKmode)
03511 tmpmode = DImode;
03512 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
03513 gen_rtx_REG (tmpmode, *intreg),
03514 GEN_INT (i*8));
03515 intreg++;
03516 break;
03517 case X86_64_SSESF_CLASS:
03518 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
03519 gen_rtx_REG (SFmode,
03520 SSE_REGNO (sse_regno)),
03521 GEN_INT (i*8));
03522 sse_regno++;
03523 break;
03524 case X86_64_SSEDF_CLASS:
03525 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
03526 gen_rtx_REG (DFmode,
03527 SSE_REGNO (sse_regno)),
03528 GEN_INT (i*8));
03529 sse_regno++;
03530 break;
03531 case X86_64_SSE_CLASS:
03532 if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
03533 tmpmode = TImode;
03534 else
03535 tmpmode = DImode;
03536 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
03537 gen_rtx_REG (tmpmode,
03538 SSE_REGNO (sse_regno)),
03539 GEN_INT (i*8));
03540 if (tmpmode == TImode)
03541 i++;
03542 sse_regno++;
03543 break;
03544 default:
03545 gcc_unreachable ();
03546 }
03547 }
03548
03549
03550 if (nexps == 0)
03551 return NULL;
03552
03553 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nexps));
03554 for (i = 0; i < nexps; i++)
03555 XVECEXP (ret, 0, i) = exp [i];
03556 return ret;
03557 }
03558
03559
03560
03561
03562
03563 void
03564 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03565 tree type, int named)
03566 {
03567 int bytes =
03568 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
03569 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03570
03571 if (type)
03572 mode = type_natural_mode (type);
03573
03574 if (TARGET_DEBUG_ARG)
03575 fprintf (stderr, "function_adv (sz=%d, wds=%2d, nregs=%d, ssenregs=%d, "
03576 "mode=%s, named=%d)\n\n",
03577 words, cum->words, cum->nregs, cum->sse_nregs,
03578 GET_MODE_NAME (mode), named);
03579
03580 if (TARGET_64BIT)
03581 {
03582 int int_nregs, sse_nregs;
03583 if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
03584 cum->words += words;
03585 else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
03586 {
03587 cum->nregs -= int_nregs;
03588 cum->sse_nregs -= sse_nregs;
03589 cum->regno += int_nregs;
03590 cum->sse_regno += sse_nregs;
03591 }
03592 else
03593 cum->words += words;
03594 }
03595 else
03596 {
03597 switch (mode)
03598 {
03599 default:
03600 break;
03601
03602 case BLKmode:
03603 if (bytes < 0)
03604 break;
03605
03606
03607 case DImode:
03608 case SImode:
03609 case HImode:
03610 case QImode:
03611 cum->words += words;
03612 cum->nregs -= words;
03613 cum->regno += words;
03614
03615 if (cum->nregs <= 0)
03616 {
03617 cum->nregs = 0;
03618 cum->regno = 0;
03619 }
03620 break;
03621
03622 case DFmode:
03623 if (cum->float_in_sse < 2)
03624 break;
03625 case SFmode:
03626 if (cum->float_in_sse < 1)
03627 break;
03628
03629
03630 case TImode:
03631 case V16QImode:
03632 case V8HImode:
03633 case V4SImode:
03634 case V2DImode:
03635 case V4SFmode:
03636 case V2DFmode:
03637 if (!type || !AGGREGATE_TYPE_P (type))
03638 {
03639 cum->sse_words += words;
03640 cum->sse_nregs -= 1;
03641 cum->sse_regno += 1;
03642 if (cum->sse_nregs <= 0)
03643 {
03644 cum->sse_nregs = 0;
03645 cum->sse_regno = 0;
03646 }
03647 }
03648 break;
03649
03650 case V8QImode:
03651 case V4HImode:
03652 case V2SImode:
03653 case V2SFmode:
03654 if (!type || !AGGREGATE_TYPE_P (type))
03655 {
03656 cum->mmx_words += words;
03657 cum->mmx_nregs -= 1;
03658 cum->mmx_regno += 1;
03659 if (cum->mmx_nregs <= 0)
03660 {
03661 cum->mmx_nregs = 0;
03662 cum->mmx_regno = 0;
03663 }
03664 }
03665 break;
03666 }
03667 }
03668 }
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683 rtx
03684 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
03685 tree type, int named)
03686 {
03687 enum machine_mode mode = orig_mode;
03688 rtx ret = NULL_RTX;
03689 int bytes =
03690 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
03691 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03692 static bool warnedsse, warnedmmx;
03693
03694
03695
03696 if (type && TREE_CODE (type) == VECTOR_TYPE)
03697 mode = type_natural_mode (type);
03698
03699
03700
03701
03702 if (mode == VOIDmode)
03703 {
03704 if (TARGET_64BIT)
03705 return GEN_INT (cum->maybe_vaarg
03706 ? (cum->sse_nregs < 0
03707 ? SSE_REGPARM_MAX
03708 : cum->sse_regno)
03709 : -1);
03710 else
03711 return constm1_rtx;
03712 }
03713 if (TARGET_64BIT)
03714 ret = construct_container (mode, orig_mode, type, 0, cum->nregs,
03715 cum->sse_nregs,
03716 &x86_64_int_parameter_registers [cum->regno],
03717 cum->sse_regno);
03718 else
03719 switch (mode)
03720 {
03721
03722 default:
03723 break;
03724
03725 case BLKmode:
03726 if (bytes < 0)
03727 break;
03728
03729 case DImode:
03730 case SImode:
03731 case HImode:
03732 case QImode:
03733 if (words <= cum->nregs)
03734 {
03735 int regno = cum->regno;
03736
03737
03738
03739 if (cum->fastcall)
03740 {
03741 if (mode == BLKmode || mode == DImode)
03742 break;
03743
03744
03745 if (regno == 0)
03746 regno = 2;
03747 }
03748 ret = gen_rtx_REG (mode, regno);
03749 }
03750 break;
03751 case DFmode:
03752 if (cum->float_in_sse < 2)
03753 break;
03754 case SFmode:
03755 if (cum->float_in_sse < 1)
03756 break;
03757
03758 case TImode:
03759 case V16QImode:
03760 case V8HImode:
03761 case V4SImode:
03762 case V2DImode:
03763 case V4SFmode:
03764 case V2DFmode:
03765 if (!type || !AGGREGATE_TYPE_P (type))
03766 {
03767 if (!TARGET_SSE && !warnedsse && cum->warn_sse)
03768 {
03769 warnedsse = true;
03770 warning (0, "SSE vector argument without SSE enabled "
03771 "changes the ABI");
03772 }
03773 if (cum->sse_nregs)
03774 ret = gen_reg_or_parallel (mode, orig_mode,
03775 cum->sse_regno + FIRST_SSE_REG);
03776 }
03777 break;
03778 case V8QImode:
03779 case V4HImode:
03780 case V2SImode:
03781 case V2SFmode:
03782 if (!type || !AGGREGATE_TYPE_P (type))
03783 {
03784 if (!TARGET_MMX && !warnedmmx && cum->warn_mmx)
03785 {
03786 warnedmmx = true;
03787 warning (0, "MMX vector argument without MMX enabled "
03788 "changes the ABI");
03789 }
03790 if (cum->mmx_nregs)
03791 ret = gen_reg_or_parallel (mode, orig_mode,
03792 cum->mmx_regno + FIRST_MMX_REG);
03793 }
03794 break;
03795 }
03796
03797 if (TARGET_DEBUG_ARG)
03798 {
03799 fprintf (stderr,
03800 "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d, ",
03801 words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
03802
03803 if (ret)
03804 print_simple_rtl (stderr, ret);
03805 else
03806 fprintf (stderr, ", stack");
03807
03808 fprintf (stderr, " )\n");
03809 }
03810
03811 return ret;
03812 }
03813
03814
03815
03816
03817
03818
03819
03820 static bool
03821 ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
03822 enum machine_mode mode ATTRIBUTE_UNUSED,
03823 tree type, bool named ATTRIBUTE_UNUSED)
03824 {
03825 if (!TARGET_64BIT)
03826 return 0;
03827
03828 if (type && int_size_in_bytes (type) == -1)
03829 {
03830 if (TARGET_DEBUG_ARG)
03831 fprintf (stderr, "function_arg_pass_by_reference\n");
03832 return 1;
03833 }
03834
03835 return 0;
03836 }
03837
03838
03839
03840 static bool
03841 contains_128bit_aligned_vector_p (tree type)
03842 {
03843 enum machine_mode mode = TYPE_MODE (type);
03844 if (SSE_REG_MODE_P (mode)
03845 && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128))
03846 return true;
03847 if (TYPE_ALIGN (type) < 128)
03848 return false;
03849
03850 if (AGGREGATE_TYPE_P (type))
03851 {
03852
03853 switch (TREE_CODE (type))
03854 {
03855 case RECORD_TYPE:
03856 case UNION_TYPE:
03857 case QUAL_UNION_TYPE:
03858 {
03859 tree field;
03860
03861 if (TYPE_BINFO (type))
03862 {
03863 tree binfo, base_binfo;
03864 int i;
03865
03866 for (binfo = TYPE_BINFO (type), i = 0;
03867 BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
03868 if (contains_128bit_aligned_vector_p
03869 (BINFO_TYPE (base_binfo)))
03870 return true;
03871 }
03872
03873 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
03874 {
03875 if (TREE_CODE (field) == FIELD_DECL
03876 && contains_128bit_aligned_vector_p (TREE_TYPE (field)))
03877 return true;
03878 }
03879 break;
03880 }
03881
03882 case ARRAY_TYPE:
03883
03884 if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
03885 return true;
03886 break;
03887
03888 default:
03889 gcc_unreachable ();
03890 }
03891 }
03892 return false;
03893 }
03894
03895
03896
03897
03898 int
03899 ix86_function_arg_boundary (enum machine_mode mode, tree type)
03900 {
03901 int align;
03902 if (type)
03903 align = TYPE_ALIGN (type);
03904 else
03905 align = GET_MODE_ALIGNMENT (mode);
03906 if (align < PARM_BOUNDARY)
03907 align = PARM_BOUNDARY;
03908 if (!TARGET_64BIT)
03909 {
03910
03911
03912
03913
03914
03915
03916
03917 if (!TARGET_SSE)
03918 align = PARM_BOUNDARY;
03919 else if (!type)
03920 {
03921 if (!SSE_REG_MODE_P (mode))
03922 align = PARM_BOUNDARY;
03923 }
03924 else
03925 {
03926 if (!contains_128bit_aligned_vector_p (type))
03927 align = PARM_BOUNDARY;
03928 }
03929 }
03930 if (align > 128)
03931 align = 128;
03932 return align;
03933 }
03934
03935
03936 bool
03937 ix86_function_value_regno_p (int regno)
03938 {
03939 if (TARGET_MACHO)
03940 {
03941 if (!TARGET_64BIT)
03942 {
03943 return ((regno) == 0
03944 || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
03945 || ((regno) == FIRST_SSE_REG && TARGET_SSE));
03946 }
03947 return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
03948 || ((regno) == FIRST_SSE_REG && TARGET_SSE)
03949 || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
03950 }
03951 else
03952 {
03953 if (regno == 0
03954 || (regno == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
03955 || (regno == FIRST_SSE_REG && TARGET_SSE))
03956 return true;
03957
03958 if (!TARGET_64BIT
03959 && (regno == FIRST_MMX_REG && TARGET_MMX))
03960 return true;
03961
03962 return false;
03963 }
03964 }
03965
03966
03967
03968
03969
03970 rtx
03971 ix86_function_value (tree valtype, tree fntype_or_decl,
03972 bool outgoing ATTRIBUTE_UNUSED)
03973 {
03974 enum machine_mode natmode = type_natural_mode (valtype);
03975
03976 if (TARGET_64BIT)
03977 {
03978 rtx ret = construct_container (natmode, TYPE_MODE (valtype), valtype,
03979 1, REGPARM_MAX, SSE_REGPARM_MAX,
03980 x86_64_int_return_registers, 0);
03981
03982
03983 if (!ret)
03984 ret = gen_rtx_REG (TYPE_MODE (valtype), 0);
03985 return ret;
03986 }
03987 else
03988 {
03989 tree fn = NULL_TREE, fntype;
03990 if (fntype_or_decl
03991 && DECL_P (fntype_or_decl))
03992 fn = fntype_or_decl;
03993 fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
03994 return gen_rtx_REG (TYPE_MODE (valtype),
03995 ix86_value_regno (natmode, fn, fntype));
03996 }
03997 }
03998
03999
04000 int
04001 ix86_return_in_memory (tree type)
04002 {
04003 int needed_intregs, needed_sseregs, size;
04004 enum machine_mode mode = type_natural_mode (type);
04005
04006 if (TARGET_64BIT)
04007 return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
04008
04009 if (mode == BLKmode)
04010 return 1;
04011
04012 size = int_size_in_bytes (type);
04013
04014 if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8)
04015 return 0;
04016
04017 if (VECTOR_MODE_P (mode) || mode == TImode)
04018 {
04019
04020 if (size < 8)
04021 return 0;
04022
04023
04024
04025 if (size == 8)
04026 return (TARGET_MMX ? 0 : 1);
04027
04028
04029 if (size == 16)
04030 return (TARGET_SSE ? 0 : 1);
04031 }
04032
04033 if (mode == XFmode)
04034 return 0;
04035
04036 if (mode == TDmode)
04037 return 1;
04038
04039 if (size > 12)
04040 return 1;
04041 return 0;
04042 }
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055 static rtx
04056 ix86_struct_value_rtx (tree type, int incoming ATTRIBUTE_UNUSED)
04057 {
04058 static bool warnedsse, warnedmmx;
04059
04060 if (type)
04061 {
04062
04063 enum machine_mode mode = TYPE_MODE (TREE_TYPE (type));
04064
04065 if (!TARGET_SSE && !warnedsse)
04066 {
04067 if (mode == TImode
04068 || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
04069 {
04070 warnedsse = true;
04071 warning (0, "SSE vector return without SSE enabled "
04072 "changes the ABI");
04073 }
04074 }
04075
04076 if (!TARGET_MMX && !warnedmmx)
04077 {
04078 if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
04079 {
04080 warnedmmx = true;
04081 warning (0, "MMX vector return without MMX enabled "
04082 "changes the ABI");
04083 }
04084 }
04085 }
04086
04087 return NULL;
04088 }
04089
04090
04091
04092 rtx
04093 ix86_libcall_value (enum machine_mode mode)
04094 {
04095 if (TARGET_64BIT)
04096 {
04097 switch (mode)
04098 {
04099 case SFmode:
04100 case SCmode:
04101 case DFmode:
04102 case DCmode:
04103 case TFmode:
04104 case SDmode:
04105 case DDmode:
04106 case TDmode:
04107 return gen_rtx_REG (mode, FIRST_SSE_REG);
04108 case XFmode:
04109 case XCmode:
04110 return gen_rtx_REG (mode, FIRST_FLOAT_REG);
04111 case TCmode:
04112 return NULL;
04113 default:
04114 return gen_rtx_REG (mode, 0);
04115 }
04116 }
04117 else
04118 return gen_rtx_REG (mode, ix86_value_regno (mode, NULL, NULL));
04119 }
04120
04121
04122
04123 static int
04124 ix86_value_regno (enum machine_mode mode, tree func, tree fntype)
04125 {
04126 gcc_assert (!TARGET_64BIT);
04127
04128
04129
04130
04131 if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
04132 return TARGET_MMX ? FIRST_MMX_REG : 0;
04133
04134
04135
04136
04137 if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
04138 return TARGET_SSE ? FIRST_SSE_REG : 0;
04139
04140
04141 if (DECIMAL_FLOAT_MODE_P (mode))
04142 return 0;
04143
04144
04145 if (!SCALAR_FLOAT_MODE_P (mode) || !TARGET_FLOAT_RETURNS_IN_80387)
04146 return 0;
04147
04148
04149
04150 if ((func || fntype)
04151 && (mode == SFmode || mode == DFmode))
04152 {
04153 int sse_level = ix86_function_sseregparm (fntype, func);
04154 if ((sse_level >= 1 && mode == SFmode)
04155 || (sse_level == 2 && mode == DFmode))
04156 return FIRST_SSE_REG;
04157 }
04158
04159 return FIRST_FLOAT_REG;
04160 }
04161
04162
04163
04164 static tree
04165 ix86_build_builtin_va_list (void)
04166 {
04167 tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
04168
04169
04170 if (!TARGET_64BIT)
04171 return build_pointer_type (char_type_node);
04172
04173 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
04174 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
04175
04176 f_gpr = build_decl (FIELD_DECL, get_identifier ("gp_offset"),
04177 unsigned_type_node);
04178 f_fpr = build_decl (FIELD_DECL, get_identifier ("fp_offset"),
04179 unsigned_type_node);
04180 f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
04181 ptr_type_node);
04182 f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
04183 ptr_type_node);
04184
04185 va_list_gpr_counter_field = f_gpr;
04186 va_list_fpr_counter_field = f_fpr;
04187
04188 DECL_FIELD_CONTEXT (f_gpr) = record;
04189 DECL_FIELD_CONTEXT (f_fpr) = record;
04190 DECL_FIELD_CONTEXT (f_ovf) = record;
04191 DECL_FIELD_CONTEXT (f_sav) = record;
04192
04193 TREE_CHAIN (record) = type_decl;
04194 TYPE_NAME (record) = type_decl;
04195 TYPE_FIELDS (record) = f_gpr;
04196 TREE_CHAIN (f_gpr) = f_fpr;
04197 TREE_CHAIN (f_fpr) = f_ovf;
04198 TREE_CHAIN (f_ovf) = f_sav;
04199
04200 layout_type (record);
04201
04202
04203 return build_array_type (record, build_index_type (size_zero_node));
04204 }
04205
04206
04207
04208 static void
04209 ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04210 tree type, int *pretend_size ATTRIBUTE_UNUSED,
04211 int no_rtl)
04212 {
04213 CUMULATIVE_ARGS next_cum;
04214 rtx save_area = NULL_RTX, mem;
04215 rtx label;
04216 rtx label_ref;
04217 rtx tmp_reg;
04218 rtx nsse_reg;
04219 int set;
04220 tree fntype;
04221 int stdarg_p;
04222 int i;
04223
04224 if (!TARGET_64BIT)
04225 return;
04226
04227 if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size)
04228 return;
04229
04230
04231 ix86_save_varrargs_registers = 1;
04232
04233 cfun->stack_alignment_needed = 128;
04234
04235 fntype = TREE_TYPE (current_function_decl);
04236 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
04237 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04238 != void_type_node));
04239
04240
04241
04242 next_cum = *cum;
04243 if (stdarg_p)
04244 function_arg_advance (&next_cum, mode, type, 1);
04245
04246 if (!no_rtl)
04247 save_area = frame_pointer_rtx;
04248
04249 set = get_varargs_alias_set ();
04250
04251 for (i = next_cum.regno;
04252 i < ix86_regparm
04253 && i < next_cum.regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
04254 i++)
04255 {
04256 mem = gen_rtx_MEM (Pmode,
04257 plus_constant (save_area, i * UNITS_PER_WORD));
04258 MEM_NOTRAP_P (mem) = 1;
04259 set_mem_alias_set (mem, set);
04260 emit_move_insn (mem, gen_rtx_REG (Pmode,
04261 x86_64_int_parameter_registers[i]));
04262 }
04263
04264 if (next_cum.sse_nregs && cfun->va_list_fpr_size)
04265 {
04266
04267
04268
04269
04270
04271 label = gen_label_rtx ();
04272 label_ref = gen_rtx_LABEL_REF (Pmode, label);
04273
04274
04275
04276 tmp_reg = gen_reg_rtx (Pmode);
04277 nsse_reg = gen_reg_rtx (Pmode);
04278 emit_insn (gen_zero_extendqidi2 (nsse_reg, gen_rtx_REG (QImode, 0)));
04279 emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
04280 gen_rtx_MULT (Pmode, nsse_reg,
04281 GEN_INT (4))));
04282 if (next_cum.sse_regno)
04283 emit_move_insn
04284 (nsse_reg,
04285 gen_rtx_CONST (DImode,
04286 gen_rtx_PLUS (DImode,
04287 label_ref,
04288 GEN_INT (next_cum.sse_regno * 4))));
04289 else
04290 emit_move_insn (nsse_reg, label_ref);
04291 emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
04292
04293
04294
04295
04296 tmp_reg = gen_reg_rtx (Pmode);
04297 emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
04298 plus_constant (save_area,
04299 8 * REGPARM_MAX + 127)));
04300 mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127));
04301 MEM_NOTRAP_P (mem) = 1;
04302 set_mem_alias_set (mem, set);
04303 set_mem_align (mem, BITS_PER_WORD);
04304
04305
04306 emit_insn (gen_sse_prologue_save (mem, nsse_reg,
04307 GEN_INT (next_cum.sse_regno), label));
04308 }
04309
04310 }
04311
04312
04313
04314 void
04315 ix86_va_start (tree valist, rtx nextarg)
04316 {
04317 HOST_WIDE_INT words, n_gpr, n_fpr;
04318 tree f_gpr, f_fpr, f_ovf, f_sav;
04319 tree gpr, fpr, ovf, sav, t;
04320 tree type;
04321
04322
04323 if (!TARGET_64BIT)
04324 {
04325 std_expand_builtin_va_start (valist, nextarg);
04326 return;
04327 }
04328
04329 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
04330 f_fpr = TREE_CHAIN (f_gpr);
04331 f_ovf = TREE_CHAIN (f_fpr);
04332 f_sav = TREE_CHAIN (f_ovf);
04333
04334 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
04335 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
04336 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
04337 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
04338 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
04339
04340
04341 words = current_function_args_info.words;
04342 n_gpr = current_function_args_info.regno;
04343 n_fpr = current_function_args_info.sse_regno;
04344
04345 if (TARGET_DEBUG_ARG)
04346 fprintf (stderr, "va_start: words = %d, n_gpr = %d, n_fpr = %d\n",
04347 (int) words, (int) n_gpr, (int) n_fpr);
04348
04349 if (cfun->va_list_gpr_size)
04350 {
04351 type = TREE_TYPE (gpr);
04352 t = build2 (MODIFY_EXPR, type, gpr,
04353 build_int_cst (type, n_gpr * 8));
04354 TREE_SIDE_EFFECTS (t) = 1;
04355 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04356 }
04357
04358 if (cfun->va_list_fpr_size)
04359 {
04360 type = TREE_TYPE (fpr);
04361 t = build2 (MODIFY_EXPR, type, fpr,
04362 build_int_cst (type, n_fpr * 16 + 8*REGPARM_MAX));
04363 TREE_SIDE_EFFECTS (t) = 1;
04364 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04365 }
04366
04367
04368 type = TREE_TYPE (ovf);
04369 t = make_tree (type, virtual_incoming_args_rtx);
04370 if (words != 0)
04371 t = build2 (PLUS_EXPR, type, t,
04372 build_int_cst (type, words * UNITS_PER_WORD));
04373 t = build2 (MODIFY_EXPR, type, ovf, t);
04374 TREE_SIDE_EFFECTS (t) = 1;
04375 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04376
04377 if (cfun->va_list_gpr_size || cfun->va_list_fpr_size)
04378 {
04379
04380
04381 type = TREE_TYPE (sav);
04382 t = make_tree (type, frame_pointer_rtx);
04383 t = build2 (MODIFY_EXPR, type, sav, t);
04384 TREE_SIDE_EFFECTS (t) = 1;
04385 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04386 }
04387 }
04388
04389
04390
04391 tree
04392 ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
04393 {
04394 static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
04395 tree f_gpr, f_fpr, f_ovf, f_sav;
04396 tree gpr, fpr, ovf, sav, t;
04397 int size, rsize;
04398 tree lab_false, lab_over = NULL_TREE;
04399 tree addr, t2;
04400 rtx container;
04401 int indirect_p = 0;
04402 tree ptrtype;
04403 enum machine_mode nat_mode;
04404
04405
04406 if (!TARGET_64BIT)
04407 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
04408
04409 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
04410 f_fpr = TREE_CHAIN (f_gpr);
04411 f_ovf = TREE_CHAIN (f_fpr);
04412 f_sav = TREE_CHAIN (f_ovf);
04413
04414 valist = build_va_arg_indirect_ref (valist);
04415 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
04416 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
04417 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
04418 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
04419
04420 indirect_p = pass_by_reference (NULL, TYPE_MODE (type), type, false);
04421 if (indirect_p)
04422 type = build_pointer_type (type);
04423 size = int_size_in_bytes (type);
04424 rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
04425
04426 nat_mode = type_natural_mode (type);
04427 container = construct_container (nat_mode, TYPE_MODE (type), type, 0,
04428 REGPARM_MAX, SSE_REGPARM_MAX, intreg, 0);
04429
04430
04431
04432 addr = create_tmp_var (ptr_type_node, "addr");
04433 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
04434
04435 if (container)
04436 {
04437 int needed_intregs, needed_sseregs;
04438 bool need_temp;
04439 tree int_addr, sse_addr;
04440
04441 lab_false = create_artificial_label ();
04442 lab_over = create_artificial_label ();
04443
04444 examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs);
04445
04446 need_temp = (!REG_P (container)
04447 && ((needed_intregs && TYPE_ALIGN (type) > 64)
04448 || TYPE_ALIGN (type) > 128));
04449
04450
04451
04452 if (!need_temp && !REG_P (container))
04453 {
04454
04455 if (SSE_REGNO_P (REGNO (XEXP (XVECEXP (container, 0, 0), 0))))
04456 {
04457 int i;
04458
04459 for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
04460 {
04461 rtx slot = XVECEXP (container, 0, i);
04462 if (REGNO (XEXP (slot, 0)) != FIRST_SSE_REG + (unsigned int) i
04463 || INTVAL (XEXP (slot, 1)) != i * 16)
04464 need_temp = 1;
04465 }
04466 }
04467 else
04468 {
04469 int i;
04470
04471 for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
04472 {
04473 rtx slot = XVECEXP (container, 0, i);
04474 if (REGNO (XEXP (slot, 0)) != (unsigned int) i
04475 || INTVAL (XEXP (slot, 1)) != i * 8)
04476 need_temp = 1;
04477 }
04478 }
04479 }
04480 if (!need_temp)
04481 {
04482 int_addr = addr;
04483 sse_addr = addr;
04484 }
04485 else
04486 {
04487 int_addr = create_tmp_var (ptr_type_node, "int_addr");
04488 DECL_POINTER_ALIAS_SET (int_addr) = get_varargs_alias_set ();
04489 sse_addr = create_tmp_var (ptr_type_node, "sse_addr");
04490 DECL_POINTER_ALIAS_SET (sse_addr) = get_varargs_alias_set ();
04491 }
04492
04493
04494 if (needed_intregs)
04495 {
04496 t = build_int_cst (TREE_TYPE (gpr),
04497 (REGPARM_MAX - needed_intregs + 1) * 8);
04498 t = build2 (GE_EXPR, boolean_type_node, gpr, t);
04499 t2 = build1 (GOTO_EXPR, void_type_node, lab_false);
04500 t = build3 (COND_EXPR, void_type_node, t, t2, NULL_TREE);
04501 gimplify_and_add (t, pre_p);
04502 }
04503 if (needed_sseregs)
04504 {
04505 t = build_int_cst (TREE_TYPE (fpr),
04506 (SSE_REGPARM_MAX - needed_sseregs + 1) * 16
04507 + REGPARM_MAX * 8);
04508 t = build2 (GE_EXPR, boolean_type_node, fpr, t);
04509 t2 = build1 (GOTO_EXPR, void_type_node, lab_false);
04510 t = build3 (COND_EXPR, void_type_node, t, t2, NULL_TREE);
04511 gimplify_and_add (t, pre_p);
04512 }
04513
04514
04515 if (needed_intregs)
04516 {
04517
04518 t = fold_convert (ptr_type_node, gpr);
04519 t = build2 (PLUS_EXPR, ptr_type_node, sav, t);
04520 t = build2 (MODIFY_EXPR, void_type_node, int_addr, t);
04521 gimplify_and_add (t, pre_p);
04522 }
04523 if (needed_sseregs)
04524 {
04525
04526 t = fold_convert (ptr_type_node, fpr);
04527 t = build2 (PLUS_EXPR, ptr_type_node, sav, t);
04528 t = build2 (MODIFY_EXPR, void_type_node, sse_addr, t);
04529 gimplify_and_add (t, pre_p);
04530 }
04531 if (need_temp)
04532 {
04533 int i;
04534 tree temp = create_tmp_var (type, "va_arg_tmp");
04535
04536
04537 t = build1 (ADDR_EXPR, build_pointer_type (type), temp);
04538 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
04539 gimplify_and_add (t, pre_p);
04540
04541 for (i = 0; i < XVECLEN (container, 0); i++)
04542 {
04543 rtx slot = XVECEXP (container, 0, i);
04544 rtx reg = XEXP (slot, 0);
04545 enum machine_mode mode = GET_MODE (reg);
04546 tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
04547 tree addr_type = build_pointer_type (piece_type);
04548 tree src_addr, src;
04549 int src_offset;
04550 tree dest_addr, dest;
04551
04552 if (SSE_REGNO_P (REGNO (reg)))
04553 {
04554 src_addr = sse_addr;
04555 src_offset = (REGNO (reg) - FIRST_SSE_REG) * 16;
04556 }
04557 else
04558 {
04559 src_addr = int_addr;
04560 src_offset = REGNO (reg) * 8;
04561 }
04562 src_addr = fold_convert (addr_type, src_addr);
04563 src_addr = fold (build2 (PLUS_EXPR, addr_type, src_addr,
04564 size_int (src_offset)));
04565 src = build_va_arg_indirect_ref (src_addr);
04566
04567 dest_addr = fold_convert (addr_type, addr);
04568 dest_addr = fold (build2 (PLUS_EXPR, addr_type, dest_addr,
04569 size_int (INTVAL (XEXP (slot, 1)))));
04570 dest = build_va_arg_indirect_ref (dest_addr);
04571
04572 t = build2 (MODIFY_EXPR, void_type_node, dest, src);
04573 gimplify_and_add (t, pre_p);
04574 }
04575 }
04576
04577 if (needed_intregs)
04578 {
04579 t = build2 (PLUS_EXPR, TREE_TYPE (gpr), gpr,
04580 build_int_cst (TREE_TYPE (gpr), needed_intregs * 8));
04581 t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
04582 gimplify_and_add (t, pre_p);
04583 }
04584 if (needed_sseregs)
04585 {
04586 t = build2 (PLUS_EXPR, TREE_TYPE (fpr), fpr,
04587 build_int_cst (TREE_TYPE (fpr), needed_sseregs * 16));
04588 t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t);
04589 gimplify_and_add (t, pre_p);
04590 }
04591
04592 t = build1 (GOTO_EXPR, void_type_node, lab_over);
04593 gimplify_and_add (t, pre_p);
04594
04595 t = build1 (LABEL_EXPR, void_type_node, lab_false);
04596 append_to_statement_list (t, pre_p);
04597 }
04598
04599
04600
04601
04602 if (FUNCTION_ARG_BOUNDARY (VOIDmode, type) <= 64
04603 || integer_zerop (TYPE_SIZE (type)))
04604 t = ovf;
04605 else
04606 {
04607 HOST_WIDE_INT align = FUNCTION_ARG_BOUNDARY (VOIDmode, type) / 8;
04608 t = build2 (PLUS_EXPR, TREE_TYPE (ovf), ovf,
04609 build_int_cst (TREE_TYPE (ovf), align - 1));
04610 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
04611 build_int_cst (TREE_TYPE (t), -align));
04612 }
04613 gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
04614
04615 t2 = build2 (MODIFY_EXPR, void_type_node, addr, t);
04616 gimplify_and_add (t2, pre_p);
04617
04618 t = build2 (PLUS_EXPR, TREE_TYPE (t), t,
04619 build_int_cst (TREE_TYPE (t), rsize * UNITS_PER_WORD));
04620 t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
04621 gimplify_and_add (t, pre_p);
04622
04623 if (container)
04624 {
04625 t = build1 (LABEL_EXPR, void_type_node, lab_over);
04626 append_to_statement_list (t, pre_p);
04627 }
04628
04629 ptrtype = build_pointer_type (type);
04630 addr = fold_convert (ptrtype, addr);
04631
04632 if (indirect_p)
04633 addr = build_va_arg_indirect_ref (addr);
04634 return build_va_arg_indirect_ref (addr);
04635 }
04636
04637
04638
04639
04640 int
04641 ix86_check_movabs (rtx insn, int opnum)
04642 {
04643 rtx set, mem;
04644
04645 set = PATTERN (insn);
04646 if (GET_CODE (set) == PARALLEL)
04647 set = XVECEXP (set, 0, 0);
04648 gcc_assert (GET_CODE (set) == SET);
04649 mem = XEXP (set, opnum);
04650 while (GET_CODE (mem) == SUBREG)
04651 mem = SUBREG_REG (mem);
04652 gcc_assert (GET_CODE (mem) == MEM);
04653 return (volatile_ok || !MEM_VOLATILE_P (mem));
04654 }
04655
04656
04657
04658 static void
04659 init_ext_80387_constants (void)
04660 {
04661 static const char * cst[5] =
04662 {
04663 "0.3010299956639811952256464283594894482",
04664 "0.6931471805599453094286904741849753009",
04665 "1.4426950408889634073876517827983434472",
04666 "3.3219280948873623478083405569094566090",
04667 "3.1415926535897932385128089594061862044",
04668 };
04669 int i;
04670
04671 for (i = 0; i < 5; i++)
04672 {
04673 real_from_string (&ext_80387_constants_table[i], cst[i]);
04674
04675 real_convert (&ext_80387_constants_table[i],
04676 XFmode, &ext_80387_constants_table[i]);
04677 }
04678
04679 ext_80387_constants_init = 1;
04680 }
04681
04682
04683
04684
04685 int
04686 standard_80387_constant_p (rtx x)
04687 {
04688 if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x)))
04689 return -1;
04690
04691 if (x == CONST0_RTX (GET_MODE (x)))
04692 return 1;
04693 if (x == CONST1_RTX (GET_MODE (x)))
04694 return 2;
04695
04696
04697
04698 if (GET_MODE (x) == XFmode
04699 && (optimize_size || x86_ext_80387_constants & TUNEMASK))
04700 {
04701 REAL_VALUE_TYPE r;
04702 int i;
04703
04704 if (! ext_80387_constants_init)
04705 init_ext_80387_constants ();
04706
04707 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
04708 for (i = 0; i < 5; i++)
04709 if (real_identical (&r, &ext_80387_constants_table[i]))
04710 return i + 3;
04711 }
04712
04713 return 0;
04714 }
04715
04716
04717
04718
04719 const char *
04720 standard_80387_constant_opcode (rtx x)
04721 {
04722 switch (standard_80387_constant_p (x))
04723 {
04724 case 1:
04725 return "fldz";
04726 case 2:
04727 return "fld1";
04728 case 3:
04729 return "fldlg2";
04730 case 4:
04731 return "fldln2";
04732 case 5:
04733 return "fldl2e";
04734 case 6:
04735 return "fldl2t";
04736 case 7:
04737 return "fldpi";
04738 default:
04739 gcc_unreachable ();
04740 }
04741 }
04742
04743
04744
04745
04746
04747 rtx
04748 standard_80387_constant_rtx (int idx)
04749 {
04750 int i;
04751
04752 if (! ext_80387_constants_init)
04753 init_ext_80387_constants ();
04754
04755 switch (idx)
04756 {
04757 case 3:
04758 case 4:
04759 case 5:
04760 case 6:
04761 case 7:
04762 i = idx - 3;
04763 break;
04764
04765 default:
04766 gcc_unreachable ();
04767 }
04768
04769 return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i],
04770 XFmode);
04771 }
04772
04773
04774 static int
04775 standard_sse_mode_p (enum machine_mode mode)
04776 {
04777 switch (mode)
04778 {
04779 case V16QImode:
04780 case V8HImode:
04781 case V4SImode:
04782 case V2DImode:
04783 case V4SFmode:
04784 case V2DFmode:
04785 return 1;
04786
04787 default:
04788 return 0;
04789 }
04790 }
04791
04792
04793
04794 int
04795 standard_sse_constant_p (rtx x)
04796 {
04797 enum machine_mode mode = GET_MODE (x);
04798
04799 if (x == const0_rtx || x == CONST0_RTX (GET_MODE (x)))
04800 return 1;
04801 if (vector_all_ones_operand (x, mode)
04802 && standard_sse_mode_p (mode))
04803 return TARGET_SSE2 ? 2 : -1;
04804
04805 return 0;
04806 }
04807
04808
04809
04810
04811 const char *
04812 standard_sse_constant_opcode (rtx insn, rtx x)
04813 {
04814 switch (standard_sse_constant_p (x))
04815 {
04816 case 1:
04817 if (get_attr_mode (insn) == MODE_V4SF)
04818 return "xorps\t%0, %0";
04819 else if (get_attr_mode (insn) == MODE_V2DF)
04820 return "xorpd\t%0, %0";
04821 else
04822 return "pxor\t%0, %0";
04823 case 2:
04824 return "pcmpeqd\t%0, %0";
04825 }
04826 gcc_unreachable ();
04827 }
04828
04829
04830
04831 int
04832 symbolic_reference_mentioned_p (rtx op)
04833 {
04834 const char *fmt;
04835 int i;
04836
04837 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
04838 return 1;
04839
04840 fmt = GET_RTX_FORMAT (GET_CODE (op));
04841 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
04842 {
04843 if (fmt[i] == 'E')
04844 {
04845 int j;
04846
04847 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
04848 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
04849 return 1;
04850 }
04851
04852 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
04853 return 1;
04854 }
04855
04856 return 0;
04857 }
04858
04859
04860
04861
04862
04863
04864
04865 int
04866 ix86_can_use_return_insn_p (void)
04867 {
04868 struct ix86_frame frame;
04869
04870 if (! reload_completed || frame_pointer_needed)
04871 return 0;
04872
04873
04874
04875 if (current_function_pops_args
04876 && current_function_args_size >= 32768)
04877 return 0;
04878
04879 ix86_compute_frame_layout (&frame);
04880 return frame.to_allocate == 0 && frame.nregs == 0;
04881 }
04882
04883
04884
04885
04886
04887 int
04888 ix86_frame_pointer_required (void)
04889 {
04890
04891
04892 if (cfun->machine->accesses_prev_frame)
04893 return 1;
04894
04895
04896
04897 if (SUBTARGET_FRAME_POINTER_REQUIRED)
04898 return 1;
04899
04900
04901
04902
04903 if (TARGET_OMIT_LEAF_FRAME_POINTER
04904 && (!current_function_is_leaf
04905 || ix86_current_function_calls_tls_descriptor))
04906 return 1;
04907
04908 if (current_function_profile)
04909 return 1;
04910
04911 return 0;
04912 }
04913
04914
04915
04916 void
04917 ix86_setup_frame_addresses (void)
04918 {
04919 cfun->machine->accesses_prev_frame = 1;
04920 }
04921
04922 #if (defined(HAVE_GAS_HIDDEN) && (SUPPORTS_ONE_ONLY - 0)) || TARGET_MACHO
04923 # define USE_HIDDEN_LINKONCE 1
04924 #else
04925 # define USE_HIDDEN_LINKONCE 0
04926 #endif
04927
04928 static int pic_labels_used;
04929
04930
04931
04932
04933 static void
04934 get_pc_thunk_name (char name[32], unsigned int regno)
04935 {
04936 gcc_assert (!TARGET_64BIT);
04937
04938 if (USE_HIDDEN_LINKONCE)
04939 sprintf (name, "__i686.get_pc_thunk.%s", reg_names[regno]);
04940 else
04941 ASM_GENERATE_INTERNAL_LABEL (name, "LPR", regno);
04942 }
04943
04944
04945
04946
04947
04948 void
04949 ix86_file_end (void)
04950 {
04951 rtx xops[2];
04952 int regno;
04953
04954 for (regno = 0; regno < 8; ++regno)
04955 {
04956 char name[32];
04957
04958 if (! ((pic_labels_used >> regno) & 1))
04959 continue;
04960
04961 get_pc_thunk_name (name, regno);
04962
04963 #if TARGET_MACHO
04964 if (TARGET_MACHO)
04965 {
04966 switch_to_section (darwin_sections[text_coal_section]);
04967 fputs ("\t.weak_definition\t", asm_out_file);
04968 assemble_name (asm_out_file, name);
04969 fputs ("\n\t.private_extern\t", asm_out_file);
04970 assemble_name (asm_out_file, name);
04971 fputs ("\n", asm_out_file);
04972 ASM_OUTPUT_LABEL (asm_out_file, name);
04973 }
04974 else
04975 #endif
04976 if (USE_HIDDEN_LINKONCE)
04977 {
04978 tree decl;
04979
04980 decl = build_decl (FUNCTION_DECL, get_identifier (name),
04981 error_mark_node);
04982 TREE_PUBLIC (decl) = 1;
04983 TREE_STATIC (decl) = 1;
04984 DECL_ONE_ONLY (decl) = 1;
04985
04986 (*targetm.asm_out.unique_section) (decl, 0);
04987 switch_to_section (get_named_section (decl, NULL, 0));
04988
04989 (*targetm.asm_out.globalize_label) (asm_out_file, name);
04990 fputs ("\t.hidden\t", asm_out_file);
04991 assemble_name (asm_out_file, name);
04992 fputc ('\n', asm_out_file);
04993 ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
04994 }
04995 else
04996 {
04997 switch_to_section (text_section);
04998 ASM_OUTPUT_LABEL (asm_out_file, name);
04999 }
05000
05001 xops[0] = gen_rtx_REG (SImode, regno);
05002 xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
05003 output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
05004 output_asm_insn ("ret", xops);
05005 }
05006
05007 if (NEED_INDICATE_EXEC_STACK)
05008 file_end_indicate_exec_stack ();
05009 }
05010
05011
05012
05013 const char *
05014 output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
05015 {
05016 rtx xops[3];
05017
05018 xops[0] = dest;
05019 xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
05020
05021 if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
05022 {
05023 xops[2] = gen_rtx_LABEL_REF (Pmode, label ? label : gen_label_rtx ());
05024
05025 if (!flag_pic)
05026 output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
05027 else
05028 output_asm_insn ("call\t%a2", xops);
05029
05030 #if TARGET_MACHO
05031
05032
05033 if (!label)
05034 ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
05035 #endif
05036
05037 (*targetm.asm_out.internal_label) (asm_out_file, "L",
05038 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
05039
05040 if (flag_pic)
05041 output_asm_insn ("pop{l}\t%0", xops);
05042 }
05043 else
05044 {
05045 char name[32];
05046 get_pc_thunk_name (name, REGNO (dest));
05047 pic_labels_used |= 1 << REGNO (dest);
05048
05049 xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
05050 xops[2] = gen_rtx_MEM (QImode, xops[2]);
05051 output_asm_insn ("call\t%X2", xops);
05052
05053
05054 #if TARGET_MACHO
05055 if (!label)
05056 ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
05057 else
05058 targetm.asm_out.internal_label (asm_out_file, "L",
05059 CODE_LABEL_NUMBER (label));
05060 #endif
05061 }
05062
05063 if (TARGET_MACHO)
05064 return "";
05065
05066 if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
05067 output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
05068 else
05069 output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %1+(.-%a2)}", xops);
05070
05071 return "";
05072 }
05073
05074
05075
05076 static rtx
05077 gen_push (rtx arg)
05078 {
05079 return gen_rtx_SET (VOIDmode,
05080 gen_rtx_MEM (Pmode,
05081 gen_rtx_PRE_DEC (Pmode,
05082 stack_pointer_rtx)),
05083 arg);
05084 }
05085
05086
05087
05088
05089 static unsigned int
05090 ix86_select_alt_pic_regnum (void)
05091 {
05092 if (current_function_is_leaf && !current_function_profile
05093 && !ix86_current_function_calls_tls_descriptor)
05094 {
05095 int i;
05096 for (i = 2; i >= 0; --i)
05097 if (!regs_ever_live[i])
05098 return i;
05099 }
05100
05101 return INVALID_REGNUM;
05102 }
05103
05104
05105 static int
05106 ix86_save_reg (unsigned int regno, int maybe_eh_return)
05107 {
05108 if (pic_offset_table_rtx
05109 && regno == REAL_PIC_OFFSET_TABLE_REGNUM
05110 && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
05111 || current_function_profile
05112 || current_function_calls_eh_return
05113 || current_function_uses_const_pool))
05114 {
05115 if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
05116 return 0;
05117 return 1;
05118 }
05119
05120 if (current_function_calls_eh_return && maybe_eh_return)
05121 {
05122 unsigned i;
05123 for (i = 0; ; i++)
05124 {
05125 unsigned test = EH_RETURN_DATA_REGNO (i);
05126 if (test == INVALID_REGNUM)
05127 break;
05128 if (test == regno)
05129 return 1;
05130 }
05131 }
05132
05133 if (cfun->machine->force_align_arg_pointer
05134 && regno == REGNO (cfun->machine->force_align_arg_pointer))
05135 return 1;
05136
05137 return (regs_ever_live[regno]
05138 && !call_used_regs[regno]
05139 && !fixed_regs[regno]
05140 && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
05141 }
05142
05143
05144
05145 static int
05146 ix86_nsaved_regs (void)
05147 {
05148 int nregs = 0;
05149 int regno;
05150
05151 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
05152 if (ix86_save_reg (regno, true))
05153 nregs++;
05154 return nregs;
05155 }
05156
05157
05158
05159
05160 HOST_WIDE_INT
05161 ix86_initial_elimination_offset (int from, int to)
05162 {
05163 struct ix86_frame frame;
05164 ix86_compute_frame_layout (&frame);
05165
05166 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
05167 return frame.hard_frame_pointer_offset;
05168 else if (from == FRAME_POINTER_REGNUM
05169 && to == HARD_FRAME_POINTER_REGNUM)
05170 return frame.hard_frame_pointer_offset - frame.frame_pointer_offset;
05171 else
05172 {
05173 gcc_assert (to == STACK_POINTER_REGNUM);
05174
05175 if (from == ARG_POINTER_REGNUM)
05176 return frame.stack_pointer_offset;
05177
05178 gcc_assert (from == FRAME_POINTER_REGNUM);
05179 return frame.stack_pointer_offset - frame.frame_pointer_offset;
05180 }
05181 }
05182
05183
05184
05185 static void
05186 ix86_compute_frame_layout (struct ix86_frame *frame)
05187 {
05188 HOST_WIDE_INT total_size;
05189 unsigned int stack_alignment_needed;
05190 HOST_WIDE_INT offset;
05191 unsigned int preferred_alignment;
05192 HOST_WIDE_INT size = get_frame_size ();
05193
05194 frame->nregs = ix86_nsaved_regs ();
05195 total_size = size;
05196
05197 stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT;
05198 preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT;
05199
05200
05201
05202
05203
05204 if (!optimize_size
05205 && cfun->machine->use_fast_prologue_epilogue_nregs != frame->nregs)
05206 {
05207 int count = frame->nregs;
05208
05209 cfun->machine->use_fast_prologue_epilogue_nregs = count;
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220 if (count)
05221 count = (count - 1) * FAST_PROLOGUE_INSN_COUNT;
05222 if (cfun->function_frequency < FUNCTION_FREQUENCY_NORMAL
05223 || (flag_branch_probabilities
05224 && cfun->function_frequency < FUNCTION_FREQUENCY_HOT))
05225 cfun->machine->use_fast_prologue_epilogue = false;
05226 else
05227 cfun->machine->use_fast_prologue_epilogue
05228 = !expensive_function_p (count);
05229 }
05230 if (TARGET_PROLOGUE_USING_MOVE
05231 && cfun->machine->use_fast_prologue_epilogue)
05232 frame->save_regs_using_mov = true;
05233 else
05234 frame->save_regs_using_mov = false;
05235
05236
05237
05238 offset = frame_pointer_needed ? UNITS_PER_WORD * 2 : UNITS_PER_WORD;
05239
05240 frame->hard_frame_pointer_offset = offset;
05241
05242
05243
05244
05245
05246 gcc_assert (!size || stack_alignment_needed);
05247 gcc_assert (preferred_alignment >= STACK_BOUNDARY / BITS_PER_UNIT);
05248 gcc_assert (preferred_alignment <= PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT);
05249 gcc_assert (stack_alignment_needed
05250 <= PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT);
05251
05252 if (stack_alignment_needed < STACK_BOUNDARY / BITS_PER_UNIT)
05253 stack_alignment_needed = STACK_BOUNDARY / BITS_PER_UNIT;
05254
05255
05256 offset += frame->nregs * UNITS_PER_WORD;
05257
05258
05259 if (ix86_save_varrargs_registers)
05260 {
05261 offset += X86_64_VARARGS_SIZE;
05262 frame->va_arg_size = X86_64_VARARGS_SIZE;
05263 }
05264 else
05265 frame->va_arg_size = 0;
05266
05267
05268 frame->padding1 = ((offset + stack_alignment_needed - 1)
05269 & -stack_alignment_needed) - offset;
05270
05271 offset += frame->padding1;
05272
05273
05274 frame->frame_pointer_offset = offset;
05275
05276 offset += size;
05277
05278
05279
05280
05281
05282
05283 if (ACCUMULATE_OUTGOING_ARGS
05284 && (!current_function_is_leaf || current_function_calls_alloca
05285 || ix86_current_function_calls_tls_descriptor))
05286 {
05287 offset += current_function_outgoing_args_size;
05288 frame->outgoing_arguments_size = current_function_outgoing_args_size;
05289 }
05290 else
05291 frame->outgoing_arguments_size = 0;
05292
05293
05294
05295 if (!current_function_is_leaf || current_function_calls_alloca
05296 || ix86_current_function_calls_tls_descriptor)
05297 frame->padding2 = ((offset + preferred_alignment - 1)
05298 & -preferred_alignment) - offset;
05299 else
05300 frame->padding2 = 0;
05301
05302 offset += frame->padding2;
05303
05304
05305 frame->stack_pointer_offset = offset;
05306
05307
05308 frame->to_allocate =
05309 (size + frame->padding1 + frame->padding2
05310 + frame->outgoing_arguments_size + frame->va_arg_size);
05311
05312 if ((!frame->to_allocate && frame->nregs <= 1)
05313 || (TARGET_64BIT && frame->to_allocate >= (HOST_WIDE_INT) 0x80000000))
05314 frame->save_regs_using_mov = false;
05315
05316 if (TARGET_RED_ZONE && current_function_sp_is_unchanging
05317 && current_function_is_leaf
05318 && !ix86_current_function_calls_tls_descriptor)
05319 {
05320 frame->red_zone_size = frame->to_allocate;
05321 if (frame->save_regs_using_mov)
05322 frame->red_zone_size += frame->nregs * UNITS_PER_WORD;
05323 if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
05324 frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
05325 }
05326 else
05327 frame->red_zone_size = 0;
05328 frame->to_allocate -= frame->red_zone_size;
05329 frame->stack_pointer_offset -= frame->red_zone_size;
05330 #if 0
05331 fprintf (stderr, "nregs: %i\n", frame->nregs);
05332 fprintf (stderr, "size: %i\n", size);
05333 fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
05334 fprintf (stderr, "padding1: %i\n", frame->padding1);
05335 fprintf (stderr, "va_arg: %i\n", frame->va_arg_size);
05336 fprintf (stderr, "padding2: %i\n", frame->padding2);
05337 fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
05338 fprintf (stderr, "red_zone_size: %i\n", frame->red_zone_size);
05339 fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
05340 fprintf (stderr, "hard_frame_pointer_offset: %i\n",
05341 frame->hard_frame_pointer_offset);
05342 fprintf (stderr, "stack_pointer_offset: %i\n", frame->stack_pointer_offset);
05343 #endif
05344 }
05345
05346
05347
05348 static void
05349 ix86_emit_save_regs (void)
05350 {
05351 unsigned int regno;
05352 rtx insn;
05353
05354 for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; )
05355 if (ix86_save_reg (regno, true))
05356 {
05357 insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
05358 RTX_FRAME_RELATED_P (insn) = 1;
05359 }
05360 }
05361
05362
05363
05364 static void
05365 ix86_emit_save_regs_using_mov (rtx pointer, HOST_WIDE_INT offset)
05366 {
05367 unsigned int regno;
05368 rtx insn;
05369
05370 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05371 if (ix86_save_reg (regno, true))
05372 {
05373 insn = emit_move_insn (adjust_address (gen_rtx_MEM (Pmode, pointer),
05374 Pmode, offset),
05375 gen_rtx_REG (Pmode, regno));
05376 RTX_FRAME_RELATED_P (insn) = 1;
05377 offset += UNITS_PER_WORD;
05378 }
05379 }
05380
05381
05382
05383
05384
05385
05386
05387 static void
05388 pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
05389 {
05390 rtx insn;
05391
05392 if (! TARGET_64BIT)
05393 insn = emit_insn (gen_pro_epilogue_adjust_stack_1 (dest, src, offset));
05394 else if (x86_64_immediate_operand (offset, DImode))
05395 insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64 (dest, src, offset));
05396 else
05397 {
05398 rtx r11;
05399
05400
05401
05402
05403 gcc_assert (style);
05404 r11 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 );
05405 insn = emit_insn (gen_rtx_SET (DImode, r11, offset));
05406 if (style < 0)
05407 RTX_FRAME_RELATED_P (insn) = 1;
05408 insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64_2 (dest, src, r11,
05409 offset));
05410 }
05411 if (style < 0)
05412 RTX_FRAME_RELATED_P (insn) = 1;
05413 }
05414
05415
05416
05417 static rtx
05418 ix86_internal_arg_pointer (void)
05419 {
05420 bool has_force_align_arg_pointer =
05421 (0 != lookup_attribute (ix86_force_align_arg_pointer_string,
05422 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))));
05423 if ((FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
05424 && DECL_NAME (current_function_decl)
05425 && MAIN_NAME_P (DECL_NAME (current_function_decl))
05426 && DECL_FILE_SCOPE_P (current_function_decl))
05427 || ix86_force_align_arg_pointer
05428 || has_force_align_arg_pointer)
05429 {
05430
05431
05432 if (DECL_CONTEXT (current_function_decl)
05433 && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
05434 {
05435 if (ix86_force_align_arg_pointer)
05436 warning (0, "-mstackrealign ignored for nested functions");
05437 if (has_force_align_arg_pointer)
05438 error ("%s not supported for nested functions",
05439 ix86_force_align_arg_pointer_string);
05440 return virtual_incoming_args_rtx;
05441 }
05442 cfun->machine->force_align_arg_pointer = gen_rtx_REG (Pmode, 2);
05443 return copy_to_reg (cfun->machine->force_align_arg_pointer);
05444 }
05445 else
05446 return virtual_incoming_args_rtx;
05447 }
05448
05449
05450
05451
05452 static void
05453 ix86_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
05454 {
05455 rtx unspec = SET_SRC (pattern);
05456 gcc_assert (GET_CODE (unspec) == UNSPEC);
05457
05458 switch (index)
05459 {
05460 case UNSPEC_REG_SAVE:
05461 dwarf2out_reg_save_reg (label, XVECEXP (unspec, 0, 0),
05462 SET_DEST (pattern));
05463 break;
05464 case UNSPEC_DEF_CFA:
05465 dwarf2out_def_cfa (label, REGNO (SET_DEST (pattern)),
05466 INTVAL (XVECEXP (unspec, 0, 0)));
05467 break;
05468 default:
05469 gcc_unreachable ();
05470 }
05471 }
05472
05473
05474
05475 void
05476 ix86_expand_prologue (void)
05477 {
05478 rtx insn;
05479 bool pic_reg_used;
05480 struct ix86_frame frame;
05481 HOST_WIDE_INT allocate;
05482
05483 ix86_compute_frame_layout (&frame);
05484
05485 if (cfun->machine->force_align_arg_pointer)
05486 {
05487 rtx x, y;
05488
05489
05490 x = plus_constant (stack_pointer_rtx, 4);
05491 y = cfun->machine->force_align_arg_pointer;
05492 insn = emit_insn (gen_rtx_SET (VOIDmode, y, x));
05493 RTX_FRAME_RELATED_P (insn) = 1;
05494
05495
05496
05497
05498
05499 x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_DEF_CFA);
05500 x = gen_rtx_SET (VOIDmode, y, x);
05501 RTX_FRAME_RELATED_P (x) = 1;
05502 y = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, stack_pointer_rtx),
05503 UNSPEC_REG_SAVE);
05504 y = gen_rtx_SET (VOIDmode, cfun->machine->force_align_arg_pointer, y);
05505 RTX_FRAME_RELATED_P (y) = 1;
05506 x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, y));
05507 x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
05508 REG_NOTES (insn) = x;
05509
05510
05511 emit_insn (gen_andsi3 (stack_pointer_rtx, stack_pointer_rtx,
05512 GEN_INT (-16)));
05513
05514
05515
05516
05517
05518
05519 x = cfun->machine->force_align_arg_pointer;
05520 x = gen_frame_mem (Pmode, plus_constant (x, -4));
05521 insn = emit_insn (gen_push (x));
05522 RTX_FRAME_RELATED_P (insn) = 1;
05523
05524 x = GEN_INT (4);
05525 x = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, x), UNSPEC_DEF_CFA);
05526 x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
05527 x = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, x, NULL);
05528 REG_NOTES (insn) = x;
05529 }
05530
05531
05532
05533
05534 if (frame_pointer_needed)
05535 {
05536 insn = emit_insn (gen_push (hard_frame_pointer_rtx));
05537 RTX_FRAME_RELATED_P (insn) = 1;
05538
05539 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
05540 RTX_FRAME_RELATED_P (insn) = 1;
05541 }
05542
05543 allocate = frame.to_allocate;
05544
05545 if (!frame.save_regs_using_mov)
05546 ix86_emit_save_regs ();
05547 else
05548 allocate += frame.nregs * UNITS_PER_WORD;
05549
05550
05551
05552 if (TARGET_RED_ZONE && frame.save_regs_using_mov)
05553 ix86_emit_save_regs_using_mov (frame_pointer_needed ? hard_frame_pointer_rtx
05554 : stack_pointer_rtx,
05555 -frame.nregs * UNITS_PER_WORD);
05556
05557 if (allocate == 0)
05558 ;
05559 else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT)
05560 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
05561 GEN_INT (-allocate), -1);
05562 else
05563 {
05564
05565 rtx eax = gen_rtx_REG (SImode, 0);
05566 bool eax_live = ix86_eax_live_at_start_p ();
05567 rtx t;
05568
05569 gcc_assert (!TARGET_64BIT);
05570
05571 if (eax_live)
05572 {
05573 emit_insn (gen_push (eax));
05574 allocate -= 4;
05575 }
05576
05577 emit_move_insn (eax, GEN_INT (allocate));
05578
05579 insn = emit_insn (gen_allocate_stack_worker (eax));
05580 RTX_FRAME_RELATED_P (insn) = 1;
05581 t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
05582 t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
05583 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
05584 t, REG_NOTES (insn));
05585
05586 if (eax_live)
05587 {
05588 if (frame_pointer_needed)
05589 t = plus_constant (hard_frame_pointer_rtx,
05590 allocate
05591 - frame.to_allocate
05592 - frame.nregs * UNITS_PER_WORD);
05593 else
05594 t = plus_constant (stack_pointer_rtx, allocate);
05595 emit_move_insn (eax, gen_rtx_MEM (SImode, t));
05596 }
05597 }
05598
05599 if (frame.save_regs_using_mov && !TARGET_RED_ZONE)
05600 {
05601 if (!frame_pointer_needed || !frame.to_allocate)
05602 ix86_emit_save_regs_using_mov (stack_pointer_rtx, frame.to_allocate);
05603 else
05604 ix86_emit_save_regs_using_mov (hard_frame_pointer_rtx,
05605 -frame.nregs * UNITS_PER_WORD);
05606 }
05607
05608 pic_reg_used = false;
05609 if (pic_offset_table_rtx
05610 && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
05611 || current_function_profile))
05612 {
05613 unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum ();
05614
05615 if (alt_pic_reg_used != INVALID_REGNUM)
05616 REGNO (pic_offset_table_rtx) = alt_pic_reg_used;
05617
05618 pic_reg_used = true;
05619 }
05620
05621 if (pic_reg_used)
05622 {
05623 if (TARGET_64BIT)
05624 insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
05625 else
05626 insn = emit_insn (gen_set_got (pic_offset_table_rtx));
05627
05628
05629
05630
05631
05632
05633
05634 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
05635 }
05636
05637
05638
05639 if (current_function_profile)
05640 emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx));
05641 }
05642
05643
05644
05645 static void
05646 ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
05647 int maybe_eh_return)
05648 {
05649 int regno;
05650 rtx base_address = gen_rtx_MEM (Pmode, pointer);
05651
05652 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05653 if (ix86_save_reg (regno, maybe_eh_return))
05654 {
05655
05656
05657 if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
05658 {
05659 rtx r11;
05660
05661 r11 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 );
05662 emit_move_insn (r11, GEN_INT (offset));
05663 emit_insn (gen_adddi3 (r11, r11, pointer));
05664 base_address = gen_rtx_MEM (Pmode, r11);
05665 offset = 0;
05666 }
05667 emit_move_insn (gen_rtx_REG (Pmode, regno),
05668 adjust_address (base_address, Pmode, offset));
05669 offset += UNITS_PER_WORD;
05670 }
05671 }
05672
05673
05674
05675 void
05676 ix86_expand_epilogue (int style)
05677 {
05678 int regno;
05679 int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
05680 struct ix86_frame frame;
05681 HOST_WIDE_INT offset;
05682
05683 ix86_compute_frame_layout (&frame);
05684
05685
05686
05687
05688
05689 offset = frame.nregs;
05690 if (current_function_calls_eh_return && style != 2)
05691 offset -= 2;
05692 offset *= -UNITS_PER_WORD;
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704 if ((!sp_valid && frame.nregs <= 1)
05705 || (TARGET_EPILOGUE_USING_MOVE
05706 && cfun->machine->use_fast_prologue_epilogue
05707 && (frame.nregs > 1 || frame.to_allocate))
05708 || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
05709 || (frame_pointer_needed && TARGET_USE_LEAVE
05710 && cfun->machine->use_fast_prologue_epilogue
05711 && frame.nregs == 1)
05712 || current_function_calls_eh_return)
05713 {
05714
05715
05716
05717
05718
05719
05720 if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
05721 ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
05722 frame.to_allocate, style == 2);
05723 else
05724 ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
05725 offset, style == 2);
05726
05727
05728 if (style == 2)
05729 {
05730 rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
05731
05732 if (frame_pointer_needed)
05733 {
05734 tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
05735 tmp = plus_constant (tmp, UNITS_PER_WORD);
05736 emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
05737
05738 tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
05739 emit_move_insn (hard_frame_pointer_rtx, tmp);
05740
05741 pro_epilogue_adjust_stack (stack_pointer_rtx, sa,
05742 const0_rtx, style);
05743 }
05744 else
05745 {
05746 tmp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, sa);
05747 tmp = plus_constant (tmp, (frame.to_allocate
05748 + frame.nregs * UNITS_PER_WORD));
05749 emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
05750 }
05751 }
05752 else if (!frame_pointer_needed)
05753 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
05754 GEN_INT (frame.to_allocate
05755 + frame.nregs * UNITS_PER_WORD),
05756 style);
05757
05758 else if (TARGET_USE_LEAVE || optimize_size
05759 || !cfun->machine->use_fast_prologue_epilogue)
05760 emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
05761 else
05762 {
05763 pro_epilogue_adjust_stack (stack_pointer_rtx,
05764 hard_frame_pointer_rtx,
05765 const0_rtx, style);
05766 if (TARGET_64BIT)
05767 emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
05768 else
05769 emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
05770 }
05771 }
05772 else
05773 {
05774
05775
05776 if (!sp_valid)
05777 {
05778 gcc_assert (frame_pointer_needed);
05779 pro_epilogue_adjust_stack (stack_pointer_rtx,
05780 hard_frame_pointer_rtx,
05781 GEN_INT (offset), style);
05782 }
05783 else if (frame.to_allocate)
05784 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
05785 GEN_INT (frame.to_allocate), style);
05786
05787 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
05788 if (ix86_save_reg (regno, false))
05789 {
05790 if (TARGET_64BIT)
05791 emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
05792 else
05793 emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, regno)));
05794 }
05795 if (frame_pointer_needed)
05796 {
05797
05798
05799 if (TARGET_USE_LEAVE)
05800 emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
05801 else if (TARGET_64BIT)
05802 emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
05803 else
05804 emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
05805 }
05806 }
05807
05808 if (cfun->machine->force_align_arg_pointer)
05809 {
05810 emit_insn (gen_addsi3 (stack_pointer_rtx,
05811 cfun->machine->force_align_arg_pointer,
05812 GEN_INT (-4)));
05813 }
05814
05815
05816 if (style == 0)
05817 return;
05818
05819 if (current_function_pops_args && current_function_args_size)
05820 {
05821 rtx popc = GEN_INT (current_function_pops_args);
05822
05823
05824
05825
05826
05827 if (current_function_pops_args >= 65536)
05828 {
05829 rtx ecx = gen_rtx_REG (SImode, 2);
05830
05831
05832 gcc_assert (!TARGET_64BIT);
05833
05834 emit_insn (gen_popsi1 (ecx));
05835 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
05836 emit_jump_insn (gen_return_indirect_internal (ecx));
05837 }
05838 else
05839 emit_jump_insn (gen_return_pop_internal (popc));
05840 }
05841 else
05842 emit_jump_insn (gen_return_internal ());
05843 }
05844
05845
05846
05847 static void
05848 ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
05849 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
05850 {
05851 if (pic_offset_table_rtx)
05852 REGNO (pic_offset_table_rtx) = REAL_PIC_OFFSET_TABLE_REGNUM;
05853 #if TARGET_MACHO
05854
05855
05856 {
05857 rtx insn = get_last_insn ();
05858 while (insn
05859 && NOTE_P (insn)
05860 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL)
05861 insn = PREV_INSN (insn);
05862 if (insn
05863 && (LABEL_P (insn)
05864 || (NOTE_P (insn)
05865 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
05866 fputs ("\tnop\n", file);
05867 }
05868 #endif
05869
05870 }
05871
05872
05873
05874
05875
05876
05877 int
05878 ix86_decompose_address (rtx addr, struct ix86_address *out)
05879 {
05880 rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
05881 rtx base_reg, index_reg;
05882 HOST_WIDE_INT scale = 1;
05883 rtx scale_rtx = NULL_RTX;
05884 int retval = 1;
05885 enum ix86_address_seg seg = SEG_DEFAULT;
05886
05887 if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
05888 base = addr;
05889 else if (GET_CODE (addr) == PLUS)
05890 {
05891 rtx addends[4], op;
05892 int n = 0, i;
05893
05894 op = addr;
05895 do
05896 {
05897 if (n >= 4)
05898 return 0;
05899 addends[n++] = XEXP (op, 1);
05900 op = XEXP (op, 0);
05901 }
05902 while (GET_CODE (op) == PLUS);
05903 if (n >= 4)
05904 return 0;
05905 addends[n] = op;
05906
05907 for (i = n; i >= 0; --i)
05908 {
05909 op = addends[i];
05910 switch (GET_CODE (op))
05911 {
05912 case MULT:
05913 if (index)
05914 return 0;
05915 index = XEXP (op, 0);
05916 scale_rtx = XEXP (op, 1);
05917 break;
05918
05919 case UNSPEC:
05920 if (XINT (op, 1) == UNSPEC_TP
05921 && TARGET_TLS_DIRECT_SEG_REFS
05922 && seg == SEG_DEFAULT)
05923 seg = TARGET_64BIT ? SEG_FS : SEG_GS;
05924 else
05925 return 0;
05926 break;
05927
05928 case REG:
05929 case SUBREG:
05930 if (!base)
05931 base = op;
05932 else if (!index)
05933 index = op;
05934 else
05935 return 0;
05936 break;
05937
05938 case CONST:
05939 case CONST_INT:
05940 case SYMBOL_REF:
05941 case LABEL_REF:
05942 if (disp)
05943 return 0;
05944 disp = op;
05945 break;
05946
05947 default:
05948 return 0;
05949 }
05950 }
05951 }
05952 else if (GET_CODE (addr) == MULT)
05953 {
05954 index = XEXP (addr, 0);
05955 scale_rtx = XEXP (addr, 1);
05956 }
05957 else if (GET_CODE (addr) == ASHIFT)
05958 {
05959 rtx tmp;
05960
05961
05962 index = XEXP (addr, 0);
05963 tmp = XEXP (addr, 1);
05964 if (GET_CODE (tmp) != CONST_INT)
05965 return 0;
05966 scale = INTVAL (tmp);
05967 if ((unsigned HOST_WIDE_INT) scale > 3)
05968 return 0;
05969 scale = 1 << scale;
05970 retval = -1;
05971 }
05972 else
05973 disp = addr;
05974
05975
05976 if (scale_rtx)
05977 {
05978 if (GET_CODE (scale_rtx) != CONST_INT)
05979 return 0;
05980 scale = INTVAL (scale_rtx);
05981 }
05982
05983 base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
05984 index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
05985
05986
05987 if (base_reg && index_reg && scale == 1
05988 && (index_reg == arg_pointer_rtx
05989 || index_reg == frame_pointer_rtx
05990 || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
05991 {
05992 rtx tmp;
05993 tmp = base, base = index, index = tmp;
05994 tmp = base_reg, base_reg = index_reg, index_reg = tmp;
05995 }
05996
05997
05998 if ((base_reg == hard_frame_pointer_rtx
05999 || base_reg == frame_pointer_rtx
06000 || base_reg == arg_pointer_rtx) && !disp)
06001 disp = const0_rtx;
06002
06003
06004
06005 if (ix86_tune == PROCESSOR_K6 && !optimize_size
06006 && base_reg && !index_reg && !disp
06007 && REG_P (base_reg)
06008 && REGNO_REG_CLASS (REGNO (base_reg)) == SIREG)
06009 disp = const0_rtx;
06010
06011
06012 if (!base && index && scale && scale == 2)
06013 base = index, base_reg = index_reg, scale = 1;
06014
06015
06016 if (!base && !disp && index && scale != 1)
06017 disp = const0_rtx;
06018
06019 out->base = base;
06020 out->index = index;
06021 out->disp = disp;
06022 out->scale = scale;
06023 out->seg = seg;
06024
06025 return retval;
06026 }
06027
06028
06029
06030
06031
06032
06033 static int
06034 ix86_address_cost (rtx x)
06035 {
06036 struct ix86_address parts;
06037 int cost = 1;
06038 int ok = ix86_decompose_address (x, &parts);
06039
06040 gcc_assert (ok);
06041
06042 if (parts.base && GET_CODE (parts.base) == SUBREG)
06043 parts.base = SUBREG_REG (parts.base);
06044 if (parts.index && GET_CODE (parts.index) == SUBREG)
06045 parts.index = SUBREG_REG (parts.index);
06046
06047
06048 if (parts.disp && parts.disp != const0_rtx)
06049 cost--;
06050 if (parts.seg != SEG_DEFAULT)
06051 cost--;
06052
06053
06054 if ((parts.base
06055 && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER))
06056 || (parts.index
06057 && (!REG_P (parts.index)
06058 || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)))
06059 cost++;
06060
06061 if (parts.base
06062 && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER)
06063 && parts.index
06064 && (!REG_P (parts.index) || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)
06065 && parts.base != parts.index)
06066 cost++;
06067
06068
06069
06070
06071
06072
06073
06074
06075
06076
06077
06078
06079
06080
06081
06082
06083 if (TARGET_K6
06084 && ((!parts.disp && parts.base && parts.index && parts.scale != 1)
06085 || (parts.disp && !parts.base && parts.index && parts.scale != 1)
06086 || (!parts.disp && parts.base && parts.index && parts.scale == 1)))
06087 cost += 10;
06088
06089 return cost;
06090 }
06091
06092
06093
06094
06095
06096 rtx
06097 ix86_find_base_term (rtx x)
06098 {
06099 rtx term;
06100
06101 if (TARGET_64BIT)
06102 {
06103 if (GET_CODE (x) != CONST)
06104 return x;
06105 term = XEXP (x, 0);
06106 if (GET_CODE (term) == PLUS
06107 && (GET_CODE (XEXP (term, 1)) == CONST_INT
06108 || GET_CODE (XEXP (term, 1)) == CONST_DOUBLE))
06109 term = XEXP (term, 0);
06110 if (GET_CODE (term) != UNSPEC
06111 || XINT (term, 1) != UNSPEC_GOTPCREL)
06112 return x;
06113
06114 term = XVECEXP (term, 0, 0);
06115
06116 if (GET_CODE (term) != SYMBOL_REF
06117 && GET_CODE (term) != LABEL_REF)
06118 return x;
06119
06120 return term;
06121 }
06122
06123 term = ix86_delegitimize_address (x);
06124
06125 if (GET_CODE (term) != SYMBOL_REF
06126 && GET_CODE (term) != LABEL_REF)
06127 return x;
06128
06129 return term;
06130 }
06131
06132
06133
06134
06135
06136 static bool
06137 darwin_local_data_pic (rtx disp)
06138 {
06139 if (GET_CODE (disp) == MINUS)
06140 {
06141 if (GET_CODE (XEXP (disp, 0)) == LABEL_REF
06142 || GET_CODE (XEXP (disp, 0)) == SYMBOL_REF)
06143 if (GET_CODE (XEXP (disp, 1)) == SYMBOL_REF)
06144 {
06145 const char *sym_name = XSTR (XEXP (disp, 1), 0);
06146 if (! strcmp (sym_name, "<pic base>"))
06147 return true;
06148 }
06149 }
06150
06151 return false;
06152 }
06153
06154
06155
06156
06157 bool
06158 legitimate_constant_p (rtx x)
06159 {
06160 switch (GET_CODE (x))
06161 {
06162 case CONST:
06163 x = XEXP (x, 0);
06164
06165 if (GET_CODE (x) == PLUS)
06166 {
06167 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
06168 return false;
06169 x = XEXP (x, 0);
06170 }
06171
06172 if (TARGET_MACHO && darwin_local_data_pic (x))
06173 return true;
06174
06175
06176 if (GET_CODE (x) == UNSPEC)
06177 switch (XINT (x, 1))
06178 {
06179 case UNSPEC_GOTOFF:
06180 return TARGET_64BIT;
06181 case UNSPEC_TPOFF:
06182 case UNSPEC_NTPOFF:
06183 x = XVECEXP (x, 0, 0);
06184 return (GET_CODE (x) == SYMBOL_REF
06185 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_EXEC);
06186 case UNSPEC_DTPOFF:
06187 x = XVECEXP (x, 0, 0);
06188 return (GET_CODE (x) == SYMBOL_REF
06189 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC);
06190 default:
06191 return false;
06192 }
06193
06194
06195 if (GET_CODE (x) == LABEL_REF)
06196 return true;
06197 if (GET_CODE (x) != SYMBOL_REF)
06198 return false;
06199
06200
06201 case SYMBOL_REF:
06202
06203 if (SYMBOL_REF_TLS_MODEL (x))
06204 return false;
06205 break;
06206
06207 case CONST_DOUBLE:
06208 if (GET_MODE (x) == TImode
06209 && x != CONST0_RTX (TImode)
06210 && !TARGET_64BIT)
06211 return false;
06212 break;
06213
06214 case CONST_VECTOR:
06215 if (x == CONST0_RTX (GET_MODE (x)))
06216 return true;
06217 return false;
06218
06219 default:
06220 break;
06221 }
06222
06223
06224 return true;
06225 }
06226
06227
06228
06229
06230
06231 static bool
06232 ix86_cannot_force_const_mem (rtx x)
06233 {
06234
06235 switch (GET_CODE (x))
06236 {
06237 case CONST_INT:
06238 case CONST_DOUBLE:
06239 case CONST_VECTOR:
06240 return false;
06241
06242 default:
06243 break;
06244 }
06245 return !legitimate_constant_p (x);
06246 }
06247
06248
06249
06250 bool
06251 constant_address_p (rtx x)
06252 {
06253 return CONSTANT_P (x) && legitimate_address_p (Pmode, x, 1);
06254 }
06255
06256
06257
06258
06259
06260 bool
06261 legitimate_pic_operand_p (rtx x)
06262 {
06263 rtx inner;
06264
06265 switch (GET_CODE (x))
06266 {
06267 case CONST:
06268 inner = XEXP (x, 0);
06269 if (GET_CODE (inner) == PLUS
06270 && GET_CODE (XEXP (inner, 1)) == CONST_INT)
06271 inner = XEXP (inner, 0);
06272
06273
06274 if (GET_CODE (inner) == UNSPEC)
06275 switch (XINT (inner, 1))
06276 {
06277 case UNSPEC_GOTOFF:
06278 return TARGET_64BIT;
06279 case UNSPEC_TPOFF:
06280 x = XVECEXP (inner, 0, 0);
06281 return (GET_CODE (x) == SYMBOL_REF
06282 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_EXEC);
06283 default:
06284 return false;
06285 }
06286
06287
06288 case SYMBOL_REF:
06289 case LABEL_REF:
06290 return legitimate_pic_address_disp_p (x);
06291
06292 default:
06293 return true;
06294 }
06295 }
06296
06297
06298
06299
06300 int
06301 legitimate_pic_address_disp_p (rtx disp)
06302 {
06303 bool saw_plus;
06304
06305
06306
06307 if (TARGET_64BIT)
06308 {
06309 rtx op0 = disp, op1;
06310
06311 switch (GET_CODE (disp))
06312 {
06313 case LABEL_REF:
06314 return true;
06315
06316 case CONST:
06317 if (GET_CODE (XEXP (disp, 0)) != PLUS)
06318 break;
06319 op0 = XEXP (XEXP (disp, 0), 0);
06320 op1 = XEXP (XEXP (disp, 0), 1);
06321 if (GET_CODE (op1) != CONST_INT
06322 || INTVAL (op1) >= 16*1024*1024
06323 || INTVAL (op1) < -16*1024*1024)
06324 break;
06325 if (GET_CODE (op0) == LABEL_REF)
06326 return true;
06327 if (GET_CODE (op0) != SYMBOL_REF)
06328 break;
06329
06330
06331 case SYMBOL_REF:
06332
06333 if (SYMBOL_REF_TLS_MODEL (op0))
06334 return false;
06335 if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0))
06336 return true;
06337 break;
06338
06339 default:
06340 break;
06341 }
06342 }
06343 if (GET_CODE (disp) != CONST)
06344 return 0;
06345 disp = XEXP (disp, 0);
06346
06347 if (TARGET_64BIT)
06348 {
06349
06350
06351 if (GET_CODE (disp) != UNSPEC
06352 || (XINT (disp, 1) != UNSPEC_GOTPCREL
06353 && XINT (disp, 1) != UNSPEC_GOTOFF))
06354 return 0;
06355
06356 if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
06357 && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
06358 return 0;
06359 return 1;
06360 }
06361
06362 saw_plus = false;
06363 if (GET_CODE (disp) == PLUS)
06364 {
06365 if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
06366 return 0;
06367 disp = XEXP (disp, 0);
06368 saw_plus = true;
06369 }
06370
06371 if (TARGET_MACHO && darwin_local_data_pic (disp))
06372 return 1;
06373
06374 if (GET_CODE (disp) != UNSPEC)
06375 return 0;
06376
06377 switch (XINT (disp, 1))
06378 {
06379 case UNSPEC_GOT:
06380 if (saw_plus)
06381 return false;
06382 return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF;
06383 case UNSPEC_GOTOFF:
06384
06385
06386
06387 if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
06388 || GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
06389 && !TARGET_64BIT)
06390 return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
06391 return false;
06392 case UNSPEC_GOTTPOFF:
06393 case UNSPEC_GOTNTPOFF:
06394 case UNSPEC_INDNTPOFF:
06395 if (saw_plus)
06396 return false;
06397 disp = XVECEXP (disp, 0, 0);
06398 return (GET_CODE (disp) == SYMBOL_REF
06399 && SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_INITIAL_EXEC);
06400 case UNSPEC_NTPOFF:
06401 disp = XVECEXP (disp, 0, 0);
06402 return (GET_CODE (disp) == SYMBOL_REF
06403 && SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_LOCAL_EXEC);
06404 case UNSPEC_DTPOFF:
06405 disp = XVECEXP (disp, 0, 0);
06406 return (GET_CODE (disp) == SYMBOL_REF
06407 && SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_LOCAL_DYNAMIC);
06408 }
06409
06410 return 0;
06411 }
06412
06413
06414
06415
06416
06417
06418
06419
06420
06421 int
06422 legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
06423 {
06424 struct ix86_address parts;
06425 rtx base, index, disp;
06426 HOST_WIDE_INT scale;
06427 const char *reason = NULL;
06428 rtx reason_rtx = NULL_RTX;
06429
06430 if (TARGET_DEBUG_ADDR)
06431 {
06432 fprintf (stderr,
06433 "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
06434 GET_MODE_NAME (mode), strict);
06435 debug_rtx (addr);
06436 }
06437
06438 if (ix86_decompose_address (addr, &parts) <= 0)
06439 {
06440 reason = "decomposition failed";
06441 goto report_error;
06442 }
06443
06444 base = parts.base;
06445 index = parts.index;
06446 disp = parts.disp;
06447 scale = parts.scale;
06448
06449
06450
06451
06452
06453
06454
06455 if (base)
06456 {
06457 rtx reg;
06458 reason_rtx = base;
06459
06460 if (REG_P (base))
06461 reg = base;
06462 else if (GET_CODE (base) == SUBREG
06463 && REG_P (SUBREG_REG (base))
06464 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base)))
06465 <= UNITS_PER_WORD)
06466 reg = SUBREG_REG (base);
06467 else
06468 {
06469 reason = "base is not a register";
06470 goto report_error;
06471 }
06472
06473 if (GET_MODE (base) != Pmode)
06474 {
06475 reason = "base is not in Pmode";
06476 goto report_error;
06477 }
06478
06479 if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
06480 || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg)))
06481 {
06482 reason = "base is not valid";
06483 goto report_error;
06484 }
06485 }
06486
06487
06488
06489
06490
06491 if (index)
06492 {
06493 rtx reg;
06494 reason_rtx = index;
06495
06496 if (REG_P (index))
06497 reg = index;
06498 else if (GET_CODE (index) == SUBREG
06499 && REG_P (SUBREG_REG (index))
06500 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index)))
06501 <= UNITS_PER_WORD)
06502 reg = SUBREG_REG (index);
06503 else
06504 {
06505 reason = "index is not a register";
06506 goto report_error;
06507 }
06508
06509 if (GET_MODE (index) != Pmode)
06510 {
06511 reason = "index is not in Pmode";
06512 goto report_error;
06513 }
06514
06515 if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
06516 || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg)))
06517 {
06518 reason = "index is not valid";
06519 goto report_error;
06520 }
06521 }
06522
06523
06524 if (scale != 1)
06525 {
06526 reason_rtx = GEN_INT (scale);
06527 if (!index)
06528 {
06529 reason = "scale without index";
06530 goto report_error;
06531 }
06532
06533 if (scale != 2 && scale != 4 && scale != 8)
06534 {
06535 reason = "scale is not a valid multiplier";
06536 goto report_error;
06537 }
06538 }
06539
06540
06541 if (disp)
06542 {
06543 reason_rtx = disp;
06544
06545 if (GET_CODE (disp) == CONST
06546 && GET_CODE (XEXP (disp, 0)) == UNSPEC)
06547 switch (XINT (XEXP (disp, 0), 1))
06548 {
06549
06550
06551
06552 case UNSPEC_GOT:
06553 case UNSPEC_GOTOFF:
06554 gcc_assert (flag_pic);
06555 if (!TARGET_64BIT)
06556 goto is_legitimate_pic;
06557 reason = "64bit address unspec";
06558 goto report_error;
06559
06560 case UNSPEC_GOTPCREL:
06561 gcc_assert (flag_pic);
06562 goto is_legitimate_pic;
06563
06564 case UNSPEC_GOTTPOFF:
06565 case UNSPEC_GOTNTPOFF:
06566 case UNSPEC_INDNTPOFF:
06567 case UNSPEC_NTPOFF:
06568 case UNSPEC_DTPOFF:
06569 break;
06570
06571 default:
06572 reason = "invalid address unspec";
06573 goto report_error;
06574 }
06575
06576 else if (SYMBOLIC_CONST (disp)
06577 && (flag_pic
06578 || (TARGET_MACHO
06579 #if TARGET_MACHO
06580 && MACHOPIC_INDIRECT
06581 && !machopic_operand_p (disp)
06582 #endif
06583 )))
06584 {
06585
06586 is_legitimate_pic:
06587 if (TARGET_64BIT && (index || base))
06588 {
06589
06590 if (GET_CODE (disp) != CONST
06591 || GET_CODE (XEXP (disp, 0)) != PLUS
06592 || GET_CODE (XEXP (XEXP (disp, 0), 0)) != UNSPEC
06593 || GET_CODE (XEXP (XEXP (disp, 0), 1)) != CONST_INT
06594 || (XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_DTPOFF
06595 && XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_NTPOFF))
06596 {
06597 reason = "non-constant pic memory reference";
06598 goto report_error;
06599 }
06600 }
06601 else if (! legitimate_pic_address_disp_p (disp))
06602 {
06603 reason = "displacement is an invalid pic construct";
06604 goto report_error;
06605 }
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627
06628 }
06629 else if (GET_CODE (disp) != LABEL_REF
06630 && GET_CODE (disp) != CONST_INT
06631 && (GET_CODE (disp) != CONST
06632 || !legitimate_constant_p (disp))
06633 && (GET_CODE (disp) != SYMBOL_REF
06634 || !legitimate_constant_p (disp)))
06635 {
06636 reason = "displacement is not constant";
06637 goto report_error;
06638 }
06639 else if (TARGET_64BIT
06640 && !x86_64_immediate_operand (disp, VOIDmode))
06641 {
06642 reason = "displacement is out of range";
06643 goto report_error;
06644 }
06645 }
06646
06647
06648 if (TARGET_DEBUG_ADDR)
06649 fprintf (stderr, "Success.\n");
06650 return TRUE;
06651
06652 report_error:
06653 if (TARGET_DEBUG_ADDR)
06654 {
06655 fprintf (stderr, "Error: %s\n", reason);
06656 debug_rtx (reason_rtx);
06657 }
06658 return FALSE;
06659 }
06660
06661
06662
06663 static HOST_WIDE_INT
06664 ix86_GOT_alias_set (void)
06665 {
06666 static HOST_WIDE_INT set = -1;
06667 if (set == -1)
06668 set = new_alias_set ();
06669 return set;
06670 }
06671
06672
06673
06674
06675
06676
06677
06678
06679
06680
06681
06682
06683
06684
06685
06686
06687
06688
06689
06690 static rtx
06691 legitimize_pic_address (rtx orig, rtx reg)
06692 {
06693 rtx addr = orig;
06694 rtx new = orig;
06695 rtx base;
06696
06697 #if TARGET_MACHO
06698 if (TARGET_MACHO && !TARGET_64BIT)
06699 {
06700 if (reg == 0)
06701 reg = gen_reg_rtx (Pmode);
06702
06703 return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
06704 }
06705 #endif
06706
06707 if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
06708 new = addr;
06709 else if (TARGET_64BIT
06710 && ix86_cmodel != CM_SMALL_PIC
06711 && local_symbolic_operand (addr, Pmode))
06712 {
06713 rtx tmpreg;
06714
06715
06716
06717 if (reload_in_progress)
06718 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
06719 if (GET_CODE (addr) == CONST)
06720 addr = XEXP (addr, 0);
06721 if (GET_CODE (addr) == PLUS)
06722 {
06723 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
06724 new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
06725 }
06726 else
06727 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
06728 new = gen_rtx_CONST (Pmode, new);
06729 if (!reg)
06730 tmpreg = gen_reg_rtx (Pmode);
06731 else
06732 tmpreg = reg;
06733 emit_move_insn (tmpreg, new);
06734
06735 if (reg != 0)
06736 {
06737 new = expand_simple_binop (Pmode, PLUS, reg, pic_offset_table_rtx,
06738 tmpreg, 1, OPTAB_DIRECT);
06739 new = reg;
06740 }
06741 else new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
06742 }
06743 else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
06744 {
06745
06746
06747
06748 if (reload_in_progress)
06749 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
06750 if (GET_CODE (addr) == CONST)
06751 addr = XEXP (addr, 0);
06752 if (GET_CODE (addr) == PLUS)
06753 {
06754 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
06755 new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
06756 }
06757 else
06758 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
06759 new = gen_rtx_CONST (Pmode, new);
06760 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
06761
06762 if (reg != 0)
06763 {
06764 emit_move_insn (reg, new);
06765 new = reg;
06766 }
06767 }
06768 else if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0)
06769 {
06770 if (TARGET_64BIT)
06771 {
06772 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
06773 new = gen_rtx_CONST (Pmode, new);
06774 new = gen_const_mem (Pmode, new);
06775 set_mem_alias_set (new, ix86_GOT_alias_set ());
06776
06777 if (reg == 0)
06778 reg = gen_reg_rtx (Pmode);
06779
06780
06781
06782 emit_insn (gen_movsi (reg, new));
06783 new = reg;
06784 }
06785 else
06786 {
06787
06788
06789
06790 if (reload_in_progress)
06791 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
06792 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
06793 new = gen_rtx_CONST (Pmode, new);
06794 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
06795 new = gen_const_mem (Pmode, new);
06796 set_mem_alias_set (new, ix86_GOT_alias_set ());
06797
06798 if (reg == 0)
06799 reg = gen_reg_rtx (Pmode);
06800 emit_move_insn (reg, new);
06801 new = reg;
06802 }
06803 }
06804 else
06805 {
06806 if (GET_CODE (addr) == CONST_INT
06807 && !x86_64_immediate_operand (addr, VOIDmode))
06808 {
06809 if (reg)
06810 {
06811 emit_move_insn (reg, addr);
06812 new = reg;
06813 }
06814 else
06815 new = force_reg (Pmode, addr);
06816 }
06817 else if (GET_CODE (addr) == CONST)
06818 {
06819 addr = XEXP (addr, 0);
06820
06821
06822
06823
06824 if (GET_CODE (addr) == UNSPEC
06825 || (GET_CODE (addr) == PLUS
06826 && GET_CODE (XEXP (addr, 0)) == UNSPEC))
06827 return orig;
06828 gcc_assert (GET_CODE (addr) == PLUS);
06829 }
06830 if (GET_CODE (addr) == PLUS)
06831 {
06832 rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
06833
06834
06835
06836 if (local_symbolic_operand (op0, Pmode)
06837 && GET_CODE (op1) == CONST_INT)
06838 {
06839 if (!TARGET_64BIT)
06840 {
06841 if (reload_in_progress)
06842 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
06843 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
06844 UNSPEC_GOTOFF);
06845 new = gen_rtx_PLUS (Pmode, new, op1);
06846 new = gen_rtx_CONST (Pmode, new);
06847 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
06848
06849 if (reg != 0)
06850 {
06851 emit_move_insn (reg, new);
06852 new = reg;
06853 }
06854 }
06855 else
06856 {
06857 if (INTVAL (op1) < -16*1024*1024
06858 || INTVAL (op1) >= 16*1024*1024)
06859 {
06860 if (!x86_64_immediate_operand (op1, Pmode))
06861 op1 = force_reg (Pmode, op1);
06862 new = gen_rtx_PLUS (Pmode, force_reg (Pmode, op0), op1);
06863 }
06864 }
06865 }
06866 else
06867 {
06868 base = legitimize_pic_address (XEXP (addr, 0), reg);
06869 new = legitimize_pic_address (XEXP (addr, 1),
06870 base == reg ? NULL_RTX : reg);
06871
06872 if (GET_CODE (new) == CONST_INT)
06873 new = plus_constant (base, INTVAL (new));
06874 else
06875 {
06876 if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
06877 {
06878 base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
06879 new = XEXP (new, 1);
06880 }
06881 new = gen_rtx_PLUS (Pmode, base, new);
06882 }
06883 }
06884 }
06885 }
06886 return new;
06887 }
06888
06889
06890
06891 static rtx
06892 get_thread_pointer (int to_reg)
06893 {
06894 rtx tp, reg, insn;
06895
06896 tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
06897 if (!to_reg)
06898 return tp;
06899
06900 reg = gen_reg_rtx (Pmode);
06901 insn = gen_rtx_SET (VOIDmode, reg, tp);
06902 insn = emit_insn (insn);
06903
06904 return reg;
06905 }
06906
06907
06908
06909
06910
06911 static rtx
06912 legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
06913 {
06914 rtx dest, base, off, pic, tp;
06915 int type;
06916
06917 switch (model)
06918 {
06919 case TLS_MODEL_GLOBAL_DYNAMIC:
06920 dest = gen_reg_rtx (Pmode);
06921 tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
06922
06923 if (TARGET_64BIT && ! TARGET_GNU2_TLS)
06924 {
06925 rtx rax = gen_rtx_REG (Pmode, 0), insns;
06926
06927 start_sequence ();
06928 emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
06929 insns = get_insns ();
06930 end_sequence ();
06931
06932 emit_libcall_block (insns, dest, rax, x);
06933 }
06934 else if (TARGET_64BIT && TARGET_GNU2_TLS)
06935 emit_insn (gen_tls_global_dynamic_64 (dest, x));
06936 else
06937 emit_insn (gen_tls_global_dynamic_32 (dest, x));
06938
06939 if (TARGET_GNU2_TLS)
06940 {
06941 dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
06942
06943 set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
06944 }
06945 break;
06946
06947 case TLS_MODEL_LOCAL_DYNAMIC:
06948 base = gen_reg_rtx (Pmode);
06949 tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
06950
06951 if (TARGET_64BIT && ! TARGET_GNU2_TLS)
06952 {
06953 rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
06954
06955 start_sequence ();
06956 emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
06957 insns = get_insns ();
06958 end_sequence ();
06959
06960 note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
06961 note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
06962 emit_libcall_block (insns, base, rax, note);
06963 }
06964 else if (TARGET_64BIT && TARGET_GNU2_TLS)
06965 emit_insn (gen_tls_local_dynamic_base_64 (base));
06966 else
06967 emit_insn (gen_tls_local_dynamic_base_32 (base));
06968
06969 if (TARGET_GNU2_TLS)
06970 {
06971 rtx x = ix86_tls_module_base ();
06972
06973 set_unique_reg_note (get_last_insn (), REG_EQUIV,
06974 gen_rtx_MINUS (Pmode, x, tp));
06975 }
06976
06977 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
06978 off = gen_rtx_CONST (Pmode, off);
06979
06980 dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, off));
06981
06982 if (TARGET_GNU2_TLS)
06983 {
06984 dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, dest, tp));
06985
06986 set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
06987 }
06988
06989 break;
06990
06991 case TLS_MODEL_INITIAL_EXEC:
06992 if (TARGET_64BIT)
06993 {
06994 pic = NULL;
06995 type = UNSPEC_GOTNTPOFF;
06996 }
06997 else if (flag_pic)
06998 {
06999 if (reload_in_progress)
07000 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
07001 pic = pic_offset_table_rtx;
07002 type = TARGET_ANY_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
07003 }
07004 else if (!TARGET_ANY_GNU_TLS)
07005 {
07006 pic = gen_reg_rtx (Pmode);
07007 emit_insn (gen_set_got (pic));
07008 type = UNSPEC_GOTTPOFF;
07009 }
07010 else
07011 {
07012 pic = NULL;
07013 type = UNSPEC_INDNTPOFF;
07014 }
07015
07016 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
07017 off = gen_rtx_CONST (Pmode, off);
07018 if (pic)
07019 off = gen_rtx_PLUS (Pmode, pic, off);
07020 off = gen_const_mem (Pmode, off);
07021 set_mem_alias_set (off, ix86_GOT_alias_set ());
07022
07023 if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
07024 {
07025 base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
07026 off = force_reg (Pmode, off);
07027 return gen_rtx_PLUS (Pmode, base, off);
07028 }
07029 else
07030 {
07031 base = get_thread_pointer (true);
07032 dest = gen_reg_rtx (Pmode);
07033 emit_insn (gen_subsi3 (dest, base, off));
07034 }
07035 break;
07036
07037 case TLS_MODEL_LOCAL_EXEC:
07038 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
07039 (TARGET_64BIT || TARGET_ANY_GNU_TLS)
07040 ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
07041 off = gen_rtx_CONST (Pmode, off);
07042
07043 if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
07044 {
07045 base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
07046 return gen_rtx_PLUS (Pmode, base, off);
07047 }
07048 else
07049 {
07050 base = get_thread_pointer (true);
07051 dest = gen_reg_rtx (Pmode);
07052 emit_insn (gen_subsi3 (dest, base, off));
07053 }
07054 break;
07055
07056 default:
07057 gcc_unreachable ();
07058 }
07059
07060 return dest;
07061 }
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084 rtx
07085 legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
07086 {
07087 int changed = 0;
07088 unsigned log;
07089
07090 if (TARGET_DEBUG_ADDR)
07091 {
07092 fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n",
07093 GET_MODE_NAME (mode));
07094 debug_rtx (x);
07095 }
07096
07097 log = GET_CODE (x) == SYMBOL_REF ? SYMBOL_REF_TLS_MODEL (x) : 0;
07098 if (log)
07099 return legitimize_tls_address (x, log, false);
07100 if (GET_CODE (x) == CONST
07101 && GET_CODE (XEXP (x, 0)) == PLUS
07102 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
07103 && (log = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (x, 0), 0))))
07104 {
07105 rtx t = legitimize_tls_address (XEXP (XEXP (x, 0), 0), log, false);
07106 return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (x, 0), 1));
07107 }
07108
07109 if (flag_pic && SYMBOLIC_CONST (x))
07110 return legitimize_pic_address (x, 0);
07111
07112
07113 if (GET_CODE (x) == ASHIFT
07114 && GET_CODE (XEXP (x, 1)) == CONST_INT
07115 && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) < 4)
07116 {
07117 changed = 1;
07118 log = INTVAL (XEXP (x, 1));
07119 x = gen_rtx_MULT (Pmode, force_reg (Pmode, XEXP (x, 0)),
07120 GEN_INT (1 << log));
07121 }
07122
07123 if (GET_CODE (x) == PLUS)
07124 {
07125
07126
07127 if (GET_CODE (XEXP (x, 0)) == ASHIFT
07128 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
07129 && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (x, 0), 1)) < 4)
07130 {
07131 changed = 1;
07132 log = INTVAL (XEXP (XEXP (x, 0), 1));
07133 XEXP (x, 0) = gen_rtx_MULT (Pmode,
07134 force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
07135 GEN_INT (1 << log));
07136 }
07137
07138 if (GET_CODE (XEXP (x, 1)) == ASHIFT
07139 && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
07140 && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (x, 1), 1)) < 4)
07141 {
07142 changed = 1;
07143 log = INTVAL (XEXP (XEXP (x, 1), 1));
07144 XEXP (x, 1) = gen_rtx_MULT (Pmode,
07145 force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
07146 GEN_INT (1 << log));
07147 }
07148
07149
07150 if (GET_CODE (XEXP (x, 1)) == MULT)
07151 {
07152 rtx tmp = XEXP (x, 0);
07153 XEXP (x, 0) = XEXP (x, 1);
07154 XEXP (x, 1) = tmp;
07155 changed = 1;
07156 }
07157
07158
07159
07160
07161
07162 if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
07163 {
07164 changed = 1;
07165 x = gen_rtx_PLUS (Pmode,
07166 gen_rtx_PLUS (Pmode, XEXP (x, 0),
07167 XEXP (XEXP (x, 1), 0)),
07168 XEXP (XEXP (x, 1), 1));
07169 }
07170
07171
07172
07173
07174 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
07175 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
07176 && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
07177 && CONSTANT_P (XEXP (x, 1)))
07178 {
07179 rtx constant;
07180 rtx other = NULL_RTX;
07181
07182 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
07183 {
07184 constant = XEXP (x, 1);
07185 other = XEXP (XEXP (XEXP (x, 0), 1), 1);
07186 }
07187 else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
07188 {
07189 constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
07190 other = XEXP (x, 1);
07191 }
07192 else
07193 constant = 0;
07194
07195 if (constant)
07196 {
07197 changed = 1;
07198 x = gen_rtx_PLUS (Pmode,
07199 gen_rtx_PLUS (Pmode, XEXP (XEXP (x, 0), 0),
07200 XEXP (XEXP (XEXP (x, 0), 1), 0)),
07201 plus_constant (other, INTVAL (constant)));
07202 }
07203 }
07204
07205 if (changed && legitimate_address_p (mode, x, FALSE))
07206 return x;
07207
07208 if (GET_CODE (XEXP (x, 0)) == MULT)
07209 {
07210 changed = 1;
07211 XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
07212 }
07213
07214 if (GET_CODE (XEXP (x, 1)) == MULT)
07215 {
07216 changed = 1;
07217 XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
07218 }
07219
07220 if (changed
07221 && GET_CODE (XEXP (x, 1)) == REG
07222 && GET_CODE (XEXP (x, 0)) == REG)
07223 return x;
07224
07225 if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
07226 {
07227 changed = 1;
07228 x = legitimize_pic_address (x, 0);
07229 }
07230
07231 if (changed && legitimate_address_p (mode, x, FALSE))
07232 return x;
07233
07234 if (GET_CODE (XEXP (x, 0)) == REG)
07235 {
07236 rtx temp = gen_reg_rtx (Pmode);
07237 rtx val = force_operand (XEXP (x, 1), temp);
07238 if (val != temp)
07239 emit_move_insn (temp, val);
07240
07241 XEXP (x, 1) = temp;
07242 return x;
07243 }
07244
07245 else if (GET_CODE (XEXP (x, 1)) == REG)
07246 {
07247 rtx temp = gen_reg_rtx (Pmode);
07248 rtx val = force_operand (XEXP (x, 0), temp);
07249 if (val != temp)
07250 emit_move_insn (temp, val);
07251
07252 XEXP (x, 0) = temp;
07253 return x;
07254 }
07255 }
07256
07257 return x;
07258 }
07259
07260
07261
07262
07263
07264
07265 static void
07266 output_pic_addr_const (FILE *file, rtx x, int code)
07267 {
07268 char buf[256];
07269
07270 switch (GET_CODE (x))
07271 {
07272 case PC:
07273 gcc_assert (flag_pic);
07274 putc ('.', file);
07275 break;
07276
07277 case SYMBOL_REF:
07278 if (! TARGET_MACHO || TARGET_64BIT)
07279 output_addr_const (file, x);
07280 else
07281 {
07282 const char *name = XSTR (x, 0);
07283
07284
07285 if (SYMBOL_REF_DECL (x))
07286 mark_decl_referenced (SYMBOL_REF_DECL (x));
07287
07288 #if TARGET_MACHO
07289 if (MACHOPIC_INDIRECT
07290 && machopic_classify_symbol (x) == MACHOPIC_UNDEFINED_FUNCTION)
07291 name = machopic_indirection_name (x, true);
07292 #endif
07293 assemble_name (file, name);
07294 }
07295 if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
07296 fputs ("@PLT", file);
07297 break;
07298
07299 case LABEL_REF:
07300 x = XEXP (x, 0);
07301
07302 case CODE_LABEL:
07303 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
07304 assemble_name (asm_out_file, buf);
07305 break;
07306
07307 case CONST_INT:
07308 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
07309 break;
07310
07311 case CONST:
07312
07313
07314 output_pic_addr_const (file, XEXP (x, 0), code);
07315 break;
07316
07317 case CONST_DOUBLE:
07318 if (GET_MODE (x) == VOIDmode)
07319 {
07320
07321 if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
07322 fprintf (file, "0x%lx%08lx",
07323 (unsigned long) CONST_DOUBLE_HIGH (x),
07324 (unsigned long) CONST_DOUBLE_LOW (x));
07325 else
07326 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
07327 }
07328 else
07329
07330
07331 output_operand_lossage ("floating constant misused");
07332 break;
07333
07334 case PLUS:
07335
07336 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
07337 {
07338 output_pic_addr_const (file, XEXP (x, 0), code);
07339 putc ('+', file);
07340 output_pic_addr_const (file, XEXP (x, 1), code);
07341 }
07342 else
07343 {
07344 gcc_assert (GET_CODE (XEXP (x, 1)) == CONST_INT);
07345 output_pic_addr_const (file, XEXP (x, 1), code);
07346 putc ('+', file);
07347 output_pic_addr_const (file, XEXP (x, 0), code);
07348 }
07349 break;
07350
07351 case MINUS:
07352 if (!TARGET_MACHO)
07353 putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
07354 output_pic_addr_const (file, XEXP (x, 0), code);
07355 putc ('-', file);
07356 output_pic_addr_const (file, XEXP (x, 1), code);
07357 if (!TARGET_MACHO)
07358 putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
07359 break;
07360
07361 case UNSPEC:
07362 gcc_assert (XVECLEN (x, 0) == 1);
07363 output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
07364 switch (XINT (x, 1))
07365 {
07366 case UNSPEC_GOT:
07367 fputs ("@GOT", file);
07368 break;
07369 case UNSPEC_GOTOFF:
07370 fputs ("@GOTOFF", file);
07371 break;
07372 case UNSPEC_GOTPCREL:
07373 fputs ("@GOTPCREL(%rip)", file);
07374 break;
07375 case UNSPEC_GOTTPOFF:
07376
07377 fputs ("@GOTTPOFF", file);
07378 break;
07379 case UNSPEC_TPOFF:
07380 fputs ("@TPOFF", file);
07381 break;
07382 case UNSPEC_NTPOFF:
07383 if (TARGET_64BIT)
07384 fputs ("@TPOFF", file);
07385 else
07386 fputs ("@NTPOFF", file);
07387 break;
07388 case UNSPEC_DTPOFF:
07389 fputs ("@DTPOFF", file);
07390 break;
07391 case UNSPEC_GOTNTPOFF:
07392 if (TARGET_64BIT)
07393 fputs ("@GOTTPOFF(%rip)", file);
07394 else
07395 fputs ("@GOTNTPOFF", file);
07396 break;
07397 case UNSPEC_INDNTPOFF:
07398 fputs ("@INDNTPOFF", file);
07399 break;
07400 default:
07401 output_operand_lossage ("invalid UNSPEC as operand");
07402 break;
07403 }
07404 break;
07405
07406 default:
07407 output_operand_lossage ("invalid expression as operand");
07408 }
07409 }
07410
07411
07412
07413
07414 static void
07415 i386_output_dwarf_dtprel (FILE *file, int size, rtx x)
07416 {
07417 fputs (ASM_LONG, file);
07418 output_addr_const (file, x);
07419 fputs ("@DTPOFF", file);
07420 switch (size)
07421 {
07422 case 4:
07423 break;
07424 case 8:
07425 fputs (", 0", file);
07426 break;
07427 default:
07428 gcc_unreachable ();
07429 }
07430 }
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441
07442 static rtx
07443 ix86_delegitimize_address (rtx orig_x)
07444 {
07445 rtx x = orig_x;
07446
07447 rtx reg_addend = NULL_RTX;
07448
07449 rtx const_addend = NULL_RTX;
07450
07451 rtx result = NULL_RTX;
07452
07453 if (GET_CODE (x) == MEM)
07454 x = XEXP (x, 0);
07455
07456 if (TARGET_64BIT)
07457 {
07458 if (GET_CODE (x) != CONST
07459 || GET_CODE (XEXP (x, 0)) != UNSPEC
07460 || XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
07461 || GET_CODE (orig_x) != MEM)
07462 return orig_x;
07463 return XVECEXP (XEXP (x, 0), 0, 0);
07464 }
07465
07466 if (GET_CODE (x) != PLUS
07467 || GET_CODE (XEXP (x, 1)) != CONST)
07468 return orig_x;
07469
07470 if (GET_CODE (XEXP (x, 0)) == REG
07471 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
07472
07473 ;
07474 else if (GET_CODE (XEXP (x, 0)) == PLUS)
07475 {
07476
07477 reg_addend = XEXP (x, 0);
07478 if (GET_CODE (XEXP (reg_addend, 0)) == REG
07479 && REGNO (XEXP (reg_addend, 0)) == PIC_OFFSET_TABLE_REGNUM)
07480 reg_addend = XEXP (reg_addend, 1);
07481 else if (GET_CODE (XEXP (reg_addend, 1)) == REG
07482 && REGNO (XEXP (reg_addend, 1)) == PIC_OFFSET_TABLE_REGNUM)
07483 reg_addend = XEXP (reg_addend, 0);
07484 else
07485 return orig_x;
07486 if (GET_CODE (reg_addend) != REG
07487 && GET_CODE (reg_addend) != MULT
07488 && GET_CODE (reg_addend) != ASHIFT)
07489 return orig_x;
07490 }
07491 else
07492 return orig_x;
07493
07494 x = XEXP (XEXP (x, 1), 0);
07495 if (GET_CODE (x) == PLUS
07496 && GET_CODE (XEXP (x, 1)) == CONST_INT)
07497 {
07498 const_addend = XEXP (x, 1);
07499 x = XEXP (x, 0);
07500 }
07501
07502 if (GET_CODE (x) == UNSPEC
07503 && ((XINT (x, 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
07504 || (XINT (x, 1) == UNSPEC_GOTOFF && GET_CODE (orig_x) != MEM)))
07505 result = XVECEXP (x, 0, 0);
07506
07507 if (TARGET_MACHO && darwin_local_data_pic (x)
07508 && GET_CODE (orig_x) != MEM)
07509 result = XEXP (x, 0);
07510
07511 if (! result)
07512 return orig_x;
07513
07514 if (const_addend)
07515 result = gen_rtx_PLUS (Pmode, result, const_addend);
07516 if (reg_addend)
07517 result = gen_rtx_PLUS (Pmode, reg_addend, result);
07518 return result;
07519 }
07520
07521 static void
07522 put_condition_code (enum rtx_code code, enum machine_mode mode, int reverse,
07523 int fp, FILE *file)
07524 {
07525 const char *suffix;
07526
07527 if (mode == CCFPmode || mode == CCFPUmode)
07528 {
07529 enum rtx_code second_code, bypass_code;
07530 ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
07531 gcc_assert (bypass_code == UNKNOWN && second_code == UNKNOWN);
07532 code = ix86_fp_compare_code_to_integer (code);
07533 mode = CCmode;
07534 }
07535 if (reverse)
07536 code = reverse_condition (code);
07537
07538 switch (code)
07539 {
07540 case EQ:
07541 suffix = "e";
07542 break;
07543 case NE:
07544 suffix = "ne";
07545 break;
07546 case GT:
07547 gcc_assert (mode == CCmode || mode == CCNOmode || mode == CCGCmode);
07548 suffix = "g";
07549 break;
07550 case GTU:
07551
07552
07553 gcc_assert (mode == CCmode);
07554 suffix = fp ? "nbe" : "a";
07555 break;
07556 case LT:
07557 switch (mode)
07558 {
07559 case CCNOmode:
07560 case CCGOCmode:
07561 suffix = "s";
07562 break;
07563
07564 case CCmode:
07565 case CCGCmode:
07566 suffix = "l";
07567 break;
07568
07569 default:
07570 gcc_unreachable ();
07571 }
07572 break;
07573 case LTU:
07574 gcc_assert (mode == CCmode);
07575 suffix = "b";
07576 break;
07577 case GE:
07578 switch (mode)
07579 {
07580 case CCNOmode:
07581 case CCGOCmode:
07582 suffix = "ns";
07583 break;
07584
07585 case CCmode:
07586 case CCGCmode:
07587 suffix = "ge";
07588 break;
07589
07590 default:
07591 gcc_unreachable ();
07592 }
07593 break;
07594 case GEU:
07595
07596 gcc_assert (mode == CCmode);
07597 suffix = fp ? "nb" : "ae";
07598 break;
07599 case LE:
07600 gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode);
07601 suffix = "le";
07602 break;
07603 case LEU:
07604 gcc_assert (mode == CCmode);
07605 suffix = "be";
07606 break;
07607 case UNORDERED:
07608 suffix = fp ? "u" : "p";
07609 break;
07610 case ORDERED:
07611 suffix = fp ? "nu" : "np";
07612 break;
07613 default:
07614 gcc_unreachable ();
07615 }
07616 fputs (suffix, file);
07617 }
07618
07619
07620
07621
07622
07623
07624
07625
07626
07627 void
07628 print_reg (rtx x, int code, FILE *file)
07629 {
07630 gcc_assert (REGNO (x) != ARG_POINTER_REGNUM
07631 && REGNO (x) != FRAME_POINTER_REGNUM
07632 && REGNO (x) != FLAGS_REG
07633 && REGNO (x) != FPSR_REG);
07634
07635 if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
07636 putc ('%', file);
07637
07638 if (code == 'w' || MMX_REG_P (x))
07639 code = 2;
07640 else if (code == 'b')
07641 code = 1;
07642 else if (code == 'k')
07643 code = 4;
07644 else if (code == 'q')
07645 code = 8;
07646 else if (code == 'y')
07647 code = 3;
07648 else if (code == 'h')
07649 code = 0;
07650 else
07651 code = GET_MODE_SIZE (GET_MODE (x));
07652
07653
07654
07655 if (REX_INT_REG_P (x))
07656 {
07657 gcc_assert (TARGET_64BIT);
07658 switch (code)
07659 {
07660 case 0:
07661 error ("extended registers have no high halves");
07662 break;
07663 case 1:
07664 fprintf (file, "r%ib", REGNO (x) - FIRST_REX_INT_REG + 8);
07665 break;
07666 case 2:
07667 fprintf (file, "r%iw", REGNO (x) - FIRST_REX_INT_REG + 8);
07668 break;
07669 case 4:
07670 fprintf (file, "r%id", REGNO (x) - FIRST_REX_INT_REG + 8);
07671 break;
07672 case 8:
07673 fprintf (file, "r%i", REGNO (x) - FIRST_REX_INT_REG + 8);
07674 break;
07675 default:
07676 error ("unsupported operand size for extended register");
07677 break;
07678 }
07679 return;
07680 }
07681 switch (code)
07682 {
07683 case 3:
07684 if (STACK_TOP_P (x))
07685 {
07686 fputs ("st(0)", file);
07687 break;
07688 }
07689
07690 case 8:
07691 case 4:
07692 case 12:
07693 if (! ANY_FP_REG_P (x))
07694 putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
07695
07696 case 16:
07697 case 2:
07698 normal:
07699 fputs (hi_reg_name[REGNO (x)], file);
07700 break;
07701 case 1:
07702 if (REGNO (x) >= ARRAY_SIZE (qi_reg_name))
07703 goto normal;
07704 fputs (qi_reg_name[REGNO (x)], file);
07705 break;
07706 case 0:
07707 if (REGNO (x) >= ARRAY_SIZE (qi_high_reg_name))
07708 goto normal;
07709 fputs (qi_high_reg_name[REGNO (x)], file);
07710 break;
07711 default:
07712 gcc_unreachable ();
07713 }
07714 }
07715
07716
07717
07718
07719
07720 static const char *
07721 get_some_local_dynamic_name (void)
07722 {
07723 rtx insn;
07724
07725 if (cfun->machine->some_ld_name)
07726 return cfun->machine->some_ld_name;
07727
07728 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
07729 if (INSN_P (insn)
07730 && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
07731 return cfun->machine->some_ld_name;
07732
07733 gcc_unreachable ();
07734 }
07735
07736 static int
07737 get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
07738 {
07739 rtx x = *px;
07740
07741 if (GET_CODE (x) == SYMBOL_REF
07742 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
07743 {
07744 cfun->machine->some_ld_name = XSTR (x, 0);
07745 return 1;
07746 }
07747
07748 return 0;
07749 }
07750
07751
07752
07753
07754
07755
07756
07757
07758
07759
07760
07761
07762
07763
07764
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774
07775
07776
07777
07778
07779 void
07780 print_operand (FILE *file, rtx x, int code)
07781 {
07782 if (code)
07783 {
07784 switch (code)
07785 {
07786 case '*':
07787 if (ASSEMBLER_DIALECT == ASM_ATT)
07788 putc ('*', file);
07789 return;
07790
07791 case '&':
07792 assemble_name (file, get_some_local_dynamic_name ());
07793 return;
07794
07795 case 'A':
07796 switch (ASSEMBLER_DIALECT)
07797 {
07798 case ASM_ATT:
07799 putc ('*', file);
07800 break;
07801
07802 case ASM_INTEL:
07803
07804
07805 if (GET_CODE (x) != REG)
07806 {
07807 putc ('[', file);
07808 PRINT_OPERAND (file, x, 0);
07809 putc (']', file);
07810 return;
07811 }
07812 break;
07813
07814 default:
07815 gcc_unreachable ();
07816 }
07817
07818 PRINT_OPERAND (file, x, 0);
07819 return;
07820
07821
07822 case 'L':
07823 if (ASSEMBLER_DIALECT == ASM_ATT)
07824 putc ('l', file);
07825 return;
07826
07827 case 'W':
07828 if (ASSEMBLER_DIALECT == ASM_ATT)
07829 putc ('w', file);
07830 return;
07831
07832 case 'B':
07833 if (ASSEMBLER_DIALECT == ASM_ATT)
07834 putc ('b', file);
07835 return;
07836
07837 case 'Q':
07838 if (ASSEMBLER_DIALECT == ASM_ATT)
07839 putc ('l', file);
07840 return;
07841
07842 case 'S':
07843 if (ASSEMBLER_DIALECT == ASM_ATT)
07844 putc ('s', file);
07845 return;
07846
07847 case 'T':
07848 if (ASSEMBLER_DIALECT == ASM_ATT)
07849 putc ('t', file);
07850 return;
07851
07852 case 'z':
07853
07854
07855 if (STACK_REG_P (x))
07856 return;
07857
07858
07859 if (ASSEMBLER_DIALECT == ASM_INTEL)
07860 return;
07861
07862
07863 switch (GET_MODE_SIZE (GET_MODE (x)))
07864 {
07865 case 2:
07866 #ifdef HAVE_GAS_FILDS_FISTS
07867 putc ('s', file);
07868 #endif
07869 return;
07870
07871 case 4:
07872 if (GET_MODE (x) == SFmode)
07873 {
07874 putc ('s', file);
07875 return;
07876 }
07877 else
07878 putc ('l', file);
07879 return;
07880
07881 case 12:
07882 case 16:
07883 putc ('t', file);
07884 return;
07885
07886 case 8:
07887 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
07888 {
07889 #ifdef GAS_MNEMONICS
07890 putc ('q', file);
07891 #else
07892 putc ('l', file);
07893 putc ('l', file);
07894 #endif
07895 }
07896 else
07897 putc ('l', file);
07898 return;
07899
07900 default:
07901 gcc_unreachable ();
07902 }
07903
07904 case 'b':
07905 case 'w':
07906 case 'k':
07907 case 'q':
07908 case 'h':
07909 case 'y':
07910 case 'X':
07911 case 'P':
07912 break;
07913
07914 case 's':
07915 if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT)
07916 {
07917 PRINT_OPERAND (file, x, 0);
07918 putc (',', file);
07919 }
07920 return;
07921
07922 case 'D':
07923
07924
07925
07926 switch (GET_CODE (x))
07927 {
07928 case EQ:
07929 case UNEQ:
07930 fputs ("eq", file);
07931 break;
07932 case LT:
07933 case UNLT:
07934 fputs ("lt", file);
07935 break;
07936 case LE:
07937 case UNLE:
07938 fputs ("le", file);
07939 break;
07940 case UNORDERED:
07941 fputs ("unord", file);
07942 break;
07943 case NE:
07944 case LTGT:
07945 fputs ("neq", file);
07946 break;
07947 case UNGE:
07948 case GE:
07949 fputs ("nlt", file);
07950 break;
07951 case UNGT:
07952 case GT:
07953 fputs ("nle", file);
07954 break;
07955 case ORDERED:
07956 fputs ("ord", file);
07957 break;
07958 default:
07959 gcc_unreachable ();
07960 }
07961 return;
07962 case 'O':
07963 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
07964 if (ASSEMBLER_DIALECT == ASM_ATT)
07965 {
07966 switch (GET_MODE (x))
07967 {
07968 case HImode: putc ('w', file); break;
07969 case SImode:
07970 case SFmode: putc ('l', file); break;
07971 case DImode:
07972 case DFmode: putc ('q', file); break;
07973 default: gcc_unreachable ();
07974 }
07975 putc ('.', file);
07976 }
07977 #endif
07978 return;
07979 case 'C':
07980 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 0, file);
07981 return;
07982 case 'F':
07983 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
07984 if (ASSEMBLER_DIALECT == ASM_ATT)
07985 putc ('.', file);
07986 #endif
07987 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 1, file);
07988 return;
07989
07990
07991 case 'c':
07992
07993
07994 if (!COMPARISON_P (x))
07995 {
07996 output_operand_lossage ("operand is neither a constant nor a condition code, invalid operand code 'c'");
07997 return;
07998 }
07999 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 0, file);
08000 return;
08001 case 'f':
08002 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
08003 if (ASSEMBLER_DIALECT == ASM_ATT)
08004 putc ('.', file);
08005 #endif
08006 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
08007 return;
08008
08009 case 'H':
08010
08011
08012 x = adjust_address_nv (x, DImode, 8);
08013 break;
08014
08015 case '+':
08016 {
08017 rtx x;
08018
08019 if (!optimize || optimize_size || !TARGET_BRANCH_PREDICTION_HINTS)
08020 return;
08021
08022 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
08023 if (x)
08024 {
08025 int pred_val = INTVAL (XEXP (x, 0));
08026
08027 if (pred_val < REG_BR_PROB_BASE * 45 / 100
08028 || pred_val > REG_BR_PROB_BASE * 55 / 100)
08029 {
08030 int taken = pred_val > REG_BR_PROB_BASE / 2;
08031 int cputaken = final_forward_branch_p (current_output_insn) == 0;
08032
08033
08034
08035 if (taken != cputaken)
08036 {
08037
08038
08039 if (taken)
08040 fputs ("ds ; ", file);
08041 else
08042 fputs ("cs ; ", file);
08043 }
08044 }
08045 }
08046 return;
08047 }
08048 default:
08049 output_operand_lossage ("invalid operand code '%c'", code);
08050 }
08051 }
08052
08053 if (GET_CODE (x) == REG)
08054 print_reg (x, code, file);
08055
08056 else if (GET_CODE (x) == MEM)
08057 {
08058
08059 if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P')
08060 {
08061 const char * size;
08062 switch (GET_MODE_SIZE (GET_MODE (x)))
08063 {
08064 case 1: size = "BYTE"; break;
08065 case 2: size = "WORD"; break;
08066 case 4: size = "DWORD"; break;
08067 case 8: size = "QWORD"; break;
08068 case 12: size = "XWORD"; break;
08069 case 16: size = "XMMWORD"; break;
08070 default:
08071 gcc_unreachable ();
08072 }
08073
08074
08075 if (code == 'b')
08076 size = "BYTE";
08077 else if (code == 'w')
08078 size = "WORD";
08079 else if (code == 'k')
08080 size = "DWORD";
08081
08082 fputs (size, file);
08083 fputs (" PTR ", file);
08084 }
08085
08086 x = XEXP (x, 0);
08087
08088 if (CONSTANT_ADDRESS_P (x) && code == 'P'
08089 && GET_CODE (x) != CONST_INT)
08090 output_addr_const (file, x);
08091 else if (this_is_asm_operands && ! address_operand (x, VOIDmode))
08092 output_operand_lossage ("invalid constraints for operand");
08093 else
08094 output_address (x);
08095 }
08096
08097 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
08098 {
08099 REAL_VALUE_TYPE r;
08100 long l;
08101
08102 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
08103 REAL_VALUE_TO_TARGET_SINGLE (r, l);
08104
08105 if (ASSEMBLER_DIALECT == ASM_ATT)
08106 putc ('$', file);
08107 fprintf (file, "0x%08lx", l);
08108 }
08109
08110
08111 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
08112 {
08113 char dstr[30];
08114
08115 real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
08116 fprintf (file, "%s", dstr);
08117 }
08118
08119 else if (GET_CODE (x) == CONST_DOUBLE
08120 && GET_MODE (x) == XFmode)
08121 {
08122 char dstr[30];
08123
08124 real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
08125 fprintf (file, "%s", dstr);
08126 }
08127
08128 else
08129 {
08130
08131
08132
08133 if (GET_CODE (x) == CONST_VECTOR)
08134 {
08135 gcc_assert (x == CONST0_RTX (GET_MODE (x)));
08136 x = const0_rtx;
08137 }
08138
08139 if (code != 'P')
08140 {
08141 if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
08142 {
08143 if (ASSEMBLER_DIALECT == ASM_ATT)
08144 putc ('$', file);
08145 }
08146 else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
08147 || GET_CODE (x) == LABEL_REF)
08148 {
08149 if (ASSEMBLER_DIALECT == ASM_ATT)
08150 putc ('$', file);
08151 else
08152 fputs ("OFFSET FLAT:", file);
08153 }
08154 }
08155 if (GET_CODE (x) == CONST_INT)
08156 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
08157 else if (flag_pic)
08158 output_pic_addr_const (file, x, code);
08159 else
08160 output_addr_const (file, x);
08161 }
08162 }
08163
08164
08165
08166 void
08167 print_operand_address (FILE *file, rtx addr)
08168 {
08169 struct ix86_address parts;
08170 rtx base, index, disp;
08171 int scale;
08172 int ok = ix86_decompose_address (addr, &parts);
08173
08174 gcc_assert (ok);
08175
08176 base = parts.base;
08177 index = parts.index;
08178 disp = parts.disp;
08179 scale = parts.scale;
08180
08181 switch (parts.seg)
08182 {
08183 case SEG_DEFAULT:
08184 break;
08185 case SEG_FS:
08186 case SEG_GS:
08187 if (USER_LABEL_PREFIX[0] == 0)
08188 putc ('%', file);
08189 fputs ((parts.seg == SEG_FS ? "fs:" : "gs:"), file);
08190 break;
08191 default:
08192 gcc_unreachable ();
08193 }
08194
08195 if (!base && !index)
08196 {
08197
08198
08199 if (GET_CODE (disp) == CONST_INT)
08200 {
08201 if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT)
08202 {
08203 if (USER_LABEL_PREFIX[0] == 0)
08204 putc ('%', file);
08205 fputs ("ds:", file);
08206 }
08207 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
08208 }
08209 else if (flag_pic)
08210 output_pic_addr_const (file, disp, 0);
08211 else
08212 output_addr_const (file, disp);
08213
08214
08215 if (TARGET_64BIT)
08216 {
08217 if (GET_CODE (disp) == CONST
08218 && GET_CODE (XEXP (disp, 0)) == PLUS
08219 && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
08220 disp = XEXP (XEXP (disp, 0), 0);
08221 if (GET_CODE (disp) == LABEL_REF
08222 || (GET_CODE (disp) == SYMBOL_REF
08223 && SYMBOL_REF_TLS_MODEL (disp) == 0))
08224 fputs ("(%rip)", file);
08225 }
08226 }
08227 else
08228 {
08229 if (ASSEMBLER_DIALECT == ASM_ATT)
08230 {
08231 if (disp)
08232 {
08233 if (flag_pic)
08234 output_pic_addr_const (file, disp, 0);
08235 else if (GET_CODE (disp) == LABEL_REF)
08236 output_asm_label (disp);
08237 else
08238 output_addr_const (file, disp);
08239 }
08240
08241 putc ('(', file);
08242 if (base)
08243 print_reg (base, 0, file);
08244 if (index)
08245 {
08246 putc (',', file);
08247 print_reg (index, 0, file);
08248 if (scale != 1)
08249 fprintf (file, ",%d", scale);
08250 }
08251 putc (')', file);
08252 }
08253 else
08254 {
08255 rtx offset = NULL_RTX;
08256
08257 if (disp)
08258 {
08259
08260 if (GET_CODE (disp) == CONST
08261 && GET_CODE (XEXP (disp, 0)) == PLUS
08262 && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
08263 {
08264 offset = XEXP (XEXP (disp, 0), 1);
08265 disp = gen_rtx_CONST (VOIDmode,
08266 XEXP (XEXP (disp, 0), 0));
08267 }
08268
08269 if (flag_pic)
08270 output_pic_addr_const (file, disp, 0);
08271 else if (GET_CODE (disp) == LABEL_REF)
08272 output_asm_label (disp);
08273 else if (GET_CODE (disp) == CONST_INT)
08274 offset = disp;
08275 else
08276 output_addr_const (file, disp);
08277 }
08278
08279 putc ('[', file);
08280 if (base)
08281 {
08282 print_reg (base, 0, file);
08283 if (offset)
08284 {
08285 if (INTVAL (offset) >= 0)
08286 putc ('+', file);
08287 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (offset));
08288 }
08289 }
08290 else if (offset)
08291 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (offset));
08292 else
08293 putc ('0', file);
08294
08295 if (index)
08296 {
08297 putc ('+', file);
08298 print_reg (index, 0, file);
08299 if (scale != 1)
08300 fprintf (file, "*%d", scale);
08301 }
08302 putc (']', file);
08303 }
08304 }
08305 }
08306
08307 bool
08308 output_addr_const_extra (FILE *file, rtx x)
08309 {
08310 rtx op;
08311
08312 if (GET_CODE (x) != UNSPEC)
08313 return false;
08314
08315 op = XVECEXP (x, 0, 0);
08316 switch (XINT (x, 1))
08317 {
08318 case UNSPEC_GOTTPOFF:
08319 output_addr_const (file, op);
08320
08321 fputs ("@GOTTPOFF", file);
08322 break;
08323 case UNSPEC_TPOFF:
08324 output_addr_const (file, op);
08325 fputs ("@TPOFF", file);
08326 break;
08327 case UNSPEC_NTPOFF:
08328 output_addr_const (file, op);
08329 if (TARGET_64BIT)
08330 fputs ("@TPOFF", file);
08331 else
08332 fputs ("@NTPOFF", file);
08333 break;
08334 case UNSPEC_DTPOFF:
08335 output_addr_const (file, op);
08336 fputs ("@DTPOFF", file);
08337 break;
08338 case UNSPEC_GOTNTPOFF:
08339 output_addr_const (file, op);
08340 if (TARGET_64BIT)
08341 fputs ("@GOTTPOFF(%rip)", file);
08342 else
08343 fputs ("@GOTNTPOFF", file);
08344 break;
08345 case UNSPEC_INDNTPOFF:
08346 output_addr_const (file, op);
08347 fputs ("@INDNTPOFF", file);
08348 break;
08349
08350 default:
08351 return false;
08352 }
08353
08354 return true;
08355 }
08356
08357
08358
08359
08360
08361
08362
08363 void
08364 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
08365 {
08366 while (num--)
08367 {
08368 rtx op = operands[num];
08369
08370
08371
08372 if (GET_CODE (op) == MEM)
08373 {
08374 lo_half[num] = adjust_address (op, SImode, 0);
08375 hi_half[num] = adjust_address (op, SImode, 4);
08376 }
08377 else
08378 {
08379 lo_half[num] = simplify_gen_subreg (SImode, op,
08380 GET_MODE (op) == VOIDmode
08381 ? DImode : GET_MODE (op), 0);
08382 hi_half[num] = simplify_gen_subreg (SImode, op,
08383 GET_MODE (op) == VOIDmode
08384 ? DImode : GET_MODE (op), 4);
08385 }
08386 }
08387 }
08388
08389
08390
08391
08392
08393
08394 void
08395 split_ti (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
08396 {
08397 while (num--)
08398 {
08399 rtx op = operands[num];
08400
08401
08402
08403 if (GET_CODE (op) == MEM)
08404 {
08405 lo_half[num] = adjust_address (op, DImode, 0);
08406 hi_half[num] = adjust_address (op, DImode, 8);
08407 }
08408 else
08409 {
08410 lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0);
08411 hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8);
08412 }
08413 }
08414 }
08415
08416
08417
08418
08419
08420
08421
08422
08423
08424 #ifndef SYSV386_COMPAT
08425
08426
08427
08428
08429
08430 #define SYSV386_COMPAT 1
08431 #endif
08432
08433 const char *
08434 output_387_binary_op (rtx insn, rtx *operands)
08435 {
08436 static char buf[30];
08437 const char *p;
08438 const char *ssep;
08439 int is_sse = SSE_REG_P (operands[0]) || SSE_REG_P (operands[1]) || SSE_REG_P (operands[2]);
08440
08441 #ifdef ENABLE_CHECKING
08442
08443
08444 if (STACK_REG_P (operands[0])
08445 && ((REG_P (operands[1])
08446 && REGNO (operands[0]) == REGNO (operands[1])
08447 && (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM))
08448 || (REG_P (operands[2])
08449 && REGNO (operands[0]) == REGNO (operands[2])
08450 && (STACK_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)))
08451 && (STACK_TOP_P (operands[1]) || STACK_TOP_P (operands[2])))
08452 ;
08453 else
08454 gcc_assert (is_sse);
08455 #endif
08456
08457 switch (GET_CODE (operands[3]))
08458 {
08459 case PLUS:
08460 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
08461 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
08462 p = "fiadd";
08463 else
08464 p = "fadd";
08465 ssep = "add";
08466 break;
08467
08468 case MINUS:
08469 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
08470 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
08471 p = "fisub";
08472 else
08473 p = "fsub";
08474 ssep = "sub";
08475 break;
08476
08477 case MULT:
08478 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
08479 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
08480 p = "fimul";
08481 else
08482 p = "fmul";
08483 ssep = "mul";
08484 break;
08485
08486 case DIV:
08487 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
08488 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
08489 p = "fidiv";
08490 else
08491 p = "fdiv";
08492 ssep = "div";
08493 break;
08494
08495 default:
08496 gcc_unreachable ();
08497 }
08498
08499 if (is_sse)
08500 {
08501 strcpy (buf, ssep);
08502 if (GET_MODE (operands[0]) == SFmode)
08503 strcat (buf, "ss\t{%2, %0|%0, %2}");
08504 else
08505 strcat (buf, "sd\t{%2, %0|%0, %2}");
08506 return buf;
08507 }
08508 strcpy (buf, p);
08509
08510 switch (GET_CODE (operands[3]))
08511 {
08512 case MULT:
08513 case PLUS:
08514 if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
08515 {
08516 rtx temp = operands[2];
08517 operands[2] = operands[1];
08518 operands[1] = temp;
08519 }
08520
08521
08522
08523 if (GET_CODE (operands[2]) == MEM)
08524 {
08525 p = "%z2\t%2";
08526 break;
08527 }
08528
08529 if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
08530 {
08531 if (STACK_TOP_P (operands[0]))
08532
08533
08534
08535
08536
08537
08538
08539 p = "p\t{%0, %2|%2, %0}";
08540 else
08541 p = "p\t{%2, %0|%0, %2}";
08542 break;
08543 }
08544
08545 if (STACK_TOP_P (operands[0]))
08546 p = "\t{%y2, %0|%0, %y2}";
08547 else
08548 p = "\t{%2, %0|%0, %2}";
08549 break;
08550
08551 case MINUS:
08552 case DIV:
08553 if (GET_CODE (operands[1]) == MEM)
08554 {
08555 p = "r%z1\t%1";
08556 break;
08557 }
08558
08559 if (GET_CODE (operands[2]) == MEM)
08560 {
08561 p = "%z2\t%2";
08562 break;
08563 }
08564
08565 if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
08566 {
08567 #if SYSV386_COMPAT
08568
08569
08570
08571
08572
08573
08574 if (STACK_TOP_P (operands[0]))
08575 p = "{p\t%0, %2|rp\t%2, %0}";
08576 else
08577 p = "{rp\t%2, %0|p\t%0, %2}";
08578 #else
08579 if (STACK_TOP_P (operands[0]))
08580
08581 p = "rp\t{%0, %2|%2, %0}";
08582 else
08583 p = "p\t{%2, %0|%0, %2}";
08584 #endif
08585 break;
08586 }
08587
08588 if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
08589 {
08590 #if SYSV386_COMPAT
08591 if (STACK_TOP_P (operands[0]))
08592 p = "{rp\t%0, %1|p\t%1, %0}";
08593 else
08594 p = "{p\t%1, %0|rp\t%0, %1}";
08595 #else
08596 if (STACK_TOP_P (operands[0]))
08597 p = "p\t{%0, %1|%1, %0}";
08598 else
08599 p = "rp\t{%1, %0|%0, %1}";
08600 #endif
08601 break;
08602 }
08603
08604 if (STACK_TOP_P (operands[0]))
08605 {
08606 if (STACK_TOP_P (operands[1]))
08607 p = "\t{%y2, %0|%0, %y2}";
08608 else
08609 p = "r\t{%y1, %0|%0, %y1}";
08610 break;
08611 }
08612 else if (STACK_TOP_P (operands[1]))
08613 {
08614 #if SYSV386_COMPAT
08615 p = "{\t%1, %0|r\t%0, %1}";
08616 #else
08617 p = "r\t{%1, %0|%0, %1}";
08618 #endif
08619 }
08620 else
08621 {
08622 #if SYSV386_COMPAT
08623 p = "{r\t%2, %0|\t%0, %2}";
08624 #else
08625 p = "\t{%2, %0|%0, %2}";
08626 #endif
08627 }
08628 break;
08629
08630 default:
08631 gcc_unreachable ();
08632 }
08633
08634 strcat (buf, p);
08635 return buf;
08636 }
08637
08638
08639
08640 int
08641 ix86_mode_needed (int entity, rtx insn)
08642 {
08643 enum attr_i387_cw mode;
08644
08645
08646
08647
08648
08649
08650 if (CALL_P (insn)
08651 || (NONJUMP_INSN_P (insn)
08652 && (asm_noperands (PATTERN (insn)) >= 0
08653 || GET_CODE (PATTERN (insn)) == ASM_INPUT)))
08654 return I387_CW_UNINITIALIZED;
08655
08656 if (recog_memoized (insn) < 0)
08657 return I387_CW_ANY;
08658
08659 mode = get_attr_i387_cw (insn);
08660
08661 switch (entity)
08662 {
08663 case I387_TRUNC:
08664 if (mode == I387_CW_TRUNC)
08665 return mode;
08666 break;
08667
08668 case I387_FLOOR:
08669 if (mode == I387_CW_FLOOR)
08670 return mode;
08671 break;
08672
08673 case I387_CEIL:
08674 if (mode == I387_CW_CEIL)
08675 return mode;
08676 break;
08677
08678 case I387_MASK_PM:
08679 if (mode == I387_CW_MASK_PM)
08680 return mode;
08681 break;
08682
08683 default:
08684 gcc_unreachable ();
08685 }
08686
08687 return I387_CW_ANY;
08688 }
08689
08690
08691
08692
08693
08694 void
08695 emit_i387_cw_initialization (int mode)
08696 {
08697 rtx stored_mode = assign_386_stack_local (HImode, SLOT_CW_STORED);
08698 rtx new_mode;
08699
08700 int slot;
08701
08702 rtx reg = gen_reg_rtx (HImode);
08703
08704 emit_insn (gen_x86_fnstcw_1 (stored_mode));
08705 emit_move_insn (reg, stored_mode);
08706
08707 if (TARGET_64BIT || TARGET_PARTIAL_REG_STALL || optimize_size)
08708 {
08709 switch (mode)
08710 {
08711 case I387_CW_TRUNC:
08712
08713 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0c00)));
08714 slot = SLOT_CW_TRUNC;
08715 break;
08716
08717 case I387_CW_FLOOR:
08718
08719 emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
08720 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0400)));
08721 slot = SLOT_CW_FLOOR;
08722 break;
08723
08724 case I387_CW_CEIL:
08725
08726 emit_insn (gen_andhi3 (reg, reg, GEN_INT (~0x0c00)));
08727 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0800)));
08728 slot = SLOT_CW_CEIL;
08729 break;
08730
08731 case I387_CW_MASK_PM:
08732
08733 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0020)));
08734 slot = SLOT_CW_MASK_PM;
08735 break;
08736
08737 default:
08738 gcc_unreachable ();
08739 }
08740 }
08741 else
08742 {
08743 switch (mode)
08744 {
08745 case I387_CW_TRUNC:
08746
08747 emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0xc)));
08748 slot = SLOT_CW_TRUNC;
08749 break;
08750
08751 case I387_CW_FLOOR:
08752
08753 emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x4)));
08754 slot = SLOT_CW_FLOOR;
08755 break;
08756
08757 case I387_CW_CEIL:
08758
08759 emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0x8)));
08760 slot = SLOT_CW_CEIL;
08761 break;
08762
08763 case I387_CW_MASK_PM:
08764
08765 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0x0020)));
08766 slot = SLOT_CW_MASK_PM;
08767 break;
08768
08769 default:
08770 gcc_unreachable ();
08771 }
08772 }
08773
08774 gcc_assert (slot < MAX_386_STACK_LOCALS);
08775
08776 new_mode = assign_386_stack_local (HImode, slot);
08777 emit_move_insn (new_mode, reg);
08778 }
08779
08780
08781
08782
08783
08784 const char *
08785 output_fix_trunc (rtx insn, rtx *operands, int fisttp)
08786 {
08787 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
08788 int dimode_p = GET_MODE (operands[0]) == DImode;
08789 int round_mode = get_attr_i387_cw (insn);
08790
08791
08792
08793
08794 if ((dimode_p || fisttp) && !stack_top_dies)
08795 output_asm_insn ("fld\t%y1", operands);
08796
08797 gcc_assert (STACK_TOP_P (operands[1]));
08798 gcc_assert (GET_CODE (operands[0]) == MEM);
08799
08800 if (fisttp)
08801 output_asm_insn ("fisttp%z0\t%0", operands);
08802 else
08803 {
08804 if (round_mode != I387_CW_ANY)
08805 output_asm_insn ("fldcw\t%3", operands);
08806 if (stack_top_dies || dimode_p)
08807 output_asm_insn ("fistp%z0\t%0", operands);
08808 else
08809 output_asm_insn ("fist%z0\t%0", operands);
08810 if (round_mode != I387_CW_ANY)
08811 output_asm_insn ("fldcw\t%2", operands);
08812 }
08813
08814 return "";
08815 }
08816
08817
08818
08819
08820
08821 static const char *
08822 output_387_ffreep (rtx *operands ATTRIBUTE_UNUSED, int opno)
08823 {
08824 if (TARGET_USE_FFREEP)
08825 #if HAVE_AS_IX86_FFREEP
08826 return opno ? "ffreep\t%y1" : "ffreep\t%y0";
08827 #else
08828 switch (REGNO (operands[opno]))
08829 {
08830 case FIRST_STACK_REG + 0: return ".word\t0xc0df";
08831 case FIRST_STACK_REG + 1: return ".word\t0xc1df";
08832 case FIRST_STACK_REG + 2: return ".word\t0xc2df";
08833 case FIRST_STACK_REG + 3: return ".word\t0xc3df";
08834 case FIRST_STACK_REG + 4: return ".word\t0xc4df";
08835 case FIRST_STACK_REG + 5: return ".word\t0xc5df";
08836 case FIRST_STACK_REG + 6: return ".word\t0xc6df";
08837 case FIRST_STACK_REG + 7: return ".word\t0xc7df";
08838 }
08839 #endif
08840
08841 return opno ? "fstp\t%y1" : "fstp\t%y0";
08842 }
08843
08844
08845
08846
08847
08848 const char *
08849 output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
08850 {
08851 int stack_top_dies;
08852 rtx cmp_op0, cmp_op1;
08853 int is_sse = SSE_REG_P (operands[0]) || SSE_REG_P (operands[1]);
08854
08855 if (eflags_p)
08856 {
08857 cmp_op0 = operands[0];
08858 cmp_op1 = operands[1];
08859 }
08860 else
08861 {
08862 cmp_op0 = operands[1];
08863 cmp_op1 = operands[2];
08864 }
08865
08866 if (is_sse)
08867 {
08868 if (GET_MODE (operands[0]) == SFmode)
08869 if (unordered_p)
08870 return "ucomiss\t{%1, %0|%0, %1}";
08871 else
08872 return "comiss\t{%1, %0|%0, %1}";
08873 else
08874 if (unordered_p)
08875 return "ucomisd\t{%1, %0|%0, %1}";
08876 else
08877 return "comisd\t{%1, %0|%0, %1}";
08878 }
08879
08880 gcc_assert (STACK_TOP_P (cmp_op0));
08881
08882 stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
08883
08884 if (cmp_op1 == CONST0_RTX (GET_MODE (cmp_op1)))
08885 {
08886 if (stack_top_dies)
08887 {
08888 output_asm_insn ("ftst\n\tfnstsw\t%0", operands);
08889 return output_387_ffreep (operands, 1);
08890 }
08891 else
08892 return "ftst\n\tfnstsw\t%0";
08893 }
08894
08895 if (STACK_REG_P (cmp_op1)
08896 && stack_top_dies
08897 && find_regno_note (insn, REG_DEAD, REGNO (cmp_op1))
08898 && REGNO (cmp_op1) != FIRST_STACK_REG)
08899 {
08900
08901
08902
08903
08904 if (eflags_p)
08905 {
08906
08907
08908 if (unordered_p)
08909 output_asm_insn ("fucomip\t{%y1, %0|%0, %y1}", operands);
08910 else
08911 output_asm_insn ("fcomip\t{%y1, %0|%0, %y1}", operands);
08912 return output_387_ffreep (operands, 0);
08913 }
08914 else
08915 {
08916 if (unordered_p)
08917 return "fucompp\n\tfnstsw\t%0";
08918 else
08919 return "fcompp\n\tfnstsw\t%0";
08920 }
08921 }
08922 else
08923 {
08924
08925
08926 static const char * const alt[16] =
08927 {
08928 "fcom%z2\t%y2\n\tfnstsw\t%0",
08929 "fcomp%z2\t%y2\n\tfnstsw\t%0",
08930 "fucom%z2\t%y2\n\tfnstsw\t%0",
08931 "fucomp%z2\t%y2\n\tfnstsw\t%0",
08932
08933 "ficom%z2\t%y2\n\tfnstsw\t%0",
08934 "ficomp%z2\t%y2\n\tfnstsw\t%0",
08935 NULL,
08936 NULL,
08937
08938 "fcomi\t{%y1, %0|%0, %y1}",
08939 "fcomip\t{%y1, %0|%0, %y1}",
08940 "fucomi\t{%y1, %0|%0, %y1}",
08941 "fucomip\t{%y1, %0|%0, %y1}",
08942
08943 NULL,
08944 NULL,
08945 NULL,
08946 NULL
08947 };
08948
08949 int mask;
08950 const char *ret;
08951
08952 mask = eflags_p << 3;
08953 mask |= (GET_MODE_CLASS (GET_MODE (cmp_op1)) == MODE_INT) << 2;
08954 mask |= unordered_p << 1;
08955 mask |= stack_top_dies;
08956
08957 gcc_assert (mask < 16);
08958 ret = alt[mask];
08959 gcc_assert (ret);
08960
08961 return ret;
08962 }
08963 }
08964
08965 void
08966 ix86_output_addr_vec_elt (FILE *file, int value)
08967 {
08968 const char *directive = ASM_LONG;
08969
08970 #ifdef ASM_QUAD
08971 if (TARGET_64BIT)
08972 directive = ASM_QUAD;
08973 #else
08974 gcc_assert (!TARGET_64BIT);
08975 #endif
08976
08977 fprintf (file, "%s%s%d\n", directive, LPREFIX, value);
08978 }
08979
08980 void
08981 ix86_output_addr_diff_elt (FILE *file, int value, int rel)
08982 {
08983 if (TARGET_64BIT)
08984 fprintf (file, "%s%s%d-%s%d\n",
08985 ASM_LONG, LPREFIX, value, LPREFIX, rel);
08986 else if (HAVE_AS_GOTOFF_IN_DATA)
08987 fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
08988 #if TARGET_MACHO
08989 else if (TARGET_MACHO)
08990 {
08991 fprintf (file, "%s%s%d-", ASM_LONG, LPREFIX, value);
08992 machopic_output_function_base_name (file);
08993 fprintf(file, "\n");
08994 }
08995 #endif
08996 else
08997 asm_fprintf (file, "%s%U%s+[.-%s%d]\n",
08998 ASM_LONG, GOT_SYMBOL_NAME, LPREFIX, value);
08999 }
09000
09001
09002
09003
09004 void
09005 ix86_expand_clear (rtx dest)
09006 {
09007 rtx tmp;
09008
09009
09010 gcc_assert (reload_completed);
09011
09012
09013 if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
09014 dest = gen_rtx_REG (SImode, REGNO (dest));
09015
09016 tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
09017
09018
09019 if (reload_completed && (!TARGET_USE_MOV0 || optimize_size))
09020 {
09021 rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, 17));
09022 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
09023 }
09024
09025 emit_insn (tmp);
09026 }
09027
09028
09029
09030
09031 rtx
09032 maybe_get_pool_constant (rtx x)
09033 {
09034 x = ix86_delegitimize_address (XEXP (x, 0));
09035
09036 if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
09037 return get_pool_constant (x);
09038
09039 return NULL_RTX;
09040 }
09041
09042 void
09043 ix86_expand_move (enum machine_mode mode, rtx operands[])
09044 {
09045 int strict = (reload_in_progress || reload_completed);
09046 rtx op0, op1;
09047 enum tls_model model;
09048
09049 op0 = operands[0];
09050 op1 = operands[1];
09051
09052 if (GET_CODE (op1) == SYMBOL_REF)
09053 {
09054 model = SYMBOL_REF_TLS_MODEL (op1);
09055 if (model)
09056 {
09057 op1 = legitimize_tls_address (op1, model, true);
09058 op1 = force_operand (op1, op0);
09059 if (op1 == op0)
09060 return;
09061 }
09062 }
09063 else if (GET_CODE (op1) == CONST
09064 && GET_CODE (XEXP (op1, 0)) == PLUS
09065 && GET_CODE (XEXP (XEXP (op1, 0), 0)) == SYMBOL_REF)
09066 {
09067 model = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (op1, 0), 0));
09068 if (model)
09069 {
09070 rtx addend = XEXP (XEXP (op1, 0), 1);
09071 op1 = legitimize_tls_address (XEXP (XEXP (op1, 0), 0), model, true);
09072 op1 = force_operand (op1, NULL);
09073 op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
09074 op0, 1, OPTAB_DIRECT);
09075 if (op1 == op0)
09076 return;
09077 }
09078 }
09079
09080 if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
09081 {
09082 if (TARGET_MACHO && !TARGET_64BIT)
09083 {
09084 #if TARGET_MACHO
09085 if (MACHOPIC_PURE)
09086 {
09087 rtx temp = ((reload_in_progress
09088 || ((op0 && GET_CODE (op0) == REG)
09089 && mode == Pmode))
09090 ? op0 : gen_reg_rtx (Pmode));
09091 op1 = machopic_indirect_data_reference (op1, temp);
09092 op1 = machopic_legitimize_pic_address (op1, mode,
09093 temp == op1 ? 0 : temp);
09094 }
09095 else if (MACHOPIC_INDIRECT)
09096 op1 = machopic_indirect_data_reference (op1, 0);
09097 if (op0 == op1)
09098 return;
09099 #endif
09100 }
09101 else
09102 {
09103 if (GET_CODE (op0) == MEM)
09104 op1 = force_reg (Pmode, op1);
09105 else
09106 op1 = legitimize_address (op1, op1, Pmode);
09107 }
09108 }
09109 else
09110 {
09111 if (GET_CODE (op0) == MEM
09112 && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
09113 || !push_operand (op0, mode))
09114 && GET_CODE (op1) == MEM)
09115 op1 = force_reg (mode, op1);
09116
09117 if (push_operand (op0, mode)
09118 && ! general_no_elim_operand (op1, mode))
09119 op1 = copy_to_mode_reg (mode, op1);
09120
09121
09122
09123 if (TARGET_64BIT && mode == DImode
09124 && immediate_operand (op1, mode)
09125 && !x86_64_zext_immediate_operand (op1, VOIDmode)
09126 && !register_operand (op0, mode)
09127 && optimize && !reload_completed && !reload_in_progress)
09128 op1 = copy_to_mode_reg (mode, op1);
09129
09130 if (FLOAT_MODE_P (mode))
09131 {
09132
09133
09134
09135
09136 if (strict)
09137 ;
09138 else if (GET_CODE (op1) == CONST_DOUBLE)
09139 {
09140 op1 = validize_mem (force_const_mem (mode, op1));
09141 if (!register_operand (op0, mode))
09142 {
09143 rtx temp = gen_reg_rtx (mode);
09144 emit_insn (gen_rtx_SET (VOIDmode, temp, op1));
09145 emit_move_insn (op0, temp);
09146 return;
09147 }
09148 }
09149 }
09150 }
09151
09152 emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
09153 }
09154
09155 void
09156 ix86_expand_vector_move (enum machine_mode mode, rtx operands[])
09157 {
09158 rtx op0 = operands[0], op1 = operands[1];
09159
09160
09161
09162
09163
09164 if ((reload_in_progress | reload_completed) == 0
09165 && register_operand (op0, mode)
09166 && CONSTANT_P (op1)
09167 && standard_sse_constant_p (op1) <= 0)
09168 op1 = validize_mem (force_const_mem (mode, op1));
09169
09170
09171 if (!no_new_pseudos
09172 && !register_operand (op0, mode)
09173 && !register_operand (op1, mode))
09174 {
09175 emit_move_insn (op0, force_reg (GET_MODE (op0), op1));
09176 return;
09177 }
09178
09179 emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
09180 }
09181
09182
09183
09184
09185 void
09186 ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
09187 {
09188 rtx op0, op1, m;
09189
09190 op0 = operands[0];
09191 op1 = operands[1];
09192
09193 if (MEM_P (op1))
09194 {
09195
09196 if (optimize_size)
09197 {
09198 op0 = gen_lowpart (V4SFmode, op0);
09199 op1 = gen_lowpart (V4SFmode, op1);
09200 emit_insn (gen_sse_movups (op0, op1));
09201 return;
09202 }
09203
09204
09205
09206
09207 if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
09208 {
09209 op0 = gen_lowpart (V16QImode, op0);
09210 op1 = gen_lowpart (V16QImode, op1);
09211 emit_insn (gen_sse2_movdqu (op0, op1));
09212 return;
09213 }
09214
09215 if (TARGET_SSE2 && mode == V2DFmode)
09216 {
09217 rtx zero;
09218
09219
09220
09221 if (TARGET_SSE_SPLIT_REGS)
09222 {
09223 emit_insn (gen_rtx_CLOBBER (VOIDmode, op0));
09224 zero = op0;
09225 }
09226 else
09227 {
09228
09229
09230
09231
09232
09233
09234
09235
09236 zero = CONST0_RTX (V2DFmode);
09237 }
09238
09239 m = adjust_address (op1, DFmode, 0);
09240 emit_insn (gen_sse2_loadlpd (op0, zero, m));
09241 m = adjust_address (op1, DFmode, 8);
09242 emit_insn (gen_sse2_loadhpd (op0, op0, m));
09243 }
09244 else
09245 {
09246 if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
09247 emit_move_insn (op0, CONST0_RTX (mode));
09248 else
09249 emit_insn (gen_rtx_CLOBBER (VOIDmode, op0));
09250
09251 if (mode != V4SFmode)
09252 op0 = gen_lowpart (V4SFmode, op0);
09253 m = adjust_address (op1, V2SFmode, 0);
09254 emit_insn (gen_sse_loadlps (op0, op0, m));
09255 m = adjust_address (op1, V2SFmode, 8);
09256 emit_insn (gen_sse_loadhps (op0, op0, m));
09257 }
09258 }
09259 else if (MEM_P (op0))
09260 {
09261
09262 if (optimize_size)
09263 {
09264 op0 = gen_lowpart (V4SFmode, op0);
09265 op1 = gen_lowpart (V4SFmode, op1);
09266 emit_insn (gen_sse_movups (op0, op1));
09267 return;
09268 }
09269
09270
09271
09272 if (TARGET_SSE2 && !TARGET_SSE_TYPELESS_STORES
09273 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
09274 {
09275 op0 = gen_lowpart (V16QImode, op0);
09276 op1 = gen_lowpart (V16QImode, op1);
09277 emit_insn (gen_sse2_movdqu (op0, op1));
09278 return;
09279 }
09280
09281 if (TARGET_SSE2 && mode == V2DFmode)
09282 {
09283 m = adjust_address (op0, DFmode, 0);
09284 emit_insn (gen_sse2_storelpd (m, op1));
09285 m = adjust_address (op0, DFmode, 8);
09286 emit_insn (gen_sse2_storehpd (m, op1));
09287 }
09288 else
09289 {
09290 if (mode != V4SFmode)
09291 op1 = gen_lowpart (V4SFmode, op1);
09292 m = adjust_address (op0, V2SFmode, 0);
09293 emit_insn (gen_sse_storelps (m, op1));
09294 m = adjust_address (op0, V2SFmode, 8);
09295 emit_insn (gen_sse_storehps (m, op1));
09296 }
09297 }
09298 else
09299 gcc_unreachable ();
09300 }
09301
09302
09303
09304
09305
09306 void
09307 ix86_expand_push (enum machine_mode mode, rtx x)
09308 {
09309 rtx tmp;
09310
09311 tmp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
09312 GEN_INT (-GET_MODE_SIZE (mode)),
09313 stack_pointer_rtx, 1, OPTAB_DIRECT);
09314 if (tmp != stack_pointer_rtx)
09315 emit_move_insn (stack_pointer_rtx, tmp);
09316
09317 tmp = gen_rtx_MEM (mode, stack_pointer_rtx);
09318 emit_move_insn (tmp, x);
09319 }
09320
09321
09322
09323
09324
09325 rtx
09326 ix86_fixup_binary_operands (enum rtx_code code, enum machine_mode mode,
09327 rtx operands[])
09328 {
09329 int matching_memory;
09330 rtx src1, src2, dst;
09331
09332 dst = operands[0];
09333 src1 = operands[1];
09334 src2 = operands[2];
09335
09336
09337 if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
09338 && (rtx_equal_p (dst, src2)
09339 || immediate_operand (src1, mode)))
09340 {
09341 rtx temp = src1;
09342 src1 = src2;
09343 src2 = temp;
09344 }
09345
09346
09347
09348 matching_memory = 0;
09349 if (GET_CODE (dst) == MEM)
09350 {
09351 if (rtx_equal_p (dst, src1))
09352 matching_memory = 1;
09353 else if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
09354 && rtx_equal_p (dst, src2))
09355 matching_memory = 2;
09356 else
09357 dst = gen_reg_rtx (mode);
09358 }
09359
09360
09361 if (GET_CODE (src1) == MEM && GET_CODE (src2) == MEM)
09362 {
09363 if (matching_memory != 2)
09364 src2 = force_reg (mode, src2);
09365 else
09366 src1 = force_reg (mode, src1);
09367 }
09368
09369
09370
09371 if ((CONSTANT_P (src1)
09372 || (!matching_memory && GET_CODE (src1) == MEM))
09373 && GET_RTX_CLASS (code) != RTX_COMM_ARITH)
09374 src1 = force_reg (mode, src1);
09375
09376 src1 = operands[1] = src1;
09377 src2 = operands[2] = src2;
09378 return dst;
09379 }
09380
09381
09382
09383
09384 void
09385 ix86_fixup_binary_operands_no_copy (enum rtx_code code,
09386 enum machine_mode mode, rtx operands[])
09387 {
09388 rtx dst = ix86_fixup_binary_operands (code, mode, operands);
09389 gcc_assert (dst == operands[0]);
09390 }
09391
09392
09393
09394
09395
09396 void
09397 ix86_expand_binary_operator (enum rtx_code code, enum machine_mode mode,
09398 rtx operands[])
09399 {
09400 rtx src1, src2, dst, op, clob;
09401
09402 dst = ix86_fixup_binary_operands (code, mode, operands);
09403 src1 = operands[1];
09404 src2 = operands[2];
09405
09406
09407
09408 op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, mode, src1, src2));
09409 if (reload_in_progress)
09410 {
09411
09412
09413 gcc_assert (code == PLUS);
09414 emit_insn (op);
09415 }
09416 else
09417 {
09418 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
09419 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
09420 }
09421
09422
09423 if (dst != operands[0])
09424 emit_move_insn (operands[0], dst);
09425 }
09426
09427
09428
09429
09430 int
09431 ix86_binary_operator_ok (enum rtx_code code,
09432 enum machine_mode mode ATTRIBUTE_UNUSED,
09433 rtx operands[3])
09434 {
09435
09436 if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
09437 return 0;
09438
09439 if (CONSTANT_P (operands[1]) && GET_RTX_CLASS (code) != RTX_COMM_ARITH)
09440 return 0;
09441
09442 if (GET_CODE (operands[0]) == MEM
09443 && ! (rtx_equal_p (operands[0], operands[1])
09444 || (GET_RTX_CLASS (code) == RTX_COMM_ARITH
09445 && rtx_equal_p (operands[0], operands[2]))))
09446 return 0;
09447
09448
09449 if (GET_CODE (operands[1]) == MEM
09450 && GET_RTX_CLASS (code) != RTX_COMM_ARITH
09451 && ! rtx_equal_p (operands[0], operands[1]))
09452 return 0;
09453 return 1;
09454 }
09455
09456
09457
09458
09459
09460 void
09461 ix86_expand_unary_operator (enum rtx_code code, enum machine_mode mode,
09462 rtx operands[])
09463 {
09464 int matching_memory;
09465 rtx src, dst, op, clob;
09466
09467 dst = operands[0];
09468 src = operands[1];
09469
09470
09471
09472 matching_memory = 0;
09473 if (MEM_P (dst))
09474 {
09475 if (rtx_equal_p (dst, src))
09476 matching_memory = 1;
09477 else
09478 dst = gen_reg_rtx (mode);
09479 }
09480
09481
09482 if (MEM_P (src) && !matching_memory)
09483 src = force_reg (mode, src);
09484
09485
09486
09487 op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_e (code, mode, src));
09488 if (reload_in_progress || code == NOT)
09489 {
09490
09491
09492 gcc_assert (code == NOT);
09493 emit_insn (op);
09494 }
09495 else
09496 {
09497 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
09498 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
09499 }
09500
09501
09502 if (dst != operands[0])
09503 emit_move_insn (operands[0], dst);
09504 }
09505
09506
09507
09508
09509 int
09510 ix86_unary_operator_ok (enum rtx_code code ATTRIBUTE_UNUSED,
09511 enum machine_mode mode ATTRIBUTE_UNUSED,
09512 rtx operands[2] ATTRIBUTE_UNUSED)
09513 {
09514
09515 if ((GET_CODE (operands[0]) == MEM
09516 || GET_CODE (operands[1]) == MEM)
09517 && ! rtx_equal_p (operands[0], operands[1]))
09518 return FALSE;
09519 return TRUE;
09520 }
09521
09522
09523
09524
09525
09526
09527 rtx
09528 ix86_build_signbit_mask (enum machine_mode mode, bool vect, bool invert)
09529 {
09530 enum machine_mode vec_mode;
09531 HOST_WIDE_INT hi, lo;
09532 int shift = 63;
09533 rtvec v;
09534 rtx mask;
09535
09536
09537 if (mode == SFmode)
09538 lo = 0x80000000, hi = lo < 0;
09539 else if (HOST_BITS_PER_WIDE_INT >= 64)
09540 lo = (HOST_WIDE_INT)1 << shift, hi = -1;
09541 else
09542 lo = 0, hi = (HOST_WIDE_INT)1 << (shift - HOST_BITS_PER_WIDE_INT);
09543
09544 if (invert)
09545 lo = ~lo, hi = ~hi;
09546
09547
09548 mask = immed_double_const (lo, hi, mode == SFmode ? SImode : DImode);
09549 mask = gen_lowpart (mode, mask);
09550
09551 if (mode == SFmode)
09552 {
09553 if (vect)
09554 v = gen_rtvec (4, mask, mask, mask, mask);
09555 else
09556 v = gen_rtvec (4, mask, CONST0_RTX (SFmode),
09557 CONST0_RTX (SFmode), CONST0_RTX (SFmode));
09558 vec_mode = V4SFmode;
09559 }
09560 else
09561 {
09562 if (vect)
09563 v = gen_rtvec (2, mask, mask);
09564 else
09565 v = gen_rtvec (2, mask, CONST0_RTX (DFmode));
09566 vec_mode = V2DFmode;
09567 }
09568
09569 return force_reg (vec_mode, gen_rtx_CONST_VECTOR (vec_mode, v));
09570 }
09571
09572
09573
09574 void
09575 ix86_expand_fp_absneg_operator (enum rtx_code code, enum machine_mode mode,
09576 rtx operands[])
09577 {
09578 rtx mask, set, use, clob, dst, src;
09579 bool matching_memory;
09580 bool use_sse = false;
09581 bool vector_mode = VECTOR_MODE_P (mode);
09582 enum machine_mode elt_mode = mode;
09583
09584 if (vector_mode)
09585 {
09586 elt_mode = GET_MODE_INNER (mode);
09587 use_sse = true;
09588 }
09589 else if (TARGET_SSE_MATH)
09590 use_sse = SSE_FLOAT_MODE_P (mode);
09591
09592
09593
09594 if (use_sse)
09595 mask = ix86_build_signbit_mask (elt_mode, vector_mode, code == ABS);
09596 else
09597 mask = NULL_RTX;
09598
09599 dst = operands[0];
09600 src = operands[1];
09601
09602
09603
09604 matching_memory = false;
09605 if (MEM_P (dst))
09606 {
09607 if (use_sse && rtx_equal_p (dst, src))
09608 matching_memory = true;
09609 else
09610 dst = gen_reg_rtx (mode);
09611 }
09612 if (MEM_P (src) && !matching_memory)
09613 src = force_reg (mode, src);
09614
09615 if (vector_mode)
09616 {
09617 set = gen_rtx_fmt_ee (code == NEG ? XOR : AND, mode, src, mask);
09618 set = gen_rtx_SET (VOIDmode, dst, set);
09619 emit_insn (set);
09620 }
09621 else
09622 {
09623 set = gen_rtx_fmt_e (code, mode, src);
09624 set = gen_rtx_SET (VOIDmode, dst, set);
09625 if (mask)
09626 {
09627 use = gen_rtx_USE (VOIDmode, mask);
09628 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
09629 emit_insn (gen_rtx_PARALLEL (VOIDmode,
09630 gen_rtvec (3, set, use, clob)));
09631 }
09632 else
09633 emit_insn (set);
09634 }
09635
09636 if (dst != operands[0])
09637 emit_move_insn (operands[0], dst);
09638 }
09639
09640
09641
09642 void
09643 ix86_expand_copysign (rtx operands[])
09644 {
09645 enum machine_mode mode, vmode;
09646 rtx dest, op0, op1, mask, nmask;
09647
09648 dest = operands[0];
09649 op0 = operands[1];
09650 op1 = operands[2];
09651
09652 mode = GET_MODE (dest);
09653 vmode = mode == SFmode ? V4SFmode : V2DFmode;
09654
09655 if (GET_CODE (op0) == CONST_DOUBLE)
09656 {
09657 rtvec v;
09658
09659 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
09660 op0 = simplify_unary_operation (ABS, mode, op0, mode);
09661
09662 if (op0 == CONST0_RTX (mode))
09663 op0 = CONST0_RTX (vmode);
09664 else
09665 {
09666 if (mode == SFmode)
09667 v = gen_rtvec (4, op0, CONST0_RTX (SFmode),
09668 CONST0_RTX (SFmode), CONST0_RTX (SFmode));
09669 else
09670 v = gen_rtvec (2, op0, CONST0_RTX (DFmode));
09671 op0 = force_reg (vmode, gen_rtx_CONST_VECTOR (vmode, v));
09672 }
09673
09674 mask = ix86_build_signbit_mask (mode, 0, 0);
09675
09676 if (mode == SFmode)
09677 emit_insn (gen_copysignsf3_const (dest, op0, op1, mask));
09678 else
09679 emit_insn (gen_copysigndf3_const (dest, op0, op1, mask));
09680 }
09681 else
09682 {
09683 nmask = ix86_build_signbit_mask (mode, 0, 1);
09684 mask = ix86_build_signbit_mask (mode, 0, 0);
09685
09686 if (mode == SFmode)
09687 emit_insn (gen_copysignsf3_var (dest, NULL, op0, op1, nmask, mask));
09688 else
09689 emit_insn (gen_copysigndf3_var (dest, NULL, op0, op1, nmask, mask));
09690 }
09691 }
09692
09693
09694
09695
09696 void
09697 ix86_split_copysign_const (rtx operands[])
09698 {
09699 enum machine_mode mode, vmode;
09700 rtx dest, op0, op1, mask, x;
09701
09702 dest = operands[0];
09703 op0 = operands[1];
09704 op1 = operands[2];
09705 mask = operands[3];
09706
09707 mode = GET_MODE (dest);
09708 vmode = GET_MODE (mask);
09709
09710 dest = simplify_gen_subreg (vmode, dest, mode, 0);
09711 x = gen_rtx_AND (vmode, dest, mask);
09712 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
09713
09714 if (op0 != CONST0_RTX (vmode))
09715 {
09716 x = gen_rtx_IOR (vmode, dest, op0);
09717 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
09718 }
09719 }
09720
09721
09722
09723
09724 void
09725 ix86_split_copysign_var (rtx operands[])
09726 {
09727 enum machine_mode mode, vmode;
09728 rtx dest, scratch, op0, op1, mask, nmask, x;
09729
09730 dest = operands[0];
09731 scratch = operands[1];
09732 op0 = operands[2];
09733 op1 = operands[3];
09734 nmask = operands[4];
09735 mask = operands[5];
09736
09737 mode = GET_MODE (dest);
09738 vmode = GET_MODE (mask);
09739
09740 if (rtx_equal_p (op0, op1))
09741 {
09742
09743
09744 emit_move_insn (dest, op0);
09745 return;
09746 }
09747
09748 if (REG_P (mask) && REGNO (dest) == REGNO (mask))
09749 {
09750 gcc_assert (REGNO (op1) == REGNO (scratch));
09751
09752 x = gen_rtx_AND (vmode, scratch, mask);
09753 emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
09754
09755 dest = mask;
09756 op0 = simplify_gen_subreg (vmode, op0, mode, 0);
09757 x = gen_rtx_NOT (vmode, dest);
09758 x = gen_rtx_AND (vmode, x, op0);
09759 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
09760 }
09761 else
09762 {
09763 if (REGNO (op1) == REGNO (scratch))
09764 {
09765 x = gen_rtx_AND (vmode, scratch, mask);
09766 }
09767 else
09768 {
09769 gcc_assert (REGNO (mask) == REGNO (scratch));
09770 op1 = simplify_gen_subreg (vmode, op1, mode, 0);
09771 x = gen_rtx_AND (vmode, scratch, op1);
09772 }
09773 emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
09774
09775 if (REGNO (op0) == REGNO (dest))
09776 {
09777 dest = simplify_gen_subreg (vmode, op0, mode, 0);
09778 x = gen_rtx_AND (vmode, dest, nmask);
09779 }
09780 else
09781 {
09782 gcc_assert (REGNO (nmask) == REGNO (dest));
09783 dest = nmask;
09784 op0 = simplify_gen_subreg (vmode, op0, mode, 0);
09785 x = gen_rtx_AND (vmode, dest, op0);
09786 }
09787 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
09788 }
09789
09790 x = gen_rtx_IOR (vmode, dest, scratch);
09791 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
09792 }
09793
09794
09795
09796
09797
09798 int
09799 ix86_match_ccmode (rtx insn, enum machine_mode req_mode)
09800 {
09801 rtx set;
09802 enum machine_mode set_mode;
09803
09804 set = PATTERN (insn);
09805 if (GET_CODE (set) == PARALLEL)
09806 set = XVECEXP (set, 0, 0);
09807 gcc_assert (GET_CODE (set) == SET);
09808 gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
09809
09810 set_mode = GET_MODE (SET_DEST (set));
09811 switch (set_mode)
09812 {
09813 case CCNOmode:
09814 if (req_mode != CCNOmode
09815 && (req_mode != CCmode
09816 || XEXP (SET_SRC (set), 1) != const0_rtx))
09817 return 0;
09818 break;
09819 case CCmode:
09820 if (req_mode == CCGCmode)
09821 return 0;
09822
09823 case CCGCmode:
09824 if (req_mode == CCGOCmode || req_mode == CCNOmode)
09825 return 0;
09826
09827 case CCGOCmode:
09828 if (req_mode == CCZmode)
09829 return 0;
09830
09831 case CCZmode:
09832 break;
09833
09834 default:
09835 gcc_unreachable ();
09836 }
09837
09838 return (GET_MODE (SET_SRC (set)) == set_mode);
09839 }
09840
09841
09842
09843 static rtx
09844 ix86_expand_int_compare (enum rtx_code code, rtx op0, rtx op1)
09845 {
09846 enum machine_mode cmpmode;
09847 rtx tmp, flags;
09848
09849 cmpmode = SELECT_CC_MODE (code, op0, op1);
09850 flags = gen_rtx_REG (cmpmode, FLAGS_REG);
09851
09852
09853
09854 tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
09855 emit_insn (gen_rtx_SET (VOIDmode, flags, tmp));
09856
09857
09858
09859 return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
09860 }
09861
09862
09863
09864
09865 enum machine_mode
09866 ix86_fp_compare_mode (enum rtx_code code ATTRIBUTE_UNUSED)
09867 {
09868
09869
09870
09871
09872
09873 return TARGET_IEEE_FP ? CCFPUmode : CCFPmode;
09874 }
09875
09876 enum machine_mode
09877 ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
09878 {
09879 if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
09880 return ix86_fp_compare_mode (code);
09881 switch (code)
09882 {
09883
09884 case EQ:
09885 case NE:
09886 return CCZmode;
09887
09888 case GEU:
09889 case GTU:
09890 case LTU:
09891 case LEU:
09892 return CCmode;
09893
09894
09895 case GE:
09896 case LT:
09897 if (op1 == const0_rtx)
09898 return CCGOCmode;
09899 else
09900
09901 return CCGCmode;
09902
09903
09904
09905
09906 case GT:
09907 case LE:
09908 if (op1 == const0_rtx)
09909 return CCNOmode;
09910 else
09911 return CCGCmode;
09912
09913
09914 case USE:
09915 return CCmode;
09916 default:
09917 gcc_unreachable ();
09918 }
09919 }
09920
09921
09922
09923 static bool
09924 ix86_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
09925 {
09926 *p1 = FLAGS_REG;
09927 *p2 = FPSR_REG;
09928 return true;
09929 }
09930
09931
09932
09933
09934
09935 static enum machine_mode
09936 ix86_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
09937 {
09938 if (m1 == m2)
09939 return m1;
09940
09941 if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
09942 return VOIDmode;
09943
09944 if ((m1 == CCGCmode && m2 == CCGOCmode)
09945 || (m1 == CCGOCmode && m2 == CCGCmode))
09946 return CCGCmode;
09947
09948 switch (m1)
09949 {
09950 default:
09951 gcc_unreachable ();
09952
09953 case CCmode:
09954 case CCGCmode:
09955 case CCGOCmode:
09956 case CCNOmode:
09957 case CCZmode:
09958 switch (m2)
09959 {
09960 default:
09961 return VOIDmode;
09962
09963 case CCmode:
09964 case CCGCmode:
09965 case CCGOCmode:
09966 case CCNOmode:
09967 case CCZmode:
09968 return CCmode;
09969 }
09970
09971 case CCFPmode:
09972 case CCFPUmode:
09973
09974
09975 return VOIDmode;
09976 }
09977 }
09978
09979
09980
09981 int
09982 ix86_use_fcomi_compare (enum rtx_code code ATTRIBUTE_UNUSED)
09983 {
09984 enum rtx_code swapped_code = swap_condition (code);
09985 return ((ix86_fp_comparison_cost (code) == ix86_fp_comparison_fcomi_cost (code))
09986 || (ix86_fp_comparison_cost (swapped_code)
09987 == ix86_fp_comparison_fcomi_cost (swapped_code)));
09988 }
09989
09990
09991
09992
09993
09994 static enum rtx_code
09995 ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
09996 {
09997 enum machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
09998 rtx op0 = *pop0, op1 = *pop1;
09999 enum machine_mode op_mode = GET_MODE (op0);
10000 int is_sse = TARGET_SSE_MATH && SSE_FLOAT_MODE_P (op_mode);
10001
10002
10003
10004
10005
10006
10007
10008 if (!is_sse
10009 && (fpcmp_mode == CCFPUmode
10010 || (op_mode == XFmode
10011 && ! (standard_80387_constant_p (op0) == 1
10012 || standard_80387_constant_p (op1) == 1)
10013 && GET_CODE (op1) != FLOAT)
10014 || ix86_use_fcomi_compare (code)))
10015 {
10016 op0 = force_reg (op_mode, op0);
10017 op1 = force_reg (op_mode, op1);
10018 }
10019 else
10020 {
10021
10022
10023
10024
10025 if (standard_80387_constant_p (op0) == 0
10026 || (GET_CODE (op0) == MEM
10027 && ! (standard_80387_constant_p (op1) == 0
10028 || GET_CODE (op1) == MEM)))
10029 {
10030 rtx tmp;
10031 tmp = op0, op0 = op1, op1 = tmp;
10032 code = swap_condition (code);
10033 }
10034
10035 if (GET_CODE (op0) != REG)
10036 op0 = force_reg (op_mode, op0);
10037
10038 if (CONSTANT_P (op1))
10039 {
10040 int tmp = standard_80387_constant_p (op1);
10041 if (tmp == 0)
10042 op1 = validize_mem (force_const_mem (op_mode, op1));
10043 else if (tmp == 1)
10044 {
10045 if (TARGET_CMOVE)
10046 op1 = force_reg (op_mode, op1);
10047 }
10048 else
10049 op1 = force_reg (op_mode, op1);
10050 }
10051 }
10052
10053
10054 if (ix86_fp_comparison_cost (code)
10055 > ix86_fp_comparison_cost (swap_condition (code))
10056 && (GET_CODE (op1) == REG || !no_new_pseudos))
10057 {
10058 rtx tmp;
10059 tmp = op0, op0 = op1, op1 = tmp;
10060 code = swap_condition (code);
10061 if (GET_CODE (op0) != REG)
10062 op0 = force_reg (op_mode, op0);
10063 }
10064
10065 *pop0 = op0;
10066 *pop1 = op1;
10067 return code;
10068 }
10069
10070
10071
10072
10073
10074 enum rtx_code
10075 ix86_fp_compare_code_to_integer (enum rtx_code code)
10076 {
10077 switch (code)
10078 {
10079 case GT:
10080 return GTU;
10081 case GE:
10082 return GEU;
10083 case ORDERED:
10084 case UNORDERED:
10085 return code;
10086 break;
10087 case UNEQ:
10088 return EQ;
10089 break;
10090 case UNLT:
10091 return LTU;
10092 break;
10093 case UNLE:
10094 return LEU;
10095 break;
10096 case LTGT:
10097 return NE;
10098 break;
10099 default:
10100 return UNKNOWN;
10101 }
10102 }
10103
10104
10105
10106
10107
10108
10109
10110 void
10111 ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *bypass_code,
10112 enum rtx_code *first_code,
10113 enum rtx_code *second_code)
10114 {
10115 *first_code = code;
10116 *bypass_code = UNKNOWN;
10117 *second_code = UNKNOWN;
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127 switch (code)
10128 {
10129 case GT:
10130 case GE:
10131 case ORDERED:
10132 case UNORDERED:
10133 case UNEQ:
10134 case UNLT:
10135 case UNLE:
10136 case LTGT:
10137 break;
10138 case LT:
10139 *first_code = UNLT;
10140 *bypass_code = UNORDERED;
10141 break;
10142 case LE:
10143 *first_code = UNLE;
10144 *bypass_code = UNORDERED;
10145 break;
10146 case EQ:
10147 *first_code = UNEQ;
10148 *bypass_code = UNORDERED;
10149 break;
10150 case NE:
10151 *first_code = LTGT;
10152 *second_code = UNORDERED;
10153 break;
10154 case UNGE:
10155 *first_code = GE;
10156 *second_code = UNORDERED;
10157 break;
10158 case UNGT:
10159 *first_code = GT;
10160 *second_code = UNORDERED;
10161 break;
10162 default:
10163 gcc_unreachable ();
10164 }
10165 if (!TARGET_IEEE_FP)
10166 {
10167 *second_code = UNKNOWN;
10168 *bypass_code = UNKNOWN;
10169 }
10170 }
10171
10172
10173
10174
10175
10176 static int
10177 ix86_fp_comparison_arithmetics_cost (enum rtx_code code)
10178 {
10179 if (!TARGET_IEEE_FP)
10180 return 4;
10181
10182 switch (code)
10183 {
10184 case UNLE:
10185 case UNLT:
10186 case LTGT:
10187 case GT:
10188 case GE:
10189 case UNORDERED:
10190 case ORDERED:
10191 case UNEQ:
10192 return 4;
10193 break;
10194 case LT:
10195 case NE:
10196 case EQ:
10197 case UNGE:
10198 return 5;
10199 break;
10200 case LE:
10201 case UNGT:
10202 return 6;
10203 break;
10204 default:
10205 gcc_unreachable ();
10206 }
10207 }
10208
10209
10210
10211 static int
10212 ix86_fp_comparison_fcomi_cost (enum rtx_code code)
10213 {
10214 enum rtx_code bypass_code, first_code, second_code;
10215
10216
10217 if (!TARGET_CMOVE)
10218 return 1024;
10219 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
10220 return (bypass_code != UNKNOWN || second_code != UNKNOWN) + 2;
10221 }
10222
10223
10224
10225 static int
10226 ix86_fp_comparison_sahf_cost (enum rtx_code code)
10227 {
10228 enum rtx_code bypass_code, first_code, second_code;
10229
10230
10231 if (!TARGET_USE_SAHF && !optimize_size)
10232 return 1024;
10233 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
10234 return (bypass_code != UNKNOWN || second_code != UNKNOWN) + 3;
10235 }
10236
10237
10238
10239 static int
10240 ix86_fp_comparison_cost (enum rtx_code code)
10241 {
10242 int fcomi_cost, sahf_cost, arithmetics_cost = 1024;
10243 int min;
10244
10245 fcomi_cost = ix86_fp_comparison_fcomi_cost (code);
10246 sahf_cost = ix86_fp_comparison_sahf_cost (code);
10247
10248 min = arithmetics_cost = ix86_fp_comparison_arithmetics_cost (code);
10249 if (min > sahf_cost)
10250 min = sahf_cost;
10251 if (min > fcomi_cost)
10252 min = fcomi_cost;
10253 return min;
10254 }
10255
10256
10257
10258 static rtx
10259 ix86_expand_fp_compare (enum rtx_code code, rtx op0, rtx op1, rtx scratch,
10260 rtx *second_test, rtx *bypass_test)
10261 {
10262 enum machine_mode fpcmp_mode, intcmp_mode;
10263 rtx tmp, tmp2;
10264 int cost = ix86_fp_comparison_cost (code);
10265 enum rtx_code bypass_code, first_code, second_code;
10266
10267 fpcmp_mode = ix86_fp_compare_mode (code);
10268 code = ix86_prepare_fp_compare_args (code, &op0, &op1);
10269
10270 if (second_test)
10271 *second_test = NULL_RTX;
10272 if (bypass_test)
10273 *bypass_test = NULL_RTX;
10274
10275 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
10276
10277
10278 if ((bypass_code == UNKNOWN || bypass_test)
10279 && (second_code == UNKNOWN || second_test)
10280 && ix86_fp_comparison_arithmetics_cost (code) > cost)
10281 {
10282 if (TARGET_CMOVE)
10283 {
10284 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
10285 tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG),
10286 tmp);
10287 emit_insn (tmp);
10288 }
10289 else
10290 {
10291 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
10292 tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
10293 if (!scratch)
10294 scratch = gen_reg_rtx (HImode);
10295 emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
10296 emit_insn (gen_x86_sahf_1 (scratch));
10297 }
10298
10299
10300 intcmp_mode = fpcmp_mode;
10301 code = first_code;
10302 if (bypass_code != UNKNOWN)
10303 *bypass_test = gen_rtx_fmt_ee (bypass_code, VOIDmode,
10304 gen_rtx_REG (intcmp_mode, FLAGS_REG),
10305 const0_rtx);
10306 if (second_code != UNKNOWN)
10307 *second_test = gen_rtx_fmt_ee (second_code, VOIDmode,
10308 gen_rtx_REG (intcmp_mode, FLAGS_REG),
10309 const0_rtx);
10310 }
10311 else
10312 {
10313
10314 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
10315 tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
10316 if (!scratch)
10317 scratch = gen_reg_rtx (HImode);
10318 emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
10319
10320
10321
10322
10323
10324
10325 intcmp_mode = CCNOmode;
10326 switch (code)
10327 {
10328 case GT:
10329 case UNGT:
10330 if (code == GT || !TARGET_IEEE_FP)
10331 {
10332 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
10333 code = EQ;
10334 }
10335 else
10336 {
10337 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10338 emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
10339 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
10340 intcmp_mode = CCmode;
10341 code = GEU;
10342 }
10343 break;
10344 case LT:
10345 case UNLT:
10346 if (code == LT && TARGET_IEEE_FP)
10347 {
10348 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10349 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01)));
10350 intcmp_mode = CCmode;
10351 code = EQ;
10352 }
10353 else
10354 {
10355 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
10356 code = NE;
10357 }
10358 break;
10359 case GE:
10360 case UNGE:
10361 if (code == GE || !TARGET_IEEE_FP)
10362 {
10363 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
10364 code = EQ;
10365 }
10366 else
10367 {
10368 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10369 emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
10370 GEN_INT (0x01)));
10371 code = NE;
10372 }
10373 break;
10374 case LE:
10375 case UNLE:
10376 if (code == LE && TARGET_IEEE_FP)
10377 {
10378 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10379 emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
10380 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
10381 intcmp_mode = CCmode;
10382 code = LTU;
10383 }
10384 else
10385 {
10386 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
10387 code = NE;
10388 }
10389 break;
10390 case EQ:
10391 case UNEQ:
10392 if (code == EQ && TARGET_IEEE_FP)
10393 {
10394 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10395 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
10396 intcmp_mode = CCmode;
10397 code = EQ;
10398 }
10399 else
10400 {
10401 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
10402 code = NE;
10403 break;
10404 }
10405 break;
10406 case NE:
10407 case LTGT:
10408 if (code == NE && TARGET_IEEE_FP)
10409 {
10410 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
10411 emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
10412 GEN_INT (0x40)));
10413 code = NE;
10414 }
10415 else
10416 {
10417 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
10418 code = EQ;
10419 }
10420 break;
10421
10422 case UNORDERED:
10423 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
10424 code = NE;
10425 break;
10426 case ORDERED:
10427 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
10428 code = EQ;
10429 break;
10430
10431 default:
10432 gcc_unreachable ();
10433 }
10434 }
10435
10436
10437
10438 return gen_rtx_fmt_ee (code, VOIDmode,
10439 gen_rtx_REG (intcmp_mode, FLAGS_REG),
10440 const0_rtx);
10441 }
10442
10443 rtx
10444 ix86_expand_compare (enum rtx_code code, rtx *second_test, rtx *bypass_test)
10445 {
10446 rtx op0, op1, ret;
10447 op0 = ix86_compare_op0;
10448 op1 = ix86_compare_op1;
10449
10450 if (second_test)
10451 *second_test = NULL_RTX;
10452 if (bypass_test)
10453 *bypass_test = NULL_RTX;
10454
10455 if (ix86_compare_emitted)
10456 {
10457 ret = gen_rtx_fmt_ee (code, VOIDmode, ix86_compare_emitted, const0_rtx);
10458 ix86_compare_emitted = NULL_RTX;
10459 }
10460 else if (SCALAR_FLOAT_MODE_P (GET_MODE (op0)))
10461 ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX,
10462 second_test, bypass_test);
10463 else
10464 ret = ix86_expand_int_compare (code, op0, op1);
10465
10466 return ret;
10467 }
10468
10469
10470 bool
10471 ix86_fp_jump_nontrivial_p (enum rtx_code code)
10472 {
10473 enum rtx_code bypass_code, first_code, second_code;
10474 if (!TARGET_CMOVE)
10475 return true;
10476 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
10477 return bypass_code != UNKNOWN || second_code != UNKNOWN;
10478 }
10479
10480 void
10481 ix86_expand_branch (enum rtx_code code, rtx label)
10482 {
10483 rtx tmp;
10484
10485
10486
10487
10488 if (ix86_compare_emitted)
10489 goto simple;
10490
10491 switch (GET_MODE (ix86_compare_op0))
10492 {
10493 case QImode:
10494 case HImode:
10495 case SImode:
10496 simple:
10497 tmp = ix86_expand_compare (code, NULL, NULL);
10498 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10499 gen_rtx_LABEL_REF (VOIDmode, label),
10500 pc_rtx);
10501 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
10502 return;
10503
10504 case SFmode:
10505 case DFmode:
10506 case XFmode:
10507 {
10508 rtvec vec;
10509 int use_fcomi;
10510 enum rtx_code bypass_code, first_code, second_code;
10511
10512 code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0,
10513 &ix86_compare_op1);
10514
10515 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
10516
10517
10518
10519
10520 if (bypass_code == UNKNOWN && second_code == UNKNOWN
10521 && TARGET_CMOVE)
10522 {
10523 ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1,
10524 gen_rtx_LABEL_REF (VOIDmode, label),
10525 pc_rtx, NULL_RTX, NULL_RTX);
10526 }
10527 else
10528 {
10529 tmp = gen_rtx_fmt_ee (code, VOIDmode,
10530 ix86_compare_op0, ix86_compare_op1);
10531 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
10532 gen_rtx_LABEL_REF (VOIDmode, label),
10533 pc_rtx);
10534 tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
10535
10536 use_fcomi = ix86_use_fcomi_compare (code);
10537 vec = rtvec_alloc (3 + !use_fcomi);
10538 RTVEC_ELT (vec, 0) = tmp;
10539 RTVEC_ELT (vec, 1)
10540 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
10541 RTVEC_ELT (vec, 2)
10542 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
10543 if (! use_fcomi)
10544 RTVEC_ELT (vec, 3)
10545 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
10546
10547 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
10548 }
10549 return;
10550 }
10551
10552 case DImode:
10553 if (TARGET_64BIT)
10554 goto simple;
10555 case TImode:
10556
10557 {
10558 rtx lo[2], hi[2], label2;
10559 enum rtx_code code1, code2, code3;
10560 enum machine_mode submode;
10561
10562 if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
10563 {
10564 tmp = ix86_compare_op0;
10565 ix86_compare_op0 = ix86_compare_op1;
10566 ix86_compare_op1 = tmp;
10567 code = swap_condition (code);
10568 }
10569 if (GET_MODE (ix86_compare_op0) == DImode)
10570 {
10571 split_di (&ix86_compare_op0, 1, lo+0, hi+0);
10572 split_di (&ix86_compare_op1, 1, lo+1, hi+1);
10573 submode = SImode;
10574 }
10575 else
10576 {
10577 split_ti (&ix86_compare_op0, 1, lo+0, hi+0);
10578 split_ti (&ix86_compare_op1, 1, lo+1, hi+1);
10579 submode = DImode;
10580 }
10581
10582
10583
10584
10585
10586 if ((code == EQ || code == NE)
10587 && (!optimize_size
10588 || hi[1] == const0_rtx || lo[1] == const0_rtx))
10589 {
10590 rtx xor0, xor1;
10591
10592 xor1 = hi[0];
10593 if (hi[1] != const0_rtx)
10594 xor1 = expand_binop (submode, xor_optab, xor1, hi[1],
10595 NULL_RTX, 0, OPTAB_WIDEN);
10596
10597 xor0 = lo[0];
10598 if (lo[1] != const0_rtx)
10599 xor0 = expand_binop (submode, xor_optab, xor0, lo[1],
10600 NULL_RTX, 0, OPTAB_WIDEN);
10601
10602 tmp = expand_binop (submode, ior_optab, xor1, xor0,
10603 NULL_RTX, 0, OPTAB_WIDEN);
10604
10605 ix86_compare_op0 = tmp;
10606 ix86_compare_op1 = const0_rtx;
10607 ix86_expand_branch (code, label);
10608 return;
10609 }
10610
10611
10612
10613
10614
10615 if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx)
10616 switch (code)
10617 {
10618 case LT: case LTU: case GE: case GEU:
10619 ix86_compare_op0 = hi[0];
10620 ix86_compare_op1 = hi[1];
10621 ix86_expand_branch (code, label);
10622 return;
10623 default:
10624 break;
10625 }
10626
10627
10628
10629 label2 = gen_label_rtx ();
10630
10631 code1 = code;
10632 code2 = swap_condition (code);
10633 code3 = unsigned_condition (code);
10634
10635 switch (code)
10636 {
10637 case LT: case GT: case LTU: case GTU:
10638 break;
10639
10640 case LE: code1 = LT; code2 = GT; break;
10641 case GE: code1 = GT; code2 = LT; break;
10642 case LEU: code1 = LTU; code2 = GTU; break;
10643 case GEU: code1 = GTU; code2 = LTU; break;
10644
10645 case EQ: code1 = UNKNOWN; code2 = NE; break;
10646 case NE: code2 = UNKNOWN; break;
10647
10648 default:
10649 gcc_unreachable ();
10650 }
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660 ix86_compare_op0 = hi[0];
10661 ix86_compare_op1 = hi[1];
10662
10663 if (code1 != UNKNOWN)
10664 ix86_expand_branch (code1, label);
10665 if (code2 != UNKNOWN)
10666 ix86_expand_branch (code2, label2);
10667
10668 ix86_compare_op0 = lo[0];
10669 ix86_compare_op1 = lo[1];
10670 ix86_expand_branch (code3, label);
10671
10672 if (code2 != UNKNOWN)
10673 emit_label (label2);
10674 return;
10675 }
10676
10677 default:
10678 gcc_unreachable ();
10679 }
10680 }
10681
10682
10683 void
10684 ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
10685 rtx target1, rtx target2, rtx tmp, rtx pushed)
10686 {
10687 rtx second, bypass;
10688 rtx label = NULL_RTX;
10689 rtx condition;
10690 int bypass_probability = -1, second_probability = -1, probability = -1;
10691 rtx i;
10692
10693 if (target2 != pc_rtx)
10694 {
10695 rtx tmp = target2;
10696 code = reverse_condition_maybe_unordered (code);
10697 target2 = target1;
10698 target1 = tmp;
10699 }
10700
10701 condition = ix86_expand_fp_compare (code, op1, op2,
10702 tmp, &second, &bypass);
10703
10704
10705 if (pushed)
10706 ix86_free_from_memory (GET_MODE (pushed));
10707
10708 if (split_branch_probability >= 0)
10709 {
10710
10711
10712
10713 probability = split_branch_probability;
10714
10715
10716
10717
10718 if (bypass)
10719 bypass_probability = 1;
10720 if (second)
10721 second_probability = 1;
10722 }
10723 if (bypass != NULL_RTX)
10724 {
10725 label = gen_label_rtx ();
10726 i = emit_jump_insn (gen_rtx_SET
10727 (VOIDmode, pc_rtx,
10728 gen_rtx_IF_THEN_ELSE (VOIDmode,
10729 bypass,
10730 gen_rtx_LABEL_REF (VOIDmode,
10731 label),
10732 pc_rtx)));
10733 if (bypass_probability >= 0)
10734 REG_NOTES (i)
10735 = gen_rtx_EXPR_LIST (REG_BR_PROB,
10736 GEN_INT (bypass_probability),
10737 REG_NOTES (i));
10738 }
10739 i = emit_jump_insn (gen_rtx_SET
10740 (VOIDmode, pc_rtx,
10741 gen_rtx_IF_THEN_ELSE (VOIDmode,
10742 condition, target1, target2)));
10743 if (probability >= 0)
10744 REG_NOTES (i)
10745 = gen_rtx_EXPR_LIST (REG_BR_PROB,
10746 GEN_INT (probability),
10747 REG_NOTES (i));
10748 if (second != NULL_RTX)
10749 {
10750 i = emit_jump_insn (gen_rtx_SET
10751 (VOIDmode, pc_rtx,
10752 gen_rtx_IF_THEN_ELSE (VOIDmode, second, target1,
10753 target2)));
10754 if (second_probability >= 0)
10755 REG_NOTES (i)
10756 = gen_rtx_EXPR_LIST (REG_BR_PROB,
10757 GEN_INT (second_probability),
10758 REG_NOTES (i));
10759 }
10760 if (label != NULL_RTX)
10761 emit_label (label);
10762 }
10763
10764 int
10765 ix86_expand_setcc (enum rtx_code code, rtx dest)
10766 {
10767 rtx ret, tmp, tmpreg, equiv;
10768 rtx second_test, bypass_test;
10769
10770 if (GET_MODE (ix86_compare_op0) == (TARGET_64BIT ? TImode : DImode))
10771 return 0;
10772
10773 gcc_assert (GET_MODE (dest) == QImode);
10774
10775 ret = ix86_expand_compare (code, &second_test, &bypass_test);
10776 PUT_MODE (ret, QImode);
10777
10778 tmp = dest;
10779 tmpreg = dest;
10780
10781 emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
10782 if (bypass_test || second_test)
10783 {
10784 rtx test = second_test;
10785 int bypass = 0;
10786 rtx tmp2 = gen_reg_rtx (QImode);
10787 if (bypass_test)
10788 {
10789 gcc_assert (!second_test);
10790 test = bypass_test;
10791 bypass = 1;
10792 PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test)));
10793 }
10794 PUT_MODE (test, QImode);
10795 emit_insn (gen_rtx_SET (VOIDmode, tmp2, test));
10796
10797 if (bypass)
10798 emit_insn (gen_andqi3 (tmp, tmpreg, tmp2));
10799 else
10800 emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
10801 }
10802
10803
10804 if (ix86_compare_op0 && ix86_compare_op1)
10805 {
10806 equiv = simplify_gen_relational (code, QImode,
10807 GET_MODE (ix86_compare_op0),
10808 ix86_compare_op0, ix86_compare_op1);
10809 set_unique_reg_note (get_last_insn (), REG_EQUAL, equiv);
10810 }
10811
10812 return 1;
10813 }
10814
10815
10816
10817 static bool
10818 ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop)
10819 {
10820 enum machine_mode mode =
10821 GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
10822
10823
10824
10825 if (mode == (TARGET_64BIT ? TImode : DImode))
10826 return false;
10827 if (FLOAT_MODE_P (mode))
10828 {
10829 rtx second_test = NULL, bypass_test = NULL;
10830 rtx compare_op, compare_seq;
10831
10832
10833 if (code == EQ || code == NE || code == UNEQ || code == LTGT
10834 || code == ORDERED || code == UNORDERED)
10835 return false;
10836
10837
10838 if ((code == GT || code == UNLE || code == LE || code == UNGT)
10839 && !TARGET_IEEE_FP)
10840 {
10841 rtx tmp = op0;
10842 op0 = op1;
10843 op1 = tmp;
10844 code = swap_condition (code);
10845 }
10846
10847
10848
10849
10850 start_sequence ();
10851 compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX,
10852 &second_test, &bypass_test);
10853 compare_seq = get_insns ();
10854 end_sequence ();
10855
10856 if (second_test || bypass_test)
10857 return false;
10858 if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
10859 || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
10860 code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
10861 else
10862 code = GET_CODE (compare_op);
10863 if (code != LTU && code != GEU)
10864 return false;
10865 emit_insn (compare_seq);
10866 *pop = compare_op;
10867 return true;
10868 }
10869 if (!INTEGRAL_MODE_P (mode))
10870 return false;
10871 switch (code)
10872 {
10873 case LTU:
10874 case GEU:
10875 break;
10876
10877
10878 case EQ:
10879 case NE:
10880 if (op1 != const0_rtx)
10881 return false;
10882 op1 = const1_rtx;
10883 code = (code == EQ ? LTU : GEU);
10884 break;
10885
10886
10887 case GTU:
10888 case LEU:
10889 if (GET_CODE (op1) == CONST_INT)
10890 {
10891 op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
10892
10893
10894 if (op1 == const0_rtx
10895 || !x86_64_immediate_operand (op1, GET_MODE (op1)))
10896 return false;
10897 code = (code == GTU ? GEU : LTU);
10898 }
10899 else
10900 {
10901 rtx tmp = op1;
10902 op1 = op0;
10903 op0 = tmp;
10904 code = (code == GTU ? LTU : GEU);
10905 }
10906 break;
10907
10908
10909 case LT:
10910 case GE:
10911 if (mode == DImode || op1 != const0_rtx)
10912 return false;
10913 op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
10914 code = (code == LT ? GEU : LTU);
10915 break;
10916 case LE:
10917 case GT:
10918 if (mode == DImode || op1 != constm1_rtx)
10919 return false;
10920 op1 = gen_int_mode (1 << (GET_MODE_BITSIZE (mode) - 1), mode);
10921 code = (code == LE ? GEU : LTU);
10922 break;
10923
10924 default:
10925 return false;
10926 }
10927
10928 if (!nonimmediate_operand (op0, VOIDmode))
10929 {
10930 if (no_new_pseudos)
10931 return false;
10932 op0 = force_reg (mode, op0);
10933 }
10934 ix86_compare_op0 = op0;
10935 ix86_compare_op1 = op1;
10936 *pop = ix86_expand_compare (code, NULL, NULL);
10937 gcc_assert (GET_CODE (*pop) == LTU || GET_CODE (*pop) == GEU);
10938 return true;
10939 }
10940
10941 int
10942 ix86_expand_int_movcc (rtx operands[])
10943 {
10944 enum rtx_code code = GET_CODE (operands[1]), compare_code;
10945 rtx compare_seq, compare_op;
10946 rtx second_test, bypass_test;
10947 enum machine_mode mode = GET_MODE (operands[0]);
10948 bool sign_bit_compare_p = false;;
10949
10950 start_sequence ();
10951 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
10952 compare_seq = get_insns ();
10953 end_sequence ();
10954
10955 compare_code = GET_CODE (compare_op);
10956
10957 if ((ix86_compare_op1 == const0_rtx && (code == GE || code == LT))
10958 || (ix86_compare_op1 == constm1_rtx && (code == GT || code == LE)))
10959 sign_bit_compare_p = true;
10960
10961
10962
10963
10964 if ((mode != HImode || TARGET_FAST_PREFIX)
10965 && (mode != (TARGET_64BIT ? TImode : DImode))
10966 && GET_CODE (operands[2]) == CONST_INT
10967 && GET_CODE (operands[3]) == CONST_INT)
10968 {
10969 rtx out = operands[0];
10970 HOST_WIDE_INT ct = INTVAL (operands[2]);
10971 HOST_WIDE_INT cf = INTVAL (operands[3]);
10972 HOST_WIDE_INT diff;
10973
10974 diff = ct - cf;
10975
10976
10977 if (sign_bit_compare_p
10978 || ix86_expand_carry_flag_compare (code, ix86_compare_op0,
10979 ix86_compare_op1, &compare_op))
10980 {
10981
10982 rtx tmp = out;
10983
10984 if (!sign_bit_compare_p)
10985 {
10986 bool fpcmp = false;
10987
10988 compare_code = GET_CODE (compare_op);
10989
10990 if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
10991 || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
10992 {
10993 fpcmp = true;
10994 compare_code = ix86_fp_compare_code_to_integer (compare_code);
10995 }
10996
10997
10998 if (compare_code == LTU)
10999 {
11000 HOST_WIDE_INT tmp = ct;
11001 ct = cf;
11002 cf = tmp;
11003 compare_code = reverse_condition (compare_code);
11004 code = reverse_condition (code);
11005 }
11006 else
11007 {
11008 if (fpcmp)
11009 PUT_CODE (compare_op,
11010 reverse_condition_maybe_unordered
11011 (GET_CODE (compare_op)));
11012 else
11013 PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
11014 }
11015 diff = ct - cf;
11016
11017 if (reg_overlap_mentioned_p (out, ix86_compare_op0)
11018 || reg_overlap_mentioned_p (out, ix86_compare_op1))
11019 tmp = gen_reg_rtx (mode);
11020
11021 if (mode == DImode)
11022 emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp, compare_op));
11023 else
11024 emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp), compare_op));
11025 }
11026 else
11027 {
11028 if (code == GT || code == GE)
11029 code = reverse_condition (code);
11030 else
11031 {
11032 HOST_WIDE_INT tmp = ct;
11033 ct = cf;
11034 cf = tmp;
11035 diff = ct - cf;
11036 }
11037 tmp = emit_store_flag (tmp, code, ix86_compare_op0,
11038 ix86_compare_op1, VOIDmode, 0, -1);
11039 }
11040
11041 if (diff == 1)
11042 {
11043
11044
11045
11046
11047
11048
11049
11050 if (ct)
11051 tmp = expand_simple_binop (mode, PLUS,
11052 tmp, GEN_INT (ct),
11053 copy_rtx (tmp), 1, OPTAB_DIRECT);
11054 }
11055 else if (cf == -1)
11056 {
11057
11058
11059
11060
11061
11062
11063
11064 tmp = expand_simple_binop (mode, IOR,
11065 tmp, GEN_INT (ct),
11066 copy_rtx (tmp), 1, OPTAB_DIRECT);
11067 }
11068 else if (diff == -1 && ct)
11069 {
11070
11071
11072
11073
11074
11075
11076
11077
11078 tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
11079 if (cf)
11080 tmp = expand_simple_binop (mode, PLUS,
11081 copy_rtx (tmp), GEN_INT (cf),
11082 copy_rtx (tmp), 1, OPTAB_DIRECT);
11083 }
11084 else
11085 {
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096 if (cf == 0)
11097 {
11098 cf = ct;
11099 ct = 0;
11100 tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
11101 }
11102
11103 tmp = expand_simple_binop (mode, AND,
11104 copy_rtx (tmp),
11105 gen_int_mode (cf - ct, mode),
11106 copy_rtx (tmp), 1, OPTAB_DIRECT);
11107 if (ct)
11108 tmp = expand_simple_binop (mode, PLUS,
11109 copy_rtx (tmp), GEN_INT (ct),
11110 copy_rtx (tmp), 1, OPTAB_DIRECT);
11111 }
11112
11113 if (!rtx_equal_p (tmp, out))
11114 emit_move_insn (copy_rtx (out), copy_rtx (tmp));
11115
11116 return 1;
11117 }
11118
11119 if (diff < 0)
11120 {
11121 HOST_WIDE_INT tmp;
11122 tmp = ct, ct = cf, cf = tmp;
11123 diff = -diff;
11124 if (FLOAT_MODE_P (GET_MODE (ix86_compare_op0)))
11125 {
11126
11127
11128
11129
11130 compare_code = reverse_condition_maybe_unordered (compare_code);
11131 code = reverse_condition_maybe_unordered (code);
11132 }
11133 else
11134 {
11135 compare_code = reverse_condition (compare_code);
11136 code = reverse_condition (code);
11137 }
11138 }
11139
11140 compare_code = UNKNOWN;
11141 if (GET_MODE_CLASS (GET_MODE (ix86_compare_op0)) == MODE_INT
11142 && GET_CODE (ix86_compare_op1) == CONST_INT)
11143 {
11144 if (ix86_compare_op1 == const0_rtx
11145 && (code == LT || code == GE))
11146 compare_code = code;
11147 else if (ix86_compare_op1 == constm1_rtx)
11148 {
11149 if (code == LE)
11150 compare_code = LT;
11151 else if (code == GT)
11152 compare_code = GE;
11153 }
11154 }
11155
11156
11157 if (compare_code != UNKNOWN
11158 && GET_MODE (ix86_compare_op0) == GET_MODE (out)
11159 && (cf == -1 || ct == -1))
11160 {
11161
11162
11163
11164 if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
11165 || diff == 3 || diff == 5 || diff == 9)
11166 || (compare_code == LT && ct == -1)
11167 || (compare_code == GE && cf == -1))
11168 {
11169
11170
11171
11172
11173
11174 if (ct != -1)
11175 {
11176 cf = ct;
11177 ct = -1;
11178 code = reverse_condition (code);
11179 }
11180
11181 out = emit_store_flag (out, code, ix86_compare_op0,
11182 ix86_compare_op1, VOIDmode, 0, -1);
11183
11184 out = expand_simple_binop (mode, IOR,
11185 out, GEN_INT (cf),
11186 out, 1, OPTAB_DIRECT);
11187 if (out != operands[0])
11188 emit_move_insn (operands[0], out);
11189
11190 return 1;
11191 }
11192 }
11193
11194
11195 if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
11196 || diff == 3 || diff == 5 || diff == 9)
11197 && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
11198 && (mode != DImode
11199 || x86_64_immediate_operand (GEN_INT (cf), VOIDmode)))
11200 {
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212 rtx tmp;
11213 int nops;
11214
11215 out = emit_store_flag (out, code, ix86_compare_op0,
11216 ix86_compare_op1, VOIDmode, 0, 1);
11217
11218 nops = 0;
11219
11220
11221 if (diff == 1)
11222 tmp = copy_rtx (out);
11223 else
11224 {
11225 rtx out1;
11226 out1 = copy_rtx (out);
11227 tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
11228 nops++;
11229 if (diff & 1)
11230 {
11231 tmp = gen_rtx_PLUS (mode, tmp, out1);
11232 nops++;
11233 }
11234 }
11235 if (cf != 0)
11236 {
11237 tmp = gen_rtx_PLUS (mode, tmp, GEN_INT (cf));
11238 nops++;
11239 }
11240 if (!rtx_equal_p (tmp, out))
11241 {
11242 if (nops == 1)
11243 out = force_operand (tmp, copy_rtx (out));
11244 else
11245 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (out), copy_rtx (tmp)));
11246 }
11247 if (!rtx_equal_p (out, operands[0]))
11248 emit_move_insn (operands[0], copy_rtx (out));
11249
11250 return 1;
11251 }
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269 if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
11270 && BRANCH_COST >= 2)
11271 {
11272 if (cf == 0)
11273 {
11274 cf = ct;
11275 ct = 0;
11276 if (FLOAT_MODE_P (GET_MODE (ix86_compare_op0)))
11277
11278
11279
11280
11281 code = reverse_condition_maybe_unordered (code);
11282 else
11283 {
11284 code = reverse_condition (code);
11285 if (compare_code != UNKNOWN)
11286 compare_code = reverse_condition (compare_code);
11287 }
11288 }
11289
11290 if (compare_code != UNKNOWN)
11291 {
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304 if (compare_code == GE || !cf)
11305 {
11306 code = reverse_condition (code);
11307 compare_code = LT;
11308 }
11309 else
11310 {
11311 HOST_WIDE_INT tmp = cf;
11312 cf = ct;
11313 ct = tmp;
11314 }
11315
11316 out = emit_store_flag (out, code, ix86_compare_op0,
11317 ix86_compare_op1, VOIDmode, 0, -1);
11318 }
11319 else
11320 {
11321 out = emit_store_flag (out, code, ix86_compare_op0,
11322 ix86_compare_op1, VOIDmode, 0, 1);
11323
11324 out = expand_simple_binop (mode, PLUS, copy_rtx (out), constm1_rtx,
11325 copy_rtx (out), 1, OPTAB_DIRECT);
11326 }
11327
11328 out = expand_simple_binop (mode, AND, copy_rtx (out),
11329 gen_int_mode (cf - ct, mode),
11330 copy_rtx (out), 1, OPTAB_DIRECT);
11331 if (ct)
11332 out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
11333 copy_rtx (out), 1, OPTAB_DIRECT);
11334 if (!rtx_equal_p (out, operands[0]))
11335 emit_move_insn (operands[0], copy_rtx (out));
11336
11337 return 1;
11338 }
11339 }
11340
11341 if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
11342 {
11343
11344
11345 optab op;
11346 rtx var, orig_out, out, tmp;
11347
11348 if (BRANCH_COST <= 2)
11349 return 0;
11350
11351
11352
11353
11354 if (GET_CODE (operands[2]) == CONST_INT)
11355 {
11356 var = operands[3];
11357 if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
11358 operands[3] = constm1_rtx, op = and_optab;
11359 else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
11360 operands[3] = const0_rtx, op = ior_optab;
11361 else
11362 return 0;
11363 }
11364 else if (GET_CODE (operands[3]) == CONST_INT)
11365 {
11366 var = operands[2];
11367 if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
11368 operands[2] = constm1_rtx, op = and_optab;
11369 else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
11370 operands[2] = const0_rtx, op = ior_optab;
11371 else
11372 return 0;
11373 }
11374 else
11375 return 0;
11376
11377 orig_out = operands[0];
11378 tmp = gen_reg_rtx (mode);
11379 operands[0] = tmp;
11380
11381
11382 if (ix86_expand_int_movcc (operands) == 0)
11383 return 0;
11384
11385
11386 out = expand_binop (mode, op, var, tmp, orig_out, 0,
11387 OPTAB_WIDEN);
11388 if (!rtx_equal_p (out, orig_out))
11389 emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
11390
11391 return 1;
11392 }
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405 if (! nonimmediate_operand (operands[2], mode))
11406 operands[2] = force_reg (mode, operands[2]);
11407 if (! nonimmediate_operand (operands[3], mode))
11408 operands[3] = force_reg (mode, operands[3]);
11409
11410 if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
11411 {
11412 rtx tmp = gen_reg_rtx (mode);
11413 emit_move_insn (tmp, operands[3]);
11414 operands[3] = tmp;
11415 }
11416 if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
11417 {
11418 rtx tmp = gen_reg_rtx (mode);
11419 emit_move_insn (tmp, operands[2]);
11420 operands[2] = tmp;
11421 }
11422
11423 if (! register_operand (operands[2], VOIDmode)
11424 && (mode == QImode
11425 || ! register_operand (operands[3], VOIDmode)))
11426 operands[2] = force_reg (mode, operands[2]);
11427
11428 if (mode == QImode
11429 && ! register_operand (operands[3], VOIDmode))
11430 operands[3] = force_reg (mode, operands[3]);
11431
11432 emit_insn (compare_seq);
11433 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
11434 gen_rtx_IF_THEN_ELSE (mode,
11435 compare_op, operands[2],
11436 operands[3])));
11437 if (bypass_test)
11438 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]),
11439 gen_rtx_IF_THEN_ELSE (mode,
11440 bypass_test,
11441 copy_rtx (operands[3]),
11442 copy_rtx (operands[0]))));
11443 if (second_test)
11444 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]),
11445 gen_rtx_IF_THEN_ELSE (mode,
11446 second_test,
11447 copy_rtx (operands[2]),
11448 copy_rtx (operands[0]))));
11449
11450 return 1;
11451 }
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461 static enum rtx_code
11462 ix86_prepare_sse_fp_compare_args (rtx dest, enum rtx_code code,
11463 rtx *pop0, rtx *pop1)
11464 {
11465 rtx tmp;
11466
11467 switch (code)
11468 {
11469 case LTGT:
11470 case UNEQ:
11471
11472
11473
11474 return UNKNOWN;
11475
11476 case LT:
11477 case LE:
11478 case UNGT:
11479 case UNGE:
11480
11481 break;
11482
11483 case EQ:
11484 case NE:
11485 case UNORDERED:
11486 case ORDERED:
11487
11488
11489
11490 if (!dest || !rtx_equal_p (dest, *pop1))
11491 break;
11492
11493
11494 case GE:
11495 case GT:
11496 case UNLE:
11497 case UNLT:
11498
11499
11500 tmp = *pop0;
11501 *pop0 = *pop1;
11502 *pop1 = tmp;
11503 code = swap_condition (code);
11504 break;
11505
11506 default:
11507 gcc_unreachable ();
11508 }
11509
11510 return code;
11511 }
11512
11513
11514
11515
11516
11517
11518
11519
11520 static bool
11521 ix86_expand_sse_fp_minmax (rtx dest, enum rtx_code code, rtx cmp_op0,
11522 rtx cmp_op1, rtx if_true, rtx if_false)
11523 {
11524 enum machine_mode mode;
11525 bool is_min;
11526 rtx tmp;
11527
11528 if (code == LT)
11529 ;
11530 else if (code == UNGE)
11531 {
11532 tmp = if_true;
11533 if_true = if_false;
11534 if_false = tmp;
11535 }
11536 else
11537 return false;
11538
11539 if (rtx_equal_p (cmp_op0, if_true) && rtx_equal_p (cmp_op1, if_false))
11540 is_min = true;
11541 else if (rtx_equal_p (cmp_op1, if_true) && rtx_equal_p (cmp_op0, if_false))
11542 is_min = false;
11543 else
11544 return false;
11545
11546 mode = GET_MODE (dest);
11547
11548
11549
11550 if (!flag_finite_math_only || !flag_unsafe_math_optimizations)
11551 {
11552 int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
11553 rtvec v;
11554
11555 if_true = force_reg (mode, if_true);
11556 v = gen_rtvec (2, if_true, if_false);
11557 tmp = gen_rtx_UNSPEC (mode, v, u);
11558 }
11559 else
11560 {
11561 code = is_min ? SMIN : SMAX;
11562 tmp = gen_rtx_fmt_ee (code, mode, if_true, if_false);
11563 }
11564
11565 emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
11566 return true;
11567 }
11568
11569
11570
11571 static rtx
11572 ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
11573 rtx op_true, rtx op_false)
11574 {
11575 enum machine_mode mode = GET_MODE (dest);
11576 rtx x;
11577
11578 cmp_op0 = force_reg (mode, cmp_op0);
11579 if (!nonimmediate_operand (cmp_op1, mode))
11580 cmp_op1 = force_reg (mode, cmp_op1);
11581
11582 if (optimize
11583 || reg_overlap_mentioned_p (dest, op_true)
11584 || reg_overlap_mentioned_p (dest, op_false))
11585 dest = gen_reg_rtx (mode);
11586
11587 x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
11588 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
11589
11590 return dest;
11591 }
11592
11593
11594
11595
11596 static void
11597 ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
11598 {
11599 enum machine_mode mode = GET_MODE (dest);
11600 rtx t2, t3, x;
11601
11602 if (op_false == CONST0_RTX (mode))
11603 {
11604 op_true = force_reg (mode, op_true);
11605 x = gen_rtx_AND (mode, cmp, op_true);
11606 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
11607 }
11608 else if (op_true == CONST0_RTX (mode))
11609 {
11610 op_false = force_reg (mode, op_false);
11611 x = gen_rtx_NOT (mode, cmp);
11612 x = gen_rtx_AND (mode, x, op_false);
11613 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
11614 }
11615 else
11616 {
11617 op_true = force_reg (mode, op_true);
11618 op_false = force_reg (mode, op_false);
11619
11620 t2 = gen_reg_rtx (mode);
11621 if (optimize)
11622 t3 = gen_reg_rtx (mode);
11623 else
11624 t3 = dest;
11625
11626 x = gen_rtx_AND (mode, op_true, cmp);
11627 emit_insn (gen_rtx_SET (VOIDmode, t2, x));
11628
11629 x = gen_rtx_NOT (mode, cmp);
11630 x = gen_rtx_AND (mode, x, op_false);
11631 emit_insn (gen_rtx_SET (VOIDmode, t3, x));
11632
11633 x = gen_rtx_IOR (mode, t3, t2);
11634 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
11635 }
11636 }
11637
11638
11639
11640 int
11641 ix86_expand_fp_movcc (rtx operands[])
11642 {
11643 enum machine_mode mode = GET_MODE (operands[0]);
11644 enum rtx_code code = GET_CODE (operands[1]);
11645 rtx tmp, compare_op, second_test, bypass_test;
11646
11647 if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
11648 {
11649 enum machine_mode cmode;
11650
11651
11652
11653
11654 cmode = GET_MODE (ix86_compare_op0);
11655 if (cmode == VOIDmode)
11656 cmode = GET_MODE (ix86_compare_op1);
11657 if (cmode != mode)
11658 return 0;
11659
11660 code = ix86_prepare_sse_fp_compare_args (operands[0], code,
11661 &ix86_compare_op0,
11662 &ix86_compare_op1);
11663 if (code == UNKNOWN)
11664 return 0;
11665
11666 if (ix86_expand_sse_fp_minmax (operands[0], code, ix86_compare_op0,
11667 ix86_compare_op1, operands[2],
11668 operands[3]))
11669 return 1;
11670
11671 tmp = ix86_expand_sse_cmp (operands[0], code, ix86_compare_op0,
11672 ix86_compare_op1, operands[2], operands[3]);
11673 ix86_expand_sse_movcc (operands[0], tmp, operands[2], operands[3]);
11674 return 1;
11675 }
11676
11677
11678
11679
11680 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
11681
11682
11683
11684
11685 if (!fcmov_comparison_operator (compare_op, VOIDmode))
11686 {
11687 gcc_assert (!second_test && !bypass_test);
11688 tmp = gen_reg_rtx (QImode);
11689 ix86_expand_setcc (code, tmp);
11690 code = NE;
11691 ix86_compare_op0 = tmp;
11692 ix86_compare_op1 = const0_rtx;
11693 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
11694 }
11695 if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
11696 {
11697 tmp = gen_reg_rtx (mode);
11698 emit_move_insn (tmp, operands[3]);
11699 operands[3] = tmp;
11700 }
11701 if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
11702 {
11703 tmp = gen_reg_rtx (mode);
11704 emit_move_insn (tmp, operands[2]);
11705 operands[2] = tmp;
11706 }
11707
11708 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
11709 gen_rtx_IF_THEN_ELSE (mode, compare_op,
11710 operands[2], operands[3])));
11711 if (bypass_test)
11712 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
11713 gen_rtx_IF_THEN_ELSE (mode, bypass_test,
11714 operands[3], operands[0])));
11715 if (second_test)
11716 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
11717 gen_rtx_IF_THEN_ELSE (mode, second_test,
11718 operands[2], operands[0])));
11719
11720 return 1;
11721 }
11722
11723
11724
11725
11726 bool
11727 ix86_expand_fp_vcond (rtx operands[])
11728 {
11729 enum rtx_code code = GET_CODE (operands[3]);
11730 rtx cmp;
11731
11732 code = ix86_prepare_sse_fp_compare_args (operands[0], code,
11733 &operands[4], &operands[5]);
11734 if (code == UNKNOWN)
11735 return false;
11736
11737 if (ix86_expand_sse_fp_minmax (operands[0], code, operands[4],
11738 operands[5], operands[1], operands[2]))
11739 return true;
11740
11741 cmp = ix86_expand_sse_cmp (operands[0], code, operands[4], operands[5],
11742 operands[1], operands[2]);
11743 ix86_expand_sse_movcc (operands[0], cmp, operands[1], operands[2]);
11744 return true;
11745 }
11746
11747
11748
11749 bool
11750 ix86_expand_int_vcond (rtx operands[])
11751 {
11752 enum machine_mode mode = GET_MODE (operands[0]);
11753 enum rtx_code code = GET_CODE (operands[3]);
11754 bool negate = false;
11755 rtx x, cop0, cop1;
11756
11757 cop0 = operands[4];
11758 cop1 = operands[5];
11759
11760
11761 switch (code)
11762 {
11763 case EQ:
11764 case GT:
11765 case GTU:
11766 break;
11767
11768 case NE:
11769 case LE:
11770 case LEU:
11771 code = reverse_condition (code);
11772 negate = true;
11773 break;
11774
11775 case GE:
11776 case GEU:
11777 code = reverse_condition (code);
11778 negate = true;
11779
11780
11781 case LT:
11782 case LTU:
11783 code = swap_condition (code);
11784 x = cop0, cop0 = cop1, cop1 = x;
11785 break;
11786
11787 default:
11788 gcc_unreachable ();
11789 }
11790
11791
11792
11793 if (code == GTU)
11794 {
11795 cop0 = force_reg (mode, cop0);
11796
11797 switch (mode)
11798 {
11799 case V4SImode:
11800 {
11801 rtx t1, t2, mask;
11802
11803
11804 t1 = gen_reg_rtx (mode);
11805 emit_insn (gen_subv4si3 (t1, cop0, cop1));
11806
11807
11808 mask = GEN_INT (-0x80000000);
11809 mask = gen_rtx_CONST_VECTOR (mode,
11810 gen_rtvec (4, mask, mask, mask, mask));
11811 mask = force_reg (mode, mask);
11812 t2 = gen_reg_rtx (mode);
11813 emit_insn (gen_andv4si3 (t2, cop0, mask));
11814
11815
11816
11817 x = gen_reg_rtx (mode);
11818 emit_insn (gen_xorv4si3 (x, t1, t2));
11819
11820 code = GT;
11821 }
11822 break;
11823
11824 case V16QImode:
11825 case V8HImode:
11826
11827 x = gen_reg_rtx (mode);
11828 emit_insn (gen_rtx_SET (VOIDmode, x,
11829 gen_rtx_US_MINUS (mode, cop0, cop1)));
11830
11831 code = EQ;
11832 negate = !negate;
11833 break;
11834
11835 default:
11836 gcc_unreachable ();
11837 }
11838
11839 cop0 = x;
11840 cop1 = CONST0_RTX (mode);
11841 }
11842
11843 x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
11844 operands[1+negate], operands[2-negate]);
11845
11846 ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
11847 operands[2-negate]);
11848 return true;
11849 }
11850
11851
11852
11853
11854 int
11855 ix86_expand_int_addcc (rtx operands[])
11856 {
11857 enum rtx_code code = GET_CODE (operands[1]);
11858 rtx compare_op;
11859 rtx val = const0_rtx;
11860 bool fpcmp = false;
11861 enum machine_mode mode = GET_MODE (operands[0]);
11862
11863 if (operands[3] != const1_rtx
11864 && operands[3] != constm1_rtx)
11865 return 0;
11866 if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0,
11867 ix86_compare_op1, &compare_op))
11868 return 0;
11869 code = GET_CODE (compare_op);
11870
11871 if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
11872 || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
11873 {
11874 fpcmp = true;
11875 code = ix86_fp_compare_code_to_integer (code);
11876 }
11877
11878 if (code != LTU)
11879 {
11880 val = constm1_rtx;
11881 if (fpcmp)
11882 PUT_CODE (compare_op,
11883 reverse_condition_maybe_unordered
11884 (GET_CODE (compare_op)));
11885 else
11886 PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
11887 }
11888 PUT_MODE (compare_op, mode);
11889
11890
11891 if ((code == LTU) == (operands[3] == constm1_rtx))
11892 {
11893 switch (GET_MODE (operands[0]))
11894 {
11895 case QImode:
11896 emit_insn (gen_subqi3_carry (operands[0], operands[2], val, compare_op));
11897 break;
11898 case HImode:
11899 emit_insn (gen_subhi3_carry (operands[0], operands[2], val, compare_op));
11900 break;
11901 case SImode:
11902 emit_insn (gen_subsi3_carry (operands[0], operands[2], val, compare_op));
11903 break;
11904 case DImode:
11905 emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val, compare_op));
11906 break;
11907 default:
11908 gcc_unreachable ();
11909 }
11910 }
11911 else
11912 {
11913 switch (GET_MODE (operands[0]))
11914 {
11915 case QImode:
11916 emit_insn (gen_addqi3_carry (operands[0], operands[2], val, compare_op));
11917 break;
11918 case HImode:
11919 emit_insn (gen_addhi3_carry (operands[0], operands[2], val, compare_op));
11920 break;
11921 case SImode:
11922 emit_insn (gen_addsi3_carry (operands[0], operands[2], val, compare_op));
11923 break;
11924 case DImode:
11925 emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val, compare_op));
11926 break;
11927 default:
11928 gcc_unreachable ();
11929 }
11930 }
11931 return 1;
11932 }
11933
11934
11935
11936
11937
11938
11939
11940 static int
11941 ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
11942 {
11943 int size;
11944
11945 if (!TARGET_64BIT)
11946 size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
11947 else
11948 size = (GET_MODE_SIZE (mode) + 4) / 8;
11949
11950 gcc_assert (GET_CODE (operand) != REG || !MMX_REGNO_P (REGNO (operand)));
11951 gcc_assert (size >= 2 && size <= 3);
11952
11953
11954
11955 if (GET_CODE (operand) == MEM && MEM_READONLY_P (operand))
11956 {
11957 rtx tmp = maybe_get_pool_constant (operand);
11958 if (tmp)
11959 operand = tmp;
11960 }
11961
11962 if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
11963 {
11964
11965 int ok = push_operand (operand, VOIDmode);
11966
11967 gcc_assert (ok);
11968
11969 operand = copy_rtx (operand);
11970 PUT_MODE (operand, Pmode);
11971 parts[0] = parts[1] = parts[2] = operand;
11972 return size;
11973 }
11974
11975 if (GET_CODE (operand) == CONST_VECTOR)
11976 {
11977 enum machine_mode imode = int_mode_for_mode (mode);
11978
11979
11980
11981 operand = simplify_subreg (imode, operand, GET_MODE (operand), 0);
11982 gcc_assert (operand != NULL);
11983 mode = imode;
11984 }
11985
11986 if (!TARGET_64BIT)
11987 {
11988 if (mode == DImode)
11989 split_di (&operand, 1, &parts[0], &parts[1]);
11990 else
11991 {
11992 if (REG_P (operand))
11993 {
11994 gcc_assert (reload_completed);
11995 parts[0] = gen_rtx_REG (SImode, REGNO (operand) + 0);
11996 parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
11997 if (size == 3)
11998 parts[2] = gen_rtx_REG (SImode, REGNO (operand) + 2);
11999 }
12000 else if (offsettable_memref_p (operand))
12001 {
12002 operand = adjust_address (operand, SImode, 0);
12003 parts[0] = operand;
12004 parts[1] = adjust_address (operand, SImode, 4);
12005 if (size == 3)
12006 parts[2] = adjust_address (operand, SImode, 8);
12007 }
12008 else if (GET_CODE (operand) == CONST_DOUBLE)
12009 {
12010 REAL_VALUE_TYPE r;
12011 long l[4];
12012
12013 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
12014 switch (mode)
12015 {
12016 case XFmode:
12017 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
12018 parts[2] = gen_int_mode (l[2], SImode);
12019 break;
12020 case DFmode:
12021 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
12022 break;
12023 default:
12024 gcc_unreachable ();
12025 }
12026 parts[1] = gen_int_mode (l[1], SImode);
12027 parts[0] = gen_int_mode (l[0], SImode);
12028 }
12029 else
12030 gcc_unreachable ();
12031 }
12032 }
12033 else
12034 {
12035 if (mode == TImode)
12036 split_ti (&operand, 1, &parts[0], &parts[1]);
12037 if (mode == XFmode || mode == TFmode)
12038 {
12039 enum machine_mode upper_mode = mode==XFmode ? SImode : DImode;
12040 if (REG_P (operand))
12041 {
12042 gcc_assert (reload_completed);
12043 parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
12044 parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
12045 }
12046 else if (offsettable_memref_p (operand))
12047 {
12048 operand = adjust_address (operand, DImode, 0);
12049 parts[0] = operand;
12050 parts[1] = adjust_address (operand, upper_mode, 8);
12051 }
12052 else if (GET_CODE (operand) == CONST_DOUBLE)
12053 {
12054 REAL_VALUE_TYPE r;
12055 long l[4];
12056
12057 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
12058 real_to_target (l, &r, mode);
12059
12060
12061 if (HOST_BITS_PER_WIDE_INT >= 64)
12062 parts[0]
12063 = gen_int_mode
12064 ((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1))
12065 + ((((HOST_WIDE_INT) l[1]) << 31) << 1),
12066 DImode);
12067 else
12068 parts[0] = immed_double_const (l[0], l[1], DImode);
12069
12070 if (upper_mode == SImode)
12071 parts[1] = gen_int_mode (l[2], SImode);
12072 else if (HOST_BITS_PER_WIDE_INT >= 64)
12073 parts[1]
12074 = gen_int_mode
12075 ((l[2] & (((HOST_WIDE_INT) 2 << 31) - 1))
12076 + ((((HOST_WIDE_INT) l[3]) << 31) << 1),
12077 DImode);
12078 else
12079 parts[1] = immed_double_const (l[2], l[3], DImode);
12080 }
12081 else
12082 gcc_unreachable ();
12083 }
12084 }
12085
12086 return size;
12087 }
12088
12089
12090
12091
12092
12093
12094 void
12095 ix86_split_long_move (rtx operands[])
12096 {
12097 rtx part[2][3];
12098 int nparts;
12099 int push = 0;
12100 int collisions = 0;
12101 enum machine_mode mode = GET_MODE (operands[0]);
12102
12103
12104
12105
12106 if (GET_MODE_SIZE (GET_MODE (operands[0])) == 8 && TARGET_64BIT)
12107 {
12108
12109
12110
12111 if (GET_CODE (operands[1]) == MEM
12112 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
12113 && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
12114 operands[1] = get_pool_constant (XEXP (operands[1], 0));
12115 if (push_operand (operands[0], VOIDmode))
12116 {
12117 operands[0] = copy_rtx (operands[0]);
12118 PUT_MODE (operands[0], Pmode);
12119 }
12120 else
12121 operands[0] = gen_lowpart (DImode, operands[0]);
12122 operands[1] = gen_lowpart (DImode, operands[1]);
12123 emit_move_insn (operands[0], operands[1]);
12124 return;
12125 }
12126
12127
12128 if (push_operand (operands[0], VOIDmode))
12129 push = 1;
12130 else
12131 gcc_assert (GET_CODE (operands[0]) != MEM
12132 || offsettable_memref_p (operands[0]));
12133
12134 nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
12135 ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
12136
12137
12138 if (push && GET_CODE (operands[1]) == MEM
12139 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
12140 {
12141 if (nparts == 3)
12142 part[1][1] = change_address (part[1][1], GET_MODE (part[1][1]),
12143 XEXP (part[1][2], 0));
12144 part[1][0] = change_address (part[1][0], GET_MODE (part[1][0]),
12145 XEXP (part[1][1], 0));
12146 }
12147
12148
12149
12150 if (REG_P (part[0][0]) && GET_CODE (part[1][0]) == MEM)
12151 {
12152 if (reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0)))
12153 collisions++;
12154 if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
12155 collisions++;
12156 if (nparts == 3
12157 && reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
12158 collisions++;
12159
12160
12161 if (collisions == 1 && nparts == 3
12162 && reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
12163 {
12164 rtx tmp;
12165 tmp = part[0][1]; part[0][1] = part[0][2]; part[0][2] = tmp;
12166 tmp = part[1][1]; part[1][1] = part[1][2]; part[1][2] = tmp;
12167 }
12168
12169
12170
12171 else if (collisions > 1)
12172 {
12173 rtx base;
12174
12175 collisions = 1;
12176
12177 base = part[0][nparts - 1];
12178
12179
12180
12181 if (GET_MODE (base) != Pmode)
12182 base = gen_rtx_REG (Pmode, REGNO (base));
12183
12184 emit_insn (gen_rtx_SET (VOIDmode, base, XEXP (part[1][0], 0)));
12185 part[1][0] = replace_equiv_address (part[1][0], base);
12186 part[1][1] = replace_equiv_address (part[1][1],
12187 plus_constant (base, UNITS_PER_WORD));
12188 if (nparts == 3)
12189 part[1][2] = replace_equiv_address (part[1][2],
12190 plus_constant (base, 8));
12191 }
12192 }
12193
12194 if (push)
12195 {
12196 if (!TARGET_64BIT)
12197 {
12198 if (nparts == 3)
12199 {
12200 if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
12201 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-4)));
12202 emit_move_insn (part[0][2], part[1][2]);
12203 }
12204 }
12205 else
12206 {
12207
12208
12209
12210
12211 if (GET_MODE (part[1][1]) == SImode)
12212 {
12213 switch (GET_CODE (part[1][1]))
12214 {
12215 case MEM:
12216 part[1][1] = adjust_address (part[1][1], DImode, 0);
12217 break;
12218
12219 case REG:
12220 part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
12221 break;
12222
12223 default:
12224 gcc_unreachable ();
12225 }
12226
12227 if (GET_MODE (part[1][0]) == SImode)
12228 part[1][0] = part[1][1];
12229 }
12230 }
12231 emit_move_insn (part[0][1], part[1][1]);
12232 emit_move_insn (part[0][0], part[1][0]);
12233 return;
12234 }
12235
12236
12237 if ((REG_P (part[0][0])
12238 && REG_P (part[1][1])
12239 && (REGNO (part[0][0]) == REGNO (part[1][1])
12240 || (nparts == 3
12241 && REGNO (part[0][0]) == REGNO (part[1][2]))))
12242 || (collisions > 0
12243 && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
12244 {
12245 if (nparts == 3)
12246 {
12247 operands[2] = part[0][2];
12248 operands[3] = part[0][1];
12249 operands[4] = part[0][0];
12250 operands[5] = part[1][2];
12251 operands[6] = part[1][1];
12252 operands[7] = part[1][0];
12253 }
12254 else
12255 {
12256 operands[2] = part[0][1];
12257 operands[3] = part[0][0];
12258 operands[5] = part[1][1];
12259 operands[6] = part[1][0];
12260 }
12261 }
12262 else
12263 {
12264 if (nparts == 3)
12265 {
12266 operands[2] = part[0][0];
12267 operands[3] = part[0][1];
12268 operands[4] = part[0][2];
12269 operands[5] = part[1][0];
12270 operands[6] = part[1][1];
12271 operands[7] = part[1][2];
12272 }
12273 else
12274 {
12275 operands[2] = part[0][0];
12276 operands[3] = part[0][1];
12277 operands[5] = part[1][0];
12278 operands[6] = part[1][1];
12279 }
12280 }
12281
12282
12283 if (optimize_size)
12284 {
12285 if (GET_CODE (operands[5]) == CONST_INT
12286 && operands[5] != const0_rtx
12287 && REG_P (operands[2]))
12288 {
12289 if (GET_CODE (operands[6]) == CONST_INT
12290 && INTVAL (operands[6]) == INTVAL (operands[5]))
12291 operands[6] = operands[2];
12292
12293 if (nparts == 3
12294 && GET_CODE (operands[7]) == CONST_INT
12295 && INTVAL (operands[7]) == INTVAL (operands[5]))
12296 operands[7] = operands[2];
12297 }
12298
12299 if (nparts == 3
12300 && GET_CODE (operands[6]) == CONST_INT
12301 && operands[6] != const0_rtx
12302 && REG_P (operands[3])
12303 && GET_CODE (operands[7]) == CONST_INT
12304 && INTVAL (operands[7]) == INTVAL (operands[6]))
12305 operands[7] = operands[3];
12306 }
12307
12308 emit_move_insn (operands[2], operands[5]);
12309 emit_move_insn (operands[3], operands[6]);
12310 if (nparts == 3)
12311 emit_move_insn (operands[4], operands[7]);
12312
12313 return;
12314 }
12315
12316
12317
12318
12319
12320 static void
12321 ix86_expand_ashl_const (rtx operand, int count, enum machine_mode mode)
12322 {
12323 if (count == 1)
12324 {
12325 emit_insn ((mode == DImode
12326 ? gen_addsi3
12327 : gen_adddi3) (operand, operand, operand));
12328 }
12329 else if (!optimize_size
12330 && count * ix86_cost->add <= ix86_cost->shift_const)
12331 {
12332 int i;
12333 for (i=0; i<count; i++)
12334 {
12335 emit_insn ((mode == DImode
12336 ? gen_addsi3
12337 : gen_adddi3) (operand, operand, operand));
12338 }
12339 }
12340 else
12341 emit_insn ((mode == DImode
12342 ? gen_ashlsi3
12343 : gen_ashldi3) (operand, operand, GEN_INT (count)));
12344 }
12345
12346 void
12347 ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode)
12348 {
12349 rtx low[2], high[2];
12350 int count;
12351 const int single_width = mode == DImode ? 32 : 64;
12352
12353 if (GET_CODE (operands[2]) == CONST_INT)
12354 {
12355 (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
12356 count = INTVAL (operands[2]) & (single_width * 2 - 1);
12357
12358 if (count >= single_width)
12359 {
12360 emit_move_insn (high[0], low[1]);
12361 emit_move_insn (low[0], const0_rtx);
12362
12363 if (count > single_width)
12364 ix86_expand_ashl_const (high[0], count - single_width, mode);
12365 }
12366 else
12367 {
12368 if (!rtx_equal_p (operands[0], operands[1]))
12369 emit_move_insn (operands[0], operands[1]);
12370 emit_insn ((mode == DImode
12371 ? gen_x86_shld_1
12372 : gen_x86_64_shld) (high[0], low[0], GEN_INT (count)));
12373 ix86_expand_ashl_const (low[0], count, mode);
12374 }
12375 return;
12376 }
12377
12378 (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
12379
12380 if (operands[1] == const1_rtx)
12381 {
12382
12383
12384 if (ANY_QI_REG_P (low[0]) && ANY_QI_REG_P (high[0]))
12385 {
12386 rtx s, d, flags = gen_rtx_REG (CCZmode, FLAGS_REG);
12387
12388 ix86_expand_clear (low[0]);
12389 ix86_expand_clear (high[0]);
12390 emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (single_width)));
12391
12392 d = gen_lowpart (QImode, low[0]);
12393 d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
12394 s = gen_rtx_EQ (QImode, flags, const0_rtx);
12395 emit_insn (gen_rtx_SET (VOIDmode, d, s));
12396
12397 d = gen_lowpart (QImode, high[0]);
12398 d = gen_rtx_STRICT_LOW_PART (VOIDmode, d);
12399 s = gen_rtx_NE (QImode, flags, const0_rtx);
12400 emit_insn (gen_rtx_SET (VOIDmode, d, s));
12401 }
12402
12403
12404
12405
12406
12407
12408 else
12409 {
12410 rtx x;
12411
12412 if (TARGET_PARTIAL_REG_STALL && !optimize_size)
12413 x = gen_rtx_ZERO_EXTEND (mode == DImode ? SImode : DImode, operands[2]);
12414 else
12415 x = gen_lowpart (mode == DImode ? SImode : DImode, operands[2]);
12416 emit_insn (gen_rtx_SET (VOIDmode, high[0], x));
12417
12418 emit_insn ((mode == DImode
12419 ? gen_lshrsi3
12420 : gen_lshrdi3) (high[0], high[0], GEN_INT (mode == DImode ? 5 : 6)));
12421 emit_insn ((mode == DImode
12422 ? gen_andsi3
12423 : gen_anddi3) (high[0], high[0], GEN_INT (1)));
12424 emit_move_insn (low[0], high[0]);
12425 emit_insn ((mode == DImode
12426 ? gen_xorsi3
12427 : gen_xordi3) (low[0], low[0], GEN_INT (1)));
12428 }
12429
12430 emit_insn ((mode == DImode
12431 ? gen_ashlsi3
12432 : gen_ashldi3) (low[0], low[0], operands[2]));
12433 emit_insn ((mode == DImode
12434 ? gen_ashlsi3
12435 : gen_ashldi3) (high[0], high[0], operands[2]));
12436 return;
12437 }
12438
12439 if (operands[1] == constm1_rtx)
12440 {
12441
12442
12443 emit_move_insn (low[0], constm1_rtx);
12444 if (optimize_size)
12445 emit_move_insn (high[0], low[0]);
12446 else
12447 emit_move_insn (high[0], constm1_rtx);
12448 }
12449 else
12450 {
12451 if (!rtx_equal_p (operands[0], operands[1]))
12452 emit_move_insn (operands[0], operands[1]);
12453
12454 (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
12455 emit_insn ((mode == DImode
12456 ? gen_x86_shld_1
12457 : gen_x86_64_shld) (high[0], low[0], operands[2]));
12458 }
12459
12460 emit_insn ((mode == DImode ? gen_ashlsi3 : gen_ashldi3) (low[0], low[0], operands[2]));
12461
12462 if (TARGET_CMOVE && scratch)
12463 {
12464 ix86_expand_clear (scratch);
12465 emit_insn ((mode == DImode
12466 ? gen_x86_shift_adj_1
12467 : gen_x86_64_shift_adj) (high[0], low[0], operands[2], scratch));
12468 }
12469 else
12470 emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2]));
12471 }
12472
12473 void
12474 ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode)
12475 {
12476 rtx low[2], high[2];
12477 int count;
12478 const int single_width = mode == DImode ? 32 : 64;
12479
12480 if (GET_CODE (operands[2]) == CONST_INT)
12481 {
12482 (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
12483 count = INTVAL (operands[2]) & (single_width * 2 - 1);
12484
12485 if (count == single_width * 2 - 1)
12486 {
12487 emit_move_insn (high[0], high[1]);
12488 emit_insn ((mode == DImode
12489 ? gen_ashrsi3
12490 : gen_ashrdi3) (high[0], high[0],
12491 GEN_INT (single_width - 1)));
12492 emit_move_insn (low[0], high[0]);
12493
12494 }
12495 else if (count >= single_width)
12496 {
12497 emit_move_insn (low[0], high[1]);
12498 emit_move_insn (high[0], low[0]);
12499 emit_insn ((mode == DImode
12500 ? gen_ashrsi3
12501 : gen_ashrdi3) (high[0], high[0],
12502 GEN_INT (single_width - 1)));
12503 if (count > single_width)
12504 emit_insn ((mode == DImode
12505 ? gen_ashrsi3
12506 : gen_ashrdi3) (low[0], low[0],
12507 GEN_INT (count - single_width)));
12508 }
12509 else
12510 {
12511 if (!rtx_equal_p (operands[0], operands[1]))
12512 emit_move_insn (operands[0], operands[1]);
12513 emit_insn ((mode == DImode
12514 ? gen_x86_shrd_1
12515 : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
12516 emit_insn ((mode == DImode
12517 ? gen_ashrsi3
12518 : gen_ashrdi3) (high[0], high[0], GEN_INT (count)));
12519 }
12520 }
12521 else
12522 {
12523 if (!rtx_equal_p (operands[0], operands[1]))
12524 emit_move_insn (operands[0], operands[1]);
12525
12526 (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
12527
12528 emit_insn ((mode == DImode
12529 ? gen_x86_shrd_1
12530 : gen_x86_64_shrd) (low[0], high[0], operands[2]));
12531 emit_insn ((mode == DImode
12532 ? gen_ashrsi3
12533 : gen_ashrdi3) (high[0], high[0], operands[2]));
12534
12535 if (TARGET_CMOVE && scratch)
12536 {
12537 emit_move_insn (scratch, high[0]);
12538 emit_insn ((mode == DImode
12539 ? gen_ashrsi3
12540 : gen_ashrdi3) (scratch, scratch,
12541 GEN_INT (single_width - 1)));
12542 emit_insn ((mode == DImode
12543 ? gen_x86_shift_adj_1
12544 : gen_x86_64_shift_adj) (low[0], high[0], operands[2],
12545 scratch));
12546 }
12547 else
12548 emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2]));
12549 }
12550 }
12551
12552 void
12553 ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode)
12554 {
12555 rtx low[2], high[2];
12556 int count;
12557 const int single_width = mode == DImode ? 32 : 64;
12558
12559 if (GET_CODE (operands[2]) == CONST_INT)
12560 {
12561 (mode == DImode ? split_di : split_ti) (operands, 2, low, high);
12562 count = INTVAL (operands[2]) & (single_width * 2 - 1);
12563
12564 if (count >= single_width)
12565 {
12566 emit_move_insn (low[0], high[1]);
12567 ix86_expand_clear (high[0]);
12568
12569 if (count > single_width)
12570 emit_insn ((mode == DImode
12571 ? gen_lshrsi3
12572 : gen_lshrdi3) (low[0], low[0],
12573 GEN_INT (count - single_width)));
12574 }
12575 else
12576 {
12577 if (!rtx_equal_p (operands[0], operands[1]))
12578 emit_move_insn (operands[0], operands[1]);
12579 emit_insn ((mode == DImode
12580 ? gen_x86_shrd_1
12581 : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
12582 emit_insn ((mode == DImode
12583 ? gen_lshrsi3
12584 : gen_lshrdi3) (high[0], high[0], GEN_INT (count)));
12585 }
12586 }
12587 else
12588 {
12589 if (!rtx_equal_p (operands[0], operands[1]))
12590 emit_move_insn (operands[0], operands[1]);
12591
12592 (mode == DImode ? split_di : split_ti) (operands, 1, low, high);
12593
12594 emit_insn ((mode == DImode
12595 ? gen_x86_shrd_1
12596 : gen_x86_64_shrd) (low[0], high[0], operands[2]));
12597 emit_insn ((mode == DImode
12598 ? gen_lshrsi3
12599 : gen_lshrdi3) (high[0], high[0], operands[2]));
12600
12601
12602 if (TARGET_CMOVE && scratch)
12603 {
12604 ix86_expand_clear (scratch);
12605 emit_insn ((mode == DImode
12606 ? gen_x86_shift_adj_1
12607 : gen_x86_64_shift_adj) (low[0], high[0], operands[2],
12608 scratch));
12609 }
12610 else
12611 emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2]));
12612 }
12613 }
12614
12615
12616
12617 static rtx
12618 ix86_expand_aligntest (rtx variable, int value)
12619 {
12620 rtx label = gen_label_rtx ();
12621 rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
12622 if (GET_MODE (variable) == DImode)
12623 emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
12624 else
12625 emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
12626 emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
12627 1, label);
12628 return label;
12629 }
12630
12631
12632 static void
12633 ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
12634 {
12635 if (GET_MODE (countreg) == DImode)
12636 emit_insn (gen_adddi3 (countreg, countreg, GEN_INT (-value)));
12637 else
12638 emit_insn (gen_addsi3 (countreg, countreg, GEN_INT (-value)));
12639 }
12640
12641
12642 rtx
12643 ix86_zero_extend_to_Pmode (rtx exp)
12644 {
12645 rtx r;
12646 if (GET_MODE (exp) == VOIDmode)
12647 return force_reg (Pmode, exp);
12648 if (GET_MODE (exp) == Pmode)
12649 return copy_to_mode_reg (Pmode, exp);
12650 r = gen_reg_rtx (Pmode);
12651 emit_insn (gen_zero_extendsidi2 (r, exp));
12652 return r;
12653 }
12654
12655
12656
12657 int
12658 ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
12659 {
12660 rtx srcreg, destreg, countreg, srcexp, destexp;
12661 enum machine_mode counter_mode;
12662 HOST_WIDE_INT align = 0;
12663 unsigned HOST_WIDE_INT count = 0;
12664
12665 if (GET_CODE (align_exp) == CONST_INT)
12666 align = INTVAL (align_exp);
12667
12668
12669 if (global_regs[4] || global_regs[5])
12670 return 0;
12671
12672
12673 if (!TARGET_ALIGN_STRINGOPS)
12674 align = 64;
12675
12676 if (GET_CODE (count_exp) == CONST_INT)
12677 {
12678 count = INTVAL (count_exp);
12679 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
12680 return 0;
12681 }
12682
12683
12684
12685
12686 if (!TARGET_64BIT
12687 || GET_MODE (count_exp) == SImode
12688 || x86_64_zext_immediate_operand (count_exp, VOIDmode))
12689 counter_mode = SImode;
12690 else
12691 counter_mode = DImode;
12692
12693 gcc_assert (counter_mode == SImode || counter_mode == DImode);
12694
12695 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
12696 if (destreg != XEXP (dst, 0))
12697 dst = replace_equiv_address_nv (dst, destreg);
12698 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
12699 if (srcreg != XEXP (src, 0))
12700 src = replace_equiv_address_nv (src, srcreg);
12701
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711 if ((!optimize || optimize_size)
12712 && (count == 0
12713 || ((count & 0x03)
12714 && (!optimize_size
12715 || count > 5 * 4
12716 || (count & 3) + count / 4 > 6))))
12717 {
12718 emit_insn (gen_cld ());
12719 countreg = ix86_zero_extend_to_Pmode (count_exp);
12720 destexp = gen_rtx_PLUS (Pmode, destreg, countreg);
12721 srcexp = gen_rtx_PLUS (Pmode, srcreg, countreg);
12722 emit_insn (gen_rep_mov (destreg, dst, srcreg, src, countreg,
12723 destexp, srcexp));
12724 }
12725
12726
12727
12728
12729
12730 else if (count != 0
12731 && (align >= 8
12732 || (!TARGET_PENTIUMPRO && !TARGET_64BIT && align >= 4)
12733 || optimize_size || count < (unsigned int) 64))
12734 {
12735 unsigned HOST_WIDE_INT offset = 0;
12736 int size = TARGET_64BIT && !optimize_size ? 8 : 4;
12737 rtx srcmem, dstmem;
12738
12739 emit_insn (gen_cld ());
12740 if (count & ~(size - 1))
12741 {
12742 if ((TARGET_SINGLE_STRINGOP || optimize_size) && count < 5 * 4)
12743 {
12744 enum machine_mode movs_mode = size == 4 ? SImode : DImode;
12745
12746 while (offset < (count & ~(size - 1)))
12747 {
12748 srcmem = adjust_automodify_address_nv (src, movs_mode,
12749 srcreg, offset);
12750 dstmem = adjust_automodify_address_nv (dst, movs_mode,
12751 destreg, offset);
12752 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12753 offset += size;
12754 }
12755 }
12756 else
12757 {
12758 countreg = GEN_INT ((count >> (size == 4 ? 2 : 3))
12759 & (TARGET_64BIT ? -1 : 0x3fffffff));
12760 countreg = copy_to_mode_reg (counter_mode, countreg);
12761 countreg = ix86_zero_extend_to_Pmode (countreg);
12762
12763 destexp = gen_rtx_ASHIFT (Pmode, countreg,
12764 GEN_INT (size == 4 ? 2 : 3));
12765 srcexp = gen_rtx_PLUS (Pmode, destexp, srcreg);
12766 destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
12767
12768 emit_insn (gen_rep_mov (destreg, dst, srcreg, src,
12769 countreg, destexp, srcexp));
12770 offset = count & ~(size - 1);
12771 }
12772 }
12773 if (size == 8 && (count & 0x04))
12774 {
12775 srcmem = adjust_automodify_address_nv (src, SImode, srcreg,
12776 offset);
12777 dstmem = adjust_automodify_address_nv (dst, SImode, destreg,
12778 offset);
12779 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12780 offset += 4;
12781 }
12782 if (count & 0x02)
12783 {
12784 srcmem = adjust_automodify_address_nv (src, HImode, srcreg,
12785 offset);
12786 dstmem = adjust_automodify_address_nv (dst, HImode, destreg,
12787 offset);
12788 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12789 offset += 2;
12790 }
12791 if (count & 0x01)
12792 {
12793 srcmem = adjust_automodify_address_nv (src, QImode, srcreg,
12794 offset);
12795 dstmem = adjust_automodify_address_nv (dst, QImode, destreg,
12796 offset);
12797 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12798 }
12799 }
12800
12801
12802
12803
12804
12805 else
12806 {
12807 rtx countreg2;
12808 rtx label = NULL;
12809 rtx srcmem, dstmem;
12810 int desired_alignment = (TARGET_PENTIUMPRO
12811 && (count == 0 || count >= (unsigned int) 260)
12812 ? 8 : UNITS_PER_WORD);
12813
12814 dst = change_address (dst, BLKmode, destreg);
12815 src = change_address (src, BLKmode, srcreg);
12816
12817
12818
12819
12820
12821
12822
12823 if (!TARGET_INLINE_ALL_STRINGOPS
12824 && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
12825 return 0;
12826
12827 if (TARGET_SINGLE_STRINGOP)
12828 emit_insn (gen_cld ());
12829
12830 countreg2 = gen_reg_rtx (Pmode);
12831 countreg = copy_to_mode_reg (counter_mode, count_exp);
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846 if (count == 0 && align < desired_alignment)
12847 {
12848 label = gen_label_rtx ();
12849 emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
12850 LEU, 0, counter_mode, 1, label);
12851 }
12852 if (align <= 1)
12853 {
12854 rtx label = ix86_expand_aligntest (destreg, 1);
12855 srcmem = change_address (src, QImode, srcreg);
12856 dstmem = change_address (dst, QImode, destreg);
12857 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12858 ix86_adjust_counter (countreg, 1);
12859 emit_label (label);
12860 LABEL_NUSES (label) = 1;
12861 }
12862 if (align <= 2)
12863 {
12864 rtx label = ix86_expand_aligntest (destreg, 2);
12865 srcmem = change_address (src, HImode, srcreg);
12866 dstmem = change_address (dst, HImode, destreg);
12867 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12868 ix86_adjust_counter (countreg, 2);
12869 emit_label (label);
12870 LABEL_NUSES (label) = 1;
12871 }
12872 if (align <= 4 && desired_alignment > 4)
12873 {
12874 rtx label = ix86_expand_aligntest (destreg, 4);
12875 srcmem = change_address (src, SImode, srcreg);
12876 dstmem = change_address (dst, SImode, destreg);
12877 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12878 ix86_adjust_counter (countreg, 4);
12879 emit_label (label);
12880 LABEL_NUSES (label) = 1;
12881 }
12882
12883 if (label && desired_alignment > 4 && !TARGET_64BIT)
12884 {
12885 emit_label (label);
12886 LABEL_NUSES (label) = 1;
12887 label = NULL_RTX;
12888 }
12889 if (!TARGET_SINGLE_STRINGOP)
12890 emit_insn (gen_cld ());
12891 if (TARGET_64BIT)
12892 {
12893 emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
12894 GEN_INT (3)));
12895 destexp = gen_rtx_ASHIFT (Pmode, countreg2, GEN_INT (3));
12896 }
12897 else
12898 {
12899 emit_insn (gen_lshrsi3 (countreg2, countreg, const2_rtx));
12900 destexp = gen_rtx_ASHIFT (Pmode, countreg2, const2_rtx);
12901 }
12902 srcexp = gen_rtx_PLUS (Pmode, destexp, srcreg);
12903 destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
12904 emit_insn (gen_rep_mov (destreg, dst, srcreg, src,
12905 countreg2, destexp, srcexp));
12906
12907 if (label)
12908 {
12909 emit_label (label);
12910 LABEL_NUSES (label) = 1;
12911 }
12912 if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
12913 {
12914 srcmem = change_address (src, SImode, srcreg);
12915 dstmem = change_address (dst, SImode, destreg);
12916 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12917 }
12918 if ((align <= 4 || count == 0) && TARGET_64BIT)
12919 {
12920 rtx label = ix86_expand_aligntest (countreg, 4);
12921 srcmem = change_address (src, SImode, srcreg);
12922 dstmem = change_address (dst, SImode, destreg);
12923 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12924 emit_label (label);
12925 LABEL_NUSES (label) = 1;
12926 }
12927 if (align > 2 && count != 0 && (count & 2))
12928 {
12929 srcmem = change_address (src, HImode, srcreg);
12930 dstmem = change_address (dst, HImode, destreg);
12931 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12932 }
12933 if (align <= 2 || count == 0)
12934 {
12935 rtx label = ix86_expand_aligntest (countreg, 2);
12936 srcmem = change_address (src, HImode, srcreg);
12937 dstmem = change_address (dst, HImode, destreg);
12938 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12939 emit_label (label);
12940 LABEL_NUSES (label) = 1;
12941 }
12942 if (align > 1 && count != 0 && (count & 1))
12943 {
12944 srcmem = change_address (src, QImode, srcreg);
12945 dstmem = change_address (dst, QImode, destreg);
12946 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12947 }
12948 if (align <= 1 || count == 0)
12949 {
12950 rtx label = ix86_expand_aligntest (countreg, 1);
12951 srcmem = change_address (src, QImode, srcreg);
12952 dstmem = change_address (dst, QImode, destreg);
12953 emit_insn (gen_strmov (destreg, dstmem, srcreg, srcmem));
12954 emit_label (label);
12955 LABEL_NUSES (label) = 1;
12956 }
12957 }
12958
12959 return 1;
12960 }
12961
12962
12963
12964 int
12965 ix86_expand_clrmem (rtx dst, rtx count_exp, rtx align_exp)
12966 {
12967 rtx destreg, zeroreg, countreg, destexp;
12968 enum machine_mode counter_mode;
12969 HOST_WIDE_INT align = 0;
12970 unsigned HOST_WIDE_INT count = 0;
12971
12972 if (GET_CODE (align_exp) == CONST_INT)
12973 align = INTVAL (align_exp);
12974
12975
12976 if (global_regs[4])
12977 return 0;
12978
12979
12980 if (!TARGET_ALIGN_STRINGOPS)
12981 align = 32;
12982
12983 if (GET_CODE (count_exp) == CONST_INT)
12984 {
12985 count = INTVAL (count_exp);
12986 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
12987 return 0;
12988 }
12989
12990
12991
12992 if (!TARGET_64BIT
12993 || GET_MODE (count_exp) == SImode
12994 || x86_64_zext_immediate_operand (count_exp, VOIDmode))
12995 counter_mode = SImode;
12996 else
12997 counter_mode = DImode;
12998
12999 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
13000 if (destreg != XEXP (dst, 0))
13001 dst = replace_equiv_address_nv (dst, destreg);
13002
13003
13004
13005
13006
13007
13008
13009
13010 if ((!optimize || optimize_size)
13011 && (count == 0
13012 || ((count & 0x03)
13013 && (!optimize_size || (count & 0x03) + (count >> 2) > 7))))
13014 {
13015 emit_insn (gen_cld ());
13016
13017 countreg = ix86_zero_extend_to_Pmode (count_exp);
13018 zeroreg = copy_to_mode_reg (QImode, const0_rtx);
13019 destexp = gen_rtx_PLUS (Pmode, destreg, countreg);
13020 emit_insn (gen_rep_stos (destreg, countreg, dst, zeroreg, destexp));
13021 }
13022 else if (count != 0
13023 && (align >= 8
13024 || (!TARGET_PENTIUMPRO && !TARGET_64BIT && align >= 4)
13025 || optimize_size || count < (unsigned int) 64))
13026 {
13027 int size = TARGET_64BIT && !optimize_size ? 8 : 4;
13028 unsigned HOST_WIDE_INT offset = 0;
13029
13030 emit_insn (gen_cld ());
13031
13032 zeroreg = copy_to_mode_reg (size == 4 ? SImode : DImode, const0_rtx);
13033 if (count & ~(size - 1))
13034 {
13035 unsigned HOST_WIDE_INT repcount;
13036 unsigned int max_nonrep;
13037
13038 repcount = count >> (size == 4 ? 2 : 3);
13039 if (!TARGET_64BIT)
13040 repcount &= 0x3fffffff;
13041
13042
13043
13044
13045
13046 max_nonrep = size == 4 ? 7 : 4;
13047 if (!optimize_size)
13048 switch (ix86_tune)
13049 {
13050 case PROCESSOR_PENTIUM4:
13051 case PROCESSOR_NOCONA:
13052 max_nonrep = 3;
13053 break;
13054 default:
13055 break;
13056 }
13057
13058 if (repcount <= max_nonrep)
13059 while (repcount-- > 0)
13060 {
13061 rtx mem = adjust_automodify_address_nv (dst,
13062 GET_MODE (zeroreg),
13063 destreg, offset);
13064 emit_insn (gen_strset (destreg, mem, zeroreg));
13065 offset += size;
13066 }
13067 else
13068 {
13069 countreg = copy_to_mode_reg (counter_mode, GEN_INT (repcount));
13070 countreg = ix86_zero_extend_to_Pmode (countreg);
13071 destexp = gen_rtx_ASHIFT (Pmode, countreg,
13072 GEN_INT (size == 4 ? 2 : 3));
13073 destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
13074 emit_insn (gen_rep_stos (destreg, countreg, dst, zeroreg,
13075 destexp));
13076 offset = count & ~(size - 1);
13077 }
13078 }
13079 if (size == 8 && (count & 0x04))
13080 {
13081 rtx mem = adjust_automodify_address_nv (dst, SImode, destreg,
13082 offset);
13083 emit_insn (gen_strset (destreg, mem,
13084 gen_rtx_SUBREG (SImode, zeroreg, 0)));
13085 offset += 4;
13086 }
13087 if (count & 0x02)
13088 {
13089 rtx mem = adjust_automodify_address_nv (dst, HImode, destreg,
13090 offset);
13091 emit_insn (gen_strset (destreg, mem,
13092 gen_rtx_SUBREG (HImode, zeroreg, 0)));
13093 offset += 2;
13094 }
13095 if (count & 0x01)
13096 {
13097 rtx mem = adjust_automodify_address_nv (dst, QImode, destreg,
13098 offset);
13099 emit_insn (gen_strset (destreg, mem,
13100 gen_rtx_SUBREG (QImode, zeroreg, 0)));
13101 }
13102 }
13103 else
13104 {
13105 rtx countreg2;
13106 rtx label = NULL;
13107
13108 int desired_alignment = (TARGET_PENTIUMPRO
13109 && (count == 0 || count >= (unsigned int) 260)
13110 ? 8 : UNITS_PER_WORD);
13111
13112
13113
13114
13115
13116
13117
13118 if (!TARGET_INLINE_ALL_STRINGOPS
13119 && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
13120 return 0;
13121
13122 if (TARGET_SINGLE_STRINGOP)
13123 emit_insn (gen_cld ());
13124
13125 countreg2 = gen_reg_rtx (Pmode);
13126 countreg = copy_to_mode_reg (counter_mode, count_exp);
13127 zeroreg = copy_to_mode_reg (Pmode, const0_rtx);
13128
13129 dst = change_address (dst, BLKmode, destreg);
13130
13131 if (count == 0 && align < desired_alignment)
13132 {
13133 label = gen_label_rtx ();
13134 emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
13135 LEU, 0, counter_mode, 1, label);
13136 }
13137 if (align <= 1)
13138 {
13139 rtx label = ix86_expand_aligntest (destreg, 1);
13140 emit_insn (gen_strset (destreg, dst,
13141 gen_rtx_SUBREG (QImode, zeroreg, 0)));
13142 ix86_adjust_counter (countreg, 1);
13143 emit_label (label);
13144 LABEL_NUSES (label) = 1;
13145 }
13146 if (align <= 2)
13147 {
13148 rtx label = ix86_expand_aligntest (destreg, 2);
13149 emit_insn (gen_strset (destreg, dst,
13150 gen_rtx_SUBREG (HImode, zeroreg, 0)));
13151 ix86_adjust_counter (countreg, 2);
13152 emit_label (label);
13153 LABEL_NUSES (label) = 1;
13154 }
13155 if (align <= 4 && desired_alignment > 4)
13156 {
13157 rtx label = ix86_expand_aligntest (destreg, 4);
13158 emit_insn (gen_strset (destreg, dst,
13159 (TARGET_64BIT
13160 ? gen_rtx_SUBREG (SImode, zeroreg, 0)
13161 : zeroreg)));
13162 ix86_adjust_counter (countreg, 4);
13163 emit_label (label);
13164 LABEL_NUSES (label) = 1;
13165 }
13166
13167 if (label && desired_alignment > 4 && !TARGET_64BIT)
13168 {
13169 emit_label (label);
13170 LABEL_NUSES (label) = 1;
13171 label = NULL_RTX;
13172 }
13173
13174 if (!TARGET_SINGLE_STRINGOP)
13175 emit_insn (gen_cld ());
13176 if (TARGET_64BIT)
13177 {
13178 emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
13179 GEN_INT (3)));
13180 destexp = gen_rtx_ASHIFT (Pmode, countreg2, GEN_INT (3));
13181 }
13182 else
13183 {
13184 emit_insn (gen_lshrsi3 (countreg2, countreg, const2_rtx));
13185 destexp = gen_rtx_ASHIFT (Pmode, countreg2, const2_rtx);
13186 }
13187 destexp = gen_rtx_PLUS (Pmode, destexp, destreg);
13188 emit_insn (gen_rep_stos (destreg, countreg2, dst, zeroreg, destexp));
13189
13190 if (label)
13191 {
13192 emit_label (label);
13193 LABEL_NUSES (label) = 1;
13194 }
13195
13196 if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
13197 emit_insn (gen_strset (destreg, dst,
13198 gen_rtx_SUBREG (SImode, zeroreg, 0)));
13199 if (TARGET_64BIT && (align <= 4 || count == 0))
13200 {
13201 rtx label = ix86_expand_aligntest (countreg, 4);
13202 emit_insn (gen_strset (destreg, dst,
13203 gen_rtx_SUBREG (SImode, zeroreg, 0)));
13204 emit_label (label);
13205 LABEL_NUSES (label) = 1;
13206 }
13207 if (align > 2 && count != 0 && (count & 2))
13208 emit_insn (gen_strset (destreg, dst,
13209 gen_rtx_SUBREG (HImode, zeroreg, 0)));
13210 if (align <= 2 || count == 0)
13211 {
13212 rtx label = ix86_expand_aligntest (countreg, 2);
13213 emit_insn (gen_strset (destreg, dst,
13214 gen_rtx_SUBREG (HImode, zeroreg, 0)));
13215 emit_label (label);
13216 LABEL_NUSES (label) = 1;
13217 }
13218 if (align > 1 && count != 0 && (count & 1))
13219 emit_insn (gen_strset (destreg, dst,
13220 gen_rtx_SUBREG (QImode, zeroreg, 0)));
13221 if (align <= 1 || count == 0)
13222 {
13223 rtx label = ix86_expand_aligntest (countreg, 1);
13224 emit_insn (gen_strset (destreg, dst,
13225 gen_rtx_SUBREG (QImode, zeroreg, 0)));
13226 emit_label (label);
13227 LABEL_NUSES (label) = 1;
13228 }
13229 }
13230 return 1;
13231 }
13232
13233
13234 int
13235 ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
13236 {
13237 rtx addr, scratch1, scratch2, scratch3, scratch4;
13238
13239
13240
13241
13242 if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
13243 && !TARGET_INLINE_ALL_STRINGOPS
13244 && !optimize_size
13245 && (GET_CODE (align) != CONST_INT || INTVAL (align) < 4))
13246 return 0;
13247
13248 addr = force_reg (Pmode, XEXP (src, 0));
13249 scratch1 = gen_reg_rtx (Pmode);
13250
13251 if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
13252 && !optimize_size)
13253 {
13254
13255
13256
13257
13258
13259
13260
13261
13262 emit_move_insn (out, addr);
13263
13264 ix86_expand_strlensi_unroll_1 (out, src, align);
13265
13266
13267
13268
13269 if (TARGET_64BIT)
13270 emit_insn (gen_subdi3 (out, out, addr));
13271 else
13272 emit_insn (gen_subsi3 (out, out, addr));
13273 }
13274 else
13275 {
13276 rtx unspec;
13277 scratch2 = gen_reg_rtx (Pmode);
13278 scratch3 = gen_reg_rtx (Pmode);
13279 scratch4 = force_reg (Pmode, constm1_rtx);
13280
13281 emit_move_insn (scratch3, addr);
13282 eoschar = force_reg (QImode, eoschar);
13283
13284 emit_insn (gen_cld ());
13285 src = replace_equiv_address_nv (src, scratch3);
13286
13287
13288 unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (4, src, eoschar, align,
13289 scratch4), UNSPEC_SCAS);
13290 emit_insn (gen_strlenqi_1 (scratch1, scratch3, unspec));
13291 if (TARGET_64BIT)
13292 {
13293 emit_insn (gen_one_cmpldi2 (scratch2, scratch1));
13294 emit_insn (gen_adddi3 (out, scratch2, constm1_rtx));
13295 }
13296 else
13297 {
13298 emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
13299 emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
13300 }
13301 }
13302 return 1;
13303 }
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314
13315
13316 static void
13317 ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
13318 {
13319 int align;
13320 rtx tmp;
13321 rtx align_2_label = NULL_RTX;
13322 rtx align_3_label = NULL_RTX;
13323 rtx align_4_label = gen_label_rtx ();
13324 rtx end_0_label = gen_label_rtx ();
13325 rtx mem;
13326 rtx tmpreg = gen_reg_rtx (SImode);
13327 rtx scratch = gen_reg_rtx (SImode);
13328 rtx cmp;
13329
13330 align = 0;
13331 if (GET_CODE (align_rtx) == CONST_INT)
13332 align = INTVAL (align_rtx);
13333
13334
13335
13336
13337 if (align < 4)
13338 {
13339 rtx scratch1 = gen_reg_rtx (Pmode);
13340 emit_move_insn (scratch1, out);
13341
13342 if (align != 2)
13343 {
13344 align_3_label = gen_label_rtx ();
13345 align_2_label = gen_label_rtx ();
13346
13347
13348 align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
13349 NULL_RTX, 0, OPTAB_WIDEN);
13350
13351 emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
13352 Pmode, 1, align_4_label);
13353 emit_cmp_and_jump_insns (align_rtx, const2_rtx, EQ, NULL,
13354 Pmode, 1, align_2_label);
13355 emit_cmp_and_jump_insns (align_rtx, const2_rtx, GTU, NULL,
13356 Pmode, 1, align_3_label);
13357 }
13358 else
13359 {
13360
13361
13362
13363 align_rtx = expand_binop (Pmode, and_optab, scratch1, const2_rtx,
13364 NULL_RTX, 0, OPTAB_WIDEN);
13365
13366 emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
13367 Pmode, 1, align_4_label);
13368 }
13369
13370 mem = change_address (src, QImode, out);
13371
13372
13373
13374
13375 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
13376 QImode, 1, end_0_label);
13377
13378
13379 if (TARGET_64BIT)
13380 emit_insn (gen_adddi3 (out, out, const1_rtx));
13381 else
13382 emit_insn (gen_addsi3 (out, out, const1_rtx));
13383
13384
13385 if (align != 2)
13386 {
13387 emit_label (align_2_label);
13388
13389 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
13390 end_0_label);
13391
13392 if (TARGET_64BIT)
13393 emit_insn (gen_adddi3 (out, out, const1_rtx));
13394 else
13395 emit_insn (gen_addsi3 (out, out, const1_rtx));
13396
13397 emit_label (align_3_label);
13398 }
13399
13400 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
13401 end_0_label);
13402
13403 if (TARGET_64BIT)
13404 emit_insn (gen_adddi3 (out, out, const1_rtx));
13405 else
13406 emit_insn (gen_addsi3 (out, out, const1_rtx));
13407 }
13408
13409
13410
13411
13412 emit_label (align_4_label);
13413
13414 mem = change_address (src, SImode, out);
13415 emit_move_insn (scratch, mem);
13416 if (TARGET_64BIT)
13417 emit_insn (gen_adddi3 (out, out, GEN_INT (4)));
13418 else
13419 emit_insn (gen_addsi3 (out, out, GEN_INT (4)));
13420
13421
13422
13423
13424 emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
13425 emit_insn (gen_one_cmplsi2 (scratch, scratch));
13426 emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
13427 emit_insn (gen_andsi3 (tmpreg, tmpreg,
13428 gen_int_mode (0x80808080, SImode)));
13429 emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
13430 align_4_label);
13431
13432 if (TARGET_CMOVE)
13433 {
13434 rtx reg = gen_reg_rtx (SImode);
13435 rtx reg2 = gen_reg_rtx (Pmode);
13436 emit_move_insn (reg, tmpreg);
13437 emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
13438
13439
13440 emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
13441 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
13442 tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
13443 emit_insn (gen_rtx_SET (VOIDmode, tmpreg,
13444 gen_rtx_IF_THEN_ELSE (SImode, tmp,
13445 reg,
13446 tmpreg)));
13447
13448 emit_insn (gen_rtx_SET (SImode, reg2,
13449 gen_rtx_PLUS (Pmode, out, const2_rtx)));
13450
13451 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
13452 tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
13453 emit_insn (gen_rtx_SET (VOIDmode, out,
13454 gen_rtx_IF_THEN_ELSE (Pmode, tmp,
13455 reg2,
13456 out)));
13457
13458 }
13459 else
13460 {
13461 rtx end_2_label = gen_label_rtx ();
13462
13463
13464 emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
13465 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
13466 tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
13467 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
13468 gen_rtx_LABEL_REF (VOIDmode, end_2_label),
13469 pc_rtx);
13470 tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
13471 JUMP_LABEL (tmp) = end_2_label;
13472
13473
13474 emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
13475 if (TARGET_64BIT)
13476 emit_insn (gen_adddi3 (out, out, const2_rtx));
13477 else
13478 emit_insn (gen_addsi3 (out, out, const2_rtx));
13479
13480 emit_label (end_2_label);
13481
13482 }
13483
13484
13485 tmpreg = gen_lowpart (QImode, tmpreg);
13486 emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg));
13487 cmp = gen_rtx_LTU (Pmode, gen_rtx_REG (CCmode, 17), const0_rtx);
13488 if (TARGET_64BIT)
13489 emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3), cmp));
13490 else
13491 emit_insn (gen_subsi3_carry (out, out, GEN_INT (3), cmp));
13492
13493 emit_label (end_0_label);
13494 }
13495
13496 void
13497 ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
13498 rtx callarg2 ATTRIBUTE_UNUSED,
13499 rtx pop, int sibcall)
13500 {
13501 rtx use = NULL, call;
13502
13503 if (pop == const0_rtx)
13504 pop = NULL;
13505 gcc_assert (!TARGET_64BIT || !pop);
13506
13507 if (TARGET_MACHO && !TARGET_64BIT)
13508 {
13509 #if TARGET_MACHO
13510 if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
13511 fnaddr = machopic_indirect_call_target (fnaddr);
13512 #endif
13513 }
13514 else
13515 {
13516
13517 if (! TARGET_64BIT && flag_pic
13518 && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
13519 && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
13520 use_reg (&use, pic_offset_table_rtx);
13521 }
13522
13523 if (TARGET_64BIT && INTVAL (callarg2) >= 0)
13524 {
13525 rtx al = gen_rtx_REG (QImode, 0);
13526 emit_move_insn (al, callarg2);
13527 use_reg (&use, al);
13528 }
13529
13530 if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
13531 {
13532 fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
13533 fnaddr = gen_rtx_MEM (QImode, fnaddr);
13534 }
13535 if (sibcall && TARGET_64BIT
13536 && !constant_call_address_operand (XEXP (fnaddr, 0), Pmode))
13537 {
13538 rtx addr;
13539 addr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
13540 fnaddr = gen_rtx_REG (Pmode, FIRST_REX_INT_REG + 3 );
13541 emit_move_insn (fnaddr, addr);
13542 fnaddr = gen_rtx_MEM (QImode, fnaddr);
13543 }
13544
13545 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
13546 if (retval)
13547 call = gen_rtx_SET (VOIDmode, retval, call);
13548 if (pop)
13549 {
13550 pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
13551 pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
13552 call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
13553 }
13554
13555 call = emit_call_insn (call);
13556 if (use)
13557 CALL_INSN_FUNCTION_USAGE (call) = use;
13558 }
13559
13560
13561
13562
13563
13564
13565 static struct machine_function *
13566 ix86_init_machine_status (void)
13567 {
13568 struct machine_function *f;
13569
13570 f = ggc_alloc_cleared (sizeof (struct machine_function));
13571 f->use_fast_prologue_epilogue_nregs = -1;
13572 f->tls_descriptor_call_expanded_p = 0;
13573
13574 return f;
13575 }
13576
13577
13578
13579
13580
13581
13582
13583 rtx
13584 assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
13585 {
13586 struct stack_local_entry *s;
13587
13588 gcc_assert (n < MAX_386_STACK_LOCALS);
13589
13590 for (s = ix86_stack_locals; s; s = s->next)
13591 if (s->mode == mode && s->n == n)
13592 return s->rtl;
13593
13594 s = (struct stack_local_entry *)
13595 ggc_alloc (sizeof (struct stack_local_entry));
13596 s->n = n;
13597 s->mode = mode;
13598 s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
13599
13600 s->next = ix86_stack_locals;
13601 ix86_stack_locals = s;
13602 return s->rtl;
13603 }
13604
13605
13606
13607 static GTY(()) rtx ix86_tls_symbol;
13608 rtx
13609 ix86_tls_get_addr (void)
13610 {
13611
13612 if (!ix86_tls_symbol)
13613 {
13614 ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
13615 (TARGET_ANY_GNU_TLS
13616 && !TARGET_64BIT)
13617 ? "___tls_get_addr"
13618 : "__tls_get_addr");
13619 }
13620
13621 return ix86_tls_symbol;
13622 }
13623
13624
13625
13626 static GTY(()) rtx ix86_tls_module_base_symbol;
13627 rtx
13628 ix86_tls_module_base (void)
13629 {
13630
13631 if (!ix86_tls_module_base_symbol)
13632 {
13633 ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
13634 "_TLS_MODULE_BASE_");
13635 SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
13636 |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
13637 }
13638
13639 return ix86_tls_module_base_symbol;
13640 }
13641
13642
13643
13644
13645 int
13646 memory_address_length (rtx addr)
13647 {
13648 struct ix86_address parts;
13649 rtx base, index, disp;
13650 int len;
13651 int ok;
13652
13653 if (GET_CODE (addr) == PRE_DEC
13654 || GET_CODE (addr) == POST_INC
13655 || GET_CODE (addr) == PRE_MODIFY
13656 || GET_CODE (addr) == POST_MODIFY)
13657 return 0;
13658
13659 ok = ix86_decompose_address (addr, &parts);
13660 gcc_assert (ok);
13661
13662 if (parts.base && GET_CODE (parts.base) == SUBREG)
13663 parts.base = SUBREG_REG (parts.base);
13664 if (parts.index && GET_CODE (parts.index) == SUBREG)
13665 parts.index = SUBREG_REG (parts.index);
13666
13667 base = parts.base;
13668 index = parts.index;
13669 disp = parts.disp;
13670 len = 0;
13671
13672
13673
13674
13675
13676
13677 if (base && !index && !disp)
13678 {
13679
13680
13681 if (addr == stack_pointer_rtx
13682 || addr == arg_pointer_rtx
13683 || addr == frame_pointer_rtx
13684 || addr == hard_frame_pointer_rtx)
13685 len = 1;
13686 }
13687
13688
13689 else if (disp && !base && !index)
13690 len = 4;
13691
13692 else
13693 {
13694
13695 if (disp)
13696 {
13697 if (base && satisfies_constraint_K (disp))
13698 len = 1;
13699 else
13700 len = 4;
13701 }
13702
13703 else if (base == hard_frame_pointer_rtx)
13704 len = 1;
13705
13706
13707 if (index
13708
13709 || base == stack_pointer_rtx
13710 || base == arg_pointer_rtx
13711 || base == frame_pointer_rtx)
13712 len += 1;
13713 }
13714
13715 return len;
13716 }
13717
13718
13719
13720 int
13721 ix86_attr_length_immediate_default (rtx insn, int shortform)
13722 {
13723 int len = 0;
13724 int i;
13725 extract_insn_cached (insn);
13726 for (i = recog_data.n_operands - 1; i >= 0; --i)
13727 if (CONSTANT_P (recog_data.operand[i]))
13728 {
13729 gcc_assert (!len);
13730 if (shortform && satisfies_constraint_K (recog_data.operand[i]))
13731 len = 1;
13732 else
13733 {
13734 switch (get_attr_mode (insn))
13735 {
13736 case MODE_QI:
13737 len+=1;
13738 break;
13739 case MODE_HI:
13740 len+=2;
13741 break;
13742 case MODE_SI:
13743 len+=4;
13744 break;
13745
13746 case MODE_DI:
13747 len+=4;
13748 break;
13749 default:
13750 fatal_insn ("unknown insn mode", insn);
13751 }
13752 }
13753 }
13754 return len;
13755 }
13756
13757 int
13758 ix86_attr_length_address_default (rtx insn)
13759 {
13760 int i;
13761
13762 if (get_attr_type (insn) == TYPE_LEA)
13763 {
13764 rtx set = PATTERN (insn);
13765
13766 if (GET_CODE (set) == PARALLEL)
13767 set = XVECEXP (set, 0, 0);
13768
13769 gcc_assert (GET_CODE (set) == SET);
13770
13771 return memory_address_length (SET_SRC (set));
13772 }
13773
13774 extract_insn_cached (insn);
13775 for (i = recog_data.n_operands - 1; i >= 0; --i)
13776 if (GET_CODE (recog_data.operand[i]) == MEM)
13777 {
13778 return memory_address_length (XEXP (recog_data.operand[i], 0));
13779 break;
13780 }
13781 return 0;
13782 }
13783
13784
13785
13786 static int
13787 ix86_issue_rate (void)
13788 {
13789 switch (ix86_tune)
13790 {
13791 case PROCESSOR_PENTIUM:
13792 case PROCESSOR_K6:
13793 return 2;
13794
13795 case PROCESSOR_PENTIUMPRO:
13796 case PROCESSOR_PENTIUM4:
13797 case PROCESSOR_ATHLON:
13798 case PROCESSOR_K8:
13799 case PROCESSOR_AMDFAM10:
13800 case PROCESSOR_NOCONA:
13801 case PROCESSOR_GENERIC32:
13802 case PROCESSOR_GENERIC64:
13803 return 3;
13804
13805 default:
13806 return 1;
13807 }
13808 }
13809
13810
13811
13812
13813 static int
13814 ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
13815 {
13816 rtx set, set2;
13817
13818
13819 if (insn_type != TYPE_SETCC
13820 && insn_type != TYPE_ICMOV
13821 && insn_type != TYPE_FCMOV
13822 && insn_type != TYPE_IBR)
13823 return 0;
13824
13825 if ((set = single_set (dep_insn)) != 0)
13826 {
13827 set = SET_DEST (set);
13828 set2 = NULL_RTX;
13829 }
13830 else if (GET_CODE (PATTERN (dep_insn)) == PARALLEL
13831 && XVECLEN (PATTERN (dep_insn), 0) == 2
13832 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 0)) == SET
13833 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 1)) == SET)
13834 {
13835 set = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
13836 set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
13837 }
13838 else
13839 return 0;
13840
13841 if (GET_CODE (set) != REG || REGNO (set) != FLAGS_REG)
13842 return 0;
13843
13844
13845
13846 if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
13847 return 0;
13848
13849 if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
13850 return 0;
13851
13852 return 1;
13853 }
13854
13855
13856
13857
13858 static int
13859 ix86_agi_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
13860 {
13861 rtx addr;
13862
13863 if (insn_type == TYPE_LEA
13864 && TARGET_PENTIUM)
13865 {
13866 addr = PATTERN (insn);
13867
13868 if (GET_CODE (addr) == PARALLEL)
13869 addr = XVECEXP (addr, 0, 0);
13870
13871 gcc_assert (GET_CODE (addr) == SET);
13872
13873 addr = SET_SRC (addr);
13874 }
13875 else
13876 {
13877 int i;
13878 extract_insn_cached (insn);
13879 for (i = recog_data.n_operands - 1; i >= 0; --i)
13880 if (GET_CODE (recog_data.operand[i]) == MEM)
13881 {
13882 addr = XEXP (recog_data.operand[i], 0);
13883 goto found;
13884 }
13885 return 0;
13886 found:;
13887 }
13888
13889 return modified_in_p (addr, dep_insn);
13890 }
13891
13892 static int
13893 ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
13894 {
13895 enum attr_type insn_type, dep_insn_type;
13896 enum attr_memory memory;
13897 rtx set, set2;
13898 int dep_insn_code_number;
13899
13900
13901 if (REG_NOTE_KIND (link) != 0)
13902 return 0;
13903
13904 dep_insn_code_number = recog_memoized (dep_insn);
13905
13906
13907 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
13908 return cost;
13909
13910 insn_type = get_attr_type (insn);
13911 dep_insn_type = get_attr_type (dep_insn);
13912
13913 switch (ix86_tune)
13914 {
13915 case PROCESSOR_PENTIUM:
13916
13917 if (ix86_agi_dependent (insn, dep_insn, insn_type))
13918 cost += 1;
13919
13920
13921 if (ix86_flags_dependent (insn, dep_insn, insn_type))
13922 cost = 0;
13923
13924
13925 if (insn_type == TYPE_FMOV
13926 && get_attr_memory (insn) == MEMORY_STORE
13927 && !ix86_agi_dependent (insn, dep_insn, insn_type))
13928 cost += 1;
13929 break;
13930
13931 case PROCESSOR_PENTIUMPRO:
13932 memory = get_attr_memory (insn);
13933
13934
13935 if (get_attr_fp_int_src (dep_insn))
13936 cost += 5;
13937
13938
13939 if (insn_type == TYPE_FMOV
13940 && (set = single_set (dep_insn)) != NULL_RTX
13941 && (set2 = single_set (insn)) != NULL_RTX
13942 && rtx_equal_p (SET_DEST (set), SET_SRC (set2))
13943 && GET_CODE (SET_DEST (set2)) == MEM)
13944 cost += 1;
13945
13946
13947
13948
13949 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
13950 && !ix86_agi_dependent (insn, dep_insn, insn_type))
13951 {
13952
13953
13954 if (dep_insn_type == TYPE_IMOV
13955 || dep_insn_type == TYPE_FMOV)
13956 cost = 1;
13957 else if (cost > 1)
13958 cost--;
13959 }
13960 break;
13961
13962 case PROCESSOR_K6:
13963 memory = get_attr_memory (insn);
13964
13965
13966
13967 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
13968 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
13969 return 1;
13970
13971
13972 if (get_attr_fp_int_src (dep_insn))
13973 cost += 5;
13974
13975
13976
13977
13978 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
13979 && !ix86_agi_dependent (insn, dep_insn, insn_type))
13980 {
13981
13982
13983 if (dep_insn_type == TYPE_IMOV
13984 || dep_insn_type == TYPE_FMOV)
13985 cost = 1;
13986 else if (cost > 2)
13987 cost -= 2;
13988 else
13989 cost = 1;
13990 }
13991 break;
13992
13993 case PROCESSOR_ATHLON:
13994 case PROCESSOR_K8:
13995 case PROCESSOR_AMDFAM10:
13996 case PROCESSOR_GENERIC32:
13997 case PROCESSOR_GENERIC64:
13998 memory = get_attr_memory (insn);
13999
14000
14001
14002
14003 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
14004 && !ix86_agi_dependent (insn, dep_insn, insn_type))
14005 {
14006 enum attr_unit unit = get_attr_unit (insn);
14007 int loadcost = 3;
14008
14009
14010
14011
14012
14013
14014 if (unit == UNIT_INTEGER || unit == UNIT_UNKNOWN)
14015 loadcost = 3;
14016 else
14017 loadcost = TARGET_ATHLON ? 2 : 0;
14018
14019 if (cost >= loadcost)
14020 cost -= loadcost;
14021 else
14022 cost = 0;
14023 }
14024
14025 default:
14026 break;
14027 }
14028
14029 return cost;
14030 }
14031
14032
14033
14034
14035
14036 static int
14037 ia32_multipass_dfa_lookahead (void)
14038 {
14039 if (ix86_tune == PROCESSOR_PENTIUM)
14040 return 2;
14041
14042 if (ix86_tune == PROCESSOR_PENTIUMPRO
14043 || ix86_tune == PROCESSOR_K6)
14044 return 1;
14045
14046 else
14047 return 0;
14048 }
14049
14050
14051
14052
14053
14054
14055
14056
14057 int
14058 ix86_constant_alignment (tree exp, int align)
14059 {
14060 if (TREE_CODE (exp) == REAL_CST)
14061 {
14062 if (TYPE_MODE (TREE_TYPE (exp)) == DFmode && align < 64)
14063 return 64;
14064 else if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (exp))) && align < 128)
14065 return 128;
14066 }
14067 else if (!optimize_size && TREE_CODE (exp) == STRING_CST
14068 && TREE_STRING_LENGTH (exp) >= 31 && align < BITS_PER_WORD)
14069 return BITS_PER_WORD;
14070
14071 return align;
14072 }
14073
14074
14075
14076
14077
14078
14079 int
14080 ix86_data_alignment (tree type, int align)
14081 {
14082 int max_align = optimize_size ? BITS_PER_WORD : 256;
14083
14084 if (AGGREGATE_TYPE_P (type)
14085 && TYPE_SIZE (type)
14086 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
14087 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= (unsigned) max_align
14088 || TREE_INT_CST_HIGH (TYPE_SIZE (type)))
14089 && align < max_align)
14090 align = max_align;
14091
14092
14093
14094 if (TARGET_64BIT)
14095 {
14096 if (AGGREGATE_TYPE_P (type)
14097 && TYPE_SIZE (type)
14098 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
14099 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 128
14100 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
14101 return 128;
14102 }
14103
14104 if (TREE_CODE (type) == ARRAY_TYPE)
14105 {
14106 if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
14107 return 64;
14108 if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
14109 return 128;
14110 }
14111 else if (TREE_CODE (type) == COMPLEX_TYPE)
14112 {
14113
14114 if (TYPE_MODE (type) == DCmode && align < 64)
14115 return 64;
14116 if (TYPE_MODE (type) == XCmode && align < 128)
14117 return 128;
14118 }
14119 else if ((TREE_CODE (type) == RECORD_TYPE
14120 || TREE_CODE (type) == UNION_TYPE
14121 || TREE_CODE (type) == QUAL_UNION_TYPE)
14122 && TYPE_FIELDS (type))
14123 {
14124 if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
14125 return 64;
14126 if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
14127 return 128;
14128 }
14129 else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
14130 || TREE_CODE (type) == INTEGER_TYPE)
14131 {
14132 if (TYPE_MODE (type) == DFmode && align < 64)
14133 return 64;
14134 if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
14135 return 128;
14136 }
14137
14138 return align;
14139 }
14140
14141
14142
14143
14144
14145
14146 int
14147 ix86_local_alignment (tree type, int align)
14148 {
14149
14150
14151 if (TARGET_64BIT)
14152 {
14153 if (AGGREGATE_TYPE_P (type)
14154 && TYPE_SIZE (type)
14155 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
14156 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16
14157 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
14158 return 128;
14159 }
14160 if (TREE_CODE (type) == ARRAY_TYPE)
14161 {
14162 if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
14163 return 64;
14164 if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
14165 return 128;
14166 }
14167 else if (TREE_CODE (type) == COMPLEX_TYPE)
14168 {
14169 if (TYPE_MODE (type) == DCmode && align < 64)
14170 return 64;
14171 if (TYPE_MODE (type) == XCmode && align < 128)
14172 return 128;
14173 }
14174 else if ((TREE_CODE (type) == RECORD_TYPE
14175 || TREE_CODE (type) == UNION_TYPE
14176 || TREE_CODE (type) == QUAL_UNION_TYPE)
14177 && TYPE_FIELDS (type))
14178 {
14179 if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
14180 return 64;
14181 if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
14182 return 128;
14183 }
14184 else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
14185 || TREE_CODE (type) == INTEGER_TYPE)
14186 {
14187
14188 if (TYPE_MODE (type) == DFmode && align < 64)
14189 return 64;
14190 if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
14191 return 128;
14192 }
14193 return align;
14194 }
14195
14196
14197
14198
14199 void
14200 x86_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
14201 {
14202 if (!TARGET_64BIT)
14203 {
14204
14205 rtx disp = expand_binop (SImode, sub_optab, fnaddr,
14206 plus_constant (tramp, 10),
14207 NULL_RTX, 1, OPTAB_DIRECT);
14208 emit_move_insn (gen_rtx_MEM (QImode, tramp),
14209 gen_int_mode (0xb9, QImode));
14210 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 1)), cxt);
14211 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 5)),
14212 gen_int_mode (0xe9, QImode));
14213 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 6)), disp);
14214 }
14215 else
14216 {
14217 int offset = 0;
14218
14219
14220
14221 if (x86_64_zext_immediate_operand (fnaddr, VOIDmode))
14222 {
14223 fnaddr = copy_to_mode_reg (DImode, fnaddr);
14224 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
14225 gen_int_mode (0xbb41, HImode));
14226 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, offset + 2)),
14227 gen_lowpart (SImode, fnaddr));
14228 offset += 6;
14229 }
14230 else
14231 {
14232 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
14233 gen_int_mode (0xbb49, HImode));
14234 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
14235 fnaddr);
14236 offset += 10;
14237 }
14238
14239 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
14240 gen_int_mode (0xba49, HImode));
14241 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
14242 cxt);
14243 offset += 10;
14244
14245 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
14246 gen_int_mode (0xff49, HImode));
14247 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, offset+2)),
14248 gen_int_mode (0xe3, QImode));
14249 offset += 3;
14250 gcc_assert (offset <= TRAMPOLINE_SIZE);
14251 }
14252
14253 #ifdef ENABLE_EXECUTE_STACK
14254 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
14255 LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
14256 #endif
14257 }
14258
14259
14260 #ifndef KEY
14261
14262 enum ix86_builtins
14263 {
14264 IX86_BUILTIN_ADDPS,
14265 IX86_BUILTIN_ADDSS,
14266 IX86_BUILTIN_DIVPS,
14267 IX86_BUILTIN_DIVSS,
14268 IX86_BUILTIN_MULPS,
14269 IX86_BUILTIN_MULSS,
14270 IX86_BUILTIN_SUBPS,
14271 IX86_BUILTIN_SUBSS,
14272
14273 IX86_BUILTIN_CMPEQPS,
14274 IX86_BUILTIN_CMPLTPS,
14275 IX86_BUILTIN_CMPLEPS,
14276 IX86_BUILTIN_CMPGTPS,
14277 IX86_BUILTIN_CMPGEPS,
14278 IX86_BUILTIN_CMPNEQPS,
14279 IX86_BUILTIN_CMPNLTPS,
14280 IX86_BUILTIN_CMPNLEPS,
14281 IX86_BUILTIN_CMPNGTPS,
14282 IX86_BUILTIN_CMPNGEPS,
14283 IX86_BUILTIN_CMPORDPS,
14284 IX86_BUILTIN_CMPUNORDPS,
14285 IX86_BUILTIN_CMPEQSS,
14286 IX86_BUILTIN_CMPLTSS,
14287 IX86_BUILTIN_CMPLESS,
14288 IX86_BUILTIN_CMPNEQSS,
14289 IX86_BUILTIN_CMPNLTSS,
14290 IX86_BUILTIN_CMPNLESS,
14291 IX86_BUILTIN_CMPNGTSS,
14292 IX86_BUILTIN_CMPNGESS,
14293 IX86_BUILTIN_CMPORDSS,
14294 IX86_BUILTIN_CMPUNORDSS,
14295
14296 IX86_BUILTIN_COMIEQSS,
14297 IX86_BUILTIN_COMILTSS,
14298 IX86_BUILTIN_COMILESS,
14299 IX86_BUILTIN_COMIGTSS,
14300 IX86_BUILTIN_COMIGESS,
14301 IX86_BUILTIN_COMINEQSS,
14302 IX86_BUILTIN_UCOMIEQSS,
14303 IX86_BUILTIN_UCOMILTSS,
14304 IX86_BUILTIN_UCOMILESS,
14305 IX86_BUILTIN_UCOMIGTSS,
14306 IX86_BUILTIN_UCOMIGESS,
14307 IX86_BUILTIN_UCOMINEQSS,
14308
14309 IX86_BUILTIN_CVTPI2PS,
14310 IX86_BUILTIN_CVTPS2PI,
14311 IX86_BUILTIN_CVTSI2SS,
14312 IX86_BUILTIN_CVTSI642SS,
14313 IX86_BUILTIN_CVTSS2SI,
14314 IX86_BUILTIN_CVTSS2SI64,
14315 IX86_BUILTIN_CVTTPS2PI,
14316 IX86_BUILTIN_CVTTSS2SI,
14317 IX86_BUILTIN_CVTTSS2SI64,
14318
14319 IX86_BUILTIN_MAXPS,
14320 IX86_BUILTIN_MAXSS,
14321 IX86_BUILTIN_MINPS,
14322 IX86_BUILTIN_MINSS,
14323
14324 IX86_BUILTIN_LOADUPS,
14325 IX86_BUILTIN_STOREUPS,
14326 IX86_BUILTIN_MOVSS,
14327
14328 IX86_BUILTIN_MOVHLPS,
14329 IX86_BUILTIN_MOVLHPS,
14330 IX86_BUILTIN_LOADHPS,
14331 IX86_BUILTIN_LOADLPS,
14332 IX86_BUILTIN_STOREHPS,
14333 IX86_BUILTIN_STORELPS,
14334
14335 IX86_BUILTIN_MASKMOVQ,
14336 IX86_BUILTIN_MOVMSKPS,
14337 IX86_BUILTIN_PMOVMSKB,
14338
14339 IX86_BUILTIN_MOVNTPS,
14340 IX86_BUILTIN_MOVNTQ,
14341
14342 IX86_BUILTIN_LOADDQU,
14343 IX86_BUILTIN_STOREDQU,
14344
14345 IX86_BUILTIN_PACKSSWB,
14346 IX86_BUILTIN_PACKSSDW,
14347 IX86_BUILTIN_PACKUSWB,
14348
14349 IX86_BUILTIN_PADDB,
14350 IX86_BUILTIN_PADDW,
14351 IX86_BUILTIN_PADDD,
14352 IX86_BUILTIN_PADDQ,
14353 IX86_BUILTIN_PADDSB,
14354 IX86_BUILTIN_PADDSW,
14355 IX86_BUILTIN_PADDUSB,
14356 IX86_BUILTIN_PADDUSW,
14357 IX86_BUILTIN_PSUBB,
14358 IX86_BUILTIN_PSUBW,
14359 IX86_BUILTIN_PSUBD,
14360 IX86_BUILTIN_PSUBQ,
14361 IX86_BUILTIN_PSUBSB,
14362 IX86_BUILTIN_PSUBSW,
14363 IX86_BUILTIN_PSUBUSB,
14364 IX86_BUILTIN_PSUBUSW,
14365
14366 IX86_BUILTIN_PAND,
14367 IX86_BUILTIN_PANDN,
14368 IX86_BUILTIN_POR,
14369 IX86_BUILTIN_PXOR,
14370
14371 IX86_BUILTIN_PAVGB,
14372 IX86_BUILTIN_PAVGW,
14373
14374 IX86_BUILTIN_PCMPEQB,
14375 IX86_BUILTIN_PCMPEQW,
14376 IX86_BUILTIN_PCMPEQD,
14377 IX86_BUILTIN_PCMPGTB,
14378 IX86_BUILTIN_PCMPGTW,
14379 IX86_BUILTIN_PCMPGTD,
14380
14381 IX86_BUILTIN_PMADDWD,
14382
14383 IX86_BUILTIN_PMAXSW,
14384 IX86_BUILTIN_PMAXUB,
14385 IX86_BUILTIN_PMINSW,
14386 IX86_BUILTIN_PMINUB,
14387
14388 IX86_BUILTIN_PMULHUW,
14389 IX86_BUILTIN_PMULHW,
14390 IX86_BUILTIN_PMULLW,
14391
14392 IX86_BUILTIN_PSADBW,
14393 IX86_BUILTIN_PSHUFW,
14394
14395 IX86_BUILTIN_PSLLW,
14396 IX86_BUILTIN_PSLLD,
14397 IX86_BUILTIN_PSLLQ,
14398 IX86_BUILTIN_PSRAW,
14399 IX86_BUILTIN_PSRAD,
14400 IX86_BUILTIN_PSRLW,
14401 IX86_BUILTIN_PSRLD,
14402 IX86_BUILTIN_PSRLQ,
14403 IX86_BUILTIN_PSLLWI,
14404 IX86_BUILTIN_PSLLDI,
14405 IX86_BUILTIN_PSLLQI,
14406 IX86_BUILTIN_PSRAWI,
14407 IX86_BUILTIN_PSRADI,
14408 IX86_BUILTIN_PSRLWI,
14409 IX86_BUILTIN_PSRLDI,
14410 IX86_BUILTIN_PSRLQI,
14411
14412 IX86_BUILTIN_PUNPCKHBW,
14413 IX86_BUILTIN_PUNPCKHWD,
14414 IX86_BUILTIN_PUNPCKHDQ,
14415 IX86_BUILTIN_PUNPCKLBW,
14416 IX86_BUILTIN_PUNPCKLWD,
14417 IX86_BUILTIN_PUNPCKLDQ,
14418
14419 IX86_BUILTIN_SHUFPS,
14420
14421 IX86_BUILTIN_RCPPS,
14422 IX86_BUILTIN_RCPSS,
14423 IX86_BUILTIN_RSQRTPS,
14424 IX86_BUILTIN_RSQRTSS,
14425 IX86_BUILTIN_SQRTPS,
14426 IX86_BUILTIN_SQRTSS,
14427
14428 IX86_BUILTIN_UNPCKHPS,
14429 IX86_BUILTIN_UNPCKLPS,
14430
14431 IX86_BUILTIN_ANDPS,
14432 IX86_BUILTIN_ANDNPS,
14433 IX86_BUILTIN_ORPS,
14434 IX86_BUILTIN_XORPS,
14435
14436 IX86_BUILTIN_EMMS,
14437 IX86_BUILTIN_LDMXCSR,
14438 IX86_BUILTIN_STMXCSR,
14439 IX86_BUILTIN_SFENCE,
14440
14441
14442 IX86_BUILTIN_FEMMS,
14443 IX86_BUILTIN_PAVGUSB,
14444 IX86_BUILTIN_PF2ID,
14445 IX86_BUILTIN_PFACC,
14446 IX86_BUILTIN_PFADD,
14447 IX86_BUILTIN_PFCMPEQ,
14448 IX86_BUILTIN_PFCMPGE,
14449 IX86_BUILTIN_PFCMPGT,
14450 IX86_BUILTIN_PFMAX,
14451 IX86_BUILTIN_PFMIN,
14452 IX86_BUILTIN_PFMUL,
14453 IX86_BUILTIN_PFRCP,
14454 IX86_BUILTIN_PFRCPIT1,
14455 IX86_BUILTIN_PFRCPIT2,
14456 IX86_BUILTIN_PFRSQIT1,
14457 IX86_BUILTIN_PFRSQRT,
14458 IX86_BUILTIN_PFSUB,
14459 IX86_BUILTIN_PFSUBR,
14460 IX86_BUILTIN_PI2FD,
14461 IX86_BUILTIN_PMULHRW,
14462
14463
14464 IX86_BUILTIN_PF2IW,
14465 IX86_BUILTIN_PFNACC,
14466 IX86_BUILTIN_PFPNACC,
14467 IX86_BUILTIN_PI2FW,
14468 IX86_BUILTIN_PSWAPDSI,
14469 IX86_BUILTIN_PSWAPDSF,
14470
14471
14472 IX86_BUILTIN_ADDPD,
14473 IX86_BUILTIN_ADDSD,
14474 IX86_BUILTIN_DIVPD,
14475 IX86_BUILTIN_DIVSD,
14476 IX86_BUILTIN_MULPD,
14477 IX86_BUILTIN_MULSD,
14478 IX86_BUILTIN_SUBPD,
14479 IX86_BUILTIN_SUBSD,
14480
14481 IX86_BUILTIN_CMPEQPD,
14482 IX86_BUILTIN_CMPLTPD,
14483 IX86_BUILTIN_CMPLEPD,
14484 IX86_BUILTIN_CMPGTPD,
14485 IX86_BUILTIN_CMPGEPD,
14486 IX86_BUILTIN_CMPNEQPD,
14487 IX86_BUILTIN_CMPNLTPD,
14488 IX86_BUILTIN_CMPNLEPD,
14489 IX86_BUILTIN_CMPNGTPD,
14490 IX86_BUILTIN_CMPNGEPD,
14491 IX86_BUILTIN_CMPORDPD,
14492 IX86_BUILTIN_CMPUNORDPD,
14493 IX86_BUILTIN_CMPNEPD,
14494 IX86_BUILTIN_CMPEQSD,
14495 IX86_BUILTIN_CMPLTSD,
14496 IX86_BUILTIN_CMPLESD,
14497 IX86_BUILTIN_CMPNEQSD,
14498 IX86_BUILTIN_CMPNLTSD,
14499 IX86_BUILTIN_CMPNLESD,
14500 IX86_BUILTIN_CMPORDSD,
14501 IX86_BUILTIN_CMPUNORDSD,
14502 IX86_BUILTIN_CMPNESD,
14503
14504 IX86_BUILTIN_COMIEQSD,
14505 IX86_BUILTIN_COMILTSD,
14506 IX86_BUILTIN_COMILESD,
14507 IX86_BUILTIN_COMIGTSD,
14508 IX86_BUILTIN_COMIGESD,
14509 IX86_BUILTIN_COMINEQSD,
14510 IX86_BUILTIN_UCOMIEQSD,
14511 IX86_BUILTIN_UCOMILTSD,
14512 IX86_BUILTIN_UCOMILESD,
14513 IX86_BUILTIN_UCOMIGTSD,
14514 IX86_BUILTIN_UCOMIGESD,
14515 IX86_BUILTIN_UCOMINEQSD,
14516
14517 IX86_BUILTIN_MAXPD,
14518 IX86_BUILTIN_MAXSD,
14519 IX86_BUILTIN_MINPD,
14520 IX86_BUILTIN_MINSD,
14521
14522 IX86_BUILTIN_ANDPD,
14523 IX86_BUILTIN_ANDNPD,
14524 IX86_BUILTIN_ORPD,
14525 IX86_BUILTIN_XORPD,
14526
14527 IX86_BUILTIN_SQRTPD,
14528 IX86_BUILTIN_SQRTSD,
14529
14530 IX86_BUILTIN_UNPCKHPD,
14531 IX86_BUILTIN_UNPCKLPD,
14532
14533 IX86_BUILTIN_SHUFPD,
14534
14535 IX86_BUILTIN_LOADUPD,
14536 IX86_BUILTIN_STOREUPD,
14537 IX86_BUILTIN_MOVSD,
14538
14539 IX86_BUILTIN_LOADHPD,
14540 IX86_BUILTIN_LOADLPD,
14541
14542 IX86_BUILTIN_CVTDQ2PD,
14543 IX86_BUILTIN_CVTDQ2PS,
14544
14545 IX86_BUILTIN_CVTPD2DQ,
14546 IX86_BUILTIN_CVTPD2PI,
14547 IX86_BUILTIN_CVTPD2PS,
14548 IX86_BUILTIN_CVTTPD2DQ,
14549 IX86_BUILTIN_CVTTPD2PI,
14550
14551 IX86_BUILTIN_CVTPI2PD,
14552 IX86_BUILTIN_CVTSI2SD,
14553 IX86_BUILTIN_CVTSI642SD,
14554
14555 IX86_BUILTIN_CVTSD2SI,
14556 IX86_BUILTIN_CVTSD2SI64,
14557 IX86_BUILTIN_CVTSD2SS,
14558 IX86_BUILTIN_CVTSS2SD,
14559 IX86_BUILTIN_CVTTSD2SI,
14560 IX86_BUILTIN_CVTTSD2SI64,
14561
14562 IX86_BUILTIN_CVTPS2DQ,
14563 IX86_BUILTIN_CVTPS2PD,
14564 IX86_BUILTIN_CVTTPS2DQ,
14565
14566 IX86_BUILTIN_MOVNTI,
14567 IX86_BUILTIN_MOVNTPD,
14568 IX86_BUILTIN_MOVNTDQ,
14569
14570
14571 IX86_BUILTIN_MASKMOVDQU,
14572 IX86_BUILTIN_MOVMSKPD,
14573 IX86_BUILTIN_PMOVMSKB128,
14574
14575 IX86_BUILTIN_PACKSSWB128,
14576 IX86_BUILTIN_PACKSSDW128,
14577 IX86_BUILTIN_PACKUSWB128,
14578
14579 IX86_BUILTIN_PADDB128,
14580 IX86_BUILTIN_PADDW128,
14581 IX86_BUILTIN_PADDD128,
14582 IX86_BUILTIN_PADDQ128,
14583 IX86_BUILTIN_PADDSB128,
14584 IX86_BUILTIN_PADDSW128,
14585 IX86_BUILTIN_PADDUSB128,
14586 IX86_BUILTIN_PADDUSW128,
14587 IX86_BUILTIN_PSUBB128,
14588 IX86_BUILTIN_PSUBW128,
14589 IX86_BUILTIN_PSUBD128,
14590 IX86_BUILTIN_PSUBQ128,
14591 IX86_BUILTIN_PSUBSB128,
14592 IX86_BUILTIN_PSUBSW128,
14593 IX86_BUILTIN_PSUBUSB128,
14594 IX86_BUILTIN_PSUBUSW128,
14595
14596 IX86_BUILTIN_PAND128,
14597 IX86_BUILTIN_PANDN128,
14598 IX86_BUILTIN_POR128,
14599 IX86_BUILTIN_PXOR128,
14600
14601 IX86_BUILTIN_PAVGB128,
14602 IX86_BUILTIN_PAVGW128,
14603
14604 IX86_BUILTIN_PCMPEQB128,
14605 IX86_BUILTIN_PCMPEQW128,
14606 IX86_BUILTIN_PCMPEQD128,
14607 IX86_BUILTIN_PCMPGTB128,
14608 IX86_BUILTIN_PCMPGTW128,
14609 IX86_BUILTIN_PCMPGTD128,
14610
14611 IX86_BUILTIN_PMADDWD128,
14612
14613 IX86_BUILTIN_PMAXSW128,
14614 IX86_BUILTIN_PMAXUB128,
14615 IX86_BUILTIN_PMINSW128,
14616 IX86_BUILTIN_PMINUB128,
14617
14618 IX86_BUILTIN_PMULUDQ,
14619 IX86_BUILTIN_PMULUDQ128,
14620 IX86_BUILTIN_PMULHUW128,
14621 IX86_BUILTIN_PMULHW128,
14622 IX86_BUILTIN_PMULLW128,
14623
14624 IX86_BUILTIN_PSADBW128,
14625 IX86_BUILTIN_PSHUFHW,
14626 IX86_BUILTIN_PSHUFLW,
14627 IX86_BUILTIN_PSHUFD,
14628
14629 IX86_BUILTIN_PSLLW128,
14630 IX86_BUILTIN_PSLLD128,
14631 IX86_BUILTIN_PSLLQ128,
14632 IX86_BUILTIN_PSRAW128,
14633 IX86_BUILTIN_PSRAD128,
14634 IX86_BUILTIN_PSRLW128,
14635 IX86_BUILTIN_PSRLD128,
14636 IX86_BUILTIN_PSRLQ128,
14637 IX86_BUILTIN_PSLLDQI128,
14638 IX86_BUILTIN_PSLLWI128,
14639 IX86_BUILTIN_PSLLDI128,
14640 IX86_BUILTIN_PSLLQI128,
14641 IX86_BUILTIN_PSRAWI128,
14642 IX86_BUILTIN_PSRADI128,
14643 IX86_BUILTIN_PSRLDQI128,
14644 IX86_BUILTIN_PSRLWI128,
14645 IX86_BUILTIN_PSRLDI128,
14646 IX86_BUILTIN_PSRLQI128,
14647
14648 IX86_BUILTIN_PUNPCKHBW128,
14649 IX86_BUILTIN_PUNPCKHWD128,
14650 IX86_BUILTIN_PUNPCKHDQ128,
14651 IX86_BUILTIN_PUNPCKHQDQ128,
14652 IX86_BUILTIN_PUNPCKLBW128,
14653 IX86_BUILTIN_PUNPCKLWD128,
14654 IX86_BUILTIN_PUNPCKLDQ128,
14655 IX86_BUILTIN_PUNPCKLQDQ128,
14656
14657 IX86_BUILTIN_CLFLUSH,
14658 IX86_BUILTIN_MFENCE,
14659 IX86_BUILTIN_LFENCE,
14660
14661
14662 IX86_BUILTIN_ADDSUBPS,
14663 IX86_BUILTIN_HADDPS,
14664 IX86_BUILTIN_HSUBPS,
14665 IX86_BUILTIN_MOVSHDUP,
14666 IX86_BUILTIN_MOVSLDUP,
14667 IX86_BUILTIN_ADDSUBPD,
14668 IX86_BUILTIN_HADDPD,
14669 IX86_BUILTIN_HSUBPD,
14670 IX86_BUILTIN_LDDQU,
14671
14672
14673 IX86_BUILTIN_MOVNTSS,
14674 IX86_BUILTIN_MOVNTSD,
14675 IX86_BUILTIN_EXTRQI,
14676 IX86_BUILTIN_EXTRQ,
14677 IX86_BUILTIN_INSERTQI,
14678 IX86_BUILTIN_INSERTQ,
14679
14680 IX86_BUILTIN_MONITOR,
14681 IX86_BUILTIN_MWAIT,
14682
14683 IX86_BUILTIN_VEC_INIT_V2SI,
14684 IX86_BUILTIN_VEC_INIT_V4HI,
14685 IX86_BUILTIN_VEC_INIT_V8QI,
14686 IX86_BUILTIN_VEC_EXT_V2DF,
14687 IX86_BUILTIN_VEC_EXT_V2DI,
14688 IX86_BUILTIN_VEC_EXT_V4SF,
14689 IX86_BUILTIN_VEC_EXT_V4SI,
14690 IX86_BUILTIN_VEC_EXT_V8HI,
14691 IX86_BUILTIN_VEC_EXT_V2SI,
14692 IX86_BUILTIN_VEC_EXT_V4HI,
14693 IX86_BUILTIN_VEC_SET_V8HI,
14694 IX86_BUILTIN_VEC_SET_V4HI,
14695
14696
14697 IX86_BUILTIN_MAX
14698 };
14699 #endif
14700
14701 #define def_builtin(MASK, NAME, TYPE, CODE) \
14702 do { \
14703 if ((MASK) & target_flags \
14704 && (!((MASK) & MASK_64BIT) || TARGET_64BIT)) \
14705 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
14706 NULL, NULL_TREE); \
14707 } while (0)
14708
14709
14710
14711
14712
14713 #define BUILTIN_DESC_SWAP_OPERANDS 1
14714
14715 struct builtin_description
14716 {
14717 const unsigned int mask;
14718 const enum insn_code icode;
14719 const char *const name;
14720 const enum ix86_builtins code;
14721 const enum rtx_code comparison;
14722 const unsigned int flag;
14723 };
14724
14725 static const struct builtin_description bdesc_comi[] =
14726 {
14727 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, UNEQ, 0 },
14728 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, UNLT, 0 },
14729 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, UNLE, 0 },
14730 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, GT, 0 },
14731 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, GE, 0 },
14732 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, LTGT, 0 },
14733 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, UNEQ, 0 },
14734 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, UNLT, 0 },
14735 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, UNLE, 0 },
14736 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, GT, 0 },
14737 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, GE, 0 },
14738 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, LTGT, 0 },
14739 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdeq", IX86_BUILTIN_COMIEQSD, UNEQ, 0 },
14740 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdlt", IX86_BUILTIN_COMILTSD, UNLT, 0 },
14741 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdle", IX86_BUILTIN_COMILESD, UNLE, 0 },
14742 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdgt", IX86_BUILTIN_COMIGTSD, GT, 0 },
14743 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdge", IX86_BUILTIN_COMIGESD, GE, 0 },
14744 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdneq", IX86_BUILTIN_COMINEQSD, LTGT, 0 },
14745 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdeq", IX86_BUILTIN_UCOMIEQSD, UNEQ, 0 },
14746 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdlt", IX86_BUILTIN_UCOMILTSD, UNLT, 0 },
14747 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdle", IX86_BUILTIN_UCOMILESD, UNLE, 0 },
14748 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdgt", IX86_BUILTIN_UCOMIGTSD, GT, 0 },
14749 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdge", IX86_BUILTIN_UCOMIGESD, GE, 0 },
14750 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, LTGT, 0 },
14751 };
14752
14753 static const struct builtin_description bdesc_2arg[] =
14754 {
14755
14756 { MASK_SSE, CODE_FOR_addv4sf3, "__builtin_ia32_addps", IX86_BUILTIN_ADDPS, 0, 0 },
14757 { MASK_SSE, CODE_FOR_subv4sf3, "__builtin_ia32_subps", IX86_BUILTIN_SUBPS, 0, 0 },
14758 { MASK_SSE, CODE_FOR_mulv4sf3, "__builtin_ia32_mulps", IX86_BUILTIN_MULPS, 0, 0 },
14759 { MASK_SSE, CODE_FOR_divv4sf3, "__builtin_ia32_divps", IX86_BUILTIN_DIVPS, 0, 0 },
14760 { MASK_SSE, CODE_FOR_sse_vmaddv4sf3, "__builtin_ia32_addss", IX86_BUILTIN_ADDSS, 0, 0 },
14761 { MASK_SSE, CODE_FOR_sse_vmsubv4sf3, "__builtin_ia32_subss", IX86_BUILTIN_SUBSS, 0, 0 },
14762 { MASK_SSE, CODE_FOR_sse_vmmulv4sf3, "__builtin_ia32_mulss", IX86_BUILTIN_MULSS, 0, 0 },
14763 { MASK_SSE, CODE_FOR_sse_vmdivv4sf3, "__builtin_ia32_divss", IX86_BUILTIN_DIVSS, 0, 0 },
14764
14765 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpeqps", IX86_BUILTIN_CMPEQPS, EQ, 0 },
14766 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpltps", IX86_BUILTIN_CMPLTPS, LT, 0 },
14767 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpleps", IX86_BUILTIN_CMPLEPS, LE, 0 },
14768 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpgtps", IX86_BUILTIN_CMPGTPS, LT,
14769 BUILTIN_DESC_SWAP_OPERANDS },
14770 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpgeps", IX86_BUILTIN_CMPGEPS, LE,
14771 BUILTIN_DESC_SWAP_OPERANDS },
14772 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpunordps", IX86_BUILTIN_CMPUNORDPS, UNORDERED, 0 },
14773 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpneqps", IX86_BUILTIN_CMPNEQPS, NE, 0 },
14774 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpnltps", IX86_BUILTIN_CMPNLTPS, UNGE, 0 },
14775 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpnleps", IX86_BUILTIN_CMPNLEPS, UNGT, 0 },
14776 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpngtps", IX86_BUILTIN_CMPNGTPS, UNGE,
14777 BUILTIN_DESC_SWAP_OPERANDS },
14778 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpngeps", IX86_BUILTIN_CMPNGEPS, UNGT,
14779 BUILTIN_DESC_SWAP_OPERANDS },
14780 { MASK_SSE, CODE_FOR_sse_maskcmpv4sf3, "__builtin_ia32_cmpordps", IX86_BUILTIN_CMPORDPS, ORDERED, 0 },
14781 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpeqss", IX86_BUILTIN_CMPEQSS, EQ, 0 },
14782 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpltss", IX86_BUILTIN_CMPLTSS, LT, 0 },
14783 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpless", IX86_BUILTIN_CMPLESS, LE, 0 },
14784 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpunordss", IX86_BUILTIN_CMPUNORDSS, UNORDERED, 0 },
14785 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpneqss", IX86_BUILTIN_CMPNEQSS, NE, 0 },
14786 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpnltss", IX86_BUILTIN_CMPNLTSS, UNGE, 0 },
14787 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpnless", IX86_BUILTIN_CMPNLESS, UNGT, 0 },
14788 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpngtss", IX86_BUILTIN_CMPNGTSS, UNGE,
14789 BUILTIN_DESC_SWAP_OPERANDS },
14790 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpngess", IX86_BUILTIN_CMPNGESS, UNGT,
14791 BUILTIN_DESC_SWAP_OPERANDS },
14792 { MASK_SSE, CODE_FOR_sse_vmmaskcmpv4sf3, "__builtin_ia32_cmpordss", IX86_BUILTIN_CMPORDSS, ORDERED, 0 },
14793
14794 { MASK_SSE, CODE_FOR_sminv4sf3, "__builtin_ia32_minps", IX86_BUILTIN_MINPS, 0, 0 },
14795 { MASK_SSE, CODE_FOR_smaxv4sf3, "__builtin_ia32_maxps", IX86_BUILTIN_MAXPS, 0, 0 },
14796 { MASK_SSE, CODE_FOR_sse_vmsminv4sf3, "__builtin_ia32_minss", IX86_BUILTIN_MINSS, 0, 0 },
14797 { MASK_SSE, CODE_FOR_sse_vmsmaxv4sf3, "__builtin_ia32_maxss", IX86_BUILTIN_MAXSS, 0, 0 },
14798
14799 { MASK_SSE, CODE_FOR_andv4sf3, "__builtin_ia32_andps", IX86_BUILTIN_ANDPS, 0, 0 },
14800 { MASK_SSE, CODE_FOR_sse_nandv4sf3, "__builtin_ia32_andnps", IX86_BUILTIN_ANDNPS, 0, 0 },
14801 { MASK_SSE, CODE_FOR_iorv4sf3, "__builtin_ia32_orps", IX86_BUILTIN_ORPS, 0, 0 },
14802 { MASK_SSE, CODE_FOR_xorv4sf3, "__builtin_ia32_xorps", IX86_BUILTIN_XORPS, 0, 0 },
14803
14804 { MASK_SSE, CODE_FOR_sse_movss, "__builtin_ia32_movss", IX86_BUILTIN_MOVSS, 0, 0 },
14805 { MASK_SSE, CODE_FOR_sse_movhlps, "__builtin_ia32_movhlps", IX86_BUILTIN_MOVHLPS, 0, 0 },
14806 { MASK_SSE, CODE_FOR_sse_movlhps, "__builtin_ia32_movlhps", IX86_BUILTIN_MOVLHPS, 0, 0 },
14807 { MASK_SSE, CODE_FOR_sse_unpckhps, "__builtin_ia32_unpckhps", IX86_BUILTIN_UNPCKHPS, 0, 0 },
14808 { MASK_SSE, CODE_FOR_sse_unpcklps, "__builtin_ia32_unpcklps", IX86_BUILTIN_UNPCKLPS, 0, 0 },
14809
14810
14811 { MASK_MMX, CODE_FOR_mmx_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, 0, 0 },
14812 { MASK_MMX, CODE_FOR_mmx_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, 0, 0 },
14813 { MASK_MMX, CODE_FOR_mmx_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, 0, 0 },
14814 { MASK_SSE2, CODE_FOR_mmx_adddi3, "__builtin_ia32_paddq", IX86_BUILTIN_PADDQ, 0, 0 },
14815 { MASK_MMX, CODE_FOR_mmx_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, 0, 0 },
14816 { MASK_MMX, CODE_FOR_mmx_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, 0, 0 },
14817 { MASK_MMX, CODE_FOR_mmx_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, 0, 0 },
14818 { MASK_SSE2, CODE_FOR_mmx_subdi3, "__builtin_ia32_psubq", IX86_BUILTIN_PSUBQ, 0, 0 },
14819
14820 { MASK_MMX, CODE_FOR_mmx_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, 0, 0 },
14821 { MASK_MMX, CODE_FOR_mmx_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, 0, 0 },
14822 { MASK_MMX, CODE_FOR_mmx_sssubv8qi3, "__builtin_ia32_psubsb", IX86_BUILTIN_PSUBSB, 0, 0 },
14823 { MASK_MMX, CODE_FOR_mmx_sssubv4hi3, "__builtin_ia32_psubsw", IX86_BUILTIN_PSUBSW, 0, 0 },
14824 { MASK_MMX, CODE_FOR_mmx_usaddv8qi3, "__builtin_ia32_paddusb", IX86_BUILTIN_PADDUSB, 0, 0 },
14825 { MASK_MMX, CODE_FOR_mmx_usaddv4hi3, "__builtin_ia32_paddusw", IX86_BUILTIN_PADDUSW, 0, 0 },
14826 { MASK_MMX, CODE_FOR_mmx_ussubv8qi3, "__builtin_ia32_psubusb", IX86_BUILTIN_PSUBUSB, 0, 0 },
14827 { MASK_MMX, CODE_FOR_mmx_ussubv4hi3, "__builtin_ia32_psubusw", IX86_BUILTIN_PSUBUSW, 0, 0 },
14828
14829 { MASK_MMX, CODE_FOR_mmx_mulv4hi3, "__builtin_ia32_pmullw", IX86_BUILTIN_PMULLW, 0, 0 },
14830 { MASK_MMX, CODE_FOR_mmx_smulv4hi3_highpart, "__builtin_ia32_pmulhw", IX86_BUILTIN_PMULHW, 0, 0 },
14831 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_umulv4hi3_highpart, "__builtin_ia32_pmulhuw", IX86_BUILTIN_PMULHUW, 0, 0 },
14832
14833 { MASK_MMX, CODE_FOR_mmx_andv2si3, "__builtin_ia32_pand", IX86_BUILTIN_PAND, 0, 0 },
14834 { MASK_MMX, CODE_FOR_mmx_nandv2si3, "__builtin_ia32_pandn", IX86_BUILTIN_PANDN, 0, 0 },
14835 { MASK_MMX, CODE_FOR_mmx_iorv2si3, "__builtin_ia32_por", IX86_BUILTIN_POR, 0, 0 },
14836 { MASK_MMX, CODE_FOR_mmx_xorv2si3, "__builtin_ia32_pxor", IX86_BUILTIN_PXOR, 0, 0 },
14837
14838 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv8qi3, "__builtin_ia32_pavgb", IX86_BUILTIN_PAVGB, 0, 0 },
14839 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv4hi3, "__builtin_ia32_pavgw", IX86_BUILTIN_PAVGW, 0, 0 },
14840
14841 { MASK_MMX, CODE_FOR_mmx_eqv8qi3, "__builtin_ia32_pcmpeqb", IX86_BUILTIN_PCMPEQB, 0, 0 },
14842 { MASK_MMX, CODE_FOR_mmx_eqv4hi3, "__builtin_ia32_pcmpeqw", IX86_BUILTIN_PCMPEQW, 0, 0 },
14843 { MASK_MMX, CODE_FOR_mmx_eqv2si3, "__builtin_ia32_pcmpeqd", IX86_BUILTIN_PCMPEQD, 0, 0 },
14844 { MASK_MMX, CODE_FOR_mmx_gtv8qi3, "__builtin_ia32_pcmpgtb", IX86_BUILTIN_PCMPGTB, 0, 0 },
14845 { MASK_MMX, CODE_FOR_mmx_gtv4hi3, "__builtin_ia32_pcmpgtw", IX86_BUILTIN_PCMPGTW, 0, 0 },
14846 { MASK_MMX, CODE_FOR_mmx_gtv2si3, "__builtin_ia32_pcmpgtd", IX86_BUILTIN_PCMPGTD, 0, 0 },
14847
14848 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_umaxv8qi3, "__builtin_ia32_pmaxub", IX86_BUILTIN_PMAXUB, 0, 0 },
14849 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_smaxv4hi3, "__builtin_ia32_pmaxsw", IX86_BUILTIN_PMAXSW, 0, 0 },
14850 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uminv8qi3, "__builtin_ia32_pminub", IX86_BUILTIN_PMINUB, 0, 0 },
14851 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_sminv4hi3, "__builtin_ia32_pminsw", IX86_BUILTIN_PMINSW, 0, 0 },
14852
14853 { MASK_MMX, CODE_FOR_mmx_punpckhbw, "__builtin_ia32_punpckhbw", IX86_BUILTIN_PUNPCKHBW, 0, 0 },
14854 { MASK_MMX, CODE_FOR_mmx_punpckhwd, "__builtin_ia32_punpckhwd", IX86_BUILTIN_PUNPCKHWD, 0, 0 },
14855 { MASK_MMX, CODE_FOR_mmx_punpckhdq, "__builtin_ia32_punpckhdq", IX86_BUILTIN_PUNPCKHDQ, 0, 0 },
14856 { MASK_MMX, CODE_FOR_mmx_punpcklbw, "__builtin_ia32_punpcklbw", IX86_BUILTIN_PUNPCKLBW, 0, 0 },
14857 { MASK_MMX, CODE_FOR_mmx_punpcklwd, "__builtin_ia32_punpcklwd", IX86_BUILTIN_PUNPCKLWD, 0, 0 },
14858 { MASK_MMX, CODE_FOR_mmx_punpckldq, "__builtin_ia32_punpckldq", IX86_BUILTIN_PUNPCKLDQ, 0, 0 },
14859
14860
14861 { MASK_MMX, CODE_FOR_mmx_packsswb, 0, IX86_BUILTIN_PACKSSWB, 0, 0 },
14862 { MASK_MMX, CODE_FOR_mmx_packssdw, 0, IX86_BUILTIN_PACKSSDW, 0, 0 },
14863 { MASK_MMX, CODE_FOR_mmx_packuswb, 0, IX86_BUILTIN_PACKUSWB, 0, 0 },
14864
14865 { MASK_SSE, CODE_FOR_sse_cvtpi2ps, 0, IX86_BUILTIN_CVTPI2PS, 0, 0 },
14866 { MASK_SSE, CODE_FOR_sse_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 },
14867 { MASK_SSE | MASK_64BIT, CODE_FOR_sse_cvtsi2ssq, 0, IX86_BUILTIN_CVTSI642SS, 0, 0 },
14868
14869 { MASK_MMX, CODE_FOR_mmx_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 },
14870 { MASK_MMX, CODE_FOR_mmx_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 },
14871 { MASK_MMX, CODE_FOR_mmx_ashlv2si3, 0, IX86_BUILTIN_PSLLD, 0, 0 },
14872 { MASK_MMX, CODE_FOR_mmx_ashlv2si3, 0, IX86_BUILTIN_PSLLDI, 0, 0 },
14873 { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQ, 0, 0 },
14874 { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQI, 0, 0 },
14875
14876 { MASK_MMX, CODE_FOR_mmx_lshrv4hi3, 0, IX86_BUILTIN_PSRLW, 0, 0 },
14877 { MASK_MMX, CODE_FOR_mmx_lshrv4hi3, 0, IX86_BUILTIN_PSRLWI, 0, 0 },
14878 { MASK_MMX, CODE_FOR_mmx_lshrv2si3, 0, IX86_BUILTIN_PSRLD, 0, 0 },
14879 { MASK_MMX, CODE_FOR_mmx_lshrv2si3, 0, IX86_BUILTIN_PSRLDI, 0, 0 },
14880 { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQ, 0, 0 },
14881 { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQI, 0, 0 },
14882
14883 { MASK_MMX, CODE_FOR_mmx_ashrv4hi3, 0, IX86_BUILTIN_PSRAW, 0, 0 },
14884 { MASK_MMX, CODE_FOR_mmx_ashrv4hi3, 0, IX86_BUILTIN_PSRAWI, 0, 0 },
14885 { MASK_MMX, CODE_FOR_mmx_ashrv2si3, 0, IX86_BUILTIN_PSRAD, 0, 0 },
14886 { MASK_MMX, CODE_FOR_mmx_ashrv2si3, 0, IX86_BUILTIN_PSRADI, 0, 0 },
14887
14888 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_psadbw, 0, IX86_BUILTIN_PSADBW, 0, 0 },
14889 { MASK_MMX, CODE_FOR_mmx_pmaddwd, 0, IX86_BUILTIN_PMADDWD, 0, 0 },
14890
14891
14892 { MASK_SSE2, CODE_FOR_addv2df3, "__builtin_ia32_addpd", IX86_BUILTIN_ADDPD, 0, 0 },
14893 { MASK_SSE2, CODE_FOR_subv2df3, "__builtin_ia32_subpd", IX86_BUILTIN_SUBPD, 0, 0 },
14894 { MASK_SSE2, CODE_FOR_mulv2df3, "__builtin_ia32_mulpd", IX86_BUILTIN_MULPD, 0, 0 },
14895 { MASK_SSE2, CODE_FOR_divv2df3, "__builtin_ia32_divpd", IX86_BUILTIN_DIVPD, 0, 0 },
14896 { MASK_SSE2, CODE_FOR_sse2_vmaddv2df3, "__builtin_ia32_addsd", IX86_BUILTIN_ADDSD, 0, 0 },
14897 { MASK_SSE2, CODE_FOR_sse2_vmsubv2df3, "__builtin_ia32_subsd", IX86_BUILTIN_SUBSD, 0, 0 },
14898 { MASK_SSE2, CODE_FOR_sse2_vmmulv2df3, "__builtin_ia32_mulsd", IX86_BUILTIN_MULSD, 0, 0 },
14899 { MASK_SSE2, CODE_FOR_sse2_vmdivv2df3, "__builtin_ia32_divsd", IX86_BUILTIN_DIVSD, 0, 0 },
14900
14901 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpeqpd", IX86_BUILTIN_CMPEQPD, EQ, 0 },
14902 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpltpd", IX86_BUILTIN_CMPLTPD, LT, 0 },
14903 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmplepd", IX86_BUILTIN_CMPLEPD, LE, 0 },
14904 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpgtpd", IX86_BUILTIN_CMPGTPD, LT,
14905 BUILTIN_DESC_SWAP_OPERANDS },
14906 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpgepd", IX86_BUILTIN_CMPGEPD, LE,
14907 BUILTIN_DESC_SWAP_OPERANDS },
14908 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpunordpd", IX86_BUILTIN_CMPUNORDPD, UNORDERED, 0 },
14909 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpneqpd", IX86_BUILTIN_CMPNEQPD, NE, 0 },
14910 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpnltpd", IX86_BUILTIN_CMPNLTPD, UNGE, 0 },
14911 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpnlepd", IX86_BUILTIN_CMPNLEPD, UNGT, 0 },
14912 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpngtpd", IX86_BUILTIN_CMPNGTPD, UNGE,
14913 BUILTIN_DESC_SWAP_OPERANDS },
14914 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpngepd", IX86_BUILTIN_CMPNGEPD, UNGT,
14915 BUILTIN_DESC_SWAP_OPERANDS },
14916 { MASK_SSE2, CODE_FOR_sse2_maskcmpv2df3, "__builtin_ia32_cmpordpd", IX86_BUILTIN_CMPORDPD, ORDERED, 0 },
14917 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpeqsd", IX86_BUILTIN_CMPEQSD, EQ, 0 },
14918 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpltsd", IX86_BUILTIN_CMPLTSD, LT, 0 },
14919 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmplesd", IX86_BUILTIN_CMPLESD, LE, 0 },
14920 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpunordsd", IX86_BUILTIN_CMPUNORDSD, UNORDERED, 0 },
14921 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpneqsd", IX86_BUILTIN_CMPNEQSD, NE, 0 },
14922 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpnltsd", IX86_BUILTIN_CMPNLTSD, UNGE, 0 },
14923 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpnlesd", IX86_BUILTIN_CMPNLESD, UNGT, 0 },
14924 { MASK_SSE2, CODE_FOR_sse2_vmmaskcmpv2df3, "__builtin_ia32_cmpordsd", IX86_BUILTIN_CMPORDSD, ORDERED, 0 },
14925
14926 { MASK_SSE2, CODE_FOR_sminv2df3, "__builtin_ia32_minpd", IX86_BUILTIN_MINPD, 0, 0 },
14927 { MASK_SSE2, CODE_FOR_smaxv2df3, "__builtin_ia32_maxpd", IX86_BUILTIN_MAXPD, 0, 0 },
14928 { MASK_SSE2, CODE_FOR_sse2_vmsminv2df3, "__builtin_ia32_minsd", IX86_BUILTIN_MINSD, 0, 0 },
14929 { MASK_SSE2, CODE_FOR_sse2_vmsmaxv2df3, "__builtin_ia32_maxsd", IX86_BUILTIN_MAXSD, 0, 0 },
14930
14931 { MASK_SSE2, CODE_FOR_andv2df3, "__builtin_ia32_andpd", IX86_BUILTIN_ANDPD, 0, 0 },
14932 { MASK_SSE2, CODE_FOR_sse2_nandv2df3, "__builtin_ia32_andnpd", IX86_BUILTIN_ANDNPD, 0, 0 },
14933 { MASK_SSE2, CODE_FOR_iorv2df3, "__builtin_ia32_orpd", IX86_BUILTIN_ORPD, 0, 0 },
14934 { MASK_SSE2, CODE_FOR_xorv2df3, "__builtin_ia32_xorpd", IX86_BUILTIN_XORPD, 0, 0 },
14935
14936 { MASK_SSE2, CODE_FOR_sse2_movsd, "__builtin_ia32_movsd", IX86_BUILTIN_MOVSD, 0, 0 },
14937 { MASK_SSE2, CODE_FOR_sse2_unpckhpd, "__builtin_ia32_unpckhpd", IX86_BUILTIN_UNPCKHPD, 0, 0 },
14938 { MASK_SSE2, CODE_FOR_sse2_unpcklpd, "__builtin_ia32_unpcklpd", IX86_BUILTIN_UNPCKLPD, 0, 0 },
14939
14940
14941 { MASK_SSE2, CODE_FOR_addv16qi3, "__builtin_ia32_paddb128", IX86_BUILTIN_PADDB128, 0, 0 },
14942 { MASK_SSE2, CODE_FOR_addv8hi3, "__builtin_ia32_paddw128", IX86_BUILTIN_PADDW128, 0, 0 },
14943 { MASK_SSE2, CODE_FOR_addv4si3, "__builtin_ia32_paddd128", IX86_BUILTIN_PADDD128, 0, 0 },
14944 { MASK_SSE2, CODE_FOR_addv2di3, "__builtin_ia32_paddq128", IX86_BUILTIN_PADDQ128, 0, 0 },
14945 { MASK_SSE2, CODE_FOR_subv16qi3, "__builtin_ia32_psubb128", IX86_BUILTIN_PSUBB128, 0, 0 },
14946 { MASK_SSE2, CODE_FOR_subv8hi3, "__builtin_ia32_psubw128", IX86_BUILTIN_PSUBW128, 0, 0 },
14947 { MASK_SSE2, CODE_FOR_subv4si3, "__builtin_ia32_psubd128", IX86_BUILTIN_PSUBD128, 0, 0 },
14948 { MASK_SSE2, CODE_FOR_subv2di3, "__builtin_ia32_psubq128", IX86_BUILTIN_PSUBQ128, 0, 0 },
14949
14950 { MASK_MMX, CODE_FOR_sse2_ssaddv16qi3, "__builtin_ia32_paddsb128", IX86_BUILTIN_PADDSB128, 0, 0 },
14951 { MASK_MMX, CODE_FOR_sse2_ssaddv8hi3, "__builtin_ia32_paddsw128", IX86_BUILTIN_PADDSW128, 0, 0 },
14952 { MASK_MMX, CODE_FOR_sse2_sssubv16qi3, "__builtin_ia32_psubsb128", IX86_BUILTIN_PSUBSB128, 0, 0 },
14953 { MASK_MMX, CODE_FOR_sse2_sssubv8hi3, "__builtin_ia32_psubsw128", IX86_BUILTIN_PSUBSW128, 0, 0 },
14954 { MASK_MMX, CODE_FOR_sse2_usaddv16qi3, "__builtin_ia32_paddusb128", IX86_BUILTIN_PADDUSB128, 0, 0 },
14955 { MASK_MMX, CODE_FOR_sse2_usaddv8hi3, "__builtin_ia32_paddusw128", IX86_BUILTIN_PADDUSW128, 0, 0 },
14956 { MASK_MMX, CODE_FOR_sse2_ussubv16qi3, "__builtin_ia32_psubusb128", IX86_BUILTIN_PSUBUSB128, 0, 0 },
14957 { MASK_MMX, CODE_FOR_sse2_ussubv8hi3, "__builtin_ia32_psubusw128", IX86_BUILTIN_PSUBUSW128, 0, 0 },
14958
14959 { MASK_SSE2, CODE_FOR_mulv8hi3, "__builtin_ia32_pmullw128", IX86_BUILTIN_PMULLW128, 0, 0 },
14960 { MASK_SSE2, CODE_FOR_sse2_smulv8hi3_highpart, "__builtin_ia32_pmulhw128", IX86_BUILTIN_PMULHW128, 0, 0 },
14961
14962 { MASK_SSE2, CODE_FOR_andv2di3, "__builtin_ia32_pand128", IX86_BUILTIN_PAND128, 0, 0 },
14963 { MASK_SSE2, CODE_FOR_sse2_nandv2di3, "__builtin_ia32_pandn128", IX86_BUILTIN_PANDN128, 0, 0 },
14964 { MASK_SSE2, CODE_FOR_iorv2di3, "__builtin_ia32_por128", IX86_BUILTIN_POR128, 0, 0 },
14965 { MASK_SSE2, CODE_FOR_xorv2di3, "__builtin_ia32_pxor128", IX86_BUILTIN_PXOR128, 0, 0 },
14966
14967 { MASK_SSE2, CODE_FOR_sse2_uavgv16qi3, "__builtin_ia32_pavgb128", IX86_BUILTIN_PAVGB128, 0, 0 },
14968 { MASK_SSE2, CODE_FOR_sse2_uavgv8hi3, "__builtin_ia32_pavgw128", IX86_BUILTIN_PAVGW128, 0, 0 },
14969
14970 { MASK_SSE2, CODE_FOR_sse2_eqv16qi3, "__builtin_ia32_pcmpeqb128", IX86_BUILTIN_PCMPEQB128, 0, 0 },
14971 { MASK_SSE2, CODE_FOR_sse2_eqv8hi3, "__builtin_ia32_pcmpeqw128", IX86_BUILTIN_PCMPEQW128, 0, 0 },
14972 { MASK_SSE2, CODE_FOR_sse2_eqv4si3, "__builtin_ia32_pcmpeqd128", IX86_BUILTIN_PCMPEQD128, 0, 0 },
14973 { MASK_SSE2, CODE_FOR_sse2_gtv16qi3, "__builtin_ia32_pcmpgtb128", IX86_BUILTIN_PCMPGTB128, 0, 0 },
14974 { MASK_SSE2, CODE_FOR_sse2_gtv8hi3, "__builtin_ia32_pcmpgtw128", IX86_BUILTIN_PCMPGTW128, 0, 0 },
14975 { MASK_SSE2, CODE_FOR_sse2_gtv4si3, "__builtin_ia32_pcmpgtd128", IX86_BUILTIN_PCMPGTD128, 0, 0 },
14976
14977 { MASK_SSE2, CODE_FOR_umaxv16qi3, "__builtin_ia32_pmaxub128", IX86_BUILTIN_PMAXUB128, 0, 0 },
14978 { MASK_SSE2, CODE_FOR_smaxv8hi3, "__builtin_ia32_pmaxsw128", IX86_BUILTIN_PMAXSW128, 0, 0 },
14979 { MASK_SSE2, CODE_FOR_uminv16qi3, "__builtin_ia32_pminub128", IX86_BUILTIN_PMINUB128, 0, 0 },
14980 { MASK_SSE2, CODE_FOR_sminv8hi3, "__builtin_ia32_pminsw128", IX86_BUILTIN_PMINSW128, 0, 0 },
14981
14982 { MASK_SSE2, CODE_FOR_sse2_punpckhbw, "__builtin_ia32_punpckhbw128", IX86_BUILTIN_PUNPCKHBW128, 0, 0 },
14983 { MASK_SSE2, CODE_FOR_sse2_punpckhwd, "__builtin_ia32_punpckhwd128", IX86_BUILTIN_PUNPCKHWD128, 0, 0 },
14984 { MASK_SSE2, CODE_FOR_sse2_punpckhdq, "__builtin_ia32_punpckhdq128", IX86_BUILTIN_PUNPCKHDQ128, 0, 0 },
14985 { MASK_SSE2, CODE_FOR_sse2_punpckhqdq, "__builtin_ia32_punpckhqdq128", IX86_BUILTIN_PUNPCKHQDQ128, 0, 0 },
14986 { MASK_SSE2, CODE_FOR_sse2_punpcklbw, "__builtin_ia32_punpcklbw128", IX86_BUILTIN_PUNPCKLBW128, 0, 0 },
14987 { MASK_SSE2, CODE_FOR_sse2_punpcklwd, "__builtin_ia32_punpcklwd128", IX86_BUILTIN_PUNPCKLWD128, 0, 0 },
14988 { MASK_SSE2, CODE_FOR_sse2_punpckldq, "__builtin_ia32_punpckldq128", IX86_BUILTIN_PUNPCKLDQ128, 0, 0 },
14989 { MASK_SSE2, CODE_FOR_sse2_punpcklqdq, "__builtin_ia32_punpcklqdq128", IX86_BUILTIN_PUNPCKLQDQ128, 0, 0 },
14990
14991 { MASK_SSE2, CODE_FOR_sse2_packsswb, "__builtin_ia32_packsswb128", IX86_BUILTIN_PACKSSWB128, 0, 0 },
14992 { MASK_SSE2, CODE_FOR_sse2_packssdw, "__builtin_ia32_packssdw128", IX86_BUILTIN_PACKSSDW128, 0, 0 },
14993 { MASK_SSE2, CODE_FOR_sse2_packuswb, "__builtin_ia32_packuswb128", IX86_BUILTIN_PACKUSWB128, 0, 0 },
14994
14995 { MASK_SSE2, CODE_FOR_sse2_umulv8hi3_highpart, "__builtin_ia32_pmulhuw128", IX86_BUILTIN_PMULHUW128, 0, 0 },
14996 { MASK_SSE2, CODE_FOR_sse2_psadbw, 0, IX86_BUILTIN_PSADBW128, 0, 0 },
14997
14998 { MASK_SSE2, CODE_FOR_sse2_umulsidi3, 0, IX86_BUILTIN_PMULUDQ, 0, 0 },
14999 { MASK_SSE2, CODE_FOR_sse2_umulv2siv2di3, 0, IX86_BUILTIN_PMULUDQ128, 0, 0 },
15000
15001 { MASK_SSE2, CODE_FOR_ashlv8hi3, 0, IX86_BUILTIN_PSLLWI128, 0, 0 },
15002 { MASK_SSE2, CODE_FOR_ashlv4si3, 0, IX86_BUILTIN_PSLLDI128, 0, 0 },
15003 { MASK_SSE2, CODE_FOR_ashlv2di3, 0, IX86_BUILTIN_PSLLQI128, 0, 0 },
15004
15005 { MASK_SSE2, CODE_FOR_lshrv8hi3, 0, IX86_BUILTIN_PSRLWI128, 0, 0 },
15006 { MASK_SSE2, CODE_FOR_lshrv4si3, 0, IX86_BUILTIN_PSRLDI128, 0, 0 },
15007 { MASK_SSE2, CODE_FOR_lshrv2di3, 0, IX86_BUILTIN_PSRLQI128, 0, 0 },
15008
15009 { MASK_SSE2, CODE_FOR_ashrv8hi3, 0, IX86_BUILTIN_PSRAWI128, 0, 0 },
15010 { MASK_SSE2, CODE_FOR_ashrv4si3, 0, IX86_BUILTIN_PSRADI128, 0, 0 },
15011
15012 { MASK_SSE2, CODE_FOR_sse2_pmaddwd, 0, IX86_BUILTIN_PMADDWD128, 0, 0 },
15013
15014 { MASK_SSE2, CODE_FOR_sse2_cvtsi2sd, 0, IX86_BUILTIN_CVTSI2SD, 0, 0 },
15015 { MASK_SSE2 | MASK_64BIT, CODE_FOR_sse2_cvtsi2sdq, 0, IX86_BUILTIN_CVTSI642SD, 0, 0 },
15016 { MASK_SSE2, CODE_FOR_sse2_cvtsd2ss, 0, IX86_BUILTIN_CVTSD2SS, 0, 0 },
15017 { MASK_SSE2, CODE_FOR_sse2_cvtss2sd, 0, IX86_BUILTIN_CVTSS2SD, 0, 0 },
15018
15019
15020 { MASK_SSE3, CODE_FOR_sse3_addsubv4sf3, "__builtin_ia32_addsubps", IX86_BUILTIN_ADDSUBPS, 0, 0 },
15021 { MASK_SSE3, CODE_FOR_sse3_addsubv2df3, "__builtin_ia32_addsubpd", IX86_BUILTIN_ADDSUBPD, 0, 0 },
15022 { MASK_SSE3, CODE_FOR_sse3_haddv4sf3, "__builtin_ia32_haddps", IX86_BUILTIN_HADDPS, 0, 0 },
15023 { MASK_SSE3, CODE_FOR_sse3_haddv2df3, "__builtin_ia32_haddpd", IX86_BUILTIN_HADDPD, 0, 0 },
15024 { MASK_SSE3, CODE_FOR_sse3_hsubv4sf3, "__builtin_ia32_hsubps", IX86_BUILTIN_HSUBPS, 0, 0 },
15025 { MASK_SSE3, CODE_FOR_sse3_hsubv2df3, "__builtin_ia32_hsubpd", IX86_BUILTIN_HSUBPD, 0, 0 }
15026 };
15027
15028 static const struct builtin_description bdesc_1arg[] =
15029 {
15030 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB, 0, 0 },
15031 { MASK_SSE, CODE_FOR_sse_movmskps, 0, IX86_BUILTIN_MOVMSKPS, 0, 0 },
15032
15033 { MASK_SSE, CODE_FOR_sqrtv4sf2, 0, IX86_BUILTIN_SQRTPS, 0, 0 },
15034 { MASK_SSE, CODE_FOR_sse_rsqrtv4sf2, 0, IX86_BUILTIN_RSQRTPS, 0, 0 },
15035 { MASK_SSE, CODE_FOR_sse_rcpv4sf2, 0, IX86_BUILTIN_RCPPS, 0, 0 },
15036
15037 { MASK_SSE, CODE_FOR_sse_cvtps2pi, 0, IX86_BUILTIN_CVTPS2PI, 0, 0 },
15038 { MASK_SSE, CODE_FOR_sse_cvtss2si, 0, IX86_BUILTIN_CVTSS2SI, 0, 0 },
15039 { MASK_SSE | MASK_64BIT, CODE_FOR_sse_cvtss2siq, 0, IX86_BUILTIN_CVTSS2SI64, 0, 0 },
15040 { MASK_SSE, CODE_FOR_sse_cvttps2pi, 0, IX86_BUILTIN_CVTTPS2PI, 0, 0 },
15041 { MASK_SSE, CODE_FOR_sse_cvttss2si, 0, IX86_BUILTIN_CVTTSS2SI, 0, 0 },
15042 { MASK_SSE | MASK_64BIT, CODE_FOR_sse_cvttss2siq, 0, IX86_BUILTIN_CVTTSS2SI64, 0, 0 },
15043
15044 { MASK_SSE2, CODE_FOR_sse2_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB128, 0, 0 },
15045 { MASK_SSE2, CODE_FOR_sse2_movmskpd, 0, IX86_BUILTIN_MOVMSKPD, 0, 0 },
15046
15047 { MASK_SSE2, CODE_FOR_sqrtv2df2, 0, IX86_BUILTIN_SQRTPD, 0, 0 },
15048
15049 { MASK_SSE2, CODE_FOR_sse2_cvtdq2pd, 0, IX86_BUILTIN_CVTDQ2PD, 0, 0 },
15050 { MASK_SSE2, CODE_FOR_sse2_cvtdq2ps, 0, IX86_BUILTIN_CVTDQ2PS, 0, 0 },
15051
15052 { MASK_SSE2, CODE_FOR_sse2_cvtpd2dq, 0, IX86_BUILTIN_CVTPD2DQ, 0, 0 },
15053 { MASK_SSE2, CODE_FOR_sse2_cvtpd2pi, 0, IX86_BUILTIN_CVTPD2PI, 0, 0 },
15054 { MASK_SSE2, CODE_FOR_sse2_cvtpd2ps, 0, IX86_BUILTIN_CVTPD2PS, 0, 0 },
15055 { MASK_SSE2, CODE_FOR_sse2_cvttpd2dq, 0, IX86_BUILTIN_CVTTPD2DQ, 0, 0 },
15056 { MASK_SSE2, CODE_FOR_sse2_cvttpd2pi, 0, IX86_BUILTIN_CVTTPD2PI, 0, 0 },
15057
15058 { MASK_SSE2, CODE_FOR_sse2_cvtpi2pd, 0, IX86_BUILTIN_CVTPI2PD, 0, 0 },
15059
15060 { MASK_SSE2, CODE_FOR_sse2_cvtsd2si, 0, IX86_BUILTIN_CVTSD2SI, 0, 0 },
15061 { MASK_SSE2, CODE_FOR_sse2_cvttsd2si, 0, IX86_BUILTIN_CVTTSD2SI, 0, 0 },
15062 { MASK_SSE2 | MASK_64BIT, CODE_FOR_sse2_cvtsd2siq, 0, IX86_BUILTIN_CVTSD2SI64, 0, 0 },
15063 { MASK_SSE2 | MASK_64BIT, CODE_FOR_sse2_cvttsd2siq, 0, IX86_BUILTIN_CVTTSD2SI64, 0, 0 },
15064
15065 { MASK_SSE2, CODE_FOR_sse2_cvtps2dq, 0, IX86_BUILTIN_CVTPS2DQ, 0, 0 },
15066 { MASK_SSE2, CODE_FOR_sse2_cvtps2pd, 0, IX86_BUILTIN_CVTPS2PD, 0, 0 },
15067 { MASK_SSE2, CODE_FOR_sse2_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 },
15068
15069
15070 { MASK_SSE3, CODE_FOR_sse3_movshdup, 0, IX86_BUILTIN_MOVSHDUP, 0, 0 },
15071 { MASK_SSE3, CODE_FOR_sse3_movsldup, 0, IX86_BUILTIN_MOVSLDUP, 0, 0 },
15072 };
15073
15074 static void
15075 ix86_init_builtins (void)
15076 {
15077 if (TARGET_MMX)
15078 ix86_init_mmx_sse_builtins ();
15079 }
15080
15081
15082
15083
15084 static void
15085 ix86_init_mmx_sse_builtins (void)
15086 {
15087 const struct builtin_description * d;
15088 size_t i;
15089
15090 tree V16QI_type_node = build_vector_type_for_mode (intQI_type_node, V16QImode);
15091 tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
15092 tree V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
15093 tree V2DI_type_node
15094 = build_vector_type_for_mode (long_long_integer_type_node, V2DImode);
15095 tree V2DF_type_node = build_vector_type_for_mode (double_type_node, V2DFmode);
15096 tree V4SF_type_node = build_vector_type_for_mode (float_type_node, V4SFmode);
15097 tree V4SI_type_node = build_vector_type_for_mode (intSI_type_node, V4SImode);
15098 tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
15099 tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode);
15100 tree V8HI_type_node = build_vector_type_for_mode (intHI_type_node, V8HImode);
15101
15102 tree pchar_type_node = build_pointer_type (char_type_node);
15103 tree pcchar_type_node = build_pointer_type (
15104 build_type_variant (char_type_node, 1, 0));
15105 tree pfloat_type_node = build_pointer_type (float_type_node);
15106 tree pcfloat_type_node = build_pointer_type (
15107 build_type_variant (float_type_node, 1, 0));
15108 tree pv2si_type_node = build_pointer_type (V2SI_type_node);
15109 tree pv2di_type_node = build_pointer_type (V2DI_type_node);
15110 tree pdi_type_node = build_pointer_type (long_long_unsigned_type_node);
15111
15112
15113 tree int_ftype_v4sf_v4sf
15114 = build_function_type_list (integer_type_node,
15115 V4SF_type_node, V4SF_type_node, NULL_TREE);
15116 tree v4si_ftype_v4sf_v4sf
15117 = build_function_type_list (V4SI_type_node,
15118 V4SF_type_node, V4SF_type_node, NULL_TREE);
15119
15120 tree int_ftype_v4sf
15121 = build_function_type_list (integer_type_node,
15122 V4SF_type_node, NULL_TREE);
15123 tree int64_ftype_v4sf
15124 = build_function_type_list (long_long_integer_type_node,
15125 V4SF_type_node, NULL_TREE);
15126 tree int_ftype_v8qi
15127 = build_function_type_list (integer_type_node, V8QI_type_node, NULL_TREE);
15128 tree v4sf_ftype_v4sf_int
15129 = build_function_type_list (V4SF_type_node,
15130 V4SF_type_node, integer_type_node, NULL_TREE);
15131 tree v4sf_ftype_v4sf_int64
15132 = build_function_type_list (V4SF_type_node,
15133 V4SF_type_node, long_long_integer_type_node,
15134 NULL_TREE);
15135 tree v4sf_ftype_v4sf_v2si
15136 = build_function_type_list (V4SF_type_node,
15137 V4SF_type_node, V2SI_type_node, NULL_TREE);
15138
15139
15140 tree v8qi_ftype_v4hi_v4hi
15141 = build_function_type_list (V8QI_type_node,
15142 V4HI_type_node, V4HI_type_node, NULL_TREE);
15143 tree v4hi_ftype_v2si_v2si
15144 = build_function_type_list (V4HI_type_node,
15145 V2SI_type_node, V2SI_type_node, NULL_TREE);
15146 tree v4sf_ftype_v4sf_v4sf_int
15147 = build_function_type_list (V4SF_type_node,
15148 V4SF_type_node, V4SF_type_node,
15149 integer_type_node, NULL_TREE);
15150 tree v2si_ftype_v4hi_v4hi
15151 = build_function_type_list (V2SI_type_node,
15152 V4HI_type_node, V4HI_type_node, NULL_TREE);
15153 tree v4hi_ftype_v4hi_int
15154 = build_function_type_list (V4HI_type_node,
15155 V4HI_type_node, integer_type_node, NULL_TREE);
15156 tree v4hi_ftype_v4hi_di
15157 = build_function_type_list (V4HI_type_node,
15158 V4HI_type_node, long_long_unsigned_type_node,
15159 NULL_TREE);
15160 tree v2si_ftype_v2si_di
15161 = build_function_type_list (V2SI_type_node,
15162 V2SI_type_node, long_long_unsigned_type_node,
15163 NULL_TREE);
15164 tree void_ftype_void
15165 = build_function_type (void_type_node, void_list_node);
15166 tree void_ftype_unsigned
15167 = build_function_type_list (void_type_node, unsigned_type_node, NULL_TREE);
15168 tree void_ftype_unsigned_unsigned
15169 = build_function_type_list (void_type_node, unsigned_type_node,
15170 unsigned_type_node, NULL_TREE);
15171 tree void_ftype_pcvoid_unsigned_unsigned
15172 = build_function_type_list (void_type_node, const_ptr_type_node,
15173 unsigned_type_node, unsigned_type_node,
15174 NULL_TREE);
15175 tree unsigned_ftype_void
15176 = build_function_type (unsigned_type_node, void_list_node);
15177 tree v2si_ftype_v4sf
15178 = build_function_type_list (V2SI_type_node, V4SF_type_node, NULL_TREE);
15179
15180 tree void_ftype_v8qi_v8qi_pchar
15181 = build_function_type_list (void_type_node,
15182 V8QI_type_node, V8QI_type_node,
15183 pchar_type_node, NULL_TREE);
15184 tree v4sf_ftype_pcfloat
15185 = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
15186
15187 tree v4sf_ftype_v4sf_pv2si
15188 = build_function_type_list (V4SF_type_node,
15189 V4SF_type_node, pv2si_type_node, NULL_TREE);
15190 tree void_ftype_pv2si_v4sf
15191 = build_function_type_list (void_type_node,
15192 pv2si_type_node, V4SF_type_node, NULL_TREE);
15193 tree void_ftype_pfloat_v4sf
15194 = build_function_type_list (void_type_node,
15195 pfloat_type_node, V4SF_type_node, NULL_TREE);
15196 tree void_ftype_pdi_di
15197 = build_function_type_list (void_type_node,
15198 pdi_type_node, long_long_unsigned_type_node,
15199 NULL_TREE);
15200 tree void_ftype_pv2di_v2di
15201 = build_function_type_list (void_type_node,
15202 pv2di_type_node, V2DI_type_node, NULL_TREE);
15203
15204 tree v4sf_ftype_v4sf
15205 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
15206
15207
15208 tree v4sf_ftype_v4sf_v4sf
15209 = build_function_type_list (V4SF_type_node,
15210 V4SF_type_node, V4SF_type_node, NULL_TREE);
15211 tree v8qi_ftype_v8qi_v8qi
15212 = build_function_type_list (V8QI_type_node,
15213 V8QI_type_node, V8QI_type_node, NULL_TREE);
15214 tree v4hi_ftype_v4hi_v4hi
15215 = build_function_type_list (V4HI_type_node,
15216 V4HI_type_node, V4HI_type_node, NULL_TREE);
15217 tree v2si_ftype_v2si_v2si
15218 = build_function_type_list (V2SI_type_node,
15219 V2SI_type_node, V2SI_type_node, NULL_TREE);
15220 tree di_ftype_di_di
15221 = build_function_type_list (long_long_unsigned_type_node,
15222 long_long_unsigned_type_node,
15223 long_long_unsigned_type_node, NULL_TREE);
15224
15225 tree v2si_ftype_v2sf
15226 = build_function_type_list (V2SI_type_node, V2SF_type_node, NULL_TREE);
15227 tree v2sf_ftype_v2si
15228 = build_function_type_list (V2SF_type_node, V2SI_type_node, NULL_TREE);
15229 tree v2si_ftype_v2si
15230 = build_function_type_list (V2SI_type_node, V2SI_type_node, NULL_TREE);
15231 tree v2sf_ftype_v2sf
15232 = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
15233 tree v2sf_ftype_v2sf_v2sf
15234 = build_function_type_list (V2SF_type_node,
15235 V2SF_type_node, V2SF_type_node, NULL_TREE);
15236 tree v2si_ftype_v2sf_v2sf
15237 = build_function_type_list (V2SI_type_node,
15238 V2SF_type_node, V2SF_type_node, NULL_TREE);
15239 tree pint_type_node = build_pointer_type (integer_type_node);
15240 tree pdouble_type_node = build_pointer_type (double_type_node);
15241 tree pcdouble_type_node = build_pointer_type (
15242 build_type_variant (double_type_node, 1, 0));
15243 tree int_ftype_v2df_v2df
15244 = build_function_type_list (integer_type_node,
15245 V2DF_type_node, V2DF_type_node, NULL_TREE);
15246
15247 tree void_ftype_pcvoid
15248 = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
15249 tree v4sf_ftype_v4si
15250 = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
15251 tree v4si_ftype_v4sf
15252 = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
15253 tree v2df_ftype_v4si
15254 = build_function_type_list (V2DF_type_node, V4SI_type_node, NULL_TREE);
15255 tree v4si_ftype_v2df
15256 = build_function_type_list (V4SI_type_node, V2DF_type_node, NULL_TREE);
15257 tree v2si_ftype_v2df
15258 = build_function_type_list (V2SI_type_node, V2DF_type_node, NULL_TREE);
15259 tree v4sf_ftype_v2df
15260 = build_function_type_list (V4SF_type_node, V2DF_type_node, NULL_TREE);
15261 tree v2df_ftype_v2si
15262 = build_function_type_list (V2DF_type_node, V2SI_type_node, NULL_TREE);
15263 tree v2df_ftype_v4sf
15264 = build_function_type_list (V2DF_type_node, V4SF_type_node, NULL_TREE);
15265 tree int_ftype_v2df
15266 = build_function_type_list (integer_type_node, V2DF_type_node, NULL_TREE);
15267 tree int64_ftype_v2df
15268 = build_function_type_list (long_long_integer_type_node,
15269 V2DF_type_node, NULL_TREE);
15270 tree v2df_ftype_v2df_int
15271 = build_function_type_list (V2DF_type_node,
15272 V2DF_type_node, integer_type_node, NULL_TREE);
15273 tree v2df_ftype_v2df_int64
15274 = build_function_type_list (V2DF_type_node,
15275 V2DF_type_node, long_long_integer_type_node,
15276 NULL_TREE);
15277 tree v4sf_ftype_v4sf_v2df
15278 = build_function_type_list (V4SF_type_node,
15279 V4SF_type_node, V2DF_type_node, NULL_TREE);
15280 tree v2df_ftype_v2df_v4sf
15281 = build_function_type_list (V2DF_type_node,
15282 V2DF_type_node, V4SF_type_node, NULL_TREE);
15283 tree v2df_ftype_v2df_v2df_int
15284 = build_function_type_list (V2DF_type_node,
15285 V2DF_type_node, V2DF_type_node,
15286 integer_type_node,
15287 NULL_TREE);
15288 tree v2df_ftype_v2df_pcdouble
15289 = build_function_type_list (V2DF_type_node,
15290 V2DF_type_node, pcdouble_type_node, NULL_TREE);
15291 tree void_ftype_pdouble_v2df
15292 = build_function_type_list (void_type_node,
15293 pdouble_type_node, V2DF_type_node, NULL_TREE);
15294 tree void_ftype_pint_int
15295 = build_function_type_list (void_type_node,
15296 pint_type_node, integer_type_node, NULL_TREE);
15297 tree void_ftype_v16qi_v16qi_pchar
15298 = build_function_type_list (void_type_node,
15299 V16QI_type_node, V16QI_type_node,
15300 pchar_type_node, NULL_TREE);
15301 tree v2df_ftype_pcdouble
15302 = build_function_type_list (V2DF_type_node, pcdouble_type_node, NULL_TREE);
15303 tree v2df_ftype_v2df_v2df
15304 = build_function_type_list (V2DF_type_node,
15305 V2DF_type_node, V2DF_type_node, NULL_TREE);
15306 tree v16qi_ftype_v16qi_v16qi
15307 = build_function_type_list (V16QI_type_node,
15308 V16QI_type_node, V16QI_type_node, NULL_TREE);
15309 tree v8hi_ftype_v8hi_v8hi
15310 = build_function_type_list (V8HI_type_node,
15311 V8HI_type_node, V8HI_type_node, NULL_TREE);
15312 tree v4si_ftype_v4si_v4si
15313 = build_function_type_list (V4SI_type_node,
15314 V4SI_type_node, V4SI_type_node, NULL_TREE);
15315 tree v2di_ftype_v2di_v2di
15316 = build_function_type_list (V2DI_type_node,
15317 V2DI_type_node, V2DI_type_node, NULL_TREE);
15318 tree v2di_ftype_v2df_v2df
15319 = build_function_type_list (V2DI_type_node,
15320 V2DF_type_node, V2DF_type_node, NULL_TREE);
15321 tree v2df_ftype_v2df
15322 = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
15323 tree v2di_ftype_v2di_int
15324 = build_function_type_list (V2DI_type_node,
15325 V2DI_type_node, integer_type_node, NULL_TREE);
15326 tree v4si_ftype_v4si_int
15327 = build_function_type_list (V4SI_type_node,
15328 V4SI_type_node, integer_type_node, NULL_TREE);
15329 tree v8hi_ftype_v8hi_int
15330 = build_function_type_list (V8HI_type_node,
15331 V8HI_type_node, integer_type_node, NULL_TREE);
15332 tree v4si_ftype_v8hi_v8hi
15333 = build_function_type_list (V4SI_type_node,
15334 V8HI_type_node, V8HI_type_node, NULL_TREE);
15335 tree di_ftype_v8qi_v8qi
15336 = build_function_type_list (long_long_unsigned_type_node,
15337 V8QI_type_node, V8QI_type_node, NULL_TREE);
15338 tree di_ftype_v2si_v2si
15339 = build_function_type_list (long_long_unsigned_type_node,
15340 V2SI_type_node, V2SI_type_node, NULL_TREE);
15341 tree v2di_ftype_v16qi_v16qi
15342 = build_function_type_list (V2DI_type_node,
15343 V16QI_type_node, V16QI_type_node, NULL_TREE);
15344 tree v2di_ftype_v4si_v4si
15345 = build_function_type_list (V2DI_type_node,
15346 V4SI_type_node, V4SI_type_node, NULL_TREE);
15347 tree int_ftype_v16qi
15348 = build_function_type_list (integer_type_node, V16QI_type_node, NULL_TREE);
15349 tree v16qi_ftype_pcchar
15350 = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
15351 tree void_ftype_pchar_v16qi
15352 = build_function_type_list (void_type_node,
15353 pchar_type_node, V16QI_type_node, NULL_TREE);
15354 tree v2di_ftype_v2di_unsigned_unsigned
15355 = build_function_type_list (V2DI_type_node, V2DI_type_node,
15356 unsigned_type_node, unsigned_type_node,
15357 NULL_TREE);
15358 tree v2di_ftype_v2di_v2di_unsigned_unsigned
15359 = build_function_type_list (V2DI_type_node, V2DI_type_node, V2DI_type_node,
15360 unsigned_type_node, unsigned_type_node,
15361 NULL_TREE);
15362 tree v2di_ftype_v2di_v16qi
15363 = build_function_type_list (V2DI_type_node, V2DI_type_node, V16QI_type_node,
15364 NULL_TREE);
15365
15366 tree float80_type;
15367 tree float128_type;
15368 tree ftype;
15369
15370
15371 if (TYPE_MODE (long_double_type_node) == XFmode)
15372 (*lang_hooks.types.register_builtin_type) (long_double_type_node,
15373 "__float80");
15374 else
15375 {
15376
15377 float80_type = make_node (REAL_TYPE);
15378 TYPE_PRECISION (float80_type) = 80;
15379 layout_type (float80_type);
15380 (*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
15381 }
15382
15383 if (TARGET_64BIT)
15384 {
15385 float128_type = make_node (REAL_TYPE);
15386 TYPE_PRECISION (float128_type) = 128;
15387 layout_type (float128_type);
15388 (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
15389 }
15390
15391
15392
15393 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
15394 {
15395
15396
15397 enum machine_mode mode;
15398 tree type;
15399
15400 if (d->name == 0)
15401 continue;
15402 mode = insn_data[d->icode].operand[1].mode;
15403
15404 switch (mode)
15405 {
15406 case V16QImode:
15407 type = v16qi_ftype_v16qi_v16qi;
15408 break;
15409 case V8HImode:
15410 type = v8hi_ftype_v8hi_v8hi;
15411 break;
15412 case V4SImode:
15413 type = v4si_ftype_v4si_v4si;
15414 break;
15415 case V2DImode:
15416 type = v2di_ftype_v2di_v2di;
15417 break;
15418 case V2DFmode:
15419 type = v2df_ftype_v2df_v2df;
15420 break;
15421 case V4SFmode:
15422 type = v4sf_ftype_v4sf_v4sf;
15423 break;
15424 case V8QImode:
15425 type = v8qi_ftype_v8qi_v8qi;
15426 break;
15427 case V4HImode:
15428 type = v4hi_ftype_v4hi_v4hi;
15429 break;
15430 case V2SImode:
15431 type = v2si_ftype_v2si_v2si;
15432 break;
15433 case DImode:
15434 type = di_ftype_di_di;
15435 break;
15436
15437 default:
15438 gcc_unreachable ();
15439 }
15440
15441
15442 if (d->icode == CODE_FOR_sse_maskcmpv4sf3
15443 || d->icode == CODE_FOR_sse_vmmaskcmpv4sf3)
15444 type = v4si_ftype_v4sf_v4sf;
15445
15446 if (d->icode == CODE_FOR_sse2_maskcmpv2df3
15447 || d->icode == CODE_FOR_sse2_vmmaskcmpv2df3)
15448 type = v2di_ftype_v2df_v2df;
15449
15450 def_builtin (d->mask, d->name, type, d->code);
15451 }
15452
15453
15454 def_builtin (MASK_MMX, "__builtin_ia32_emms", void_ftype_void, IX86_BUILTIN_EMMS);
15455 def_builtin (MASK_MMX, "__builtin_ia32_psllw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSLLW);
15456 def_builtin (MASK_MMX, "__builtin_ia32_pslld", v2si_ftype_v2si_di, IX86_BUILTIN_PSLLD);
15457 def_builtin (MASK_MMX, "__builtin_ia32_psllq", di_ftype_di_di, IX86_BUILTIN_PSLLQ);
15458
15459 def_builtin (MASK_MMX, "__builtin_ia32_psrlw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSRLW);
15460 def_builtin (MASK_MMX, "__builtin_ia32_psrld", v2si_ftype_v2si_di, IX86_BUILTIN_PSRLD);
15461 def_builtin (MASK_MMX, "__builtin_ia32_psrlq", di_ftype_di_di, IX86_BUILTIN_PSRLQ);
15462
15463 def_builtin (MASK_MMX, "__builtin_ia32_psraw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSRAW);
15464 def_builtin (MASK_MMX, "__builtin_ia32_psrad", v2si_ftype_v2si_di, IX86_BUILTIN_PSRAD);
15465
15466 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pshufw", v4hi_ftype_v4hi_int, IX86_BUILTIN_PSHUFW);
15467 def_builtin (MASK_MMX, "__builtin_ia32_pmaddwd", v2si_ftype_v4hi_v4hi, IX86_BUILTIN_PMADDWD);
15468
15469
15470 for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
15471 if (d->mask == MASK_SSE2)
15472 def_builtin (d->mask, d->name, int_ftype_v2df_v2df, d->code);
15473 else
15474 def_builtin (d->mask, d->name, int_ftype_v4sf_v4sf, d->code);
15475
15476 def_builtin (MASK_MMX, "__builtin_ia32_packsswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKSSWB);
15477 def_builtin (MASK_MMX, "__builtin_ia32_packssdw", v4hi_ftype_v2si_v2si, IX86_BUILTIN_PACKSSDW);
15478 def_builtin (MASK_MMX, "__builtin_ia32_packuswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKUSWB);
15479
15480 def_builtin (MASK_SSE, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
15481 def_builtin (MASK_SSE, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
15482 def_builtin (MASK_SSE, "__builtin_ia32_cvtpi2ps", v4sf_ftype_v4sf_v2si, IX86_BUILTIN_CVTPI2PS);
15483 def_builtin (MASK_SSE, "__builtin_ia32_cvtps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTPS2PI);
15484 def_builtin (MASK_SSE, "__builtin_ia32_cvtsi2ss", v4sf_ftype_v4sf_int, IX86_BUILTIN_CVTSI2SS);
15485 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvtsi642ss", v4sf_ftype_v4sf_int64, IX86_BUILTIN_CVTSI642SS);
15486 def_builtin (MASK_SSE, "__builtin_ia32_cvtss2si", int_ftype_v4sf, IX86_BUILTIN_CVTSS2SI);
15487 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvtss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTSS2SI64);
15488 def_builtin (MASK_SSE, "__builtin_ia32_cvttps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTTPS2PI);
15489 def_builtin (MASK_SSE, "__builtin_ia32_cvttss2si", int_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI);
15490 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvttss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI64);
15491
15492 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ);
15493
15494 def_builtin (MASK_SSE, "__builtin_ia32_loadups", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADUPS);
15495 def_builtin (MASK_SSE, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS);
15496
15497 def_builtin (MASK_SSE, "__builtin_ia32_loadhps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADHPS);
15498 def_builtin (MASK_SSE, "__builtin_ia32_loadlps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADLPS);
15499 def_builtin (MASK_SSE, "__builtin_ia32_storehps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STOREHPS);
15500 def_builtin (MASK_SSE, "__builtin_ia32_storelps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STORELPS);
15501
15502 def_builtin (MASK_SSE, "__builtin_ia32_movmskps", int_ftype_v4sf, IX86_BUILTIN_MOVMSKPS);
15503 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pmovmskb", int_ftype_v8qi, IX86_BUILTIN_PMOVMSKB);
15504 def_builtin (MASK_SSE, "__builtin_ia32_movntps", void_ftype_pfloat_v4sf, IX86_BUILTIN_MOVNTPS);
15505 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_movntq", void_ftype_pdi_di, IX86_BUILTIN_MOVNTQ);
15506
15507 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_sfence", void_ftype_void, IX86_BUILTIN_SFENCE);
15508
15509 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_psadbw", di_ftype_v8qi_v8qi, IX86_BUILTIN_PSADBW);
15510
15511 def_builtin (MASK_SSE, "__builtin_ia32_rcpps", v4sf_ftype_v4sf, IX86_BUILTIN_RCPPS);
15512 def_builtin (MASK_SSE, "__builtin_ia32_rcpss", v4sf_ftype_v4sf, IX86_BUILTIN_RCPSS);
15513 def_builtin (MASK_SSE, "__builtin_ia32_rsqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTPS);
15514 def_builtin (MASK_SSE, "__builtin_ia32_rsqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTSS);
15515 def_builtin (MASK_SSE, "__builtin_ia32_sqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTPS);
15516 def_builtin (MASK_SSE, "__builtin_ia32_sqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTSS);
15517
15518 def_builtin (MASK_SSE, "__builtin_ia32_shufps", v4sf_ftype_v4sf_v4sf_int, IX86_BUILTIN_SHUFPS);
15519
15520
15521 def_builtin (MASK_3DNOW, "__builtin_ia32_femms", void_ftype_void, IX86_BUILTIN_FEMMS);
15522 def_builtin (MASK_3DNOW, "__builtin_ia32_pavgusb", v8qi_ftype_v8qi_v8qi, IX86_BUILTIN_PAVGUSB);
15523 def_builtin (MASK_3DNOW, "__builtin_ia32_pf2id", v2si_ftype_v2sf, IX86_BUILTIN_PF2ID);
15524 def_builtin (MASK_3DNOW, "__builtin_ia32_pfacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFACC);
15525 def_builtin (MASK_3DNOW, "__builtin_ia32_pfadd", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFADD);
15526 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpeq", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPEQ);
15527 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpge", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPGE);
15528 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpgt", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPGT);
15529 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmax", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMAX);
15530 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmin", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMIN);
15531 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmul", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMUL);
15532 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcp", v2sf_ftype_v2sf, IX86_BUILTIN_PFRCP);
15533 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcpit1", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRCPIT1);
15534 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcpit2", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRCPIT2);
15535 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrsqrt", v2sf_ftype_v2sf, IX86_BUILTIN_PFRSQRT);
15536 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrsqit1", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRSQIT1);
15537 def_builtin (MASK_3DNOW, "__builtin_ia32_pfsub", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFSUB);
15538 def_builtin (MASK_3DNOW, "__builtin_ia32_pfsubr", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFSUBR);
15539 def_builtin (MASK_3DNOW, "__builtin_ia32_pi2fd", v2sf_ftype_v2si, IX86_BUILTIN_PI2FD);
15540 def_builtin (MASK_3DNOW, "__builtin_ia32_pmulhrw", v4hi_ftype_v4hi_v4hi, IX86_BUILTIN_PMULHRW);
15541
15542
15543 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pf2iw", v2si_ftype_v2sf, IX86_BUILTIN_PF2IW);
15544 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pfnacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFNACC);
15545 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pfpnacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFPNACC);
15546 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pi2fw", v2sf_ftype_v2si, IX86_BUILTIN_PI2FW);
15547 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsf", v2sf_ftype_v2sf, IX86_BUILTIN_PSWAPDSF);
15548 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsi", v2si_ftype_v2si, IX86_BUILTIN_PSWAPDSI);
15549
15550
15551 def_builtin (MASK_SSE2, "__builtin_ia32_maskmovdqu", void_ftype_v16qi_v16qi_pchar, IX86_BUILTIN_MASKMOVDQU);
15552
15553 def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADUPD);
15554 def_builtin (MASK_SSE2, "__builtin_ia32_storeupd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREUPD);
15555
15556 def_builtin (MASK_SSE2, "__builtin_ia32_loadhpd", v2df_ftype_v2df_pcdouble, IX86_BUILTIN_LOADHPD);
15557 def_builtin (MASK_SSE2, "__builtin_ia32_loadlpd", v2df_ftype_v2df_pcdouble, IX86_BUILTIN_LOADLPD);
15558
15559 def_builtin (MASK_SSE2, "__builtin_ia32_movmskpd", int_ftype_v2df, IX86_BUILTIN_MOVMSKPD);
15560 def_builtin (MASK_SSE2, "__builtin_ia32_pmovmskb128", int_ftype_v16qi, IX86_BUILTIN_PMOVMSKB128);
15561 def_builtin (MASK_SSE2, "__builtin_ia32_movnti", void_ftype_pint_int, IX86_BUILTIN_MOVNTI);
15562 def_builtin (MASK_SSE2, "__builtin_ia32_movntpd", void_ftype_pdouble_v2df, IX86_BUILTIN_MOVNTPD);
15563 def_builtin (MASK_SSE2, "__builtin_ia32_movntdq", void_ftype_pv2di_v2di, IX86_BUILTIN_MOVNTDQ);
15564
15565 def_builtin (MASK_SSE2, "__builtin_ia32_pshufd", v4si_ftype_v4si_int, IX86_BUILTIN_PSHUFD);
15566 def_builtin (MASK_SSE2, "__builtin_ia32_pshuflw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFLW);
15567 def_builtin (MASK_SSE2, "__builtin_ia32_pshufhw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFHW);
15568 def_builtin (MASK_SSE2, "__builtin_ia32_psadbw128", v2di_ftype_v16qi_v16qi, IX86_BUILTIN_PSADBW128);
15569
15570 def_builtin (MASK_SSE2, "__builtin_ia32_sqrtpd", v2df_ftype_v2df, IX86_BUILTIN_SQRTPD);
15571 def_builtin (MASK_SSE2, "__builtin_ia32_sqrtsd", v2df_ftype_v2df, IX86_BUILTIN_SQRTSD);
15572
15573 def_builtin (MASK_SSE2, "__builtin_ia32_shufpd", v2df_ftype_v2df_v2df_int, IX86_BUILTIN_SHUFPD);
15574
15575 def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2pd", v2df_ftype_v4si, IX86_BUILTIN_CVTDQ2PD);
15576 def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2ps", v4sf_ftype_v4si, IX86_BUILTIN_CVTDQ2PS);
15577
15578 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTPD2DQ);
15579 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTPD2PI);
15580 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2ps", v4sf_ftype_v2df, IX86_BUILTIN_CVTPD2PS);
15581 def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTTPD2DQ);
15582 def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTTPD2PI);
15583
15584 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpi2pd", v2df_ftype_v2si, IX86_BUILTIN_CVTPI2PD);
15585
15586 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2si", int_ftype_v2df, IX86_BUILTIN_CVTSD2SI);
15587 def_builtin (MASK_SSE2, "__builtin_ia32_cvttsd2si", int_ftype_v2df, IX86_BUILTIN_CVTTSD2SI);
15588 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvtsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTSD2SI64);
15589 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvttsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTTSD2SI64);
15590
15591 def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTPS2DQ);
15592 def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2pd", v2df_ftype_v4sf, IX86_BUILTIN_CVTPS2PD);
15593 def_builtin (MASK_SSE2, "__builtin_ia32_cvttps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTTPS2DQ);
15594
15595 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsi2sd", v2df_ftype_v2df_int, IX86_BUILTIN_CVTSI2SD);
15596 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvtsi642sd", v2df_ftype_v2df_int64, IX86_BUILTIN_CVTSI642SD);
15597 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2ss", v4sf_ftype_v4sf_v2df, IX86_BUILTIN_CVTSD2SS);
15598 def_builtin (MASK_SSE2, "__builtin_ia32_cvtss2sd", v2df_ftype_v2df_v4sf, IX86_BUILTIN_CVTSS2SD);
15599
15600 def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pcvoid, IX86_BUILTIN_CLFLUSH);
15601 def_builtin (MASK_SSE2, "__builtin_ia32_lfence", void_ftype_void, IX86_BUILTIN_LFENCE);
15602 def_builtin (MASK_SSE2, "__builtin_ia32_mfence", void_ftype_void, IX86_BUILTIN_MFENCE);
15603
15604 def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQU);
15605 def_builtin (MASK_SSE2, "__builtin_ia32_storedqu", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQU);
15606
15607 def_builtin (MASK_SSE2, "__builtin_ia32_pmuludq", di_ftype_v2si_v2si, IX86_BUILTIN_PMULUDQ);
15608 def_builtin (MASK_SSE2, "__builtin_ia32_pmuludq128", v2di_ftype_v4si_v4si, IX86_BUILTIN_PMULUDQ128);
15609
15610 def_builtin (MASK_SSE2, "__builtin_ia32_psllw128", v8hi_ftype_v8hi_v8hi, IX86_BUILTIN_PSLLW128);
15611 def_builtin (MASK_SSE2, "__builtin_ia32_pslld128", v4si_ftype_v4si_v4si, IX86_BUILTIN_PSLLD128);
15612 def_builtin (MASK_SSE2, "__builtin_ia32_psllq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSLLQ128);
15613
15614 def_builtin (MASK_SSE2, "__builtin_ia32_psrlw128", v8hi_ftype_v8hi_v8hi, IX86_BUILTIN_PSRLW128);
15615 def_builtin (MASK_SSE2, "__builtin_ia32_psrld128", v4si_ftype_v4si_v4si, IX86_BUILTIN_PSRLD128);
15616 def_builtin (MASK_SSE2, "__builtin_ia32_psrlq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSRLQ128);
15617
15618 def_builtin (MASK_SSE2, "__builtin_ia32_psraw128", v8hi_ftype_v8hi_v8hi, IX86_BUILTIN_PSRAW128);
15619 def_builtin (MASK_SSE2, "__builtin_ia32_psrad128", v4si_ftype_v4si_v4si, IX86_BUILTIN_PSRAD128);
15620
15621 def_builtin (MASK_SSE2, "__builtin_ia32_pslldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLDQI128);
15622 def_builtin (MASK_SSE2, "__builtin_ia32_psllwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSLLWI128);
15623 def_builtin (MASK_SSE2, "__builtin_ia32_pslldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSLLDI128);
15624 def_builtin (MASK_SSE2, "__builtin_ia32_psllqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLQI128);
15625
15626 def_builtin (MASK_SSE2, "__builtin_ia32_psrldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLDQI128);
15627 def_builtin (MASK_SSE2, "__builtin_ia32_psrlwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRLWI128);
15628 def_builtin (MASK_SSE2, "__builtin_ia32_psrldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRLDI128);
15629 def_builtin (MASK_SSE2, "__builtin_ia32_psrlqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLQI128);
15630
15631 def_builtin (MASK_SSE2, "__builtin_ia32_psrawi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRAWI128);
15632 def_builtin (MASK_SSE2, "__builtin_ia32_psradi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRADI128);
15633
15634 def_builtin (MASK_SSE2, "__builtin_ia32_pmaddwd128", v4si_ftype_v8hi_v8hi, IX86_BUILTIN_PMADDWD128);
15635
15636
15637 def_builtin (MASK_SSE3, "__builtin_ia32_monitor",
15638 void_ftype_pcvoid_unsigned_unsigned,
15639 IX86_BUILTIN_MONITOR);
15640 def_builtin (MASK_SSE3, "__builtin_ia32_mwait",
15641 void_ftype_unsigned_unsigned,
15642 IX86_BUILTIN_MWAIT);
15643 def_builtin (MASK_SSE3, "__builtin_ia32_movshdup",
15644 v4sf_ftype_v4sf,
15645 IX86_BUILTIN_MOVSHDUP);
15646 def_builtin (MASK_SSE3, "__builtin_ia32_movsldup",
15647 v4sf_ftype_v4sf,
15648 IX86_BUILTIN_MOVSLDUP);
15649 def_builtin (MASK_SSE3, "__builtin_ia32_lddqu",
15650 v16qi_ftype_pcchar, IX86_BUILTIN_LDDQU);
15651
15652
15653
15654 def_builtin (MASK_SSE4A, "__builtin_ia32_movntss", void_ftype_pfloat_v4sf, IX86_BUILTIN_MOVNTSS);
15655 def_builtin (MASK_SSE4A, "__builtin_ia32_movntsd", void_ftype_pdouble_v2df, IX86_BUILTIN_MOVNTSD);
15656 def_builtin (MASK_SSE4A, "__builtin_ia32_extrqi",v2di_ftype_v2di_unsigned_unsigned, IX86_BUILTIN_EXTRQI);
15657 def_builtin (MASK_SSE4A, "__builtin_ia32_extrq", v2di_ftype_v2di_v16qi, IX86_BUILTIN_EXTRQ);
15658 def_builtin (MASK_SSE4A, "__builtin_ia32_insertqi",v2di_ftype_v2di_v2di_unsigned_unsigned, IX86_BUILTIN_INSERTQI);
15659 def_builtin (MASK_SSE4A, "__builtin_ia32_insertq",v2di_ftype_v2di_v2di, IX86_BUILTIN_INSERTQ);
15660
15661
15662 ftype = build_function_type_list (V2SI_type_node, integer_type_node,
15663 integer_type_node, NULL_TREE);
15664 def_builtin (MASK_MMX, "__builtin_ia32_vec_init_v2si",
15665 ftype, IX86_BUILTIN_VEC_INIT_V2SI);
15666
15667 ftype = build_function_type_list (V4HI_type_node, short_integer_type_node,
15668 short_integer_type_node,
15669 short_integer_type_node,
15670 short_integer_type_node, NULL_TREE);
15671 def_builtin (MASK_MMX, "__builtin_ia32_vec_init_v4hi",
15672 ftype, IX86_BUILTIN_VEC_INIT_V4HI);
15673
15674 ftype = build_function_type_list (V8QI_type_node, char_type_node,
15675 char_type_node, char_type_node,
15676 char_type_node, char_type_node,
15677 char_type_node, char_type_node,
15678 char_type_node, NULL_TREE);
15679 def_builtin (MASK_MMX, "__builtin_ia32_vec_init_v8qi",
15680 ftype, IX86_BUILTIN_VEC_INIT_V8QI);
15681
15682
15683 ftype = build_function_type_list (double_type_node, V2DF_type_node,
15684 integer_type_node, NULL_TREE);
15685 def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v2df",
15686 ftype, IX86_BUILTIN_VEC_EXT_V2DF);
15687
15688 ftype = build_function_type_list (long_long_integer_type_node,
15689 V2DI_type_node, integer_type_node,
15690 NULL_TREE);
15691 def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v2di",
15692 ftype, IX86_BUILTIN_VEC_EXT_V2DI);
15693
15694 ftype = build_function_type_list (float_type_node, V4SF_type_node,
15695 integer_type_node, NULL_TREE);
15696 def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v4sf",
15697 ftype, IX86_BUILTIN_VEC_EXT_V4SF);
15698
15699 ftype = build_function_type_list (intSI_type_node, V4SI_type_node,
15700 integer_type_node, NULL_TREE);
15701 def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v4si",
15702 ftype, IX86_BUILTIN_VEC_EXT_V4SI);
15703
15704 ftype = build_function_type_list (intHI_type_node, V8HI_type_node,
15705 integer_type_node, NULL_TREE);
15706 def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v8hi",
15707 ftype, IX86_BUILTIN_VEC_EXT_V8HI);
15708
15709 ftype = build_function_type_list (intHI_type_node, V4HI_type_node,
15710 integer_type_node, NULL_TREE);
15711 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_vec_ext_v4hi",
15712 ftype, IX86_BUILTIN_VEC_EXT_V4HI);
15713
15714 ftype = build_function_type_list (intSI_type_node, V2SI_type_node,
15715 integer_type_node, NULL_TREE);
15716 def_builtin (MASK_MMX, "__builtin_ia32_vec_ext_v2si",
15717 ftype, IX86_BUILTIN_VEC_EXT_V2SI);
15718
15719
15720 ftype = build_function_type_list (V8HI_type_node, V8HI_type_node,
15721 intHI_type_node,
15722 integer_type_node, NULL_TREE);
15723 def_builtin (MASK_SSE, "__builtin_ia32_vec_set_v8hi",
15724 ftype, IX86_BUILTIN_VEC_SET_V8HI);
15725
15726 ftype = build_function_type_list (V4HI_type_node, V4HI_type_node,
15727 intHI_type_node,
15728 integer_type_node, NULL_TREE);
15729 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_vec_set_v4hi",
15730 ftype, IX86_BUILTIN_VEC_SET_V4HI);
15731 }
15732
15733
15734
15735
15736 static rtx
15737 safe_vector_operand (rtx x, enum machine_mode mode)
15738 {
15739 if (x == const0_rtx)
15740 x = CONST0_RTX (mode);
15741 return x;
15742 }
15743
15744
15745
15746 static rtx
15747 ix86_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
15748 {
15749 rtx pat, xops[3];
15750 tree arg0 = TREE_VALUE (arglist);
15751 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
15752 rtx op0 = expand_normal (arg0);
15753 rtx op1 = expand_normal (arg1);
15754 enum machine_mode tmode = insn_data[icode].operand[0].mode;
15755 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
15756 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
15757
15758 if (VECTOR_MODE_P (mode0))
15759 op0 = safe_vector_operand (op0, mode0);
15760 if (VECTOR_MODE_P (mode1))
15761 op1 = safe_vector_operand (op1, mode1);
15762
15763 if (optimize || !target
15764 || GET_MODE (target) != tmode
15765 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
15766 target = gen_reg_rtx (tmode);
15767
15768 if (GET_MODE (op1) == SImode && mode1 == TImode)
15769 {
15770 rtx x = gen_reg_rtx (V4SImode);
15771 emit_insn (gen_sse2_loadd (x, op1));
15772 op1 = gen_lowpart (TImode, x);
15773 }
15774
15775
15776
15777 gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
15778 && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
15779
15780 if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
15781 op0 = copy_to_mode_reg (mode0, op0);
15782 if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
15783 op1 = copy_to_mode_reg (mode1, op1);
15784
15785
15786
15787
15788 xops[0] = target;
15789 xops[1] = op0;
15790 xops[2] = op1;
15791
15792 if (tmode == mode0 && tmode == mode1)
15793 {
15794 target = ix86_fixup_binary_operands (UNKNOWN, tmode, xops);
15795 op0 = xops[1];
15796 op1 = xops[2];
15797 }
15798 else if (optimize || !ix86_binary_operator_ok (UNKNOWN, tmode, xops))
15799 {
15800 op0 = force_reg (mode0, op0);
15801 op1 = force_reg (mode1, op1);
15802 target = gen_reg_rtx (tmode);
15803 }
15804
15805 pat = GEN_FCN (icode) (target, op0, op1);
15806 if (! pat)
15807 return 0;
15808 emit_insn (pat);
15809 return target;
15810 }
15811
15812
15813
15814 static rtx
15815 ix86_expand_store_builtin (enum insn_code icode, tree arglist)
15816 {
15817 rtx pat;
15818 tree arg0 = TREE_VALUE (arglist);
15819 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
15820 rtx op0 = expand_normal (arg0);
15821 rtx op1 = expand_normal (arg1);
15822 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
15823 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
15824
15825 if (VECTOR_MODE_P (mode1))
15826 op1 = safe_vector_operand (op1, mode1);
15827
15828 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
15829 op1 = copy_to_mode_reg (mode1, op1);
15830
15831 pat = GEN_FCN (icode) (op0, op1);
15832 if (pat)
15833 emit_insn (pat);
15834 return 0;
15835 }
15836
15837
15838
15839 static rtx
15840 ix86_expand_unop_builtin (enum insn_code icode, tree arglist,
15841 rtx target, int do_load)
15842 {
15843 rtx pat;
15844 tree arg0 = TREE_VALUE (arglist);
15845 rtx op0 = expand_normal (arg0);
15846 enum machine_mode tmode = insn_data[icode].operand[0].mode;
15847 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
15848
15849 if (optimize || !target
15850 || GET_MODE (target) != tmode
15851 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
15852 target = gen_reg_rtx (tmode);
15853 if (do_load)
15854 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
15855 else
15856 {
15857 if (VECTOR_MODE_P (mode0))
15858 op0 = safe_vector_operand (op0, mode0);
15859
15860 if ((optimize && !register_operand (op0, mode0))
15861 || ! (*insn_data[icode].operand[1].predicate) (op0, mode0))
15862 op0 = copy_to_mode_reg (mode0, op0);
15863 }
15864
15865 pat = GEN_FCN (icode) (target, op0);
15866 if (! pat)
15867 return 0;
15868 emit_insn (pat);
15869 return target;
15870 }
15871
15872
15873
15874
15875 static rtx
15876 ix86_expand_unop1_builtin (enum insn_code icode, tree arglist, rtx target)
15877 {
15878 rtx pat;
15879 tree arg0 = TREE_VALUE (arglist);
15880 rtx op1, op0 = expand_normal (arg0);
15881 enum machine_mode tmode = insn_data[icode].operand[0].mode;
15882 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
15883
15884 if (optimize || !target
15885 || GET_MODE (target) != tmode
15886 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
15887 target = gen_reg_rtx (tmode);
15888
15889 if (VECTOR_MODE_P (mode0))
15890 op0 = safe_vector_operand (op0, mode0);
15891
15892 if ((optimize && !register_operand (op0, mode0))
15893 || ! (*insn_data[icode].operand[1].predicate) (op0, mode0))
15894 op0 = copy_to_mode_reg (mode0, op0);
15895
15896 op1 = op0;
15897 if (! (*insn_data[icode].operand[2].predicate) (op1, mode0))
15898 op1 = copy_to_mode_reg (mode0, op1);
15899
15900 pat = GEN_FCN (icode) (target, op0, op1);
15901 if (! pat)
15902 return 0;
15903 emit_insn (pat);
15904 return target;
15905 }
15906
15907
15908
15909 static rtx
15910 ix86_expand_sse_compare (const struct builtin_description *d, tree arglist,
15911 rtx target)
15912 {
15913 rtx pat;
15914 tree arg0 = TREE_VALUE (arglist);
15915 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
15916 rtx op0 = expand_normal (arg0);
15917 rtx op1 = expand_normal (arg1);
15918 rtx op2;
15919 enum machine_mode tmode = insn_data[d->icode].operand[0].mode;
15920 enum machine_mode mode0 = insn_data[d->icode].operand[1].mode;
15921 enum machine_mode mode1 = insn_data[d->icode].operand[2].mode;
15922 enum rtx_code comparison = d->comparison;
15923
15924 if (VECTOR_MODE_P (mode0))
15925 op0 = safe_vector_operand (op0, mode0);
15926 if (VECTOR_MODE_P (mode1))
15927 op1 = safe_vector_operand (op1, mode1);
15928
15929
15930
15931 if (d->flag & BUILTIN_DESC_SWAP_OPERANDS)
15932 {
15933 rtx tmp = gen_reg_rtx (mode1);
15934 emit_move_insn (tmp, op1);
15935 op1 = op0;
15936 op0 = tmp;
15937 }
15938
15939 if (optimize || !target
15940 || GET_MODE (target) != tmode
15941 || ! (*insn_data[d->icode].operand[0].predicate) (target, tmode))
15942 target = gen_reg_rtx (tmode);
15943
15944 if ((optimize && !register_operand (op0, mode0))
15945 || ! (*insn_data[d->icode].operand[1].predicate) (op0, mode0))
15946 op0 = copy_to_mode_reg (mode0, op0);
15947 if ((optimize && !register_operand (op1, mode1))
15948 || ! (*insn_data[d->icode].operand[2].predicate) (op1, mode1))
15949 op1 = copy_to_mode_reg (mode1, op1);
15950
15951 op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
15952 pat = GEN_FCN (d->icode) (target, op0, op1, op2);
15953 if (! pat)
15954 return 0;
15955 emit_insn (pat);
15956 return target;
15957 }
15958
15959
15960
15961 static rtx
15962 ix86_expand_sse_comi (const struct builtin_description *d, tree arglist,
15963 rtx target)
15964 {
15965 rtx pat;
15966 tree arg0 = TREE_VALUE (arglist);
15967 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
15968 rtx op0 = expand_normal (arg0);
15969 rtx op1 = expand_normal (arg1);
15970 rtx op2;
15971 enum machine_mode mode0 = insn_data[d->icode].operand[0].mode;
15972 enum machine_mode mode1 = insn_data[d->icode].operand[1].mode;
15973 enum rtx_code comparison = d->comparison;
15974
15975 if (VECTOR_MODE_P (mode0))
15976 op0 = safe_vector_operand (op0, mode0);
15977 if (VECTOR_MODE_P (mode1))
15978 op1 = safe_vector_operand (op1, mode1);
15979
15980
15981
15982 if (d->flag & BUILTIN_DESC_SWAP_OPERANDS)
15983 {
15984 rtx tmp = op1;
15985 op1 = op0;
15986 op0 = tmp;
15987 }
15988
15989 target = gen_reg_rtx (SImode);
15990 emit_move_insn (target, const0_rtx);
15991 target = gen_rtx_SUBREG (QImode, target, 0);
15992
15993 if ((optimize && !register_operand (op0, mode0))
15994 || !(*insn_data[d->icode].operand[0].predicate) (op0, mode0))
15995 op0 = copy_to_mode_reg (mode0, op0);
15996 if ((optimize && !register_operand (op1, mode1))
15997 || !(*insn_data[d->icode].operand[1].predicate) (op1, mode1))
15998 op1 = copy_to_mode_reg (mode1, op1);
15999
16000 op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
16001 pat = GEN_FCN (d->icode) (op0, op1);
16002 if (! pat)
16003 return 0;
16004 emit_insn (pat);
16005 emit_insn (gen_rtx_SET (VOIDmode,
16006 gen_rtx_STRICT_LOW_PART (VOIDmode, target),
16007 gen_rtx_fmt_ee (comparison, QImode,
16008 SET_DEST (pat),
16009 const0_rtx)));
16010
16011 return SUBREG_REG (target);
16012 }
16013
16014
16015
16016
16017 static int
16018 get_element_number (tree vec_type, tree arg)
16019 {
16020 unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
16021
16022 if (!host_integerp (arg, 1)
16023 || (elt = tree_low_cst (arg, 1), elt > max))
16024 {
16025 error ("selector must be an integer constant in the range 0..%wi", max);
16026 return 0;
16027 }
16028
16029 return elt;
16030 }
16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041 static rtx
16042 ix86_expand_vec_init_builtin (tree type, tree arglist, rtx target)
16043 {
16044 enum machine_mode tmode = TYPE_MODE (type);
16045 enum machine_mode inner_mode = GET_MODE_INNER (tmode);
16046 int i, n_elt = GET_MODE_NUNITS (tmode);
16047 rtvec v = rtvec_alloc (n_elt);
16048
16049 gcc_assert (VECTOR_MODE_P (tmode));
16050
16051 for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist))
16052 {
16053 rtx x = expand_normal (TREE_VALUE (arglist));
16054 RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
16055 }
16056
16057 gcc_assert (arglist == NULL);
16058
16059 if (!target || !register_operand (target, tmode))
16060 target = gen_reg_rtx (tmode);
16061
16062 ix86_expand_vector_init (true, target, gen_rtx_PARALLEL (tmode, v));
16063 return target;
16064 }
16065
16066
16067
16068
16069
16070 static rtx
16071 ix86_expand_vec_ext_builtin (tree arglist, rtx target)
16072 {
16073 enum machine_mode tmode, mode0;
16074 tree arg0, arg1;
16075 int elt;
16076 rtx op0;
16077
16078 arg0 = TREE_VALUE (arglist);
16079 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16080
16081 op0 = expand_normal (arg0);
16082 elt = get_element_number (TREE_TYPE (arg0), arg1);
16083
16084 tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
16085 mode0 = TYPE_MODE (TREE_TYPE (arg0));
16086 gcc_assert (VECTOR_MODE_P (mode0));
16087
16088 op0 = force_reg (mode0, op0);
16089
16090 if (optimize || !target || !register_operand (target, tmode))
16091 target = gen_reg_rtx (tmode);
16092
16093 ix86_expand_vector_extract (true, target, op0, elt);
16094
16095 return target;
16096 }
16097
16098
16099
16100
16101
16102 static rtx
16103 ix86_expand_vec_set_builtin (tree arglist)
16104 {
16105 enum machine_mode tmode, mode1;
16106 tree arg0, arg1, arg2;
16107 int elt;
16108 rtx op0, op1, target;
16109
16110 arg0 = TREE_VALUE (arglist);
16111 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16112 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16113
16114 tmode = TYPE_MODE (TREE_TYPE (arg0));
16115 mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
16116 gcc_assert (VECTOR_MODE_P (tmode));
16117
16118 op0 = expand_expr (arg0, NULL_RTX, tmode, 0);
16119 op1 = expand_expr (arg1, NULL_RTX, mode1, 0);
16120 elt = get_element_number (TREE_TYPE (arg0), arg2);
16121
16122 if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode)
16123 op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
16124
16125 op0 = force_reg (tmode, op0);
16126 op1 = force_reg (mode1, op1);
16127
16128
16129
16130 target = gen_reg_rtx (tmode);
16131 emit_move_insn (target, op0);
16132 ix86_expand_vector_set (true, target, op1, elt);
16133
16134 return target;
16135 }
16136
16137
16138
16139
16140
16141
16142
16143 static rtx
16144 ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
16145 enum machine_mode mode ATTRIBUTE_UNUSED,
16146 int ignore ATTRIBUTE_UNUSED)
16147 {
16148 const struct builtin_description *d;
16149 size_t i;
16150 enum insn_code icode;
16151 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
16152 tree arglist = TREE_OPERAND (exp, 1);
16153 tree arg0, arg1, arg2, arg3;
16154 rtx op0, op1, op2, op3, pat;
16155 enum machine_mode tmode, mode0, mode1, mode2, mode3, mode4;
16156 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
16157
16158 switch (fcode)
16159 {
16160 case IX86_BUILTIN_EMMS:
16161 emit_insn (gen_mmx_emms ());
16162 return 0;
16163
16164 case IX86_BUILTIN_SFENCE:
16165 emit_insn (gen_sse_sfence ());
16166 return 0;
16167
16168 case IX86_BUILTIN_MASKMOVQ:
16169 case IX86_BUILTIN_MASKMOVDQU:
16170 icode = (fcode == IX86_BUILTIN_MASKMOVQ
16171 ? CODE_FOR_mmx_maskmovq
16172 : CODE_FOR_sse2_maskmovdqu);
16173
16174 arg1 = TREE_VALUE (arglist);
16175 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
16176 arg0 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16177 op0 = expand_normal (arg0);
16178 op1 = expand_normal (arg1);
16179 op2 = expand_normal (arg2);
16180 mode0 = insn_data[icode].operand[0].mode;
16181 mode1 = insn_data[icode].operand[1].mode;
16182 mode2 = insn_data[icode].operand[2].mode;
16183
16184 op0 = force_reg (Pmode, op0);
16185 op0 = gen_rtx_MEM (mode1, op0);
16186
16187 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
16188 op0 = copy_to_mode_reg (mode0, op0);
16189 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
16190 op1 = copy_to_mode_reg (mode1, op1);
16191 if (! (*insn_data[icode].operand[2].predicate) (op2, mode2))
16192 op2 = copy_to_mode_reg (mode2, op2);
16193 pat = GEN_FCN (icode) (op0, op1, op2);
16194 if (! pat)
16195 return 0;
16196 emit_insn (pat);
16197 return 0;
16198
16199 case IX86_BUILTIN_SQRTSS:
16200 return ix86_expand_unop1_builtin (CODE_FOR_sse_vmsqrtv4sf2, arglist, target);
16201 case IX86_BUILTIN_RSQRTSS:
16202 return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrsqrtv4sf2, arglist, target);
16203 case IX86_BUILTIN_RCPSS:
16204 return ix86_expand_unop1_builtin (CODE_FOR_sse_vmrcpv4sf2, arglist, target);
16205
16206 case IX86_BUILTIN_LOADUPS:
16207 return ix86_expand_unop_builtin (CODE_FOR_sse_movups, arglist, target, 1);
16208
16209 case IX86_BUILTIN_STOREUPS:
16210 return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist);
16211
16212 case IX86_BUILTIN_LOADHPS:
16213 case IX86_BUILTIN_LOADLPS:
16214 case IX86_BUILTIN_LOADHPD:
16215 case IX86_BUILTIN_LOADLPD:
16216 icode = (fcode == IX86_BUILTIN_LOADHPS ? CODE_FOR_sse_loadhps
16217 : fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_loadlps
16218 : fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_loadhpd
16219 : CODE_FOR_sse2_loadlpd);
16220 arg0 = TREE_VALUE (arglist);
16221 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16222 op0 = expand_normal (arg0);
16223 op1 = expand_normal (arg1);
16224 tmode = insn_data[icode].operand[0].mode;
16225 mode0 = insn_data[icode].operand[1].mode;
16226 mode1 = insn_data[icode].operand[2].mode;
16227
16228 op0 = force_reg (mode0, op0);
16229 op1 = gen_rtx_MEM (mode1, copy_to_mode_reg (Pmode, op1));
16230 if (optimize || target == 0
16231 || GET_MODE (target) != tmode
16232 || !register_operand (target, tmode))
16233 target = gen_reg_rtx (tmode);
16234 pat = GEN_FCN (icode) (target, op0, op1);
16235 if (! pat)
16236 return 0;
16237 emit_insn (pat);
16238 return target;
16239
16240 case IX86_BUILTIN_STOREHPS:
16241 case IX86_BUILTIN_STORELPS:
16242 icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_storehps
16243 : CODE_FOR_sse_storelps);
16244 arg0 = TREE_VALUE (arglist);
16245 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16246 op0 = expand_normal (arg0);
16247 op1 = expand_normal (arg1);
16248 mode0 = insn_data[icode].operand[0].mode;
16249 mode1 = insn_data[icode].operand[1].mode;
16250
16251 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
16252 op1 = force_reg (mode1, op1);
16253
16254 pat = GEN_FCN (icode) (op0, op1);
16255 if (! pat)
16256 return 0;
16257 emit_insn (pat);
16258 return const0_rtx;
16259
16260 case IX86_BUILTIN_MOVNTPS:
16261 return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, arglist);
16262 case IX86_BUILTIN_MOVNTQ:
16263 return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, arglist);
16264
16265 case IX86_BUILTIN_LDMXCSR:
16266 op0 = expand_normal (TREE_VALUE (arglist));
16267 target = assign_386_stack_local (SImode, SLOT_TEMP);
16268 emit_move_insn (target, op0);
16269 emit_insn (gen_sse_ldmxcsr (target));
16270 return 0;
16271
16272 case IX86_BUILTIN_STMXCSR:
16273 target = assign_386_stack_local (SImode, SLOT_TEMP);
16274 emit_insn (gen_sse_stmxcsr (target));
16275 return copy_to_mode_reg (SImode, target);
16276
16277 case IX86_BUILTIN_SHUFPS:
16278 case IX86_BUILTIN_SHUFPD:
16279 icode = (fcode == IX86_BUILTIN_SHUFPS
16280 ? CODE_FOR_sse_shufps
16281 : CODE_FOR_sse2_shufpd);
16282 arg0 = TREE_VALUE (arglist);
16283 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16284 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16285 op0 = expand_normal (arg0);
16286 op1 = expand_normal (arg1);
16287 op2 = expand_normal (arg2);
16288 tmode = insn_data[icode].operand[0].mode;
16289 mode0 = insn_data[icode].operand[1].mode;
16290 mode1 = insn_data[icode].operand[2].mode;
16291 mode2 = insn_data[icode].operand[3].mode;
16292
16293 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
16294 op0 = copy_to_mode_reg (mode0, op0);
16295 if ((optimize && !register_operand (op1, mode1))
16296 || !(*insn_data[icode].operand[2].predicate) (op1, mode1))
16297 op1 = copy_to_mode_reg (mode1, op1);
16298 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
16299 {
16300
16301 error ("mask must be an immediate");
16302 return gen_reg_rtx (tmode);
16303 }
16304 if (optimize || target == 0
16305 || GET_MODE (target) != tmode
16306 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
16307 target = gen_reg_rtx (tmode);
16308 pat = GEN_FCN (icode) (target, op0, op1, op2);
16309 if (! pat)
16310 return 0;
16311 emit_insn (pat);
16312 return target;
16313
16314 case IX86_BUILTIN_PSHUFW:
16315 case IX86_BUILTIN_PSHUFD:
16316 case IX86_BUILTIN_PSHUFHW:
16317 case IX86_BUILTIN_PSHUFLW:
16318 icode = ( fcode == IX86_BUILTIN_PSHUFHW ? CODE_FOR_sse2_pshufhw
16319 : fcode == IX86_BUILTIN_PSHUFLW ? CODE_FOR_sse2_pshuflw
16320 : fcode == IX86_BUILTIN_PSHUFD ? CODE_FOR_sse2_pshufd
16321 : CODE_FOR_mmx_pshufw);
16322 arg0 = TREE_VALUE (arglist);
16323 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16324 op0 = expand_normal (arg0);
16325 op1 = expand_normal (arg1);
16326 tmode = insn_data[icode].operand[0].mode;
16327 mode1 = insn_data[icode].operand[1].mode;
16328 mode2 = insn_data[icode].operand[2].mode;
16329
16330 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16331 op0 = copy_to_mode_reg (mode1, op0);
16332 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
16333 {
16334
16335 error ("mask must be an immediate");
16336 return const0_rtx;
16337 }
16338 if (target == 0
16339 || GET_MODE (target) != tmode
16340 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
16341 target = gen_reg_rtx (tmode);
16342 pat = GEN_FCN (icode) (target, op0, op1);
16343 if (! pat)
16344 return 0;
16345 emit_insn (pat);
16346 return target;
16347
16348 case IX86_BUILTIN_PSLLWI128:
16349 icode = CODE_FOR_ashlv8hi3;
16350 goto do_pshifti;
16351 case IX86_BUILTIN_PSLLDI128:
16352 icode = CODE_FOR_ashlv4si3;
16353 goto do_pshifti;
16354 case IX86_BUILTIN_PSLLQI128:
16355 icode = CODE_FOR_ashlv2di3;
16356 goto do_pshifti;
16357 case IX86_BUILTIN_PSRAWI128:
16358 icode = CODE_FOR_ashrv8hi3;
16359 goto do_pshifti;
16360 case IX86_BUILTIN_PSRADI128:
16361 icode = CODE_FOR_ashrv4si3;
16362 goto do_pshifti;
16363 case IX86_BUILTIN_PSRLWI128:
16364 icode = CODE_FOR_lshrv8hi3;
16365 goto do_pshifti;
16366 case IX86_BUILTIN_PSRLDI128:
16367 icode = CODE_FOR_lshrv4si3;
16368 goto do_pshifti;
16369 case IX86_BUILTIN_PSRLQI128:
16370 icode = CODE_FOR_lshrv2di3;
16371 goto do_pshifti;
16372 do_pshifti:
16373 arg0 = TREE_VALUE (arglist);
16374 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16375 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
16376 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
16377
16378 if (GET_CODE (op1) != CONST_INT)
16379 {
16380 error ("shift must be an immediate");
16381 return const0_rtx;
16382 }
16383 if (INTVAL (op1) < 0 || INTVAL (op1) > 255)
16384 op1 = GEN_INT (255);
16385
16386 tmode = insn_data[icode].operand[0].mode;
16387 mode1 = insn_data[icode].operand[1].mode;
16388 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16389 op0 = copy_to_reg (op0);
16390
16391 target = gen_reg_rtx (tmode);
16392 pat = GEN_FCN (icode) (target, op0, op1);
16393 if (!pat)
16394 return 0;
16395 emit_insn (pat);
16396 return target;
16397
16398 case IX86_BUILTIN_PSLLW128:
16399 icode = CODE_FOR_ashlv8hi3;
16400 goto do_pshift;
16401 case IX86_BUILTIN_PSLLD128:
16402 icode = CODE_FOR_ashlv4si3;
16403 goto do_pshift;
16404 case IX86_BUILTIN_PSLLQ128:
16405 icode = CODE_FOR_ashlv2di3;
16406 goto do_pshift;
16407 case IX86_BUILTIN_PSRAW128:
16408 icode = CODE_FOR_ashrv8hi3;
16409 goto do_pshift;
16410 case IX86_BUILTIN_PSRAD128:
16411 icode = CODE_FOR_ashrv4si3;
16412 goto do_pshift;
16413 case IX86_BUILTIN_PSRLW128:
16414 icode = CODE_FOR_lshrv8hi3;
16415 goto do_pshift;
16416 case IX86_BUILTIN_PSRLD128:
16417 icode = CODE_FOR_lshrv4si3;
16418 goto do_pshift;
16419 case IX86_BUILTIN_PSRLQ128:
16420 icode = CODE_FOR_lshrv2di3;
16421 goto do_pshift;
16422 do_pshift:
16423 arg0 = TREE_VALUE (arglist);
16424 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16425 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
16426 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
16427
16428 tmode = insn_data[icode].operand[0].mode;
16429 mode1 = insn_data[icode].operand[1].mode;
16430
16431 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16432 op0 = copy_to_reg (op0);
16433
16434 op1 = simplify_gen_subreg (TImode, op1, GET_MODE (op1), 0);
16435 if (! (*insn_data[icode].operand[2].predicate) (op1, TImode))
16436 op1 = copy_to_reg (op1);
16437
16438 target = gen_reg_rtx (tmode);
16439 pat = GEN_FCN (icode) (target, op0, op1);
16440 if (!pat)
16441 return 0;
16442 emit_insn (pat);
16443 return target;
16444
16445 case IX86_BUILTIN_PSLLDQI128:
16446 case IX86_BUILTIN_PSRLDQI128:
16447 icode = (fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3
16448 : CODE_FOR_sse2_lshrti3);
16449 arg0 = TREE_VALUE (arglist);
16450 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16451 op0 = expand_normal (arg0);
16452 op1 = expand_normal (arg1);
16453 tmode = insn_data[icode].operand[0].mode;
16454 mode1 = insn_data[icode].operand[1].mode;
16455 mode2 = insn_data[icode].operand[2].mode;
16456
16457 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16458 {
16459 op0 = copy_to_reg (op0);
16460 op0 = simplify_gen_subreg (mode1, op0, GET_MODE (op0), 0);
16461 }
16462 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
16463 {
16464 error ("shift must be an immediate");
16465 return const0_rtx;
16466 }
16467 target = gen_reg_rtx (V2DImode);
16468 pat = GEN_FCN (icode) (simplify_gen_subreg (tmode, target, V2DImode, 0),
16469 op0, op1);
16470 if (! pat)
16471 return 0;
16472 emit_insn (pat);
16473 return target;
16474
16475 case IX86_BUILTIN_FEMMS:
16476 emit_insn (gen_mmx_femms ());
16477 return NULL_RTX;
16478
16479 case IX86_BUILTIN_PAVGUSB:
16480 return ix86_expand_binop_builtin (CODE_FOR_mmx_uavgv8qi3, arglist, target);
16481
16482 case IX86_BUILTIN_PF2ID:
16483 return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2id, arglist, target, 0);
16484
16485 case IX86_BUILTIN_PFACC:
16486 return ix86_expand_binop_builtin (CODE_FOR_mmx_haddv2sf3, arglist, target);
16487
16488 case IX86_BUILTIN_PFADD:
16489 return ix86_expand_binop_builtin (CODE_FOR_mmx_addv2sf3, arglist, target);
16490
16491 case IX86_BUILTIN_PFCMPEQ:
16492 return ix86_expand_binop_builtin (CODE_FOR_mmx_eqv2sf3, arglist, target);
16493
16494 case IX86_BUILTIN_PFCMPGE:
16495 return ix86_expand_binop_builtin (CODE_FOR_mmx_gev2sf3, arglist, target);
16496
16497 case IX86_BUILTIN_PFCMPGT:
16498 return ix86_expand_binop_builtin (CODE_FOR_mmx_gtv2sf3, arglist, target);
16499
16500 case IX86_BUILTIN_PFMAX:
16501 return ix86_expand_binop_builtin (CODE_FOR_mmx_smaxv2sf3, arglist, target);
16502
16503 case IX86_BUILTIN_PFMIN:
16504 return ix86_expand_binop_builtin (CODE_FOR_mmx_sminv2sf3, arglist, target);
16505
16506 case IX86_BUILTIN_PFMUL:
16507 return ix86_expand_binop_builtin (CODE_FOR_mmx_mulv2sf3, arglist, target);
16508
16509 case IX86_BUILTIN_PFRCP:
16510 return ix86_expand_unop_builtin (CODE_FOR_mmx_rcpv2sf2, arglist, target, 0);
16511
16512 case IX86_BUILTIN_PFRCPIT1:
16513 return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit1v2sf3, arglist, target);
16514
16515 case IX86_BUILTIN_PFRCPIT2:
16516 return ix86_expand_binop_builtin (CODE_FOR_mmx_rcpit2v2sf3, arglist, target);
16517
16518 case IX86_BUILTIN_PFRSQIT1:
16519 return ix86_expand_binop_builtin (CODE_FOR_mmx_rsqit1v2sf3, arglist, target);
16520
16521 case IX86_BUILTIN_PFRSQRT:
16522 return ix86_expand_unop_builtin (CODE_FOR_mmx_rsqrtv2sf2, arglist, target, 0);
16523
16524 case IX86_BUILTIN_PFSUB:
16525 return ix86_expand_binop_builtin (CODE_FOR_mmx_subv2sf3, arglist, target);
16526
16527 case IX86_BUILTIN_PFSUBR:
16528 return ix86_expand_binop_builtin (CODE_FOR_mmx_subrv2sf3, arglist, target);
16529
16530 case IX86_BUILTIN_PI2FD:
16531 return ix86_expand_unop_builtin (CODE_FOR_mmx_floatv2si2, arglist, target, 0);
16532
16533 case IX86_BUILTIN_PMULHRW:
16534 return ix86_expand_binop_builtin (CODE_FOR_mmx_pmulhrwv4hi3, arglist, target);
16535
16536 case IX86_BUILTIN_PF2IW:
16537 return ix86_expand_unop_builtin (CODE_FOR_mmx_pf2iw, arglist, target, 0);
16538
16539 case IX86_BUILTIN_PFNACC:
16540 return ix86_expand_binop_builtin (CODE_FOR_mmx_hsubv2sf3, arglist, target);
16541
16542 case IX86_BUILTIN_PFPNACC:
16543 return ix86_expand_binop_builtin (CODE_FOR_mmx_addsubv2sf3, arglist, target);
16544
16545 case IX86_BUILTIN_PI2FW:
16546 return ix86_expand_unop_builtin (CODE_FOR_mmx_pi2fw, arglist, target, 0);
16547
16548 case IX86_BUILTIN_PSWAPDSI:
16549 return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2si2, arglist, target, 0);
16550
16551 case IX86_BUILTIN_PSWAPDSF:
16552 return ix86_expand_unop_builtin (CODE_FOR_mmx_pswapdv2sf2, arglist, target, 0);
16553
16554 case IX86_BUILTIN_SQRTSD:
16555 return ix86_expand_unop1_builtin (CODE_FOR_sse2_vmsqrtv2df2, arglist, target);
16556 case IX86_BUILTIN_LOADUPD:
16557 return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, arglist, target, 1);
16558 case IX86_BUILTIN_STOREUPD:
16559 return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, arglist);
16560
16561 case IX86_BUILTIN_MFENCE:
16562 emit_insn (gen_sse2_mfence ());
16563 return 0;
16564 case IX86_BUILTIN_LFENCE:
16565 emit_insn (gen_sse2_lfence ());
16566 return 0;
16567
16568 case IX86_BUILTIN_CLFLUSH:
16569 arg0 = TREE_VALUE (arglist);
16570 op0 = expand_normal (arg0);
16571 icode = CODE_FOR_sse2_clflush;
16572 if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
16573 op0 = copy_to_mode_reg (Pmode, op0);
16574
16575 emit_insn (gen_sse2_clflush (op0));
16576 return 0;
16577
16578 case IX86_BUILTIN_MOVNTPD:
16579 return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, arglist);
16580 case IX86_BUILTIN_MOVNTDQ:
16581 return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, arglist);
16582 case IX86_BUILTIN_MOVNTI:
16583 return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist);
16584
16585 case IX86_BUILTIN_LOADDQU:
16586 return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1);
16587 case IX86_BUILTIN_STOREDQU:
16588 return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist);
16589
16590 case IX86_BUILTIN_MONITOR:
16591 arg0 = TREE_VALUE (arglist);
16592 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16593 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16594 op0 = expand_normal (arg0);
16595 op1 = expand_normal (arg1);
16596 op2 = expand_normal (arg2);
16597 if (!REG_P (op0))
16598 op0 = copy_to_mode_reg (Pmode, op0);
16599 if (!REG_P (op1))
16600 op1 = copy_to_mode_reg (SImode, op1);
16601 if (!REG_P (op2))
16602 op2 = copy_to_mode_reg (SImode, op2);
16603 if (!TARGET_64BIT)
16604 emit_insn (gen_sse3_monitor (op0, op1, op2));
16605 else
16606 emit_insn (gen_sse3_monitor64 (op0, op1, op2));
16607 return 0;
16608
16609 case IX86_BUILTIN_MWAIT:
16610 arg0 = TREE_VALUE (arglist);
16611 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16612 op0 = expand_normal (arg0);
16613 op1 = expand_normal (arg1);
16614 if (!REG_P (op0))
16615 op0 = copy_to_mode_reg (SImode, op0);
16616 if (!REG_P (op1))
16617 op1 = copy_to_mode_reg (SImode, op1);
16618 emit_insn (gen_sse3_mwait (op0, op1));
16619 return 0;
16620
16621 case IX86_BUILTIN_LDDQU:
16622 return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, arglist,
16623 target, 1);
16624
16625 case IX86_BUILTIN_VEC_INIT_V2SI:
16626 case IX86_BUILTIN_VEC_INIT_V4HI:
16627 case IX86_BUILTIN_VEC_INIT_V8QI:
16628 return ix86_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target);
16629
16630 case IX86_BUILTIN_VEC_EXT_V2DF:
16631 case IX86_BUILTIN_VEC_EXT_V2DI:
16632 case IX86_BUILTIN_VEC_EXT_V4SF:
16633 case IX86_BUILTIN_VEC_EXT_V4SI:
16634 case IX86_BUILTIN_VEC_EXT_V8HI:
16635 case IX86_BUILTIN_VEC_EXT_V2SI:
16636 case IX86_BUILTIN_VEC_EXT_V4HI:
16637 return ix86_expand_vec_ext_builtin (arglist, target);
16638
16639 case IX86_BUILTIN_VEC_SET_V8HI:
16640 case IX86_BUILTIN_VEC_SET_V4HI:
16641 return ix86_expand_vec_set_builtin (arglist);
16642
16643 case IX86_BUILTIN_MOVNTSD:
16644 return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv2df, arglist);
16645 case IX86_BUILTIN_MOVNTSS:
16646 return ix86_expand_store_builtin (CODE_FOR_sse4a_vmmovntv4sf, arglist);
16647
16648 case IX86_BUILTIN_INSERTQ:
16649 case IX86_BUILTIN_EXTRQ:
16650 icode = (fcode == IX86_BUILTIN_EXTRQ
16651 ? CODE_FOR_sse4a_extrq
16652 : CODE_FOR_sse4a_insertq);
16653 arg0 = TREE_VALUE (arglist);
16654 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16655 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
16656 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
16657 tmode = insn_data[icode].operand[0].mode;
16658 mode1 = insn_data[icode].operand[1].mode;
16659 mode2 = insn_data[icode].operand[2].mode;
16660 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16661 op0 = copy_to_mode_reg (mode1, op0);
16662 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
16663 op1 = copy_to_mode_reg (mode2, op1);
16664 if (optimize || target == 0
16665 || GET_MODE (target) != tmode
16666 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
16667 target = gen_reg_rtx (tmode);
16668 pat = GEN_FCN (icode) (target, op0, op1);
16669 if (! pat)
16670 return NULL_RTX;
16671 emit_insn (pat);
16672 return target;
16673
16674 case IX86_BUILTIN_EXTRQI:
16675 icode = CODE_FOR_sse4a_extrqi;
16676 arg0 = TREE_VALUE (arglist);
16677 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16678 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16679 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
16680 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
16681 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
16682 tmode = insn_data[icode].operand[0].mode;
16683 mode1 = insn_data[icode].operand[1].mode;
16684 mode2 = insn_data[icode].operand[2].mode;
16685 mode3 = insn_data[icode].operand[3].mode;
16686 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16687 op0 = copy_to_mode_reg (mode1, op0);
16688 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
16689 {
16690 error ("index mask must be an immediate");
16691 return gen_reg_rtx (tmode);
16692 }
16693 if (! (*insn_data[icode].operand[3].predicate) (op2, mode3))
16694 {
16695 error ("length mask must be an immediate");
16696 return gen_reg_rtx (tmode);
16697 }
16698 if (optimize || target == 0
16699 || GET_MODE (target) != tmode
16700 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
16701 target = gen_reg_rtx (tmode);
16702 pat = GEN_FCN (icode) (target, op0, op1, op2);
16703 if (! pat)
16704 return NULL_RTX;
16705 emit_insn (pat);
16706 return target;
16707
16708 case IX86_BUILTIN_INSERTQI:
16709 icode = CODE_FOR_sse4a_insertqi;
16710 arg0 = TREE_VALUE (arglist);
16711 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
16712 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
16713 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
16714 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
16715 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
16716 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
16717 op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
16718 tmode = insn_data[icode].operand[0].mode;
16719 mode1 = insn_data[icode].operand[1].mode;
16720 mode2 = insn_data[icode].operand[2].mode;
16721 mode3 = insn_data[icode].operand[3].mode;
16722 mode4 = insn_data[icode].operand[4].mode;
16723
16724 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
16725 op0 = copy_to_mode_reg (mode1, op0);
16726
16727 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
16728 op1 = copy_to_mode_reg (mode2, op1);
16729
16730 if (! (*insn_data[icode].operand[3].predicate) (op2, mode3))
16731 {
16732 error ("index mask must be an immediate");
16733 return gen_reg_rtx (tmode);
16734 }
16735 if (! (*insn_data[icode].operand[4].predicate) (op3, mode4))
16736 {
16737 error ("length mask must be an immediate");
16738 return gen_reg_rtx (tmode);
16739 }
16740 if (optimize || target == 0
16741 || GET_MODE (target) != tmode
16742 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
16743 target = gen_reg_rtx (tmode);
16744 pat = GEN_FCN (icode) (target, op0, op1, op2, op3);
16745 if (! pat)
16746 return NULL_RTX;
16747 emit_insn (pat);
16748 return target;
16749
16750 default:
16751 break;
16752 }
16753
16754 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
16755 if (d->code == fcode)
16756 {
16757
16758 if (d->icode == CODE_FOR_sse_maskcmpv4sf3
16759 || d->icode == CODE_FOR_sse_vmmaskcmpv4sf3
16760 || d->icode == CODE_FOR_sse2_maskcmpv2df3
16761 || d->icode == CODE_FOR_sse2_vmmaskcmpv2df3)
16762 return ix86_expand_sse_compare (d, arglist, target);
16763
16764 return ix86_expand_binop_builtin (d->icode, arglist, target);
16765 }
16766
16767 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
16768 if (d->code == fcode)
16769 return ix86_expand_unop_builtin (d->icode, arglist, target, 0);
16770
16771 for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
16772 if (d->code == fcode)
16773 return ix86_expand_sse_comi (d, arglist, target);
16774
16775 gcc_unreachable ();
16776 }
16777
16778
16779
16780 rtx
16781 ix86_force_to_memory (enum machine_mode mode, rtx operand)
16782 {
16783 rtx result;
16784
16785 gcc_assert (reload_completed);
16786 if (TARGET_RED_ZONE)
16787 {
16788 result = gen_rtx_MEM (mode,
16789 gen_rtx_PLUS (Pmode,
16790 stack_pointer_rtx,
16791 GEN_INT (-RED_ZONE_SIZE)));
16792 emit_move_insn (result, operand);
16793 }
16794 else if (!TARGET_RED_ZONE && TARGET_64BIT)
16795 {
16796 switch (mode)
16797 {
16798 case HImode:
16799 case SImode:
16800 operand = gen_lowpart (DImode, operand);
16801
16802 case DImode:
16803 emit_insn (
16804 gen_rtx_SET (VOIDmode,
16805 gen_rtx_MEM (DImode,
16806 gen_rtx_PRE_DEC (DImode,
16807 stack_pointer_rtx)),
16808 operand));
16809 break;
16810 default:
16811 gcc_unreachable ();
16812 }
16813 result = gen_rtx_MEM (mode, stack_pointer_rtx);
16814 }
16815 else
16816 {
16817 switch (mode)
16818 {
16819 case DImode:
16820 {
16821 rtx operands[2];
16822 split_di (&operand, 1, operands, operands + 1);
16823 emit_insn (
16824 gen_rtx_SET (VOIDmode,
16825 gen_rtx_MEM (SImode,
16826 gen_rtx_PRE_DEC (Pmode,
16827 stack_pointer_rtx)),
16828 operands[1]));
16829 emit_insn (
16830 gen_rtx_SET (VOIDmode,
16831 gen_rtx_MEM (SImode,
16832 gen_rtx_PRE_DEC (Pmode,
16833 stack_pointer_rtx)),
16834 operands[0]));
16835 }
16836 break;
16837 case HImode:
16838
16839 operand = gen_lowpart (SImode, operand);
16840
16841 case SImode:
16842 emit_insn (
16843 gen_rtx_SET (VOIDmode,
16844 gen_rtx_MEM (GET_MODE (operand),
16845 gen_rtx_PRE_DEC (SImode,
16846 stack_pointer_rtx)),
16847 operand));
16848 break;
16849 default:
16850 gcc_unreachable ();
16851 }
16852 result = gen_rtx_MEM (mode, stack_pointer_rtx);
16853 }
16854 return result;
16855 }
16856
16857
16858 void
16859 ix86_free_from_memory (enum machine_mode mode)
16860 {
16861 if (!TARGET_RED_ZONE)
16862 {
16863 int size;
16864
16865 if (mode == DImode || TARGET_64BIT)
16866 size = 8;
16867 else
16868 size = 4;
16869
16870
16871 emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
16872 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
16873 GEN_INT (size))));
16874 }
16875 }
16876
16877
16878
16879
16880
16881 enum reg_class
16882 ix86_preferred_reload_class (rtx x, enum reg_class class)
16883 {
16884 enum machine_mode mode = GET_MODE (x);
16885
16886
16887
16888 if (class == NO_REGS)
16889 return NO_REGS;
16890
16891
16892 if (x == CONST0_RTX (mode))
16893 return class;
16894
16895
16896
16897
16898 if (CONSTANT_P (x)
16899 && (MAYBE_MMX_CLASS_P (class) || MAYBE_SSE_CLASS_P (class)))
16900 return NO_REGS;
16901
16902
16903 if (TARGET_SSE_MATH && !TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (mode))
16904 return SSE_CLASS_P (class) ? class : NO_REGS;
16905
16906
16907 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
16908 {
16909
16910 if (reg_class_subset_p (class, GENERAL_REGS))
16911 return class;
16912
16913
16914
16915
16916 if (TARGET_80387
16917 && standard_80387_constant_p (x))
16918 {
16919
16920 if (class == FLOAT_SSE_REGS)
16921 return FLOAT_REGS;
16922 if (class == FP_TOP_SSE_REGS)
16923 return FP_TOP_REG;
16924 if (class == FP_SECOND_SSE_REGS)
16925 return FP_SECOND_REG;
16926 if (class == FLOAT_INT_REGS || class == FLOAT_REGS)
16927 return class;
16928 }
16929
16930 return NO_REGS;
16931 }
16932
16933
16934
16935
16936 if (GET_CODE (x) == PLUS)
16937 return reg_class_subset_p (class, GENERAL_REGS) ? class : NO_REGS;
16938
16939
16940
16941 if (GET_MODE (x) == QImode && !CONSTANT_P (x))
16942 {
16943 if (reg_class_subset_p (class, Q_REGS))
16944 return class;
16945 if (reg_class_subset_p (Q_REGS, class))
16946 return Q_REGS;
16947 return NO_REGS;
16948 }
16949
16950 return class;
16951 }
16952
16953
16954
16955 enum reg_class
16956 ix86_preferred_output_reload_class (rtx x, enum reg_class class)
16957 {
16958 enum machine_mode mode = GET_MODE (x);
16959
16960
16961
16962
16963 mode = GET_MODE (x);
16964 if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
16965 return MAYBE_SSE_CLASS_P (class) ? SSE_REGS : NO_REGS;
16966
16967 if (TARGET_80387 && SCALAR_FLOAT_MODE_P (mode))
16968 {
16969 if (class == FP_TOP_SSE_REGS)
16970 return FP_TOP_REG;
16971 else if (class == FP_SECOND_SSE_REGS)
16972 return FP_SECOND_REG;
16973 else
16974 return FLOAT_CLASS_P (class) ? class : NO_REGS;
16975 }
16976
16977 return class;
16978 }
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991 int
16992 ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
16993 enum machine_mode mode, int strict)
16994 {
16995 if (MAYBE_FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class1)
16996 || MAYBE_FLOAT_CLASS_P (class2) != FLOAT_CLASS_P (class2)
16997 || MAYBE_SSE_CLASS_P (class1) != SSE_CLASS_P (class1)
16998 || MAYBE_SSE_CLASS_P (class2) != SSE_CLASS_P (class2)
16999 || MAYBE_MMX_CLASS_P (class1) != MMX_CLASS_P (class1)
17000 || MAYBE_MMX_CLASS_P (class2) != MMX_CLASS_P (class2))
17001 {
17002 gcc_assert (!strict);
17003 return true;
17004 }
17005
17006 if (FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class2))
17007 return true;
17008
17009
17010
17011
17012 if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2))
17013 return true;
17014
17015 if (SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
17016 {
17017
17018 if (!TARGET_SSE2)
17019 return true;
17020
17021
17022
17023 if (!TARGET_INTER_UNIT_MOVES && !optimize_size)
17024 return true;
17025
17026
17027 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
17028 return true;
17029
17030
17031
17032
17033 if (mode == SFmode || mode == DFmode)
17034 return true;
17035 }
17036
17037 return false;
17038 }
17039
17040
17041
17042
17043 bool
17044 ix86_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
17045 enum reg_class class)
17046 {
17047 if (from == to)
17048 return false;
17049
17050
17051
17052 if (MAYBE_FLOAT_CLASS_P (class))
17053 return true;
17054
17055 if (MAYBE_SSE_CLASS_P (class) || MAYBE_MMX_CLASS_P (class))
17056 {
17057
17058
17059
17060
17061 if (GET_MODE_SIZE (from) < 4)
17062 return true;
17063
17064
17065
17066
17067
17068 if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from))
17069 return true;
17070 }
17071
17072 return false;
17073 }
17074
17075
17076
17077
17078
17079
17080
17081
17082 int
17083 ix86_register_move_cost (enum machine_mode mode, enum reg_class class1,
17084 enum reg_class class2)
17085 {
17086
17087
17088
17089
17090 if (ix86_secondary_memory_needed (class1, class2, mode, 0))
17091 {
17092 int cost = 1;
17093
17094 cost += MAX (MEMORY_MOVE_COST (mode, class1, 0),
17095 MEMORY_MOVE_COST (mode, class1, 1));
17096 cost += MAX (MEMORY_MOVE_COST (mode, class2, 0),
17097 MEMORY_MOVE_COST (mode, class2, 1));
17098
17099
17100
17101
17102 if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode))
17103 cost += 20;
17104
17105
17106
17107 if ((MMX_CLASS_P (class1) && MAYBE_FLOAT_CLASS_P (class2))
17108 || (MMX_CLASS_P (class2) && MAYBE_FLOAT_CLASS_P (class1)))
17109 cost += 20;
17110
17111 return cost;
17112 }
17113
17114
17115 if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
17116 || SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
17117 return ix86_cost->mmxsse_to_integer;
17118 if (MAYBE_FLOAT_CLASS_P (class1))
17119 return ix86_cost->fp_move;
17120 if (MAYBE_SSE_CLASS_P (class1))
17121 return ix86_cost->sse_move;
17122 if (MAYBE_MMX_CLASS_P (class1))
17123 return ix86_cost->mmx_move;
17124 return 2;
17125 }
17126
17127
17128
17129 bool
17130 ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
17131 {
17132
17133 if (CC_REGNO_P (regno))
17134 return GET_MODE_CLASS (mode) == MODE_CC;
17135 if (GET_MODE_CLASS (mode) == MODE_CC
17136 || GET_MODE_CLASS (mode) == MODE_RANDOM
17137 || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
17138 return 0;
17139 if (FP_REGNO_P (regno))
17140 return VALID_FP_MODE_P (mode);
17141 if (SSE_REGNO_P (regno))
17142 {
17143
17144
17145
17146 return (VALID_SSE_REG_MODE (mode)
17147 || VALID_SSE2_REG_MODE (mode)
17148 || VALID_MMX_REG_MODE (mode)
17149 || VALID_MMX_REG_MODE_3DNOW (mode));
17150 }
17151 if (MMX_REGNO_P (regno))
17152 {
17153
17154
17155
17156 return (VALID_MMX_REG_MODE (mode)
17157 || VALID_MMX_REG_MODE_3DNOW (mode));
17158 }
17159
17160 if (mode == QImode)
17161 {
17162
17163
17164 if (regno < 4 || TARGET_64BIT)
17165 return 1;
17166 if (!TARGET_PARTIAL_REG_STALL)
17167 return 1;
17168 return reload_in_progress || reload_completed;
17169 }
17170
17171 else if (VALID_INT_MODE_P (mode))
17172 return 1;
17173 else if (VALID_FP_MODE_P (mode))
17174 return 1;
17175
17176
17177
17178
17179 else if (VALID_MMX_REG_MODE_3DNOW (mode) || VALID_MMX_REG_MODE (mode))
17180 return 1;
17181
17182 return 0;
17183 }
17184
17185
17186
17187
17188 static bool
17189 ix86_tieable_integer_mode_p (enum machine_mode mode)
17190 {
17191 switch (mode)
17192 {
17193 case HImode:
17194 case SImode:
17195 return true;
17196
17197 case QImode:
17198 return TARGET_64BIT || !TARGET_PARTIAL_REG_STALL;
17199
17200 case DImode:
17201 return TARGET_64BIT;
17202
17203 default:
17204 return false;
17205 }
17206 }
17207
17208
17209
17210
17211
17212 bool
17213 ix86_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
17214 {
17215 if (mode1 == mode2)
17216 return true;
17217
17218 if (ix86_tieable_integer_mode_p (mode1)
17219 && ix86_tieable_integer_mode_p (mode2))
17220 return true;
17221
17222
17223
17224
17225 if (mode2 == XFmode)
17226 return mode1 == SFmode || mode1 == DFmode;
17227
17228
17229
17230 if (mode2 == DFmode)
17231 return mode1 == SFmode;
17232
17233
17234
17235 if (GET_MODE_SIZE (mode2) >= 8
17236 && ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
17237 return ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1);
17238
17239
17240
17241 if (GET_MODE_SIZE (mode2) == 8
17242 && ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode2))
17243 return ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode1);
17244
17245 return false;
17246 }
17247
17248
17249
17250
17251
17252
17253
17254
17255
17256
17257
17258
17259 int
17260 ix86_memory_move_cost (enum machine_mode mode, enum reg_class class, int in)
17261 {
17262 if (FLOAT_CLASS_P (class))
17263 {
17264 int index;
17265 switch (mode)
17266 {
17267 case SFmode:
17268 index = 0;
17269 break;
17270 case DFmode:
17271 index = 1;
17272 break;
17273 case XFmode:
17274 index = 2;
17275 break;
17276 default:
17277 return 100;
17278 }
17279 return in ? ix86_cost->fp_load [index] : ix86_cost->fp_store [index];
17280 }
17281 if (SSE_CLASS_P (class))
17282 {
17283 int index;
17284 switch (GET_MODE_SIZE (mode))
17285 {
17286 case 4:
17287 index = 0;
17288 break;
17289 case 8:
17290 index = 1;
17291 break;
17292 case 16:
17293 index = 2;
17294 break;
17295 default:
17296 return 100;
17297 }
17298 return in ? ix86_cost->sse_load [index] : ix86_cost->sse_store [index];
17299 }
17300 if (MMX_CLASS_P (class))
17301 {
17302 int index;
17303 switch (GET_MODE_SIZE (mode))
17304 {
17305 case 4:
17306 index = 0;
17307 break;
17308 case 8:
17309 index = 1;
17310 break;
17311 default:
17312 return 100;
17313 }
17314 return in ? ix86_cost->mmx_load [index] : ix86_cost->mmx_store [index];
17315 }
17316 switch (GET_MODE_SIZE (mode))
17317 {
17318 case 1:
17319 if (in)
17320 return (Q_CLASS_P (class) ? ix86_cost->int_load[0]
17321 : ix86_cost->movzbl_load);
17322 else
17323 return (Q_CLASS_P (class) ? ix86_cost->int_store[0]
17324 : ix86_cost->int_store[0] + 4);
17325 break;
17326 case 2:
17327 return in ? ix86_cost->int_load[1] : ix86_cost->int_store[1];
17328 default:
17329
17330 if (mode == TFmode)
17331 mode = XFmode;
17332 return ((in ? ix86_cost->int_load[2] : ix86_cost->int_store[2])
17333 * (((int) GET_MODE_SIZE (mode)
17334 + UNITS_PER_WORD - 1) / UNITS_PER_WORD));
17335 }
17336 }
17337
17338
17339
17340
17341
17342 static bool
17343 ix86_rtx_costs (rtx x, int code, int outer_code, int *total)
17344 {
17345 enum machine_mode mode = GET_MODE (x);
17346
17347 switch (code)
17348 {
17349 case CONST_INT:
17350 case CONST:
17351 case LABEL_REF:
17352 case SYMBOL_REF:
17353 if (TARGET_64BIT && !x86_64_immediate_operand (x, VOIDmode))
17354 *total = 3;
17355 else if (TARGET_64BIT && !x86_64_zext_immediate_operand (x, VOIDmode))
17356 *total = 2;
17357 else if (flag_pic && SYMBOLIC_CONST (x)
17358 && (!TARGET_64BIT
17359 || (!GET_CODE (x) != LABEL_REF
17360 && (GET_CODE (x) != SYMBOL_REF
17361 || !SYMBOL_REF_LOCAL_P (x)))))
17362 *total = 1;
17363 else
17364 *total = 0;
17365 return true;
17366
17367 case CONST_DOUBLE:
17368 if (mode == VOIDmode)
17369 *total = 0;
17370 else
17371 switch (standard_80387_constant_p (x))
17372 {
17373 case 1:
17374 *total = 1;
17375 break;
17376 default:
17377 *total = 2;
17378 break;
17379 case 0:
17380 case -1:
17381
17382
17383 *total = (COSTS_N_INSNS (1)
17384 + (flag_pic != 0 && !TARGET_64BIT)
17385 + (mode == SFmode ? 0 : mode == DFmode ? 1 : 2));
17386 break;
17387 }
17388 return true;
17389
17390 case ZERO_EXTEND:
17391
17392
17393 if (TARGET_64BIT && mode == DImode
17394 && GET_MODE (XEXP (x, 0)) == SImode)
17395 *total = 1;
17396 else if (TARGET_ZERO_EXTEND_WITH_AND)
17397 *total = ix86_cost->add;
17398 else
17399 *total = ix86_cost->movzx;
17400 return false;
17401
17402 case SIGN_EXTEND:
17403 *total = ix86_cost->movsx;
17404 return false;
17405
17406 case ASHIFT:
17407 if (GET_CODE (XEXP (x, 1)) == CONST_INT
17408 && (GET_MODE (XEXP (x, 0)) != DImode || TARGET_64BIT))
17409 {
17410 HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
17411 if (value == 1)
17412 {
17413 *total = ix86_cost->add;
17414 return false;
17415 }
17416 if ((value == 2 || value == 3)
17417 && ix86_cost->lea <= ix86_cost->shift_const)
17418 {
17419 *total = ix86_cost->lea;
17420 return false;
17421 }
17422 }
17423
17424
17425 case ROTATE:
17426 case ASHIFTRT:
17427 case LSHIFTRT:
17428 case ROTATERT:
17429 if (!TARGET_64BIT && GET_MODE (XEXP (x, 0)) == DImode)
17430 {
17431 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
17432 {
17433 if (INTVAL (XEXP (x, 1)) > 32)
17434 *total = ix86_cost->shift_const + COSTS_N_INSNS (2);
17435 else
17436 *total = ix86_cost->shift_const * 2;
17437 }
17438 else
17439 {
17440 if (GET_CODE (XEXP (x, 1)) == AND)
17441 *total = ix86_cost->shift_var * 2;
17442 else
17443 *total = ix86_cost->shift_var * 6 + COSTS_N_INSNS (2);
17444 }
17445 }
17446 else
17447 {
17448 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
17449 *total = ix86_cost->shift_const;
17450 else
17451 *total = ix86_cost->shift_var;
17452 }
17453 return false;
17454
17455 case MULT:
17456 if (FLOAT_MODE_P (mode))
17457 {
17458 *total = ix86_cost->fmul;
17459 return false;
17460 }
17461 else
17462 {
17463 rtx op0 = XEXP (x, 0);
17464 rtx op1 = XEXP (x, 1);
17465 int nbits;
17466 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
17467 {
17468 unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
17469 for (nbits = 0; value != 0; value &= value - 1)
17470 nbits++;
17471 }
17472 else
17473
17474 nbits = 7;
17475
17476
17477 if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op1) == ZERO_EXTEND)
17478 && GET_MODE_SIZE (GET_MODE (XEXP (op0, 0))) * 2
17479 == GET_MODE_SIZE (mode))
17480 {
17481 int is_mulwiden = 0;
17482 enum machine_mode inner_mode = GET_MODE (op0);
17483
17484 if (GET_CODE (op0) == GET_CODE (op1))
17485 is_mulwiden = 1, op1 = XEXP (op1, 0);
17486 else if (GET_CODE (op1) == CONST_INT)
17487 {
17488 if (GET_CODE (op0) == SIGN_EXTEND)
17489 is_mulwiden = trunc_int_for_mode (INTVAL (op1), inner_mode)
17490 == INTVAL (op1);
17491 else
17492 is_mulwiden = !(INTVAL (op1) & ~GET_MODE_MASK (inner_mode));
17493 }
17494
17495 if (is_mulwiden)
17496 op0 = XEXP (op0, 0), mode = GET_MODE (op0);
17497 }
17498
17499 *total = (ix86_cost->mult_init[MODE_INDEX (mode)]
17500 + nbits * ix86_cost->mult_bit
17501 + rtx_cost (op0, outer_code) + rtx_cost (op1, outer_code));
17502
17503 return true;
17504 }
17505
17506 case DIV:
17507 case UDIV:
17508 case MOD:
17509 case UMOD:
17510 if (FLOAT_MODE_P (mode))
17511 *total = ix86_cost->fdiv;
17512 else
17513 *total = ix86_cost->divide[MODE_INDEX (mode)];
17514 return false;
17515
17516 case PLUS:
17517 if (FLOAT_MODE_P (mode))
17518 *total = ix86_cost->fadd;
17519 else if (GET_MODE_CLASS (mode) == MODE_INT
17520 && GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (Pmode))
17521 {
17522 if (GET_CODE (XEXP (x, 0)) == PLUS
17523 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
17524 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
17525 && CONSTANT_P (XEXP (x, 1)))
17526 {
17527 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1));
17528 if (val == 2 || val == 4 || val == 8)
17529 {
17530 *total = ix86_cost->lea;
17531 *total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
17532 *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
17533 outer_code);
17534 *total += rtx_cost (XEXP (x, 1), outer_code);
17535 return true;
17536 }
17537 }
17538 else if (GET_CODE (XEXP (x, 0)) == MULT
17539 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
17540 {
17541 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
17542 if (val == 2 || val == 4 || val == 8)
17543 {
17544 *total = ix86_cost->lea;
17545 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
17546 *total += rtx_cost (XEXP (x, 1), outer_code);
17547 return true;
17548 }
17549 }
17550 else if (GET_CODE (XEXP (x, 0)) == PLUS)
17551 {
17552 *total = ix86_cost->lea;
17553 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
17554 *total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
17555 *total += rtx_cost (XEXP (x, 1), outer_code);
17556 return true;
17557 }
17558 }
17559
17560
17561 case MINUS:
17562 if (FLOAT_MODE_P (mode))
17563 {
17564 *total = ix86_cost->fadd;
17565 return false;
17566 }
17567
17568
17569 case AND:
17570 case IOR:
17571 case XOR:
17572 if (!TARGET_64BIT && mode == DImode)
17573 {
17574 *total = (ix86_cost->add * 2
17575 + (rtx_cost (XEXP (x, 0), outer_code)
17576 << (GET_MODE (XEXP (x, 0)) != DImode))
17577 + (rtx_cost (XEXP (x, 1), outer_code)
17578 << (GET_MODE (XEXP (x, 1)) != DImode)));
17579 return true;
17580 }
17581
17582
17583 case NEG:
17584 if (FLOAT_MODE_P (mode))
17585 {
17586 *total = ix86_cost->fchs;
17587 return false;
17588 }
17589
17590
17591 case NOT:
17592 if (!TARGET_64BIT && mode == DImode)
17593 *total = ix86_cost->add * 2;
17594 else
17595 *total = ix86_cost->add;
17596 return false;
17597
17598 case COMPARE:
17599 if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
17600 && XEXP (XEXP (x, 0), 1) == const1_rtx
17601 && GET_CODE (XEXP (XEXP (x, 0), 2)) == CONST_INT
17602 && XEXP (x, 1) == const0_rtx)
17603 {
17604
17605
17606 *total = (ix86_cost->add
17607 + rtx_cost (XEXP (XEXP (x, 0), 0), outer_code)
17608 + rtx_cost (const1_rtx, outer_code));
17609 return true;
17610 }
17611 return false;
17612
17613 case FLOAT_EXTEND:
17614 if (!TARGET_SSE_MATH
17615 || mode == XFmode
17616 || (mode == DFmode && !TARGET_SSE2))
17617
17618
17619 switch (standard_80387_constant_p (XEXP (x, 0)))
17620 {
17621 case -1:
17622 case 0:
17623 *total = 0;
17624 break;
17625 case 1:
17626 *total = 1;
17627 break;
17628 default:
17629 *total = (x86_ext_80387_constants & TUNEMASK
17630 || optimize_size
17631 ? 1 : 0);
17632 }
17633 return false;
17634
17635 case ABS:
17636 if (FLOAT_MODE_P (mode))
17637 *total = ix86_cost->fabs;
17638 return false;
17639
17640 case SQRT:
17641 if (FLOAT_MODE_P (mode))
17642 *total = ix86_cost->fsqrt;
17643 return false;
17644
17645 case UNSPEC:
17646 if (XINT (x, 1) == UNSPEC_TP)
17647 *total = 0;
17648 return false;
17649
17650 default:
17651 return false;
17652 }
17653 }
17654
17655 #if TARGET_MACHO
17656
17657 static int current_machopic_label_num;
17658
17659
17660
17661
17662 void
17663 machopic_output_stub (FILE *file, const char *symb, const char *stub)
17664 {
17665 unsigned int length;
17666 char *binder_name, *symbol_name, lazy_ptr_name[32];
17667 int label = ++current_machopic_label_num;
17668
17669
17670 gcc_assert (!TARGET_64BIT);
17671
17672
17673 symb = (*targetm.strip_name_encoding) (symb);
17674
17675 length = strlen (stub);
17676 binder_name = alloca (length + 32);
17677 GEN_BINDER_NAME_FOR_STUB (binder_name, stub, length);
17678
17679 length = strlen (symb);
17680 symbol_name = alloca (length + 32);
17681 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
17682
17683 sprintf (lazy_ptr_name, "L%d$lz", label);
17684
17685 if (MACHOPIC_PURE)
17686 switch_to_section (darwin_sections[machopic_picsymbol_stub_section]);
17687 else
17688 switch_to_section (darwin_sections[machopic_symbol_stub_section]);
17689
17690 fprintf (file, "%s:\n", stub);
17691 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
17692
17693 if (MACHOPIC_PURE)
17694 {
17695 fprintf (file, "\tcall\tLPC$%d\nLPC$%d:\tpopl\t%%eax\n", label, label);
17696 fprintf (file, "\tmovl\t%s-LPC$%d(%%eax),%%edx\n", lazy_ptr_name, label);
17697 fprintf (file, "\tjmp\t*%%edx\n");
17698 }
17699 else
17700 fprintf (file, "\tjmp\t*%s\n", lazy_ptr_name);
17701
17702 fprintf (file, "%s:\n", binder_name);
17703
17704 if (MACHOPIC_PURE)
17705 {
17706 fprintf (file, "\tlea\t%s-LPC$%d(%%eax),%%eax\n", lazy_ptr_name, label);
17707 fprintf (file, "\tpushl\t%%eax\n");
17708 }
17709 else
17710 fprintf (file, "\tpushl\t$%s\n", lazy_ptr_name);
17711
17712 fprintf (file, "\tjmp\tdyld_stub_binding_helper\n");
17713
17714 switch_to_section (darwin_sections[machopic_lazy_symbol_ptr_section]);
17715 fprintf (file, "%s:\n", lazy_ptr_name);
17716 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
17717 fprintf (file, "\t.long %s\n", binder_name);
17718 }
17719
17720 void
17721 darwin_x86_file_end (void)
17722 {
17723 darwin_file_end ();
17724 ix86_file_end ();
17725 }
17726 #endif
17727
17728
17729
17730 void
17731 x86_order_regs_for_local_alloc (void)
17732 {
17733 int pos = 0;
17734 int i;
17735
17736
17737 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
17738 if (GENERAL_REGNO_P (i) && call_used_regs[i])
17739 reg_alloc_order [pos++] = i;
17740
17741
17742 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
17743 if (GENERAL_REGNO_P (i) && !call_used_regs[i])
17744 reg_alloc_order [pos++] = i;
17745
17746
17747
17748 if (!TARGET_SSE_MATH)
17749 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
17750 reg_alloc_order [pos++] = i;
17751
17752
17753 for (i = FIRST_SSE_REG; i <= LAST_SSE_REG; i++)
17754 reg_alloc_order [pos++] = i;
17755 for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)
17756 reg_alloc_order [pos++] = i;
17757
17758
17759 if (TARGET_SSE_MATH)
17760 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
17761 reg_alloc_order [pos++] = i;
17762
17763 for (i = FIRST_MMX_REG; i <= LAST_MMX_REG; i++)
17764 reg_alloc_order [pos++] = i;
17765
17766
17767
17768 while (pos < FIRST_PSEUDO_REGISTER)
17769 reg_alloc_order [pos++] = 0;
17770 }
17771
17772
17773
17774 static tree
17775 ix86_handle_struct_attribute (tree *node, tree name,
17776 tree args ATTRIBUTE_UNUSED,
17777 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
17778 {
17779 tree *type = NULL;
17780 if (DECL_P (*node))
17781 {
17782 if (TREE_CODE (*node) == TYPE_DECL)
17783 type = &TREE_TYPE (*node);
17784 }
17785 else
17786 type = node;
17787
17788 if (!(type && (TREE_CODE (*type) == RECORD_TYPE
17789 || TREE_CODE (*type) == UNION_TYPE)))
17790 {
17791 warning (OPT_Wattributes, "%qs attribute ignored",
17792 IDENTIFIER_POINTER (name));
17793 *no_add_attrs = true;
17794 }
17795
17796 else if ((is_attribute_p ("ms_struct", name)
17797 && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
17798 || ((is_attribute_p ("gcc_struct", name)
17799 && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
17800 {
17801 warning (OPT_Wattributes, "%qs incompatible attribute ignored",
17802 IDENTIFIER_POINTER (name));
17803 *no_add_attrs = true;
17804 }
17805
17806 return NULL_TREE;
17807 }
17808
17809 static bool
17810 ix86_ms_bitfield_layout_p (tree record_type)
17811 {
17812 return (TARGET_MS_BITFIELD_LAYOUT &&
17813 !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
17814 || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
17815 }
17816
17817
17818
17819
17820 static rtx
17821 x86_this_parameter (tree function)
17822 {
17823 tree type = TREE_TYPE (function);
17824
17825 if (TARGET_64BIT)
17826 {
17827 int n = aggregate_value_p (TREE_TYPE (type), type) != 0;
17828 return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
17829 }
17830
17831 if (ix86_function_regparm (type, function) > 0)
17832 {
17833 tree parm;
17834
17835 parm = TYPE_ARG_TYPES (type);
17836
17837
17838 for (; parm; parm = TREE_CHAIN (parm))
17839 if (TREE_VALUE (parm) == void_type_node)
17840 break;
17841
17842 if (parm)
17843 {
17844 int regno = 0;
17845 if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
17846 regno = 2;
17847 return gen_rtx_REG (SImode, regno);
17848 }
17849 }
17850
17851 if (aggregate_value_p (TREE_TYPE (type), type))
17852 return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
17853 else
17854 return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
17855 }
17856
17857
17858
17859 static bool
17860 x86_can_output_mi_thunk (tree thunk ATTRIBUTE_UNUSED,
17861 HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
17862 HOST_WIDE_INT vcall_offset, tree function)
17863 {
17864
17865 if (TARGET_64BIT)
17866 return true;
17867
17868
17869 if (ix86_function_regparm (TREE_TYPE (function), function) < 3)
17870 return true;
17871
17872
17873 if (vcall_offset)
17874 return false;
17875
17876
17877 if (flag_pic && !(*targetm.binds_local_p) (function))
17878 return false;
17879
17880
17881 return true;
17882 }
17883
17884
17885
17886
17887
17888
17889
17890 static void
17891 x86_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
17892 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
17893 HOST_WIDE_INT vcall_offset, tree function)
17894 {
17895 rtx xops[3];
17896 rtx this = x86_this_parameter (function);
17897 rtx this_reg, tmp;
17898
17899
17900
17901 if (REG_P (this))
17902 this_reg = this;
17903 else if (vcall_offset)
17904 {
17905
17906 xops[0] = this;
17907 xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
17908 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
17909 }
17910 else
17911 this_reg = NULL_RTX;
17912
17913
17914 if (delta)
17915 {
17916 xops[0] = GEN_INT (delta);
17917 xops[1] = this_reg ? this_reg : this;
17918 if (TARGET_64BIT)
17919 {
17920 if (!x86_64_general_operand (xops[0], DImode))
17921 {
17922 tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 );
17923 xops[1] = tmp;
17924 output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
17925 xops[0] = tmp;
17926 xops[1] = this;
17927 }
17928 output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
17929 }
17930 else
17931 output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
17932 }
17933
17934
17935 if (vcall_offset)
17936 {
17937 if (TARGET_64BIT)
17938 tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 );
17939 else
17940 {
17941 int tmp_regno = 2 ;
17942 if (lookup_attribute ("fastcall",
17943 TYPE_ATTRIBUTES (TREE_TYPE (function))))
17944 tmp_regno = 0 ;
17945 tmp = gen_rtx_REG (SImode, tmp_regno);
17946 }
17947
17948 xops[0] = gen_rtx_MEM (Pmode, this_reg);
17949 xops[1] = tmp;
17950 if (TARGET_64BIT)
17951 output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
17952 else
17953 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
17954
17955
17956 xops[0] = gen_rtx_MEM (Pmode, plus_constant (tmp, vcall_offset));
17957 if (TARGET_64BIT && !memory_operand (xops[0], Pmode))
17958 {
17959 rtx tmp2 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 );
17960 xops[0] = GEN_INT (vcall_offset);
17961 xops[1] = tmp2;
17962 output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
17963 xops[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tmp, tmp2));
17964 }
17965 xops[1] = this_reg;
17966 if (TARGET_64BIT)
17967 output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
17968 else
17969 output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
17970 }
17971
17972
17973 if (this_reg && this_reg != this)
17974 {
17975 xops[0] = this_reg;
17976 xops[1] = this;
17977 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
17978 }
17979
17980 xops[0] = XEXP (DECL_RTL (function), 0);
17981 if (TARGET_64BIT)
17982 {
17983 if (!flag_pic || (*targetm.binds_local_p) (function))
17984 output_asm_insn ("jmp\t%P0", xops);
17985 else
17986 {
17987 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xops[0]), UNSPEC_GOTPCREL);
17988 tmp = gen_rtx_CONST (Pmode, tmp);
17989 tmp = gen_rtx_MEM (QImode, tmp);
17990 xops[0] = tmp;
17991 output_asm_insn ("jmp\t%A0", xops);
17992 }
17993 }
17994 else
17995 {
17996 if (!flag_pic || (*targetm.binds_local_p) (function))
17997 output_asm_insn ("jmp\t%P0", xops);
17998 else
17999 #if TARGET_MACHO
18000 if (TARGET_MACHO)
18001 {
18002 rtx sym_ref = XEXP (DECL_RTL (function), 0);
18003 tmp = (gen_rtx_SYMBOL_REF
18004 (Pmode,
18005 machopic_indirection_name (sym_ref, true)));
18006 tmp = gen_rtx_MEM (QImode, tmp);
18007 xops[0] = tmp;
18008 output_asm_insn ("jmp\t%0", xops);
18009 }
18010 else
18011 #endif
18012 {
18013 tmp = gen_rtx_REG (SImode, 2 );
18014 output_set_got (tmp, NULL_RTX);
18015
18016 xops[1] = tmp;
18017 output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops);
18018 output_asm_insn ("jmp\t{*}%1", xops);
18019 }
18020 }
18021 }
18022
18023 static void
18024 x86_file_start (void)
18025 {
18026 default_file_start ();
18027 #if TARGET_MACHO
18028 darwin_file_start ();
18029 #endif
18030 if (X86_FILE_START_VERSION_DIRECTIVE)
18031 fputs ("\t.version\t\"01.01\"\n", asm_out_file);
18032 if (X86_FILE_START_FLTUSED)
18033 fputs ("\t.global\t__fltused\n", asm_out_file);
18034 if (ix86_asm_dialect == ASM_INTEL)
18035 fputs ("\t.intel_syntax\n", asm_out_file);
18036 }
18037
18038 int
18039 x86_field_alignment (tree field, int computed)
18040 {
18041 enum machine_mode mode;
18042 tree type = TREE_TYPE (field);
18043
18044 if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
18045 return computed;
18046 mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE
18047 ? get_inner_array_type (type) : type);
18048 if (mode == DFmode || mode == DCmode
18049 || GET_MODE_CLASS (mode) == MODE_INT
18050 || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
18051 return MIN (32, computed);
18052 return computed;
18053 }
18054
18055
18056
18057 void
18058 x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
18059 {
18060 if (TARGET_64BIT)
18061 if (flag_pic)
18062 {
18063 #ifndef NO_PROFILE_COUNTERS
18064 fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
18065 #endif
18066 fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME);
18067 }
18068 else
18069 {
18070 #ifndef NO_PROFILE_COUNTERS
18071 fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno);
18072 #endif
18073 fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
18074 }
18075 else if (flag_pic)
18076 {
18077 #ifndef NO_PROFILE_COUNTERS
18078 fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%%s\n",
18079 LPREFIX, labelno, PROFILE_COUNT_REGISTER);
18080 #endif
18081 fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", MCOUNT_NAME);
18082 }
18083 else
18084 {
18085 #ifndef NO_PROFILE_COUNTERS
18086 fprintf (file, "\tmovl\t$%sP%d,%%%s\n", LPREFIX, labelno,
18087 PROFILE_COUNT_REGISTER);
18088 #endif
18089 fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
18090 }
18091 }
18092
18093
18094
18095
18096
18097
18098 static int
18099 min_insn_size (rtx insn)
18100 {
18101 int l = 0;
18102
18103 if (!INSN_P (insn) || !active_insn_p (insn))
18104 return 0;
18105
18106
18107 if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
18108 && XINT (PATTERN (insn), 1) == UNSPECV_ALIGN)
18109 return 0;
18110 if (GET_CODE (insn) == JUMP_INSN
18111 && (GET_CODE (PATTERN (insn)) == ADDR_VEC
18112 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
18113 return 0;
18114
18115
18116
18117 if (GET_CODE (insn) == CALL_INSN
18118 && symbolic_reference_mentioned_p (PATTERN (insn))
18119 && !SIBLING_CALL_P (insn))
18120 return 5;
18121 if (get_attr_length (insn) <= 1)
18122 return 1;
18123
18124
18125
18126
18127 if (GET_CODE (insn) != JUMP_INSN)
18128 {
18129 l = get_attr_length_address (insn);
18130 if (l < 4 && symbolic_reference_mentioned_p (PATTERN (insn)))
18131 l = 4;
18132 }
18133 if (l)
18134 return 1+l;
18135 else
18136 return 2;
18137 }
18138
18139
18140
18141
18142 static void
18143 ix86_avoid_jump_misspredicts (void)
18144 {
18145 rtx insn, start = get_insns ();
18146 int nbytes = 0, njumps = 0;
18147 int isjump = 0;
18148
18149
18150
18151
18152
18153
18154
18155
18156
18157
18158
18159 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
18160 {
18161
18162 nbytes += min_insn_size (insn);
18163 if (dump_file)
18164 fprintf(dump_file, "Insn %i estimated to %i bytes\n",
18165 INSN_UID (insn), min_insn_size (insn));
18166 if ((GET_CODE (insn) == JUMP_INSN
18167 && GET_CODE (PATTERN (insn)) != ADDR_VEC
18168 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
18169 || GET_CODE (insn) == CALL_INSN)
18170 njumps++;
18171 else
18172 continue;
18173
18174 while (njumps > 3)
18175 {
18176 start = NEXT_INSN (start);
18177 if ((GET_CODE (start) == JUMP_INSN
18178 && GET_CODE (PATTERN (start)) != ADDR_VEC
18179 && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC)
18180 || GET_CODE (start) == CALL_INSN)
18181 njumps--, isjump = 1;
18182 else
18183 isjump = 0;
18184 nbytes -= min_insn_size (start);
18185 }
18186 gcc_assert (njumps >= 0);
18187 if (dump_file)
18188 fprintf (dump_file, "Interval %i to %i has %i bytes\n",
18189 INSN_UID (start), INSN_UID (insn), nbytes);
18190
18191 if (njumps == 3 && isjump && nbytes < 16)
18192 {
18193 int padsize = 15 - nbytes + min_insn_size (insn);
18194
18195 if (dump_file)
18196 fprintf (dump_file, "Padding insn %i by %i bytes!\n",
18197 INSN_UID (insn), padsize);
18198 emit_insn_before (gen_align (GEN_INT (padsize)), insn);
18199 }
18200 }
18201 }
18202
18203
18204
18205
18206
18207 static void
18208 ix86_pad_returns (void)
18209 {
18210 edge e;
18211 edge_iterator ei;
18212
18213 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
18214 {
18215 basic_block bb = e->src;
18216 rtx ret = BB_END (bb);
18217 rtx prev;
18218 bool replace = false;
18219
18220 if (GET_CODE (ret) != JUMP_INSN || GET_CODE (PATTERN (ret)) != RETURN
18221 || !maybe_hot_bb_p (bb))
18222 continue;
18223 for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
18224 if (active_insn_p (prev) || GET_CODE (prev) == CODE_LABEL)
18225 break;
18226 if (prev && GET_CODE (prev) == CODE_LABEL)
18227 {
18228 edge e;
18229 edge_iterator ei;
18230
18231 FOR_EACH_EDGE (e, ei, bb->preds)
18232 if (EDGE_FREQUENCY (e) && e->src->index >= 0
18233 && !(e->flags & EDGE_FALLTHRU))
18234 replace = true;
18235 }
18236 if (!replace)
18237 {
18238 prev = prev_active_insn (ret);
18239 if (prev
18240 && ((GET_CODE (prev) == JUMP_INSN && any_condjump_p (prev))
18241 || GET_CODE (prev) == CALL_INSN))
18242 replace = true;
18243
18244
18245 if (!prev && cfun->function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
18246 replace = true;
18247 }
18248 if (replace)
18249 {
18250 emit_insn_before (gen_return_internal_long (), ret);
18251 delete_insn (ret);
18252 }
18253 }
18254 }
18255
18256
18257
18258 static void
18259 ix86_reorg (void)
18260 {
18261 if (TARGET_PAD_RETURNS && optimize && !optimize_size)
18262 ix86_pad_returns ();
18263 if (TARGET_FOUR_JUMP_LIMIT && optimize && !optimize_size)
18264 ix86_avoid_jump_misspredicts ();
18265 }
18266
18267
18268
18269 bool
18270 x86_extended_QIreg_mentioned_p (rtx insn)
18271 {
18272 int i;
18273 extract_insn_cached (insn);
18274 for (i = 0; i < recog_data.n_operands; i++)
18275 if (REG_P (recog_data.operand[i])
18276 && REGNO (recog_data.operand[i]) >= 4)
18277 return true;
18278 return false;
18279 }
18280
18281
18282
18283 static int
18284 extended_reg_mentioned_1 (rtx *p, void *data ATTRIBUTE_UNUSED)
18285 {
18286 unsigned int regno;
18287 if (!REG_P (*p))
18288 return 0;
18289 regno = REGNO (*p);
18290 return REX_INT_REGNO_P (regno) || REX_SSE_REGNO_P (regno);
18291 }
18292
18293
18294
18295 bool
18296 x86_extended_reg_mentioned_p (rtx insn)
18297 {
18298 return for_each_rtx (&PATTERN (insn), extended_reg_mentioned_1, NULL);
18299 }
18300
18301
18302
18303
18304 void
18305 x86_emit_floatuns (rtx operands[2])
18306 {
18307 rtx neglab, donelab, i0, i1, f0, in, out;
18308 enum machine_mode mode, inmode;
18309
18310 inmode = GET_MODE (operands[1]);
18311 gcc_assert (inmode == SImode || inmode == DImode);
18312
18313 out = operands[0];
18314 in = force_reg (inmode, operands[1]);
18315 mode = GET_MODE (out);
18316 neglab = gen_label_rtx ();
18317 donelab = gen_label_rtx ();
18318 i1 = gen_reg_rtx (Pmode);
18319 f0 = gen_reg_rtx (mode);
18320
18321 emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, Pmode, 0, neglab);
18322
18323 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
18324 emit_jump_insn (gen_jump (donelab));
18325 emit_barrier ();
18326
18327 emit_label (neglab);
18328
18329 i0 = expand_simple_binop (Pmode, LSHIFTRT, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
18330 i1 = expand_simple_binop (Pmode, AND, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
18331 i0 = expand_simple_binop (Pmode, IOR, i0, i1, i0, 1, OPTAB_DIRECT);
18332 expand_float (f0, i0, 0);
18333 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
18334
18335 emit_label (donelab);
18336 }
18337
18338
18339
18340
18341 static bool
18342 ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
18343 rtx target, rtx val)
18344 {
18345 enum machine_mode smode, wsmode, wvmode;
18346 rtx x;
18347
18348 switch (mode)
18349 {
18350 case V2SImode:
18351 case V2SFmode:
18352 if (!mmx_ok)
18353 return false;
18354
18355
18356 case V2DFmode:
18357 case V2DImode:
18358 case V4SFmode:
18359 case V4SImode:
18360 val = force_reg (GET_MODE_INNER (mode), val);
18361 x = gen_rtx_VEC_DUPLICATE (mode, val);
18362 emit_insn (gen_rtx_SET (VOIDmode, target, x));
18363 return true;
18364
18365 case V4HImode:
18366 if (!mmx_ok)
18367 return false;
18368 if (TARGET_SSE || TARGET_3DNOW_A)
18369 {
18370 val = gen_lowpart (SImode, val);
18371 x = gen_rtx_TRUNCATE (HImode, val);
18372 x = gen_rtx_VEC_DUPLICATE (mode, x);
18373 emit_insn (gen_rtx_SET (VOIDmode, target, x));
18374 return true;
18375 }
18376 else
18377 {
18378 smode = HImode;
18379 wsmode = SImode;
18380 wvmode = V2SImode;
18381 goto widen;
18382 }
18383
18384 case V8QImode:
18385 if (!mmx_ok)
18386 return false;
18387 smode = QImode;
18388 wsmode = HImode;
18389 wvmode = V4HImode;
18390 goto widen;
18391 case V8HImode:
18392 if (TARGET_SSE2)
18393 {
18394 rtx tmp1, tmp2;
18395
18396 tmp1 = gen_reg_rtx (SImode);
18397 emit_move_insn (tmp1, gen_lowpart (SImode, val));
18398
18399 tmp2 = gen_reg_rtx (V4SImode);
18400 tmp1 = gen_rtx_VEC_MERGE (V4SImode,
18401 gen_rtx_VEC_DUPLICATE (V4SImode, tmp1),
18402 CONST0_RTX (V4SImode),
18403 const1_rtx);
18404 emit_insn (gen_rtx_SET (VOIDmode, tmp2, tmp1));
18405
18406 tmp1 = gen_reg_rtx (V8HImode);
18407 emit_move_insn (tmp1, gen_lowpart (V8HImode, tmp2));
18408
18409 emit_insn (gen_sse2_punpcklwd (tmp1, tmp1, tmp1));
18410
18411 tmp2 = gen_reg_rtx (V4SImode);
18412 emit_move_insn (tmp2, gen_lowpart (V4SImode, tmp1));
18413
18414 emit_insn (gen_sse2_pshufd (tmp2, tmp2, const0_rtx));
18415
18416 emit_move_insn (target, gen_lowpart (V8HImode, tmp2));
18417 return true;
18418 }
18419 smode = HImode;
18420 wsmode = SImode;
18421 wvmode = V4SImode;
18422 goto widen;
18423 case V16QImode:
18424 if (TARGET_SSE2)
18425 {
18426 rtx tmp1, tmp2;
18427
18428 tmp1 = gen_reg_rtx (SImode);
18429 emit_move_insn (tmp1, gen_lowpart (SImode, val));
18430
18431 tmp2 = gen_reg_rtx (V4SImode);
18432 tmp1 = gen_rtx_VEC_MERGE (V4SImode,
18433 gen_rtx_VEC_DUPLICATE (V4SImode, tmp1),
18434 CONST0_RTX (V4SImode),
18435 const1_rtx);
18436 emit_insn (gen_rtx_SET (VOIDmode, tmp2, tmp1));
18437
18438 tmp1 = gen_reg_rtx (V16QImode);
18439 emit_move_insn (tmp1, gen_lowpart (V16QImode, tmp2));
18440
18441 emit_insn (gen_sse2_punpcklbw (tmp1, tmp1, tmp1));
18442 emit_insn (gen_sse2_punpcklbw (tmp1, tmp1, tmp1));
18443
18444 tmp2 = gen_reg_rtx (V4SImode);
18445 emit_move_insn (tmp2, gen_lowpart (V4SImode, tmp1));
18446
18447 emit_insn (gen_sse2_pshufd (tmp2, tmp2, const0_rtx));
18448
18449 emit_move_insn (target, gen_lowpart (V16QImode, tmp2));
18450 return true;
18451 }
18452 smode = QImode;
18453 wsmode = HImode;
18454 wvmode = V8HImode;
18455 goto widen;
18456 widen:
18457
18458 val = convert_modes (wsmode, smode, val, true);
18459 x = expand_simple_binop (wsmode, ASHIFT, val,
18460 GEN_INT (GET_MODE_BITSIZE (smode)),
18461 NULL_RTX, 1, OPTAB_LIB_WIDEN);
18462 val = expand_simple_binop (wsmode, IOR, val, x, x, 1, OPTAB_LIB_WIDEN);
18463
18464 x = gen_reg_rtx (wvmode);
18465 if (!ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val))
18466 gcc_unreachable ();
18467 emit_move_insn (target, gen_lowpart (mode, x));
18468 return true;
18469
18470 default:
18471 return false;
18472 }
18473 }
18474
18475
18476
18477
18478
18479 static bool
18480 ix86_expand_vector_init_one_nonzero (bool mmx_ok, enum machine_mode mode,
18481 rtx target, rtx var, int one_var)
18482 {
18483 enum machine_mode vsimode;
18484 rtx new_target;
18485 rtx x, tmp;
18486
18487 switch (mode)
18488 {
18489 case V2SFmode:
18490 case V2SImode:
18491 if (!mmx_ok)
18492 return false;
18493
18494
18495 case V2DFmode:
18496 case V2DImode:
18497 if (one_var != 0)
18498 return false;
18499 var = force_reg (GET_MODE_INNER (mode), var);
18500 x = gen_rtx_VEC_CONCAT (mode, var, CONST0_RTX (GET_MODE_INNER (mode)));
18501 emit_insn (gen_rtx_SET (VOIDmode, target, x));
18502 return true;
18503
18504 case V4SFmode:
18505 case V4SImode:
18506 if (!REG_P (target) || REGNO (target) < FIRST_PSEUDO_REGISTER)
18507 new_target = gen_reg_rtx (mode);
18508 else
18509 new_target = target;
18510 var = force_reg (GET_MODE_INNER (mode), var);
18511 x = gen_rtx_VEC_DUPLICATE (mode, var);
18512 x = gen_rtx_VEC_MERGE (mode, x, CONST0_RTX (mode), const1_rtx);
18513 emit_insn (gen_rtx_SET (VOIDmode, new_target, x));
18514 if (one_var != 0)
18515 {
18516
18517
18518
18519
18520 if (mode != V4SFmode && TARGET_SSE2)
18521 {
18522 emit_insn (gen_sse2_pshufd_1 (new_target, new_target,
18523 GEN_INT (1),
18524 GEN_INT (one_var == 1 ? 0 : 1),
18525 GEN_INT (one_var == 2 ? 0 : 1),
18526 GEN_INT (one_var == 3 ? 0 : 1)));
18527 if (target != new_target)
18528 emit_move_insn (target, new_target);
18529 return true;
18530 }
18531
18532
18533
18534 if (mode != V4SFmode)
18535 {
18536 tmp = gen_reg_rtx (V4SFmode);
18537 emit_move_insn (tmp, gen_lowpart (V4SFmode, new_target));
18538 }
18539 else
18540 tmp = new_target;
18541
18542 emit_insn (gen_sse_shufps_1 (tmp, tmp, tmp,
18543 GEN_INT (1),
18544 GEN_INT (one_var == 1 ? 0 : 1),
18545 GEN_INT (one_var == 2 ? 0+4 : 1+4),
18546 GEN_INT (one_var == 3 ? 0+4 : 1+4)));
18547
18548 if (mode != V4SFmode)
18549 emit_move_insn (target, gen_lowpart (V4SImode, tmp));
18550 else if (tmp != target)
18551 emit_move_insn (target, tmp);
18552 }
18553 else if (target != new_target)
18554 emit_move_insn (target, new_target);
18555 return true;
18556
18557 case V8HImode:
18558 case V16QImode:
18559 vsimode = V4SImode;
18560 goto widen;
18561 case V4HImode:
18562 case V8QImode:
18563 if (!mmx_ok)
18564 return false;
18565 vsimode = V2SImode;
18566 goto widen;
18567 widen:
18568 if (one_var != 0)
18569 return false;
18570
18571
18572 var = convert_modes (SImode, GET_MODE_INNER (mode), var, true);
18573
18574 x = gen_reg_rtx (vsimode);
18575 if (!ix86_expand_vector_init_one_nonzero (mmx_ok, vsimode, x,
18576 var, one_var))
18577 gcc_unreachable ();
18578
18579 emit_move_insn (target, gen_lowpart (mode, x));
18580 return true;
18581
18582 default:
18583 return false;
18584 }
18585 }
18586
18587
18588
18589
18590
18591 static bool
18592 ix86_expand_vector_init_one_var (bool mmx_ok, enum machine_mode mode,
18593 rtx target, rtx vals, int one_var)
18594 {
18595 rtx var = XVECEXP (vals, 0, one_var);
18596 enum machine_mode wmode;
18597 rtx const_vec, x;
18598
18599 const_vec = copy_rtx (vals);
18600 XVECEXP (const_vec, 0, one_var) = CONST0_RTX (GET_MODE_INNER (mode));
18601 const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (const_vec, 0));
18602
18603 switch (mode)
18604 {
18605 case V2DFmode:
18606 case V2DImode:
18607 case V2SFmode:
18608 case V2SImode:
18609
18610
18611 return false;
18612
18613 case V4SFmode:
18614 case V4SImode:
18615 case V8HImode:
18616 case V4HImode:
18617 break;
18618
18619 case V16QImode:
18620 wmode = V8HImode;
18621 goto widen;
18622 case V8QImode:
18623 wmode = V4HImode;
18624 goto widen;
18625 widen:
18626
18627
18628
18629 x = XVECEXP (vals, 0, one_var ^ 1);
18630 if (one_var & 1)
18631 {
18632 var = convert_modes (HImode, QImode, var, true);
18633 var = expand_simple_binop (HImode, ASHIFT, var, GEN_INT (8),
18634 NULL_RTX, 1, OPTAB_LIB_WIDEN);
18635 x = GEN_INT (INTVAL (x) & 0xff);
18636 }
18637 else
18638 {
18639 var = convert_modes (HImode, QImode, var, true);
18640 x = gen_int_mode (INTVAL (x) << 8, HImode);
18641 }
18642 if (x != const0_rtx)
18643 var = expand_simple_binop (HImode, IOR, var, x, var,
18644 1, OPTAB_LIB_WIDEN);
18645
18646 x = gen_reg_rtx (wmode);
18647 emit_move_insn (x, gen_lowpart (wmode, const_vec));
18648 ix86_expand_vector_set (mmx_ok, x, var, one_var >> 1);
18649
18650 emit_move_insn (target, gen_lowpart (mode, x));
18651 return true;
18652
18653 default:
18654 return false;
18655 }
18656
18657 emit_move_insn (target, const_vec);
18658 ix86_expand_vector_set (mmx_ok, target, var, one_var);
18659 return true;
18660 }
18661
18662
18663
18664
18665 static void
18666 ix86_expand_vector_init_general (bool mmx_ok, enum machine_mode mode,
18667 rtx target, rtx vals)
18668 {
18669 enum machine_mode half_mode = GET_MODE_INNER (mode);
18670 rtx op0 = NULL, op1 = NULL;
18671 bool use_vec_concat = false;
18672
18673 switch (mode)
18674 {
18675 case V2SFmode:
18676 case V2SImode:
18677 if (!mmx_ok && !TARGET_SSE)
18678 break;
18679
18680
18681 case V2DFmode:
18682 case V2DImode:
18683
18684 op0 = XVECEXP (vals, 0, 0);
18685 op1 = XVECEXP (vals, 0, 1);
18686 use_vec_concat = true;
18687 break;
18688
18689 case V4SFmode:
18690 half_mode = V2SFmode;
18691 goto half;
18692 case V4SImode:
18693 half_mode = V2SImode;
18694 goto half;
18695 half:
18696 {
18697 rtvec v;
18698
18699
18700
18701
18702 op0 = gen_reg_rtx (half_mode);
18703 v = gen_rtvec (2, XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1));
18704 ix86_expand_vector_init (false, op0, gen_rtx_PARALLEL (half_mode, v));
18705
18706 op1 = gen_reg_rtx (half_mode);
18707 v = gen_rtvec (2, XVECEXP (vals, 0, 2), XVECEXP (vals, 0, 3));
18708 ix86_expand_vector_init (false, op1, gen_rtx_PARALLEL (half_mode, v));
18709
18710 use_vec_concat = true;
18711 }
18712 break;
18713
18714 case V8HImode:
18715 case V16QImode:
18716 case V4HImode:
18717 case V8QImode:
18718 break;
18719
18720 default:
18721 gcc_unreachable ();
18722 }
18723
18724 if (use_vec_concat)
18725 {
18726 if (!register_operand (op0, half_mode))
18727 op0 = force_reg (half_mode, op0);
18728 if (!register_operand (op1, half_mode))
18729 op1 = force_reg (half_mode, op1);
18730
18731 emit_insn (gen_rtx_SET (VOIDmode, target,
18732 gen_rtx_VEC_CONCAT (mode, op0, op1)));
18733 }
18734 else
18735 {
18736 int i, j, n_elts, n_words, n_elt_per_word;
18737 enum machine_mode inner_mode;
18738 rtx words[4], shift;
18739
18740 inner_mode = GET_MODE_INNER (mode);
18741 n_elts = GET_MODE_NUNITS (mode);
18742 n_words = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
18743 n_elt_per_word = n_elts / n_words;
18744 shift = GEN_INT (GET_MODE_BITSIZE (inner_mode));
18745
18746 for (i = 0; i < n_words; ++i)
18747 {
18748 rtx word = NULL_RTX;
18749
18750 for (j = 0; j < n_elt_per_word; ++j)
18751 {
18752 rtx elt = XVECEXP (vals, 0, (i+1)*n_elt_per_word - j - 1);
18753 elt = convert_modes (word_mode, inner_mode, elt, true);
18754
18755 if (j == 0)
18756 word = elt;
18757 else
18758 {
18759 word = expand_simple_binop (word_mode, ASHIFT, word, shift,
18760 word, 1, OPTAB_LIB_WIDEN);
18761 word = expand_simple_binop (word_mode, IOR, word, elt,
18762 word, 1, OPTAB_LIB_WIDEN);
18763 }
18764 }
18765
18766 words[i] = word;
18767 }
18768
18769 if (n_words == 1)
18770 emit_move_insn (target, gen_lowpart (mode, words[0]));
18771 else if (n_words == 2)
18772 {
18773 rtx tmp = gen_reg_rtx (mode);
18774 emit_insn (gen_rtx_CLOBBER (VOIDmode, tmp));
18775 emit_move_insn (gen_lowpart (word_mode, tmp), words[0]);
18776 emit_move_insn (gen_highpart (word_mode, tmp), words[1]);
18777 emit_move_insn (target, tmp);
18778 }
18779 else if (n_words == 4)
18780 {
18781 rtx tmp = gen_reg_rtx (V4SImode);
18782 vals = gen_rtx_PARALLEL (V4SImode, gen_rtvec_v (4, words));
18783 ix86_expand_vector_init_general (false, V4SImode, tmp, vals);
18784 emit_move_insn (target, gen_lowpart (mode, tmp));
18785 }
18786 else
18787 gcc_unreachable ();
18788 }
18789 }
18790
18791
18792
18793
18794 void
18795 ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals)
18796 {
18797 enum machine_mode mode = GET_MODE (target);
18798 enum machine_mode inner_mode = GET_MODE_INNER (mode);
18799 int n_elts = GET_MODE_NUNITS (mode);
18800 int n_var = 0, one_var = -1;
18801 bool all_same = true, all_const_zero = true;
18802 int i;
18803 rtx x;
18804
18805 for (i = 0; i < n_elts; ++i)
18806 {
18807 x = XVECEXP (vals, 0, i);
18808 if (!CONSTANT_P (x))
18809 n_var++, one_var = i;
18810 else if (x != CONST0_RTX (inner_mode))
18811 all_const_zero = false;
18812 if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
18813 all_same = false;
18814 }
18815
18816
18817 if (n_var == 0)
18818 {
18819 emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
18820 return;
18821 }
18822
18823
18824 if (all_same
18825 && ix86_expand_vector_init_duplicate (mmx_ok, mode, target,
18826 XVECEXP (vals, 0, 0)))
18827 return;
18828
18829
18830
18831 if (n_var == 1)
18832 {
18833 if (all_const_zero
18834 && ix86_expand_vector_init_one_nonzero (mmx_ok, mode, target,
18835 XVECEXP (vals, 0, one_var),
18836 one_var))
18837 return;
18838
18839 if (ix86_expand_vector_init_one_var (mmx_ok, mode, target, vals, one_var))
18840 return;
18841 }
18842
18843 ix86_expand_vector_init_general (mmx_ok, mode, target, vals);
18844 }
18845
18846 void
18847 ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
18848 {
18849 enum machine_mode mode = GET_MODE (target);
18850 enum machine_mode inner_mode = GET_MODE_INNER (mode);
18851 bool use_vec_merge = false;
18852 rtx tmp;
18853
18854 switch (mode)
18855 {
18856 case V2SFmode:
18857 case V2SImode:
18858 if (mmx_ok)
18859 {
18860 tmp = gen_reg_rtx (GET_MODE_INNER (mode));
18861 ix86_expand_vector_extract (true, tmp, target, 1 - elt);
18862 if (elt == 0)
18863 tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
18864 else
18865 tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
18866 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
18867 return;
18868 }
18869 break;
18870
18871 case V2DFmode:
18872 case V2DImode:
18873 {
18874 rtx op0, op1;
18875
18876
18877
18878
18879 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (1 - elt)));
18880 tmp = gen_rtx_VEC_SELECT (inner_mode, target, tmp);
18881
18882 if (elt == 0)
18883 op0 = val, op1 = tmp;
18884 else
18885 op0 = tmp, op1 = val;
18886
18887 tmp = gen_rtx_VEC_CONCAT (mode, op0, op1);
18888 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
18889 }
18890 return;
18891
18892 case V4SFmode:
18893 switch (elt)
18894 {
18895 case 0:
18896 use_vec_merge = true;
18897 break;
18898
18899 case 1:
18900
18901 tmp = copy_to_reg (target);
18902
18903 emit_insn (gen_sse_unpcklps (target, target, target));
18904
18905 ix86_expand_vector_set (false, target, val, 0);
18906
18907 emit_insn (gen_sse_shufps_1 (target, target, tmp,
18908 GEN_INT (1), GEN_INT (0),
18909 GEN_INT (2+4), GEN_INT (3+4)));
18910 return;
18911
18912 case 2:
18913
18914 tmp = copy_to_reg (target);
18915
18916 ix86_expand_vector_set (false, tmp, val, 0);
18917
18918 emit_insn (gen_sse_shufps_1 (target, target, tmp,
18919 GEN_INT (0), GEN_INT (1),
18920 GEN_INT (0+4), GEN_INT (3+4)));
18921 return;
18922
18923 case 3:
18924
18925 tmp = copy_to_reg (target);
18926
18927 ix86_expand_vector_set (false, tmp, val, 0);
18928
18929 emit_insn (gen_sse_shufps_1 (target, target, tmp,
18930 GEN_INT (0), GEN_INT (1),
18931 GEN_INT (2+4), GEN_INT (0+4)));
18932 return;
18933
18934 default:
18935 gcc_unreachable ();
18936 }
18937 break;
18938
18939 case V4SImode:
18940
18941 if (elt == 0)
18942 {
18943 use_vec_merge = true;
18944 break;
18945 }
18946
18947 if (TARGET_SSE2)
18948 {
18949
18950
18951
18952 rtx order[4];
18953
18954 order[0] = GEN_INT (elt);
18955 order[1] = const1_rtx;
18956 order[2] = const2_rtx;
18957 order[3] = GEN_INT (3);
18958 order[elt] = const0_rtx;
18959
18960 emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18961 order[1], order[2], order[3]));
18962
18963 ix86_expand_vector_set (false, target, val, 0);
18964
18965 emit_insn (gen_sse2_pshufd_1 (target, target, order[0],
18966 order[1], order[2], order[3]));
18967 }
18968 else
18969 {
18970
18971 ix86_expand_vector_set (false, gen_lowpart (V4SFmode, target),
18972 gen_lowpart (SFmode, val), elt);
18973 }
18974 return;
18975
18976 case V8HImode:
18977 use_vec_merge = TARGET_SSE2;
18978 break;
18979 case V4HImode:
18980 use_vec_merge = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
18981 break;
18982
18983 case V16QImode:
18984 case V8QImode:
18985 default:
18986 break;
18987 }
18988
18989 if (use_vec_merge)
18990 {
18991 tmp = gen_rtx_VEC_DUPLICATE (mode, val);
18992 tmp = gen_rtx_VEC_MERGE (mode, tmp, target, GEN_INT (1 << elt));
18993 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
18994 }
18995 else
18996 {
18997 rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), false);
18998
18999 emit_move_insn (mem, target);
19000
19001 tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
19002 emit_move_insn (tmp, val);
19003
19004 emit_move_insn (target, mem);
19005 }
19006 }
19007
19008 void
19009 ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
19010 {
19011 enum machine_mode mode = GET_MODE (vec);
19012 enum machine_mode inner_mode = GET_MODE_INNER (mode);
19013 bool use_vec_extr = false;
19014 rtx tmp;
19015
19016 switch (mode)
19017 {
19018 case V2SImode:
19019 case V2SFmode:
19020 if (!mmx_ok)
19021 break;
19022
19023
19024 case V2DFmode:
19025 case V2DImode:
19026 use_vec_extr = true;
19027 break;
19028
19029 case V4SFmode:
19030 switch (elt)
19031 {
19032 case 0:
19033 tmp = vec;
19034 break;
19035
19036 case 1:
19037 case 3:
19038 tmp = gen_reg_rtx (mode);
19039 emit_insn (gen_sse_shufps_1 (tmp, vec, vec,
19040 GEN_INT (elt), GEN_INT (elt),
19041 GEN_INT (elt+4), GEN_INT (elt+4)));
19042 break;
19043
19044 case 2:
19045 tmp = gen_reg_rtx (mode);
19046 emit_insn (gen_sse_unpckhps (tmp, vec, vec));
19047 break;
19048
19049 default:
19050 gcc_unreachable ();
19051 }
19052 vec = tmp;
19053 use_vec_extr = true;
19054 elt = 0;
19055 break;
19056
19057 case V4SImode:
19058 if (TARGET_SSE2)
19059 {
19060 switch (elt)
19061 {
19062 case 0:
19063 tmp = vec;
19064 break;
19065
19066 case 1:
19067 case 3:
19068 tmp = gen_reg_rtx (mode);
19069 emit_insn (gen_sse2_pshufd_1 (tmp, vec,
19070 GEN_INT (elt), GEN_INT (elt),
19071 GEN_INT (elt), GEN_INT (elt)));
19072 break;
19073
19074 case 2:
19075 tmp = gen_reg_rtx (mode);
19076 emit_insn (gen_sse2_punpckhdq (tmp, vec, vec));
19077 break;
19078
19079 default:
19080 gcc_unreachable ();
19081 }
19082 vec = tmp;
19083 use_vec_extr = true;
19084 elt = 0;
19085 }
19086 else
19087 {
19088
19089 ix86_expand_vector_extract (false, gen_lowpart (SFmode, target),
19090 gen_lowpart (V4SFmode, vec), elt);
19091 return;
19092 }
19093 break;
19094
19095 case V8HImode:
19096 use_vec_extr = TARGET_SSE2;
19097 break;
19098 case V4HImode:
19099 use_vec_extr = mmx_ok && (TARGET_SSE || TARGET_3DNOW_A);
19100 break;
19101
19102 case V16QImode:
19103 case V8QImode:
19104
19105 default:
19106 break;
19107 }
19108
19109 if (use_vec_extr)
19110 {
19111 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt)));
19112 tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp);
19113
19114
19115 if (inner_mode == HImode)
19116 {
19117 tmp = gen_rtx_ZERO_EXTEND (SImode, tmp);
19118 target = gen_lowpart (SImode, target);
19119 }
19120
19121 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
19122 }
19123 else
19124 {
19125 rtx mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), false);
19126
19127 emit_move_insn (mem, vec);
19128
19129 tmp = adjust_address (mem, inner_mode, elt*GET_MODE_SIZE (inner_mode));
19130 emit_move_insn (target, tmp);
19131 }
19132 }
19133
19134
19135
19136
19137 void
19138 ix86_expand_reduc_v4sf (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
19139 {
19140 rtx tmp1, tmp2, tmp3;
19141
19142 tmp1 = gen_reg_rtx (V4SFmode);
19143 tmp2 = gen_reg_rtx (V4SFmode);
19144 tmp3 = gen_reg_rtx (V4SFmode);
19145
19146 emit_insn (gen_sse_movhlps (tmp1, in, in));
19147 emit_insn (fn (tmp2, tmp1, in));
19148
19149 emit_insn (gen_sse_shufps_1 (tmp3, tmp2, tmp2,
19150 GEN_INT (1), GEN_INT (1),
19151 GEN_INT (1+4), GEN_INT (1+4)));
19152 emit_insn (fn (dest, tmp2, tmp3));
19153 }
19154
19155
19156 static bool
19157 ix86_scalar_mode_supported_p (enum machine_mode mode)
19158 {
19159 if (DECIMAL_FLOAT_MODE_P (mode))
19160 return true;
19161 else
19162 return default_scalar_mode_supported_p (mode);
19163 }
19164
19165
19166 static bool
19167 ix86_vector_mode_supported_p (enum machine_mode mode)
19168 {
19169 if (TARGET_SSE && VALID_SSE_REG_MODE (mode))
19170 return true;
19171 if (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode))
19172 return true;
19173 if (TARGET_MMX && VALID_MMX_REG_MODE (mode))
19174 return true;
19175 if (TARGET_3DNOW && VALID_MMX_REG_MODE_3DNOW (mode))
19176 return true;
19177 return false;
19178 }
19179
19180
19181
19182
19183
19184
19185 static tree
19186 ix86_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
19187 tree inputs ATTRIBUTE_UNUSED,
19188 tree clobbers)
19189 {
19190 clobbers = tree_cons (NULL_TREE, build_string (5, "flags"),
19191 clobbers);
19192 clobbers = tree_cons (NULL_TREE, build_string (4, "fpsr"),
19193 clobbers);
19194 clobbers = tree_cons (NULL_TREE, build_string (7, "dirflag"),
19195 clobbers);
19196 return clobbers;
19197 }
19198
19199
19200
19201 static bool
19202 ix86_in_large_data_p (tree exp)
19203 {
19204 if (ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC)
19205 return false;
19206
19207
19208 if (TREE_CODE (exp) == FUNCTION_DECL)
19209 return false;
19210
19211 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
19212 {
19213 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
19214 if (strcmp (section, ".ldata") == 0
19215 || strcmp (section, ".lbss") == 0)
19216 return true;
19217 return false;
19218 }
19219 else
19220 {
19221 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
19222
19223
19224
19225 if (!size || size > ix86_section_threshold)
19226 return true;
19227 }
19228
19229 return false;
19230 }
19231 static void
19232 ix86_encode_section_info (tree decl, rtx rtl, int first)
19233 {
19234 default_encode_section_info (decl, rtl, first);
19235
19236 if (TREE_CODE (decl) == VAR_DECL
19237 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
19238 && ix86_in_large_data_p (decl))
19239 SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FAR_ADDR;
19240 }
19241
19242
19243
19244 enum rtx_code
19245 ix86_reverse_condition (enum rtx_code code, enum machine_mode mode)
19246 {
19247 return (mode != CCFPmode && mode != CCFPUmode
19248 ? reverse_condition (code)
19249 : reverse_condition_maybe_unordered (code));
19250 }
19251
19252
19253
19254
19255 const char *
19256 output_387_reg_move (rtx insn, rtx *operands)
19257 {
19258 if (REG_P (operands[1])
19259 && find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
19260 {
19261 if (REGNO (operands[0]) == FIRST_STACK_REG)
19262 return output_387_ffreep (operands, 0);
19263 return "fstp\t%y0";
19264 }
19265 if (STACK_TOP_P (operands[0]))
19266 return "fld%z1\t%y1";
19267 return "fst\t%y0";
19268 }
19269
19270
19271
19272
19273 void
19274 ix86_emit_fp_unordered_jump (rtx label)
19275 {
19276 rtx reg = gen_reg_rtx (HImode);
19277 rtx temp;
19278
19279 emit_insn (gen_x86_fnstsw_1 (reg));
19280
19281 if (TARGET_USE_SAHF)
19282 {
19283 emit_insn (gen_x86_sahf_1 (reg));
19284
19285 temp = gen_rtx_REG (CCmode, FLAGS_REG);
19286 temp = gen_rtx_UNORDERED (VOIDmode, temp, const0_rtx);
19287 }
19288 else
19289 {
19290 emit_insn (gen_testqi_ext_ccno_0 (reg, GEN_INT (0x04)));
19291
19292 temp = gen_rtx_REG (CCNOmode, FLAGS_REG);
19293 temp = gen_rtx_NE (VOIDmode, temp, const0_rtx);
19294 }
19295
19296 temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
19297 gen_rtx_LABEL_REF (VOIDmode, label),
19298 pc_rtx);
19299 temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
19300 emit_jump_insn (temp);
19301 }
19302
19303
19304
19305 void ix86_emit_i387_log1p (rtx op0, rtx op1)
19306 {
19307 rtx label1 = gen_label_rtx ();
19308 rtx label2 = gen_label_rtx ();
19309
19310 rtx tmp = gen_reg_rtx (XFmode);
19311 rtx tmp2 = gen_reg_rtx (XFmode);
19312
19313 emit_insn (gen_absxf2 (tmp, op1));
19314 emit_insn (gen_cmpxf (tmp,
19315 CONST_DOUBLE_FROM_REAL_VALUE (
19316 REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode),
19317 XFmode)));
19318 emit_jump_insn (gen_bge (label1));
19319
19320 emit_move_insn (tmp2, standard_80387_constant_rtx (4));
19321 emit_insn (gen_fyl2xp1_xf3 (op0, tmp2, op1));
19322 emit_jump (label2);
19323
19324 emit_label (label1);
19325 emit_move_insn (tmp, CONST1_RTX (XFmode));
19326 emit_insn (gen_addxf3 (tmp, op1, tmp));
19327 emit_move_insn (tmp2, standard_80387_constant_rtx (4));
19328 emit_insn (gen_fyl2x_xf3 (op0, tmp2, tmp));
19329
19330 emit_label (label2);
19331 }
19332
19333
19334
19335 static void
19336 i386_solaris_elf_named_section (const char *name, unsigned int flags,
19337 tree decl)
19338 {
19339
19340
19341
19342 if (TARGET_64BIT
19343 && strcmp (name, ".eh_frame") == 0)
19344 {
19345 fprintf (asm_out_file, "\t.section\t%s,\"%s\",@unwind\n", name,
19346 flags & SECTION_WRITE ? "aw" : "a");
19347 return;
19348 }
19349 default_elf_asm_named_section (name, flags, decl);
19350 }
19351
19352
19353
19354 static const char *
19355 ix86_mangle_fundamental_type (tree type)
19356 {
19357 switch (TYPE_MODE (type))
19358 {
19359 case TFmode:
19360
19361 return "g";
19362 case XFmode:
19363
19364 return "e";
19365 default:
19366 return NULL;
19367 }
19368 }
19369
19370
19371
19372
19373
19374
19375 static tree
19376 ix86_stack_protect_fail (void)
19377 {
19378 return TARGET_64BIT
19379 ? default_external_stack_protect_fail ()
19380 : default_hidden_stack_protect_fail ();
19381 }
19382
19383
19384
19385
19386
19387
19388
19389
19390
19391 int
19392 asm_preferred_eh_data_format (int code, int global)
19393 {
19394 if (flag_pic)
19395 {
19396 int type = DW_EH_PE_sdata8;
19397 if (!TARGET_64BIT
19398 || ix86_cmodel == CM_SMALL_PIC
19399 || (ix86_cmodel == CM_MEDIUM_PIC && (global || code)))
19400 type = DW_EH_PE_sdata4;
19401 return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
19402 }
19403 if (ix86_cmodel == CM_SMALL
19404 || (ix86_cmodel == CM_MEDIUM && code))
19405 return DW_EH_PE_udata4;
19406 return DW_EH_PE_absptr;
19407 }
19408
19409 #include "gt-i386.h"