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 "rtl.h"
00029 #include "tree.h"
00030 #include "tm_p.h"
00031 #include "regs.h"
00032 #include "hard-reg-set.h"
00033 #include "real.h"
00034 #include "insn-config.h"
00035 #include "conditions.h"
00036 #include "output.h"
00037 #include "insn-attr.h"
00038 #include "flags.h"
00039 #include "except.h"
00040 #include "function.h"
00041 #include "recog.h"
00042 #include "expr.h"
00043 #include "optabs.h"
00044 #include "toplev.h"
00045 #include "basic-block.h"
00046 #include "ggc.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 #include "langhooks.h"
00050
00051 #ifndef CHECK_STACK_LIMIT
00052 #define CHECK_STACK_LIMIT (-1)
00053 #endif
00054
00055
00056 static const
00057 struct processor_costs size_cost = {
00058 2,
00059 3,
00060 2,
00061 3,
00062 3,
00063 0,
00064 3,
00065 3,
00066 3,
00067 0,
00068 2,
00069 2,
00070 {2, 2, 2},
00071
00072
00073 {2, 2, 2},
00074 2,
00075 {2, 2, 2},
00076
00077 {2, 2, 2},
00078 3,
00079 {3, 3},
00080
00081 {3, 3},
00082
00083 3,
00084 {3, 3, 3},
00085
00086 {3, 3, 3},
00087
00088 3,
00089 0,
00090 0,
00091 2,
00092 2,
00093 2,
00094 2,
00095 2,
00096 2,
00097 };
00098
00099
00100 static const
00101 struct processor_costs i386_cost = {
00102 1,
00103 1,
00104 3,
00105 2,
00106 6,
00107 1,
00108 23,
00109 3,
00110 2,
00111 15,
00112 3,
00113 4,
00114 {2, 4, 2},
00115
00116
00117 {2, 4, 2},
00118 2,
00119 {8, 8, 8},
00120
00121 {8, 8, 8},
00122 2,
00123 {4, 8},
00124
00125 {4, 8},
00126
00127 2,
00128 {4, 8, 16},
00129
00130 {4, 8, 16},
00131
00132 3,
00133 0,
00134 0,
00135 23,
00136 27,
00137 88,
00138 22,
00139 24,
00140 122,
00141 };
00142
00143 static const
00144 struct processor_costs i486_cost = {
00145 1,
00146 1,
00147 3,
00148 2,
00149 12,
00150 1,
00151 40,
00152 3,
00153 2,
00154 15,
00155 3,
00156 4,
00157 {2, 4, 2},
00158
00159
00160 {2, 4, 2},
00161 2,
00162 {8, 8, 8},
00163
00164 {8, 8, 8},
00165 2,
00166 {4, 8},
00167
00168 {4, 8},
00169
00170 2,
00171 {4, 8, 16},
00172
00173 {4, 8, 16},
00174
00175 3,
00176 0,
00177 0,
00178 8,
00179 16,
00180 73,
00181 3,
00182 3,
00183 83,
00184 };
00185
00186 static const
00187 struct processor_costs pentium_cost = {
00188 1,
00189 1,
00190 4,
00191 1,
00192 11,
00193 0,
00194 25,
00195 3,
00196 2,
00197 8,
00198 6,
00199 6,
00200 {2, 4, 2},
00201
00202
00203 {2, 4, 2},
00204 2,
00205 {2, 2, 6},
00206
00207 {4, 4, 6},
00208 8,
00209 {8, 8},
00210
00211 {8, 8},
00212
00213 2,
00214 {4, 8, 16},
00215
00216 {4, 8, 16},
00217
00218 3,
00219 0,
00220 0,
00221 3,
00222 3,
00223 39,
00224 1,
00225 1,
00226 70,
00227 };
00228
00229 static const
00230 struct processor_costs pentiumpro_cost = {
00231 1,
00232 1,
00233 1,
00234 1,
00235 4,
00236 0,
00237 17,
00238 1,
00239 1,
00240 8,
00241 6,
00242 2,
00243 {4, 4, 4},
00244
00245
00246 {2, 2, 2},
00247 2,
00248 {2, 2, 6},
00249
00250 {4, 4, 6},
00251 2,
00252 {2, 2},
00253
00254 {2, 2},
00255
00256 2,
00257 {2, 2, 8},
00258
00259 {2, 2, 8},
00260
00261 3,
00262 32,
00263 6,
00264 3,
00265 5,
00266 56,
00267 2,
00268 2,
00269 56,
00270 };
00271
00272 static const
00273 struct processor_costs k6_cost = {
00274 1,
00275 2,
00276 1,
00277 1,
00278 3,
00279 0,
00280 18,
00281 2,
00282 2,
00283 8,
00284 4,
00285 3,
00286 {4, 5, 4},
00287
00288
00289 {2, 3, 2},
00290 4,
00291 {6, 6, 6},
00292
00293 {4, 4, 4},
00294 2,
00295 {2, 2},
00296
00297 {2, 2},
00298
00299 2,
00300 {2, 2, 8},
00301
00302 {2, 2, 8},
00303
00304 6,
00305 32,
00306 1,
00307 2,
00308 2,
00309 56,
00310 2,
00311 2,
00312 56,
00313 };
00314
00315 static const
00316 struct processor_costs athlon_cost = {
00317 1,
00318 2,
00319 1,
00320 1,
00321 5,
00322 0,
00323 42,
00324 1,
00325 1,
00326 8,
00327 9,
00328 4,
00329 {3, 4, 3},
00330
00331
00332 {3, 4, 3},
00333 4,
00334 {4, 4, 12},
00335
00336 {6, 6, 8},
00337 2,
00338 {4, 4},
00339
00340 {4, 4},
00341
00342 2,
00343 {4, 4, 6},
00344
00345 {4, 4, 5},
00346
00347 5,
00348 64,
00349 6,
00350 4,
00351 4,
00352 24,
00353 2,
00354 2,
00355 35,
00356 };
00357
00358 static const
00359 struct processor_costs pentium4_cost = {
00360 1,
00361 1,
00362 8,
00363 8,
00364 30,
00365 0,
00366 112,
00367 1,
00368 1,
00369 16,
00370 6,
00371 2,
00372 {4, 5, 4},
00373
00374
00375 {2, 3, 2},
00376 2,
00377 {2, 2, 6},
00378
00379 {4, 4, 6},
00380 2,
00381 {2, 2},
00382
00383 {2, 2},
00384
00385 12,
00386 {12, 12, 12},
00387
00388 {2, 2, 8},
00389
00390 10,
00391 64,
00392 6,
00393 5,
00394 7,
00395 43,
00396 2,
00397 2,
00398 43,
00399 };
00400
00401 const struct processor_costs *ix86_cost = &pentium_cost;
00402
00403
00404 #define m_386 (1<<PROCESSOR_I386)
00405 #define m_486 (1<<PROCESSOR_I486)
00406 #define m_PENT (1<<PROCESSOR_PENTIUM)
00407 #define m_PPRO (1<<PROCESSOR_PENTIUMPRO)
00408 #define m_K6 (1<<PROCESSOR_K6)
00409 #define m_ATHLON (1<<PROCESSOR_ATHLON)
00410 #define m_PENT4 (1<<PROCESSOR_PENTIUM4)
00411
00412 const int x86_use_leave = m_386 | m_K6 | m_ATHLON;
00413 const int x86_push_memory = m_386 | m_K6 | m_ATHLON | m_PENT4;
00414 const int x86_zero_extend_with_and = m_486 | m_PENT;
00415 const int x86_movx = m_ATHLON | m_PPRO | m_PENT4 ;
00416 const int x86_double_with_add = ~m_386;
00417 const int x86_use_bit_test = m_386;
00418 const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;
00419 const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;
00420 const int x86_3dnow_a = m_ATHLON;
00421 const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;
00422 const int x86_branch_hints = m_PENT4;
00423 const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;
00424 const int x86_partial_reg_stall = m_PPRO;
00425 const int x86_use_loop = m_K6;
00426 const int x86_use_fiop = ~(m_PPRO | m_ATHLON | m_PENT);
00427 const int x86_use_mov0 = m_K6;
00428 const int x86_use_cltd = ~(m_PENT | m_K6);
00429 const int x86_read_modify_write = ~m_PENT;
00430 const int x86_read_modify = ~(m_PENT | m_PPRO);
00431 const int x86_split_long_moves = m_PPRO;
00432 const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON;
00433 const int x86_fast_prefix = ~(m_PENT | m_486 | m_386);
00434 const int x86_single_stringop = m_386 | m_PENT4;
00435 const int x86_qimode_math = ~(0);
00436 const int x86_promote_qi_regs = 0;
00437 const int x86_himode_math = ~(m_PPRO);
00438 const int x86_promote_hi_regs = m_PPRO;
00439 const int x86_sub_esp_4 = m_ATHLON | m_PPRO | m_PENT4;
00440 const int x86_sub_esp_8 = m_ATHLON | m_PPRO | m_386 | m_486 | m_PENT4;
00441 const int x86_add_esp_4 = m_ATHLON | m_K6 | m_PENT4;
00442 const int x86_add_esp_8 = m_ATHLON | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;
00443 const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4 | m_PPRO);
00444 const int x86_partial_reg_dependency = m_ATHLON | m_PENT4;
00445 const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;
00446 const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
00447 const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
00448 const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
00449 const int x86_decompose_lea = m_PENT4;
00450 const int x86_shift1 = ~m_486;
00451 const int x86_arch_always_fancy_math_387 = m_PENT | m_PPRO | m_ATHLON | m_PENT4;
00452
00453
00454
00455
00456 #define FAST_PROLOGUE_INSN_COUNT 30
00457
00458
00459
00460 static int use_fast_prologue_epilogue;
00461
00462
00463 static const char *const qi_reg_name[] = QI_REGISTER_NAMES;
00464 static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
00465 static const char *const hi_reg_name[] = HI_REGISTER_NAMES;
00466
00467
00468
00469
00470 enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
00471 {
00472
00473 AREG, DREG, CREG, BREG,
00474
00475 SIREG, DIREG, NON_Q_REGS, NON_Q_REGS,
00476
00477 FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
00478 FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
00479
00480 NON_Q_REGS,
00481
00482 NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS,
00483 SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
00484 SSE_REGS, SSE_REGS,
00485 MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
00486 MMX_REGS, MMX_REGS,
00487 NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
00488 NON_Q_REGS, NON_Q_REGS, NON_Q_REGS, NON_Q_REGS,
00489 SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
00490 SSE_REGS, SSE_REGS,
00491 };
00492
00493
00494
00495 int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
00496 {
00497 0, 2, 1, 3, 6, 7, 4, 5,
00498 12, 13, 14, 15, 16, 17, 18, 19,
00499 -1, -1, -1, -1, -1,
00500 21, 22, 23, 24, 25, 26, 27, 28,
00501 29, 30, 31, 32, 33, 34, 35, 36,
00502 -1, -1, -1, -1, -1, -1, -1, -1,
00503 -1, -1, -1, -1, -1, -1, -1, -1,
00504 };
00505
00506 static int const x86_64_int_parameter_registers[6] =
00507 {
00508 5 , 4 , 1 , 2 ,
00509 FIRST_REX_INT_REG , FIRST_REX_INT_REG + 1
00510 };
00511
00512 static int const x86_64_int_return_registers[4] =
00513 {
00514 0 , 1 , 5 , 4
00515 };
00516
00517
00518 int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
00519 {
00520 0, 1, 2, 3, 4, 5, 6, 7,
00521 33, 34, 35, 36, 37, 38, 39, 40,
00522 -1, -1, -1, -1, -1,
00523 17, 18, 19, 20, 21, 22, 23, 24,
00524 41, 42, 43, 44, 45, 46, 47, 48,
00525 8,9,10,11,12,13,14,15,
00526 25, 26, 27, 28, 29, 30, 31, 32,
00527 };
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
00584 {
00585 0, 2, 1, 3, 6, 7, 5, 4,
00586 11, 12, 13, 14, 15, 16, 17, 18,
00587 -1, 9, -1, -1, -1,
00588 21, 22, 23, 24, 25, 26, 27, 28,
00589 29, 30, 31, 32, 33, 34, 35, 36,
00590 -1, -1, -1, -1, -1, -1, -1, -1,
00591 -1, -1, -1, -1, -1, -1, -1, -1,
00592 };
00593
00594
00595
00596
00597 rtx ix86_compare_op0 = NULL_RTX;
00598 rtx ix86_compare_op1 = NULL_RTX;
00599
00600
00601
00602 static char const tls_model_chars[] = " GLil";
00603
00604 #define MAX_386_STACK_LOCALS 3
00605
00606 #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
00607
00608
00609 struct machine_function GTY(())
00610 {
00611 rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
00612 const char *some_ld_name;
00613 int save_varrargs_registers;
00614 int accesses_prev_frame;
00615 };
00616
00617 #define ix86_stack_locals (cfun->machine->stack_locals)
00618 #define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 struct ix86_frame
00640 {
00641 int nregs;
00642 int padding1;
00643 int va_arg_size;
00644 HOST_WIDE_INT frame;
00645 int padding2;
00646 int outgoing_arguments_size;
00647 int red_zone_size;
00648
00649 HOST_WIDE_INT to_allocate;
00650
00651 HOST_WIDE_INT frame_pointer_offset;
00652 HOST_WIDE_INT hard_frame_pointer_offset;
00653 HOST_WIDE_INT stack_pointer_offset;
00654 };
00655
00656
00657 const char *ix86_debug_arg_string, *ix86_debug_addr_string;
00658
00659 const char *ix86_cmodel_string;
00660
00661 enum cmodel ix86_cmodel;
00662
00663 const char *ix86_asm_string;
00664 enum asm_dialect ix86_asm_dialect = ASM_ATT;
00665
00666 const char *ix86_tls_dialect_string;
00667 enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
00668
00669
00670 enum fpmath_unit ix86_fpmath;
00671
00672
00673 enum processor_type ix86_cpu;
00674
00675 enum processor_type ix86_arch;
00676
00677
00678 const char *ix86_cpu_string;
00679 const char *ix86_arch_string;
00680 const char *ix86_fpmath_string;
00681
00682
00683 const char *ix86_regparm_string;
00684
00685
00686 int x86_prefetch_sse;
00687
00688
00689 int ix86_regparm;
00690
00691
00692
00693
00694 const char *ix86_align_loops_string;
00695
00696
00697 const char *ix86_align_jumps_string;
00698
00699
00700 const char *ix86_preferred_stack_boundary_string;
00701
00702
00703 int ix86_preferred_stack_boundary;
00704
00705
00706 int ix86_branch_cost;
00707 const char *ix86_branch_cost_string;
00708
00709
00710 const char *ix86_align_funcs_string;
00711
00712
00713 static char internal_label_prefix[16];
00714 static int internal_label_prefix_len;
00715
00716 static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
00717 static int tls_symbolic_operand_1 PARAMS ((rtx, enum tls_model));
00718 static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
00719 static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
00720 int, int, FILE *));
00721 static const char *get_some_local_dynamic_name PARAMS ((void));
00722 static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
00723 static rtx maybe_get_pool_constant PARAMS ((rtx));
00724 static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
00725 static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
00726 rtx *, rtx *));
00727 static rtx get_thread_pointer PARAMS ((int));
00728 static rtx legitimize_tls_address PARAMS ((rtx, enum tls_model, int));
00729 static void get_pc_thunk_name PARAMS ((char [32], unsigned int));
00730 static rtx gen_push PARAMS ((rtx));
00731 static int memory_address_length PARAMS ((rtx addr));
00732 static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
00733 static int ix86_agi_dependant PARAMS ((rtx, rtx, enum attr_type));
00734 static enum attr_ppro_uops ix86_safe_ppro_uops PARAMS ((rtx));
00735 static void ix86_dump_ppro_packet PARAMS ((FILE *));
00736 static void ix86_reorder_insn PARAMS ((rtx *, rtx *));
00737 static struct machine_function * ix86_init_machine_status PARAMS ((void));
00738 static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
00739 static int ix86_nsaved_regs PARAMS ((void));
00740 static void ix86_emit_save_regs PARAMS ((void));
00741 static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));
00742 static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
00743 static void ix86_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00744 static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
00745 static void ix86_sched_reorder_ppro PARAMS ((rtx *, rtx *));
00746 static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));
00747 static void ix86_adjust_counter PARAMS ((rtx, HOST_WIDE_INT));
00748 static rtx ix86_expand_aligntest PARAMS ((rtx, int));
00749 static void ix86_expand_strlensi_unroll_1 PARAMS ((rtx, rtx));
00750 static int ix86_issue_rate PARAMS ((void));
00751 static int ix86_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00752 static void ix86_sched_init PARAMS ((FILE *, int, int));
00753 static int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
00754 static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
00755 static int ia32_use_dfa_pipeline_interface PARAMS ((void));
00756 static int ia32_multipass_dfa_lookahead PARAMS ((void));
00757 static void ix86_init_mmx_sse_builtins PARAMS ((void));
00758 static rtx x86_this_parameter PARAMS ((tree));
00759 static void x86_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
00760 HOST_WIDE_INT, tree));
00761 static bool x86_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,
00762 HOST_WIDE_INT, tree));
00763
00764 struct ix86_address
00765 {
00766 rtx base, index, disp;
00767 HOST_WIDE_INT scale;
00768 enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS } seg;
00769 };
00770
00771 static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));
00772 static bool ix86_cannot_force_const_mem PARAMS ((rtx));
00773
00774 static void ix86_encode_section_info PARAMS ((tree, int)) ATTRIBUTE_UNUSED;
00775 static const char *ix86_strip_name_encoding PARAMS ((const char *))
00776 ATTRIBUTE_UNUSED;
00777
00778 struct builtin_description;
00779 static rtx ix86_expand_sse_comi PARAMS ((const struct builtin_description *,
00780 tree, rtx));
00781 static rtx ix86_expand_sse_compare PARAMS ((const struct builtin_description *,
00782 tree, rtx));
00783 static rtx ix86_expand_unop1_builtin PARAMS ((enum insn_code, tree, rtx));
00784 static rtx ix86_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx, int));
00785 static rtx ix86_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
00786 static rtx ix86_expand_store_builtin PARAMS ((enum insn_code, tree));
00787 static rtx safe_vector_operand PARAMS ((rtx, enum machine_mode));
00788 static enum rtx_code ix86_fp_compare_code_to_integer PARAMS ((enum rtx_code));
00789 static void ix86_fp_comparison_codes PARAMS ((enum rtx_code code,
00790 enum rtx_code *,
00791 enum rtx_code *,
00792 enum rtx_code *));
00793 static rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, rtx,
00794 rtx *, rtx *));
00795 static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
00796 static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
00797 static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
00798 static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
00799 static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
00800 static int ix86_save_reg PARAMS ((unsigned int, int));
00801 static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
00802 static int ix86_comp_type_attributes PARAMS ((tree, tree));
00803 static int ix86_fntype_regparm PARAMS ((tree));
00804 const struct attribute_spec ix86_attribute_table[];
00805 static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
00806 static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
00807 static int ix86_value_regno PARAMS ((enum machine_mode));
00808 static bool contains_128bit_aligned_vector_p PARAMS ((tree));
00809
00810 #if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
00811 static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
00812 #endif
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 enum x86_64_reg_class
00823 {
00824 X86_64_NO_CLASS,
00825 X86_64_INTEGER_CLASS,
00826 X86_64_INTEGERSI_CLASS,
00827 X86_64_SSE_CLASS,
00828 X86_64_SSESF_CLASS,
00829 X86_64_SSEDF_CLASS,
00830 X86_64_SSEUP_CLASS,
00831 X86_64_X87_CLASS,
00832 X86_64_X87UP_CLASS,
00833 X86_64_MEMORY_CLASS
00834 };
00835 static const char * const x86_64_reg_class_name[] =
00836 {"no", "integer", "integerSI", "sse", "sseSF", "sseDF", "sseup", "x87", "x87up", "no"};
00837
00838 #define MAX_CLASSES 4
00839 static int classify_argument PARAMS ((enum machine_mode, tree,
00840 enum x86_64_reg_class [MAX_CLASSES],
00841 int));
00842 static int examine_argument PARAMS ((enum machine_mode, tree, int, int *,
00843 int *));
00844 static rtx construct_container PARAMS ((enum machine_mode, tree, int, int, int,
00845 const int *, int));
00846 static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
00847 enum x86_64_reg_class));
00848
00849
00850 #undef TARGET_ATTRIBUTE_TABLE
00851 #define TARGET_ATTRIBUTE_TABLE ix86_attribute_table
00852 #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
00853 # undef TARGET_MERGE_DECL_ATTRIBUTES
00854 # define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
00855 #endif
00856
00857 #undef TARGET_COMP_TYPE_ATTRIBUTES
00858 #define TARGET_COMP_TYPE_ATTRIBUTES ix86_comp_type_attributes
00859
00860 #undef TARGET_INIT_BUILTINS
00861 #define TARGET_INIT_BUILTINS ix86_init_builtins
00862
00863 #undef TARGET_EXPAND_BUILTIN
00864 #define TARGET_EXPAND_BUILTIN ix86_expand_builtin
00865
00866 #undef TARGET_ASM_FUNCTION_EPILOGUE
00867 #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
00868
00869 #undef TARGET_ASM_OPEN_PAREN
00870 #define TARGET_ASM_OPEN_PAREN ""
00871 #undef TARGET_ASM_CLOSE_PAREN
00872 #define TARGET_ASM_CLOSE_PAREN ""
00873
00874 #undef TARGET_ASM_ALIGNED_HI_OP
00875 #define TARGET_ASM_ALIGNED_HI_OP ASM_SHORT
00876 #undef TARGET_ASM_ALIGNED_SI_OP
00877 #define TARGET_ASM_ALIGNED_SI_OP ASM_LONG
00878 #ifdef ASM_QUAD
00879 #undef TARGET_ASM_ALIGNED_DI_OP
00880 #define TARGET_ASM_ALIGNED_DI_OP ASM_QUAD
00881 #endif
00882
00883 #undef TARGET_ASM_UNALIGNED_HI_OP
00884 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00885 #undef TARGET_ASM_UNALIGNED_SI_OP
00886 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00887 #undef TARGET_ASM_UNALIGNED_DI_OP
00888 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00889
00890 #undef TARGET_SCHED_ADJUST_COST
00891 #define TARGET_SCHED_ADJUST_COST ix86_adjust_cost
00892 #undef TARGET_SCHED_ISSUE_RATE
00893 #define TARGET_SCHED_ISSUE_RATE ix86_issue_rate
00894 #undef TARGET_SCHED_VARIABLE_ISSUE
00895 #define TARGET_SCHED_VARIABLE_ISSUE ix86_variable_issue
00896 #undef TARGET_SCHED_INIT
00897 #define TARGET_SCHED_INIT ix86_sched_init
00898 #undef TARGET_SCHED_REORDER
00899 #define TARGET_SCHED_REORDER ix86_sched_reorder
00900 #undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
00901 #define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
00902 ia32_use_dfa_pipeline_interface
00903 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
00904 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
00905 ia32_multipass_dfa_lookahead
00906
00907 #ifdef HAVE_AS_TLS
00908 #undef TARGET_HAVE_TLS
00909 #define TARGET_HAVE_TLS true
00910 #endif
00911 #undef TARGET_CANNOT_FORCE_CONST_MEM
00912 #define TARGET_CANNOT_FORCE_CONST_MEM ix86_cannot_force_const_mem
00913
00914 #undef TARGET_ASM_OUTPUT_MI_THUNK
00915 #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
00916 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00917 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
00918
00919 struct gcc_target targetm = TARGET_INITIALIZER;
00920
00921
00922
00923 #ifndef DEFAULT_PCC_STRUCT_RETURN
00924 #define DEFAULT_PCC_STRUCT_RETURN 1
00925 #endif
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 void
00937 override_options ()
00938 {
00939 int i;
00940
00941 #define MAX_CODE_ALIGN 16
00942
00943 static struct ptt
00944 {
00945 const struct processor_costs *cost;
00946 const int target_enable;
00947 const int target_disable;
00948 const int align_loop;
00949 const int align_loop_max_skip;
00950 const int align_jump;
00951 const int align_jump_max_skip;
00952 const int align_func;
00953 const int branch_cost;
00954 }
00955 const processor_target_table[PROCESSOR_max] =
00956 {
00957 {&i386_cost, 0, 0, 4, 3, 4, 3, 4, 1},
00958 {&i486_cost, 0, 0, 16, 15, 16, 15, 16, 1},
00959 {&pentium_cost, 0, 0, 16, 7, 16, 7, 16, 1},
00960 {&pentiumpro_cost, 0, 0, 16, 15, 16, 7, 16, 1},
00961 {&k6_cost, 0, 0, 32, 7, 32, 7, 32, 1},
00962 {&athlon_cost, 0, 0, 16, 7, 64, 7, 16, 1},
00963 {&pentium4_cost, 0, 0, 0, 0, 0, 0, 0, 1}
00964 };
00965
00966 static const char * const cpu_names[] = TARGET_CPU_DEFAULT_NAMES;
00967 static struct pta
00968 {
00969 const char *const name;
00970 const enum processor_type processor;
00971 const enum pta_flags
00972 {
00973 PTA_SSE = 1,
00974 PTA_SSE2 = 2,
00975 PTA_MMX = 4,
00976 PTA_PREFETCH_SSE = 8,
00977 PTA_3DNOW = 16,
00978 PTA_3DNOW_A = 64
00979 } flags;
00980 }
00981 const processor_alias_table[] =
00982 {
00983 {"i386", PROCESSOR_I386, 0},
00984 {"i486", PROCESSOR_I486, 0},
00985 {"i586", PROCESSOR_PENTIUM, 0},
00986 {"pentium", PROCESSOR_PENTIUM, 0},
00987 {"pentium-mmx", PROCESSOR_PENTIUM, PTA_MMX},
00988 {"winchip-c6", PROCESSOR_I486, PTA_MMX},
00989 {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
00990 {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
00991 {"i686", PROCESSOR_PENTIUMPRO, 0},
00992 {"pentiumpro", PROCESSOR_PENTIUMPRO, 0},
00993 {"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX},
00994 {"pentium3", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_SSE | PTA_PREFETCH_SSE},
00995 {"pentium4", PROCESSOR_PENTIUM4, PTA_SSE | PTA_SSE2 |
00996 PTA_MMX | PTA_PREFETCH_SSE},
00997 {"k6", PROCESSOR_K6, PTA_MMX},
00998 {"k6-2", PROCESSOR_K6, PTA_MMX | PTA_3DNOW},
00999 {"k6-3", PROCESSOR_K6, PTA_MMX | PTA_3DNOW},
01000 {"athlon", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01001 | PTA_3DNOW_A},
01002 {"athlon-tbird", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE
01003 | PTA_3DNOW | PTA_3DNOW_A},
01004 {"athlon-4", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01005 | PTA_3DNOW_A | PTA_SSE},
01006 {"athlon-xp", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01007 | PTA_3DNOW_A | PTA_SSE},
01008 {"athlon-mp", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
01009 | PTA_3DNOW_A | PTA_SSE},
01010 };
01011
01012 int const pta_size = ARRAY_SIZE (processor_alias_table);
01013
01014
01015
01016 real_format_for_mode[XFmode - QFmode] = &ieee_extended_intel_96_format;
01017 real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
01018
01019
01020
01021 if (TARGET_64BIT)
01022 {
01023 if (flag_omit_frame_pointer == 2)
01024 flag_omit_frame_pointer = 1;
01025 if (flag_asynchronous_unwind_tables == 2)
01026 flag_asynchronous_unwind_tables = 1;
01027 if (flag_pcc_struct_return == 2)
01028 flag_pcc_struct_return = 0;
01029 }
01030 else
01031 {
01032 if (flag_omit_frame_pointer == 2)
01033 flag_omit_frame_pointer = 0;
01034 if (flag_asynchronous_unwind_tables == 2)
01035 flag_asynchronous_unwind_tables = 0;
01036 if (flag_pcc_struct_return == 2)
01037 flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
01038 }
01039
01040 #ifdef SUBTARGET_OVERRIDE_OPTIONS
01041 SUBTARGET_OVERRIDE_OPTIONS;
01042 #endif
01043
01044 if (!ix86_cpu_string && ix86_arch_string)
01045 ix86_cpu_string = ix86_arch_string;
01046 if (!ix86_cpu_string)
01047 ix86_cpu_string = cpu_names [TARGET_CPU_DEFAULT];
01048 if (!ix86_arch_string)
01049 ix86_arch_string = TARGET_64BIT ? "athlon-4" : "i386";
01050
01051 if (ix86_cmodel_string != 0)
01052 {
01053 if (!strcmp (ix86_cmodel_string, "small"))
01054 ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
01055 else if (flag_pic)
01056 sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
01057 else if (!strcmp (ix86_cmodel_string, "32"))
01058 ix86_cmodel = CM_32;
01059 else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
01060 ix86_cmodel = CM_KERNEL;
01061 else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
01062 ix86_cmodel = CM_MEDIUM;
01063 else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
01064 ix86_cmodel = CM_LARGE;
01065 else
01066 error ("bad value (%s) for -mcmodel= switch", ix86_cmodel_string);
01067 }
01068 else
01069 {
01070 ix86_cmodel = CM_32;
01071 if (TARGET_64BIT)
01072 ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
01073 }
01074 if (ix86_asm_string != 0)
01075 {
01076 if (!strcmp (ix86_asm_string, "intel"))
01077 ix86_asm_dialect = ASM_INTEL;
01078 else if (!strcmp (ix86_asm_string, "att"))
01079 ix86_asm_dialect = ASM_ATT;
01080 else
01081 error ("bad value (%s) for -masm= switch", ix86_asm_string);
01082 }
01083 if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
01084 error ("code model `%s' not supported in the %s bit mode",
01085 ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
01086 if (ix86_cmodel == CM_LARGE)
01087 sorry ("code model `large' not supported yet");
01088 if ((TARGET_64BIT != 0) != ((target_flags & MASK_64BIT) != 0))
01089 sorry ("%i-bit mode not compiled in",
01090 (target_flags & MASK_64BIT) ? 64 : 32);
01091
01092 for (i = 0; i < pta_size; i++)
01093 if (! strcmp (ix86_arch_string, processor_alias_table[i].name))
01094 {
01095 ix86_arch = processor_alias_table[i].processor;
01096
01097 ix86_cpu = ix86_arch;
01098 if (processor_alias_table[i].flags & PTA_MMX
01099 && !(target_flags_explicit & MASK_MMX))
01100 target_flags |= MASK_MMX;
01101 if (processor_alias_table[i].flags & PTA_3DNOW
01102 && !(target_flags_explicit & MASK_3DNOW))
01103 target_flags |= MASK_3DNOW;
01104 if (processor_alias_table[i].flags & PTA_3DNOW_A
01105 && !(target_flags_explicit & MASK_3DNOW_A))
01106 target_flags |= MASK_3DNOW_A;
01107 if (processor_alias_table[i].flags & PTA_SSE
01108 && !(target_flags_explicit & MASK_SSE))
01109 target_flags |= MASK_SSE;
01110 if (processor_alias_table[i].flags & PTA_SSE2
01111 && !(target_flags_explicit & MASK_SSE2))
01112 target_flags |= MASK_SSE2;
01113 if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
01114 x86_prefetch_sse = true;
01115 break;
01116 }
01117
01118 if (i == pta_size)
01119 error ("bad value (%s) for -march= switch", ix86_arch_string);
01120
01121 for (i = 0; i < pta_size; i++)
01122 if (! strcmp (ix86_cpu_string, processor_alias_table[i].name))
01123 {
01124 ix86_cpu = processor_alias_table[i].processor;
01125 break;
01126 }
01127 if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
01128 x86_prefetch_sse = true;
01129 if (i == pta_size)
01130 error ("bad value (%s) for -mcpu= switch", ix86_cpu_string);
01131
01132 if (optimize_size)
01133 ix86_cost = &size_cost;
01134 else
01135 ix86_cost = processor_target_table[ix86_cpu].cost;
01136 target_flags |= processor_target_table[ix86_cpu].target_enable;
01137 target_flags &= ~processor_target_table[ix86_cpu].target_disable;
01138
01139
01140 init_machine_status = ix86_init_machine_status;
01141
01142
01143 if (ix86_regparm_string)
01144 {
01145 i = atoi (ix86_regparm_string);
01146 if (i < 0 || i > REGPARM_MAX)
01147 error ("-mregparm=%d is not between 0 and %d", i, REGPARM_MAX);
01148 else
01149 ix86_regparm = i;
01150 }
01151 else
01152 if (TARGET_64BIT)
01153 ix86_regparm = REGPARM_MAX;
01154
01155
01156
01157
01158 if (ix86_align_loops_string)
01159 {
01160 warning ("-malign-loops is obsolete, use -falign-loops");
01161 if (align_loops == 0)
01162 {
01163 i = atoi (ix86_align_loops_string);
01164 if (i < 0 || i > MAX_CODE_ALIGN)
01165 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01166 else
01167 align_loops = 1 << i;
01168 }
01169 }
01170
01171 if (ix86_align_jumps_string)
01172 {
01173 warning ("-malign-jumps is obsolete, use -falign-jumps");
01174 if (align_jumps == 0)
01175 {
01176 i = atoi (ix86_align_jumps_string);
01177 if (i < 0 || i > MAX_CODE_ALIGN)
01178 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01179 else
01180 align_jumps = 1 << i;
01181 }
01182 }
01183
01184 if (ix86_align_funcs_string)
01185 {
01186 warning ("-malign-functions is obsolete, use -falign-functions");
01187 if (align_functions == 0)
01188 {
01189 i = atoi (ix86_align_funcs_string);
01190 if (i < 0 || i > MAX_CODE_ALIGN)
01191 error ("-malign-loops=%d is not between 0 and %d", i, MAX_CODE_ALIGN);
01192 else
01193 align_functions = 1 << i;
01194 }
01195 }
01196
01197
01198 if (align_loops == 0)
01199 {
01200 align_loops = processor_target_table[ix86_cpu].align_loop;
01201 align_loops_max_skip = processor_target_table[ix86_cpu].align_loop_max_skip;
01202 }
01203 if (align_jumps == 0)
01204 {
01205 align_jumps = processor_target_table[ix86_cpu].align_jump;
01206 align_jumps_max_skip = processor_target_table[ix86_cpu].align_jump_max_skip;
01207 }
01208 if (align_functions == 0)
01209 {
01210 align_functions = processor_target_table[ix86_cpu].align_func;
01211 }
01212
01213
01214
01215
01216
01217 ix86_preferred_stack_boundary = (optimize_size
01218 ? TARGET_64BIT ? 128 : 32
01219 : 128);
01220 if (ix86_preferred_stack_boundary_string)
01221 {
01222 i = atoi (ix86_preferred_stack_boundary_string);
01223 if (i < (TARGET_64BIT ? 4 : 2) || i > 12)
01224 error ("-mpreferred-stack-boundary=%d is not between %d and 12", i,
01225 TARGET_64BIT ? 4 : 2);
01226 else
01227 ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
01228 }
01229
01230
01231 ix86_branch_cost = processor_target_table[ix86_cpu].branch_cost;
01232 if (ix86_branch_cost_string)
01233 {
01234 i = atoi (ix86_branch_cost_string);
01235 if (i < 0 || i > 5)
01236 error ("-mbranch-cost=%d is not between 0 and 5", i);
01237 else
01238 ix86_branch_cost = i;
01239 }
01240
01241 if (ix86_tls_dialect_string)
01242 {
01243 if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
01244 ix86_tls_dialect = TLS_DIALECT_GNU;
01245 else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
01246 ix86_tls_dialect = TLS_DIALECT_SUN;
01247 else
01248 error ("bad value (%s) for -mtls-dialect= switch",
01249 ix86_tls_dialect_string);
01250 }
01251
01252
01253 if (TARGET_OMIT_LEAF_FRAME_POINTER)
01254 flag_omit_frame_pointer = 1;
01255
01256
01257
01258 if (flag_unsafe_math_optimizations)
01259 target_flags &= ~MASK_IEEE_FP;
01260
01261
01262
01263 if (x86_arch_always_fancy_math_387 & (1 << ix86_arch))
01264 target_flags &= ~MASK_NO_FANCY_MATH_387;
01265
01266
01267 if (TARGET_PNI)
01268 target_flags |= MASK_SSE2;
01269
01270
01271 if (TARGET_SSE2)
01272 target_flags |= MASK_SSE;
01273
01274 if (TARGET_64BIT)
01275 {
01276 if (TARGET_ALIGN_DOUBLE)
01277 #ifdef TARG_NVISA
01278
01279 target_flags &= ~MASK_ALIGN_DOUBLE;
01280 #else
01281 error ("-malign-double makes no sense in the 64bit mode");
01282 #endif
01283 if (TARGET_RTD)
01284 error ("-mrtd calling convention not supported in the 64bit mode");
01285
01286 target_flags |= (MASK_SSE2 | MASK_SSE | MASK_MMX | MASK_128BIT_LONG_DOUBLE);
01287 ix86_fpmath = FPMATH_SSE;
01288 }
01289 else
01290 ix86_fpmath = FPMATH_387;
01291
01292 if (ix86_fpmath_string != 0)
01293 {
01294 if (! strcmp (ix86_fpmath_string, "387"))
01295 ix86_fpmath = FPMATH_387;
01296 else if (! strcmp (ix86_fpmath_string, "sse"))
01297 {
01298 if (!TARGET_SSE)
01299 {
01300 warning ("SSE instruction set disabled, using 387 arithmetics");
01301 ix86_fpmath = FPMATH_387;
01302 }
01303 else
01304 ix86_fpmath = FPMATH_SSE;
01305 }
01306 else if (! strcmp (ix86_fpmath_string, "387,sse")
01307 || ! strcmp (ix86_fpmath_string, "sse,387"))
01308 {
01309 if (!TARGET_SSE)
01310 {
01311 warning ("SSE instruction set disabled, using 387 arithmetics");
01312 ix86_fpmath = FPMATH_387;
01313 }
01314 else if (!TARGET_80387)
01315 {
01316 warning ("387 instruction set disabled, using SSE arithmetics");
01317 ix86_fpmath = FPMATH_SSE;
01318 }
01319 else
01320 ix86_fpmath = FPMATH_SSE | FPMATH_387;
01321 }
01322 else
01323 error ("bad value (%s) for -mfpmath= switch", ix86_fpmath_string);
01324 }
01325
01326
01327
01328 if (TARGET_SSE)
01329 {
01330 target_flags |= MASK_MMX;
01331 x86_prefetch_sse = true;
01332 }
01333
01334
01335 if (TARGET_3DNOW)
01336 {
01337 target_flags |= MASK_MMX;
01338
01339
01340 if (x86_3dnow_a & (1 << ix86_arch))
01341 target_flags |= MASK_3DNOW_A;
01342 }
01343 if ((x86_accumulate_outgoing_args & CPUMASK)
01344 && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
01345 && !optimize_size)
01346 target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
01347
01348
01349 {
01350 char *p;
01351 ASM_GENERATE_INTERNAL_LABEL (internal_label_prefix, "LX", 0);
01352 p = strchr (internal_label_prefix, 'X');
01353 internal_label_prefix_len = p - internal_label_prefix;
01354 *p = '\0';
01355 }
01356 }
01357
01358 void
01359 optimization_options (level, size)
01360 int level;
01361 int size ATTRIBUTE_UNUSED;
01362 {
01363
01364
01365 #ifdef INSN_SCHEDULING
01366 if (level > 1)
01367 flag_schedule_insns = 0;
01368 #endif
01369
01370
01371
01372
01373
01374 if (optimize >= 1)
01375 flag_omit_frame_pointer = 2;
01376 flag_pcc_struct_return = 2;
01377 flag_asynchronous_unwind_tables = 2;
01378 }
01379
01380
01381 const struct attribute_spec ix86_attribute_table[] =
01382 {
01383
01384
01385
01386 { "stdcall", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
01387
01388 { "cdecl", 0, 0, false, true, true, ix86_handle_cdecl_attribute },
01389
01390
01391 { "regparm", 1, 1, false, true, true, ix86_handle_regparm_attribute },
01392 #ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
01393 { "dllimport", 0, 0, false, false, false, ix86_handle_dll_attribute },
01394 { "dllexport", 0, 0, false, false, false, ix86_handle_dll_attribute },
01395 { "shared", 0, 0, true, false, false, ix86_handle_shared_attribute },
01396 #endif
01397 { NULL, 0, 0, false, false, false, NULL }
01398 };
01399
01400
01401
01402 static tree
01403 ix86_handle_cdecl_attribute (node, name, args, flags, no_add_attrs)
01404 tree *node;
01405 tree name;
01406 tree args ATTRIBUTE_UNUSED;
01407 int flags ATTRIBUTE_UNUSED;
01408 bool *no_add_attrs;
01409 {
01410 if (TREE_CODE (*node) != FUNCTION_TYPE
01411 && TREE_CODE (*node) != METHOD_TYPE
01412 && TREE_CODE (*node) != FIELD_DECL
01413 && TREE_CODE (*node) != TYPE_DECL)
01414 {
01415 warning ("`%s' attribute only applies to functions",
01416 IDENTIFIER_POINTER (name));
01417 *no_add_attrs = true;
01418 }
01419
01420 if (TARGET_64BIT)
01421 {
01422 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
01423 *no_add_attrs = true;
01424 }
01425
01426 return NULL_TREE;
01427 }
01428
01429
01430
01431 static tree
01432 ix86_handle_regparm_attribute (node, name, args, flags, no_add_attrs)
01433 tree *node;
01434 tree name;
01435 tree args;
01436 int flags ATTRIBUTE_UNUSED;
01437 bool *no_add_attrs;
01438 {
01439 if (TREE_CODE (*node) != FUNCTION_TYPE
01440 && TREE_CODE (*node) != METHOD_TYPE
01441 && TREE_CODE (*node) != FIELD_DECL
01442 && TREE_CODE (*node) != TYPE_DECL)
01443 {
01444 warning ("`%s' attribute only applies to functions",
01445 IDENTIFIER_POINTER (name));
01446 *no_add_attrs = true;
01447 }
01448 else
01449 {
01450 tree cst;
01451
01452 cst = TREE_VALUE (args);
01453 if (TREE_CODE (cst) != INTEGER_CST)
01454 {
01455 warning ("`%s' attribute requires an integer constant argument",
01456 IDENTIFIER_POINTER (name));
01457 *no_add_attrs = true;
01458 }
01459 else if (compare_tree_int (cst, REGPARM_MAX) > 0)
01460 {
01461 warning ("argument to `%s' attribute larger than %d",
01462 IDENTIFIER_POINTER (name), REGPARM_MAX);
01463 *no_add_attrs = true;
01464 }
01465 }
01466
01467 return NULL_TREE;
01468 }
01469
01470
01471
01472
01473
01474 static int
01475 ix86_comp_type_attributes (type1, type2)
01476 tree type1;
01477 tree type2;
01478 {
01479
01480 const char *const rtdstr = TARGET_RTD ? "cdecl" : "stdcall";
01481
01482 if (TREE_CODE (type1) != FUNCTION_TYPE)
01483 return 1;
01484
01485
01486 if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
01487 != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
01488 return 0;
01489 return 1;
01490 }
01491
01492
01493
01494 static int
01495 ix86_fntype_regparm (type)
01496 tree type;
01497 {
01498 tree attr;
01499
01500 attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
01501 if (attr)
01502 return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
01503 else
01504 return ix86_regparm;
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 int
01525 ix86_return_pops_args (fundecl, funtype, size)
01526 tree fundecl;
01527 tree funtype;
01528 int size;
01529 {
01530 int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
01531
01532
01533 if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
01534
01535
01536 if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
01537 rtd = 1;
01538
01539 if (rtd
01540 && (TYPE_ARG_TYPES (funtype) == NULL_TREE
01541 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))
01542 == void_type_node)))
01543 return size;
01544 }
01545
01546
01547 if (aggregate_value_p (TREE_TYPE (funtype))
01548 && !TARGET_64BIT)
01549 {
01550 int nregs = ix86_fntype_regparm (funtype);
01551
01552 if (!nregs)
01553 return GET_MODE_SIZE (Pmode);
01554 }
01555
01556 return 0;
01557 }
01558
01559
01560
01561
01562 bool
01563 ix86_function_arg_regno_p (regno)
01564 int regno;
01565 {
01566 int i;
01567 if (!TARGET_64BIT)
01568 return (regno < REGPARM_MAX
01569 || (TARGET_SSE && SSE_REGNO_P (regno) && !fixed_regs[regno]));
01570 if (SSE_REGNO_P (regno) && TARGET_SSE)
01571 return true;
01572
01573 if (!regno)
01574 return true;
01575 for (i = 0; i < REGPARM_MAX; i++)
01576 if (regno == x86_64_int_parameter_registers[i])
01577 return true;
01578 return false;
01579 }
01580
01581
01582
01583
01584
01585 void
01586 init_cumulative_args (cum, fntype, libname)
01587 CUMULATIVE_ARGS *cum;
01588 tree fntype;
01589 rtx libname;
01590 {
01591 static CUMULATIVE_ARGS zero_cum;
01592 tree param, next_param;
01593
01594 if (TARGET_DEBUG_ARG)
01595 {
01596 fprintf (stderr, "\ninit_cumulative_args (");
01597 if (fntype)
01598 fprintf (stderr, "fntype code = %s, ret code = %s",
01599 tree_code_name[(int) TREE_CODE (fntype)],
01600 tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]);
01601 else
01602 fprintf (stderr, "no fntype");
01603
01604 if (libname)
01605 fprintf (stderr, ", libname = %s", XSTR (libname, 0));
01606 }
01607
01608 *cum = zero_cum;
01609
01610
01611 cum->nregs = ix86_regparm;
01612 cum->sse_nregs = SSE_REGPARM_MAX;
01613 if (fntype && !TARGET_64BIT)
01614 {
01615 tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
01616
01617 if (attr)
01618 cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
01619 }
01620 cum->maybe_vaarg = false;
01621
01622
01623
01624
01625
01626
01627 if (cum->nregs)
01628 {
01629 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
01630 param != 0; param = next_param)
01631 {
01632 next_param = TREE_CHAIN (param);
01633 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
01634 {
01635 if (!TARGET_64BIT)
01636 cum->nregs = 0;
01637 cum->maybe_vaarg = true;
01638 }
01639 }
01640 }
01641 if ((!fntype && !libname)
01642 || (fntype && !TYPE_ARG_TYPES (fntype)))
01643 cum->maybe_vaarg = 1;
01644
01645 if (TARGET_DEBUG_ARG)
01646 fprintf (stderr, ", nregs=%d )\n", cum->nregs);
01647
01648 return;
01649 }
01650
01651
01652
01653
01654
01655
01656
01657
01658 static enum x86_64_reg_class
01659 merge_classes (class1, class2)
01660 enum x86_64_reg_class class1, class2;
01661 {
01662
01663 if (class1 == class2)
01664 return class1;
01665
01666
01667
01668 if (class1 == X86_64_NO_CLASS)
01669 return class2;
01670 if (class2 == X86_64_NO_CLASS)
01671 return class1;
01672
01673
01674 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
01675 return X86_64_MEMORY_CLASS;
01676
01677
01678 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
01679 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
01680 return X86_64_INTEGERSI_CLASS;
01681 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
01682 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
01683 return X86_64_INTEGER_CLASS;
01684
01685
01686 if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
01687 || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
01688 return X86_64_MEMORY_CLASS;
01689
01690
01691 return X86_64_SSE_CLASS;
01692 }
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706 static int
01707 classify_argument (mode, type, classes, bit_offset)
01708 enum machine_mode mode;
01709 tree type;
01710 enum x86_64_reg_class classes[MAX_CLASSES];
01711 int bit_offset;
01712 {
01713 int bytes =
01714 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
01715 int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01716
01717
01718 if (bytes < 0)
01719 return 0;
01720
01721 if (type && AGGREGATE_TYPE_P (type))
01722 {
01723 int i;
01724 tree field;
01725 enum x86_64_reg_class subclasses[MAX_CLASSES];
01726
01727
01728 if (bytes > 16)
01729 return 0;
01730
01731 for (i = 0; i < words; i++)
01732 classes[i] = X86_64_NO_CLASS;
01733
01734
01735
01736 if (!words)
01737 {
01738 classes[0] = X86_64_NO_CLASS;
01739 return 1;
01740 }
01741
01742
01743 if (TREE_CODE (type) == RECORD_TYPE)
01744 {
01745
01746 if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)
01747 {
01748 tree bases = TYPE_BINFO_BASETYPES (type);
01749 int n_bases = TREE_VEC_LENGTH (bases);
01750 int i;
01751
01752 for (i = 0; i < n_bases; ++i)
01753 {
01754 #ifdef KEY
01755 int j;
01756 #endif
01757 tree binfo = TREE_VEC_ELT (bases, i);
01758 int num;
01759 int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
01760 tree type = BINFO_TYPE (binfo);
01761
01762 num = classify_argument (TYPE_MODE (type),
01763 type, subclasses,
01764 (offset + bit_offset) % 256);
01765 if (!num)
01766 return 0;
01767
01768 #ifdef KEY
01769 for (j = 0; j < num; j++)
01770 {
01771 int pos = (offset + (bit_offset % 64)) / 8 / 8;
01772 classes[j + pos] =
01773 merge_classes (subclasses[j], classes[j + pos]);
01774 }
01775 #else
01776 for (i = 0; i < num; i++)
01777 {
01778 int pos = (offset + (bit_offset % 64)) / 8 / 8;
01779 classes[i + pos] =
01780 merge_classes (subclasses[i], classes[i + pos]);
01781 }
01782 #endif
01783 }
01784 }
01785
01786 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
01787 {
01788 if (TREE_CODE (field) == FIELD_DECL)
01789 {
01790 int num;
01791
01792
01793
01794
01795 if (DECL_BIT_FIELD (field))
01796 {
01797 for (i = int_bit_position (field) / 8 / 8;
01798 i < (int_bit_position (field)
01799 + tree_low_cst (DECL_SIZE (field), 0)
01800 + 63) / 8 / 8; i++)
01801 classes[i] =
01802 merge_classes (X86_64_INTEGER_CLASS,
01803 classes[i]);
01804 }
01805 else
01806 {
01807 num = classify_argument (TYPE_MODE (TREE_TYPE (field)),
01808 TREE_TYPE (field), subclasses,
01809 (int_bit_position (field)
01810 + bit_offset) % 256);
01811 if (!num)
01812 return 0;
01813 for (i = 0; i < num; i++)
01814 {
01815 int pos =
01816 (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
01817 classes[i + pos] =
01818 merge_classes (subclasses[i], classes[i + pos]);
01819 }
01820 }
01821 }
01822 }
01823 }
01824
01825 else if (TREE_CODE (type) == ARRAY_TYPE)
01826 {
01827 int num;
01828 num = classify_argument (TYPE_MODE (TREE_TYPE (type)),
01829 TREE_TYPE (type), subclasses, bit_offset);
01830 if (!num)
01831 return 0;
01832
01833
01834 if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4)
01835 subclasses[0] = X86_64_SSE_CLASS;
01836 if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4)
01837 subclasses[0] = X86_64_INTEGER_CLASS;
01838
01839 for (i = 0; i < words; i++)
01840 classes[i] = subclasses[i % num];
01841 }
01842
01843 else if (TREE_CODE (type) == UNION_TYPE
01844 || TREE_CODE (type) == QUAL_UNION_TYPE)
01845 {
01846
01847 if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)
01848 {
01849 tree bases = TYPE_BINFO_BASETYPES (type);
01850 int n_bases = TREE_VEC_LENGTH (bases);
01851 int i;
01852
01853 for (i = 0; i < n_bases; ++i)
01854 {
01855 tree binfo = TREE_VEC_ELT (bases, i);
01856 #ifdef KEY
01857 int j;
01858 #endif
01859 int num;
01860 int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8;
01861 tree type = BINFO_TYPE (binfo);
01862
01863 num = classify_argument (TYPE_MODE (type),
01864 type, subclasses,
01865 (offset + (bit_offset % 64)) % 256);
01866 if (!num)
01867 return 0;
01868 #ifdef KEY
01869 for (j = 0; j < num; j++)
01870 {
01871 int pos = (offset + (bit_offset % 64)) / 8 / 8;
01872 classes[j + pos] =
01873 merge_classes (subclasses[j], classes[j + pos]);
01874 }
01875 #else
01876 for (i = 0; i < num; i++)
01877 {
01878 int pos = (offset + (bit_offset % 64)) / 8 / 8;
01879 classes[i + pos] =
01880 merge_classes (subclasses[i], classes[i + pos]);
01881 }
01882 #endif
01883 }
01884 }
01885 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
01886 {
01887 if (TREE_CODE (field) == FIELD_DECL)
01888 {
01889 int num;
01890 num = classify_argument (TYPE_MODE (TREE_TYPE (field)),
01891 TREE_TYPE (field), subclasses,
01892 bit_offset);
01893 if (!num)
01894 return 0;
01895 for (i = 0; i < num; i++)
01896 classes[i] = merge_classes (subclasses[i], classes[i]);
01897 }
01898 }
01899 }
01900 else
01901 abort ();
01902
01903
01904 for (i = 0; i < words; i++)
01905 {
01906
01907
01908 if (classes[i] == X86_64_MEMORY_CLASS)
01909 return 0;
01910
01911
01912
01913 if (classes[i] == X86_64_SSEUP_CLASS
01914 && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
01915 classes[i] = X86_64_SSE_CLASS;
01916
01917
01918 if (classes[i] == X86_64_X87UP_CLASS
01919 && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
01920 classes[i] = X86_64_SSE_CLASS;
01921 }
01922 return words;
01923 }
01924
01925
01926
01927 if (mode != VOIDmode && mode != BLKmode)
01928 {
01929 int mode_alignment = GET_MODE_BITSIZE (mode);
01930
01931 if (mode == XFmode)
01932 mode_alignment = 128;
01933 else if (mode == XCmode)
01934 mode_alignment = 256;
01935
01936 if (bit_offset % mode_alignment)
01937 return 0;
01938 }
01939
01940
01941 switch (mode)
01942 {
01943 case DImode:
01944 case SImode:
01945 case HImode:
01946 case QImode:
01947 case CSImode:
01948 case CHImode:
01949 case CQImode:
01950 if (bit_offset + GET_MODE_BITSIZE (mode) <= 32)
01951 classes[0] = X86_64_INTEGERSI_CLASS;
01952 else
01953 classes[0] = X86_64_INTEGER_CLASS;
01954 return 1;
01955 case CDImode:
01956 case TImode:
01957 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
01958 return 2;
01959 case CTImode:
01960 classes[0] = classes[1] = X86_64_INTEGER_CLASS;
01961 classes[2] = classes[3] = X86_64_INTEGER_CLASS;
01962 return 4;
01963 case SFmode:
01964 if (!(bit_offset % 64))
01965 classes[0] = X86_64_SSESF_CLASS;
01966 else
01967 classes[0] = X86_64_SSE_CLASS;
01968 return 1;
01969 case DFmode:
01970 classes[0] = X86_64_SSEDF_CLASS;
01971 return 1;
01972 case TFmode:
01973 classes[0] = X86_64_X87_CLASS;
01974 classes[1] = X86_64_X87UP_CLASS;
01975 return 2;
01976 case TCmode:
01977 classes[0] = X86_64_X87_CLASS;
01978 classes[1] = X86_64_X87UP_CLASS;
01979 classes[2] = X86_64_X87_CLASS;
01980 classes[3] = X86_64_X87UP_CLASS;
01981 return 4;
01982 case DCmode:
01983 classes[0] = X86_64_SSEDF_CLASS;
01984 classes[1] = X86_64_SSEDF_CLASS;
01985 return 2;
01986 case SCmode:
01987 classes[0] = X86_64_SSE_CLASS;
01988 return 1;
01989 case V4SFmode:
01990 case V4SImode:
01991 case V16QImode:
01992 case V8HImode:
01993 case V2DFmode:
01994 case V2DImode:
01995 classes[0] = X86_64_SSE_CLASS;
01996 classes[1] = X86_64_SSEUP_CLASS;
01997 return 2;
01998 case V2SFmode:
01999 case V2SImode:
02000 case V4HImode:
02001 case V8QImode:
02002 return 0;
02003 case BLKmode:
02004 case VOIDmode:
02005 return 0;
02006 default:
02007 abort ();
02008 }
02009 }
02010
02011
02012
02013 static int
02014 examine_argument (mode, type, in_return, int_nregs, sse_nregs)
02015 enum machine_mode mode;
02016 tree type;
02017 int *int_nregs, *sse_nregs;
02018 int in_return;
02019 {
02020 enum x86_64_reg_class class[MAX_CLASSES];
02021 int n = classify_argument (mode, type, class, 0);
02022
02023 *int_nregs = 0;
02024 *sse_nregs = 0;
02025 if (!n)
02026 return 0;
02027 for (n--; n >= 0; n--)
02028 switch (class[n])
02029 {
02030 case X86_64_INTEGER_CLASS:
02031 case X86_64_INTEGERSI_CLASS:
02032 (*int_nregs)++;
02033 break;
02034 case X86_64_SSE_CLASS:
02035 case X86_64_SSESF_CLASS:
02036 case X86_64_SSEDF_CLASS:
02037 (*sse_nregs)++;
02038 break;
02039 case X86_64_NO_CLASS:
02040 case X86_64_SSEUP_CLASS:
02041 break;
02042 case X86_64_X87_CLASS:
02043 case X86_64_X87UP_CLASS:
02044 if (!in_return)
02045 return 0;
02046 break;
02047 case X86_64_MEMORY_CLASS:
02048 abort ();
02049 }
02050 return 1;
02051 }
02052
02053
02054 static rtx
02055 construct_container (mode, type, in_return, nintregs, nsseregs, intreg, sse_regno)
02056 enum machine_mode mode;
02057 tree type;
02058 int in_return;
02059 int nintregs, nsseregs;
02060 const int * intreg;
02061 int sse_regno;
02062 {
02063 enum machine_mode tmpmode;
02064 int bytes =
02065 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
02066 enum x86_64_reg_class class[MAX_CLASSES];
02067 int n;
02068 int i;
02069 int nexps = 0;
02070 int needed_sseregs, needed_intregs;
02071 rtx exp[MAX_CLASSES];
02072 rtx ret;
02073
02074 n = classify_argument (mode, type, class, 0);
02075 if (TARGET_DEBUG_ARG)
02076 {
02077 if (!n)
02078 fprintf (stderr, "Memory class\n");
02079 else
02080 {
02081 fprintf (stderr, "Classes:");
02082 for (i = 0; i < n; i++)
02083 {
02084 fprintf (stderr, " %s", x86_64_reg_class_name[class[i]]);
02085 }
02086 fprintf (stderr, "\n");
02087 }
02088 }
02089 if (!n)
02090 return NULL;
02091 if (!examine_argument (mode, type, in_return, &needed_intregs, &needed_sseregs))
02092 return NULL;
02093 if (needed_intregs > nintregs || needed_sseregs > nsseregs)
02094 return NULL;
02095
02096
02097
02098 if (n == 1 && mode != SCmode)
02099 switch (class[0])
02100 {
02101 case X86_64_INTEGER_CLASS:
02102 case X86_64_INTEGERSI_CLASS:
02103 return gen_rtx_REG (mode, intreg[0]);
02104 case X86_64_SSE_CLASS:
02105 case X86_64_SSESF_CLASS:
02106 case X86_64_SSEDF_CLASS:
02107 return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
02108 case X86_64_X87_CLASS:
02109 return gen_rtx_REG (mode, FIRST_STACK_REG);
02110 case X86_64_NO_CLASS:
02111
02112 return NULL;
02113 default:
02114 abort ();
02115 }
02116 if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS)
02117 return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
02118 if (n == 2
02119 && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
02120 return gen_rtx_REG (TFmode, FIRST_STACK_REG);
02121 if (n == 2 && class[0] == X86_64_INTEGER_CLASS
02122 && class[1] == X86_64_INTEGER_CLASS
02123 && (mode == CDImode || mode == TImode)
02124 && intreg[0] + 1 == intreg[1])
02125 return gen_rtx_REG (mode, intreg[0]);
02126 if (n == 4
02127 && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS
02128 && class[2] == X86_64_X87_CLASS && class[3] == X86_64_X87UP_CLASS)
02129 return gen_rtx_REG (TCmode, FIRST_STACK_REG);
02130
02131
02132 for (i = 0; i < n; i++)
02133 {
02134 switch (class[i])
02135 {
02136 case X86_64_NO_CLASS:
02137 break;
02138 case X86_64_INTEGER_CLASS:
02139 case X86_64_INTEGERSI_CLASS:
02140
02141 if (i * 8 + 8 > bytes)
02142 tmpmode = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
02143 else if (class[i] == X86_64_INTEGERSI_CLASS)
02144 tmpmode = SImode;
02145 else
02146 tmpmode = DImode;
02147
02148 if (tmpmode == BLKmode)
02149 tmpmode = DImode;
02150 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
02151 gen_rtx_REG (tmpmode, *intreg),
02152 GEN_INT (i*8));
02153 intreg++;
02154 break;
02155 case X86_64_SSESF_CLASS:
02156 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
02157 gen_rtx_REG (SFmode,
02158 SSE_REGNO (sse_regno)),
02159 GEN_INT (i*8));
02160 sse_regno++;
02161 break;
02162 case X86_64_SSEDF_CLASS:
02163 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
02164 gen_rtx_REG (DFmode,
02165 SSE_REGNO (sse_regno)),
02166 GEN_INT (i*8));
02167 sse_regno++;
02168 break;
02169 case X86_64_SSE_CLASS:
02170 if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
02171 tmpmode = TImode;
02172 else
02173 tmpmode = DImode;
02174 exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
02175 gen_rtx_REG (tmpmode,
02176 SSE_REGNO (sse_regno)),
02177 GEN_INT (i*8));
02178 if (tmpmode == TImode)
02179 i++;
02180 sse_regno++;
02181 break;
02182 default:
02183 abort ();
02184 }
02185 }
02186 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nexps));
02187 for (i = 0; i < nexps; i++)
02188 XVECEXP (ret, 0, i) = exp [i];
02189 return ret;
02190 }
02191
02192
02193
02194
02195
02196 void
02197 function_arg_advance (cum, mode, type, named)
02198 CUMULATIVE_ARGS *cum;
02199 enum machine_mode mode;
02200 tree type;
02201 int named;
02202 {
02203 int bytes =
02204 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
02205 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
02206
02207 if (TARGET_DEBUG_ARG)
02208 fprintf (stderr,
02209 "function_adv (sz=%d, wds=%2d, nregs=%d, mode=%s, named=%d)\n\n",
02210 words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
02211 if (TARGET_64BIT)
02212 {
02213 int int_nregs, sse_nregs;
02214 if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
02215 cum->words += words;
02216 else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
02217 {
02218 cum->nregs -= int_nregs;
02219 cum->sse_nregs -= sse_nregs;
02220 cum->regno += int_nregs;
02221 cum->sse_regno += sse_nregs;
02222 }
02223 else
02224 cum->words += words;
02225 }
02226 else
02227 {
02228 if (TARGET_SSE && mode == TImode)
02229 {
02230 cum->sse_words += words;
02231 cum->sse_nregs -= 1;
02232 cum->sse_regno += 1;
02233 if (cum->sse_nregs <= 0)
02234 {
02235 cum->sse_nregs = 0;
02236 cum->sse_regno = 0;
02237 }
02238 }
02239 else
02240 {
02241 cum->words += words;
02242 cum->nregs -= words;
02243 cum->regno += words;
02244
02245 if (cum->nregs <= 0)
02246 {
02247 cum->nregs = 0;
02248 cum->regno = 0;
02249 }
02250 }
02251 }
02252 return;
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268 rtx
02269 function_arg (cum, mode, type, named)
02270 CUMULATIVE_ARGS *cum;
02271 enum machine_mode mode;
02272 tree type;
02273 int named;
02274 {
02275 rtx ret = NULL_RTX;
02276 int bytes =
02277 (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
02278 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
02279
02280
02281
02282
02283 if (mode == VOIDmode)
02284 {
02285 if (TARGET_64BIT)
02286 return GEN_INT (cum->maybe_vaarg
02287 ? (cum->sse_nregs < 0
02288 ? SSE_REGPARM_MAX
02289 : cum->sse_regno)
02290 : -1);
02291 else
02292 return constm1_rtx;
02293 }
02294 if (TARGET_64BIT)
02295 ret = construct_container (mode, type, 0, cum->nregs, cum->sse_nregs,
02296 &x86_64_int_parameter_registers [cum->regno],
02297 cum->sse_regno);
02298 else
02299 switch (mode)
02300 {
02301
02302 default:
02303 break;
02304
02305 case BLKmode:
02306 if (bytes < 0)
02307 break;
02308
02309 case DImode:
02310 case SImode:
02311 case HImode:
02312 case QImode:
02313 if (words <= cum->nregs)
02314 ret = gen_rtx_REG (mode, cum->regno);
02315 break;
02316 case TImode:
02317 if (cum->sse_nregs)
02318 ret = gen_rtx_REG (mode, cum->sse_regno);
02319 break;
02320 }
02321
02322 if (TARGET_DEBUG_ARG)
02323 {
02324 fprintf (stderr,
02325 "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d, ",
02326 words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
02327
02328 if (ret)
02329 print_simple_rtl (stderr, ret);
02330 else
02331 fprintf (stderr, ", stack");
02332
02333 fprintf (stderr, " )\n");
02334 }
02335
02336 return ret;
02337 }
02338
02339
02340
02341 static bool
02342 contains_128bit_aligned_vector_p (type)
02343 tree type;
02344 {
02345 enum machine_mode mode = TYPE_MODE (type);
02346 if (SSE_REG_MODE_P (mode)
02347 && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128))
02348 return true;
02349 if (TYPE_ALIGN (type) < 128)
02350 return false;
02351
02352 if (AGGREGATE_TYPE_P (type))
02353 {
02354
02355 if (TREE_CODE (type) == RECORD_TYPE
02356 || TREE_CODE (type) == UNION_TYPE
02357 || TREE_CODE (type) == QUAL_UNION_TYPE)
02358 {
02359 tree field;
02360
02361 if (TYPE_BINFO (type) != NULL
02362 && TYPE_BINFO_BASETYPES (type) != NULL)
02363 {
02364 tree bases = TYPE_BINFO_BASETYPES (type);
02365 int n_bases = TREE_VEC_LENGTH (bases);
02366 int i;
02367
02368 for (i = 0; i < n_bases; ++i)
02369 {
02370 tree binfo = TREE_VEC_ELT (bases, i);
02371 tree type = BINFO_TYPE (binfo);
02372
02373 if (contains_128bit_aligned_vector_p (type))
02374 return true;
02375 }
02376 }
02377
02378 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
02379 {
02380 if (TREE_CODE (field) == FIELD_DECL
02381 && contains_128bit_aligned_vector_p (TREE_TYPE (field)))
02382 return true;
02383 }
02384 }
02385
02386 else if (TREE_CODE (type) == ARRAY_TYPE)
02387 {
02388 if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
02389 return true;
02390 }
02391 else
02392 abort ();
02393 }
02394 return false;
02395 }
02396
02397
02398
02399
02400
02401
02402
02403 int
02404 function_arg_pass_by_reference (cum, mode, type, named)
02405 CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
02406 enum machine_mode mode ATTRIBUTE_UNUSED;
02407 tree type;
02408 int named ATTRIBUTE_UNUSED;
02409 {
02410 if (!TARGET_64BIT)
02411 return 0;
02412
02413 if (type && int_size_in_bytes (type) == -1)
02414 {
02415 if (TARGET_DEBUG_ARG)
02416 fprintf (stderr, "function_arg_pass_by_reference\n");
02417 return 1;
02418 }
02419
02420 return 0;
02421 }
02422
02423
02424
02425
02426 int
02427 ix86_function_arg_boundary (mode, type)
02428 enum machine_mode mode;
02429 tree type;
02430 {
02431 int align;
02432 if (type)
02433 align = TYPE_ALIGN (type);
02434 else
02435 align = GET_MODE_ALIGNMENT (mode);
02436 if (align < PARM_BOUNDARY)
02437 align = PARM_BOUNDARY;
02438 if (!TARGET_64BIT)
02439 {
02440
02441
02442
02443
02444
02445
02446
02447 if (!type)
02448 {
02449 if (!SSE_REG_MODE_P (mode))
02450 align = PARM_BOUNDARY;
02451 }
02452 else
02453 {
02454 if (!contains_128bit_aligned_vector_p (type))
02455 align = PARM_BOUNDARY;
02456 }
02457 if (align != PARM_BOUNDARY && !TARGET_SSE)
02458 abort();
02459 }
02460 if (align > 128)
02461 align = 128;
02462 return align;
02463 }
02464
02465
02466 bool
02467 ix86_function_value_regno_p (regno)
02468 int regno;
02469 {
02470 if (!TARGET_64BIT)
02471 {
02472 return ((regno) == 0
02473 || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
02474 || ((regno) == FIRST_SSE_REG && TARGET_SSE));
02475 }
02476 return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
02477 || ((regno) == FIRST_SSE_REG && TARGET_SSE)
02478 || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
02479 }
02480
02481
02482
02483
02484
02485 rtx
02486 ix86_function_value (valtype)
02487 tree valtype;
02488 {
02489 if (TARGET_64BIT)
02490 {
02491 rtx ret = construct_container (TYPE_MODE (valtype), valtype, 1,
02492 REGPARM_MAX, SSE_REGPARM_MAX,
02493 x86_64_int_return_registers, 0);
02494
02495
02496 if (!ret)
02497 ret = gen_rtx_REG (TYPE_MODE (valtype), 0);
02498 return ret;
02499 }
02500 else
02501 return gen_rtx_REG (TYPE_MODE (valtype),
02502 ix86_value_regno (TYPE_MODE (valtype)));
02503 }
02504
02505
02506 int
02507 ix86_return_in_memory (type)
02508 tree type;
02509 {
02510 int needed_intregs, needed_sseregs, size;
02511 enum machine_mode mode = TYPE_MODE (type);
02512
02513 if (TARGET_64BIT)
02514 return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
02515
02516 if (mode == BLKmode)
02517 return 1;
02518
02519 size = int_size_in_bytes (type);
02520
02521 if (VECTOR_MODE_P (mode) || mode == TImode)
02522 {
02523
02524 if (size < 8)
02525 return 0;
02526
02527
02528
02529 if (size == 8)
02530 return 1;
02531
02532
02533
02534
02535
02536
02537
02538 if (size == 16)
02539 {
02540 static bool warned;
02541
02542 if (TARGET_SSE)
02543 return 0;
02544
02545 if (!warned)
02546 {
02547 warned = true;
02548 warning ("SSE vector return without SSE enabled changes the ABI");
02549 }
02550 return 1;
02551 }
02552 }
02553
02554 if (mode == TFmode)
02555 return 0;
02556 if (size > 12)
02557 return 1;
02558 return 0;
02559 }
02560
02561
02562
02563 rtx
02564 ix86_libcall_value (mode)
02565 enum machine_mode mode;
02566 {
02567 if (TARGET_64BIT)
02568 {
02569 switch (mode)
02570 {
02571 case SFmode:
02572 case SCmode:
02573 case DFmode:
02574 case DCmode:
02575 return gen_rtx_REG (mode, FIRST_SSE_REG);
02576 case TFmode:
02577 case TCmode:
02578 return gen_rtx_REG (mode, FIRST_FLOAT_REG);
02579 default:
02580 return gen_rtx_REG (mode, 0);
02581 }
02582 }
02583 else
02584 return gen_rtx_REG (mode, ix86_value_regno (mode));
02585 }
02586
02587
02588
02589 static int
02590 ix86_value_regno (mode)
02591 enum machine_mode mode;
02592 {
02593
02594 if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_FLOAT_RETURNS_IN_80387)
02595 return FIRST_FLOAT_REG;
02596
02597
02598 if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
02599 return FIRST_SSE_REG;
02600
02601 return 0;
02602 }
02603
02604
02605
02606 tree
02607 ix86_build_va_list ()
02608 {
02609 tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
02610
02611
02612 if (!TARGET_64BIT)
02613 return build_pointer_type (char_type_node);
02614
02615 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
02616 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
02617
02618 f_gpr = build_decl (FIELD_DECL, get_identifier ("gp_offset"),
02619 unsigned_type_node);
02620 f_fpr = build_decl (FIELD_DECL, get_identifier ("fp_offset"),
02621 unsigned_type_node);
02622 f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
02623 ptr_type_node);
02624 f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
02625 ptr_type_node);
02626
02627 DECL_FIELD_CONTEXT (f_gpr) = record;
02628 DECL_FIELD_CONTEXT (f_fpr) = record;
02629 DECL_FIELD_CONTEXT (f_ovf) = record;
02630 DECL_FIELD_CONTEXT (f_sav) = record;
02631
02632 TREE_CHAIN (record) = type_decl;
02633 TYPE_NAME (record) = type_decl;
02634 TYPE_FIELDS (record) = f_gpr;
02635 TREE_CHAIN (f_gpr) = f_fpr;
02636 TREE_CHAIN (f_fpr) = f_ovf;
02637 TREE_CHAIN (f_ovf) = f_sav;
02638
02639 layout_type (record);
02640
02641
02642 return build_array_type (record, build_index_type (size_zero_node));
02643 }
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659 void
02660 ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
02661 CUMULATIVE_ARGS *cum;
02662 enum machine_mode mode;
02663 tree type;
02664 int *pretend_size ATTRIBUTE_UNUSED;
02665 int no_rtl;
02666
02667 {
02668 CUMULATIVE_ARGS next_cum;
02669 rtx save_area = NULL_RTX, mem;
02670 rtx label;
02671 rtx label_ref;
02672 rtx tmp_reg;
02673 rtx nsse_reg;
02674 int set;
02675 tree fntype;
02676 int stdarg_p;
02677 int i;
02678
02679 if (!TARGET_64BIT)
02680 return;
02681
02682
02683 ix86_save_varrargs_registers = 1;
02684
02685 cfun->stack_alignment_needed = 128;
02686
02687 fntype = TREE_TYPE (current_function_decl);
02688 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
02689 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
02690 != void_type_node));
02691
02692
02693
02694 next_cum = *cum;
02695 if (stdarg_p)
02696 function_arg_advance (&next_cum, mode, type, 1);
02697
02698 if (!no_rtl)
02699 save_area = frame_pointer_rtx;
02700
02701 set = get_varargs_alias_set ();
02702
02703 for (i = next_cum.regno; i < ix86_regparm; i++)
02704 {
02705 mem = gen_rtx_MEM (Pmode,
02706 plus_constant (save_area, i * UNITS_PER_WORD));
02707 set_mem_alias_set (mem, set);
02708 emit_move_insn (mem, gen_rtx_REG (Pmode,
02709 x86_64_int_parameter_registers[i]));
02710 }
02711
02712 if (next_cum.sse_nregs)
02713 {
02714
02715
02716
02717
02718
02719 label = gen_label_rtx ();
02720 label_ref = gen_rtx_LABEL_REF (Pmode, label);
02721
02722
02723
02724 tmp_reg = gen_reg_rtx (Pmode);
02725 nsse_reg = gen_reg_rtx (Pmode);
02726 emit_insn (gen_zero_extendqidi2 (nsse_reg, gen_rtx_REG (QImode, 0)));
02727 emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
02728 gen_rtx_MULT (Pmode, nsse_reg,
02729 GEN_INT (4))));
02730 if (next_cum.sse_regno)
02731 emit_move_insn
02732 (nsse_reg,
02733 gen_rtx_CONST (DImode,
02734 gen_rtx_PLUS (DImode,
02735 label_ref,
02736 GEN_INT (next_cum.sse_regno * 4))));
02737 else
02738 emit_move_insn (nsse_reg, label_ref);
02739 emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
02740
02741
02742
02743
02744 tmp_reg = gen_reg_rtx (Pmode);
02745 emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
02746 plus_constant (save_area,
02747 8 * REGPARM_MAX + 127)));
02748 mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127));
02749 set_mem_alias_set (mem, set);
02750 set_mem_align (mem, BITS_PER_WORD);
02751
02752
02753 emit_insn (gen_sse_prologue_save (mem, nsse_reg,
02754 GEN_INT (next_cum.sse_regno), label));
02755 }
02756
02757 }
02758
02759
02760
02761 void
02762 ix86_va_start (valist, nextarg)
02763 tree valist;
02764 rtx nextarg;
02765 {
02766 HOST_WIDE_INT words, n_gpr, n_fpr;
02767 tree f_gpr, f_fpr, f_ovf, f_sav;
02768 tree gpr, fpr, ovf, sav, t;
02769
02770
02771 if (!TARGET_64BIT)
02772 {
02773 std_expand_builtin_va_start (valist, nextarg);
02774 return;
02775 }
02776
02777 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
02778 f_fpr = TREE_CHAIN (f_gpr);
02779 f_ovf = TREE_CHAIN (f_fpr);
02780 f_sav = TREE_CHAIN (f_ovf);
02781
02782 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
02783 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
02784 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
02785 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
02786 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
02787
02788
02789 words = current_function_args_info.words;
02790 n_gpr = current_function_args_info.regno;
02791 n_fpr = current_function_args_info.sse_regno;
02792
02793 if (TARGET_DEBUG_ARG)
02794 fprintf (stderr, "va_start: words = %d, n_gpr = %d, n_fpr = %d\n",
02795 (int) words, (int) n_gpr, (int) n_fpr);
02796
02797 t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
02798 build_int_2 (n_gpr * 8, 0));
02799 TREE_SIDE_EFFECTS (t) = 1;
02800 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02801
02802 t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
02803 build_int_2 (n_fpr * 16 + 8*REGPARM_MAX, 0));
02804 TREE_SIDE_EFFECTS (t) = 1;
02805 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02806
02807
02808 t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
02809 if (words != 0)
02810 t = build (PLUS_EXPR, TREE_TYPE (ovf), t,
02811 build_int_2 (words * UNITS_PER_WORD, 0));
02812 t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
02813 TREE_SIDE_EFFECTS (t) = 1;
02814 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02815
02816
02817
02818 t = make_tree (TREE_TYPE (sav), frame_pointer_rtx);
02819 t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
02820 TREE_SIDE_EFFECTS (t) = 1;
02821 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02822 }
02823
02824
02825 rtx
02826 ix86_va_arg (valist, type)
02827 tree valist, type;
02828 {
02829 static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
02830 tree f_gpr, f_fpr, f_ovf, f_sav;
02831 tree gpr, fpr, ovf, sav, t;
02832 int size, rsize;
02833 rtx lab_false, lab_over = NULL_RTX;
02834 rtx addr_rtx, r;
02835 rtx container;
02836 int indirect_p = 0;
02837
02838
02839 if (!TARGET_64BIT)
02840 {
02841 return std_expand_builtin_va_arg (valist, type);
02842 }
02843
02844 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
02845 f_fpr = TREE_CHAIN (f_gpr);
02846 f_ovf = TREE_CHAIN (f_fpr);
02847 f_sav = TREE_CHAIN (f_ovf);
02848
02849 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
02850 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
02851 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
02852 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
02853 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
02854
02855 size = int_size_in_bytes (type);
02856 if (size == -1)
02857 {
02858
02859 indirect_p = 1;
02860 type = build_pointer_type (type);
02861 size = int_size_in_bytes (type);
02862 }
02863 rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
02864
02865 container = construct_container (TYPE_MODE (type), type, 0,
02866 REGPARM_MAX, SSE_REGPARM_MAX, intreg, 0);
02867
02868
02869
02870
02871 addr_rtx = gen_reg_rtx (Pmode);
02872
02873 if (container)
02874 {
02875 rtx int_addr_rtx, sse_addr_rtx;
02876 int needed_intregs, needed_sseregs;
02877 int need_temp;
02878
02879 lab_over = gen_label_rtx ();
02880 lab_false = gen_label_rtx ();
02881
02882 examine_argument (TYPE_MODE (type), type, 0,
02883 &needed_intregs, &needed_sseregs);
02884
02885
02886 need_temp = ((needed_intregs && TYPE_ALIGN (type) > 64)
02887 || TYPE_ALIGN (type) > 128);
02888
02889
02890
02891 if (!need_temp && !REG_P (container))
02892 {
02893
02894 if (SSE_REGNO_P (REGNO (XEXP (XVECEXP (container, 0, 0), 0))))
02895 {
02896 int i;
02897
02898 for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
02899 {
02900 rtx slot = XVECEXP (container, 0, i);
02901 if (REGNO (XEXP (slot, 0)) != FIRST_SSE_REG + (unsigned int) i
02902 || INTVAL (XEXP (slot, 1)) != i * 16)
02903 need_temp = 1;
02904 }
02905 }
02906 else
02907 {
02908 int i;
02909
02910 for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
02911 {
02912 rtx slot = XVECEXP (container, 0, i);
02913 if (REGNO (XEXP (slot, 0)) != (unsigned int) i
02914 || INTVAL (XEXP (slot, 1)) != i * 8)
02915 need_temp = 1;
02916 }
02917 }
02918 }
02919 if (!need_temp)
02920 {
02921 int_addr_rtx = addr_rtx;
02922 sse_addr_rtx = addr_rtx;
02923 }
02924 else
02925 {
02926 int_addr_rtx = gen_reg_rtx (Pmode);
02927 sse_addr_rtx = gen_reg_rtx (Pmode);
02928 }
02929
02930 if (needed_intregs)
02931 {
02932 emit_cmp_and_jump_insns (expand_expr
02933 (gpr, NULL_RTX, SImode, EXPAND_NORMAL),
02934 GEN_INT ((REGPARM_MAX - needed_intregs +
02935 1) * 8), GE, const1_rtx, SImode,
02936 1, lab_false);
02937 }
02938 if (needed_sseregs)
02939 {
02940 emit_cmp_and_jump_insns (expand_expr
02941 (fpr, NULL_RTX, SImode, EXPAND_NORMAL),
02942 GEN_INT ((SSE_REGPARM_MAX -
02943 needed_sseregs + 1) * 16 +
02944 REGPARM_MAX * 8), GE, const1_rtx,
02945 SImode, 1, lab_false);
02946 }
02947
02948
02949 if (needed_intregs)
02950 {
02951 t = build (PLUS_EXPR, ptr_type_node, sav, gpr);
02952 r = expand_expr (t, int_addr_rtx, Pmode, EXPAND_NORMAL);
02953 if (r != int_addr_rtx)
02954 emit_move_insn (int_addr_rtx, r);
02955 }
02956 if (needed_sseregs)
02957 {
02958 t = build (PLUS_EXPR, ptr_type_node, sav, fpr);
02959 r = expand_expr (t, sse_addr_rtx, Pmode, EXPAND_NORMAL);
02960 if (r != sse_addr_rtx)
02961 emit_move_insn (sse_addr_rtx, r);
02962 }
02963 if (need_temp)
02964 {
02965 int i;
02966 rtx mem;
02967 rtx x;
02968
02969
02970 x = XEXP (assign_temp (type, 0, 1, 0), 0);
02971 mem = gen_rtx_MEM (BLKmode, x);
02972 force_operand (x, addr_rtx);
02973 set_mem_alias_set (mem, get_varargs_alias_set ());
02974 set_mem_align (mem, BITS_PER_UNIT);
02975
02976 for (i = 0; i < XVECLEN (container, 0); i++)
02977 {
02978 rtx slot = XVECEXP (container, 0, i);
02979 rtx reg = XEXP (slot, 0);
02980 enum machine_mode mode = GET_MODE (reg);
02981 rtx src_addr;
02982 rtx src_mem;
02983 int src_offset;
02984 rtx dest_mem;
02985
02986 if (SSE_REGNO_P (REGNO (reg)))
02987 {
02988 src_addr = sse_addr_rtx;
02989 src_offset = (REGNO (reg) - FIRST_SSE_REG) * 16;
02990 }
02991 else
02992 {
02993 src_addr = int_addr_rtx;
02994 src_offset = REGNO (reg) * 8;
02995 }
02996 src_mem = gen_rtx_MEM (mode, src_addr);
02997 set_mem_alias_set (src_mem, get_varargs_alias_set ());
02998 src_mem = adjust_address (src_mem, mode, src_offset);
02999 dest_mem = adjust_address (mem, mode, INTVAL (XEXP (slot, 1)));
03000 emit_move_insn (dest_mem, src_mem);
03001 }
03002 }
03003
03004 if (needed_intregs)
03005 {
03006 t =
03007 build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
03008 build_int_2 (needed_intregs * 8, 0));
03009 t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
03010 TREE_SIDE_EFFECTS (t) = 1;
03011 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03012 }
03013 if (needed_sseregs)
03014 {
03015 t =
03016 build (PLUS_EXPR, TREE_TYPE (fpr), fpr,
03017 build_int_2 (needed_sseregs * 16, 0));
03018 t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t);
03019 TREE_SIDE_EFFECTS (t) = 1;
03020 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03021 }
03022
03023 emit_jump_insn (gen_jump (lab_over));
03024 emit_barrier ();
03025 emit_label (lab_false);
03026 }
03027
03028
03029
03030
03031 if (FUNCTION_ARG_BOUNDARY (VOIDmode, type) <= 64)
03032 t = ovf;
03033 else
03034 {
03035 HOST_WIDE_INT align = FUNCTION_ARG_BOUNDARY (VOIDmode, type) / 8;
03036 t = build (PLUS_EXPR, TREE_TYPE (ovf), ovf, build_int_2 (align - 1, 0));
03037 t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
03038 }
03039 t = save_expr (t);
03040
03041 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
03042 if (r != addr_rtx)
03043 emit_move_insn (addr_rtx, r);
03044
03045 t =
03046 build (PLUS_EXPR, TREE_TYPE (t), t,
03047 build_int_2 (rsize * UNITS_PER_WORD, 0));
03048 t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
03049 TREE_SIDE_EFFECTS (t) = 1;
03050 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03051
03052 if (container)
03053 emit_label (lab_over);
03054
03055 if (indirect_p)
03056 {
03057 r = gen_rtx_MEM (Pmode, addr_rtx);
03058 set_mem_alias_set (r, get_varargs_alias_set ());
03059 emit_move_insn (addr_rtx, r);
03060 }
03061
03062 return addr_rtx;
03063 }
03064
03065
03066 int
03067 any_fp_register_operand (op, mode)
03068 rtx op;
03069 enum machine_mode mode ATTRIBUTE_UNUSED;
03070 {
03071 return ANY_FP_REG_P (op);
03072 }
03073
03074
03075 int
03076 fp_register_operand (op, mode)
03077 rtx op;
03078 enum machine_mode mode ATTRIBUTE_UNUSED;
03079 {
03080 return FP_REG_P (op);
03081 }
03082
03083
03084 int
03085 register_and_not_any_fp_reg_operand (op, mode)
03086 rtx op;
03087 enum machine_mode mode;
03088 {
03089 return register_operand (op, mode) && !ANY_FP_REG_P (op);
03090 }
03091
03092
03093
03094 int
03095 register_and_not_fp_reg_operand (op, mode)
03096 rtx op;
03097 enum machine_mode mode;
03098 {
03099 return register_operand (op, mode) && !FP_REG_P (op);
03100 }
03101
03102
03103
03104 int
03105 x86_64_general_operand (op, mode)
03106 rtx op;
03107 enum machine_mode mode;
03108 {
03109 if (!TARGET_64BIT)
03110 return general_operand (op, mode);
03111 if (nonimmediate_operand (op, mode))
03112 return 1;
03113 return x86_64_sign_extended_value (op);
03114 }
03115
03116
03117
03118
03119 int
03120 x86_64_szext_general_operand (op, mode)
03121 rtx op;
03122 enum machine_mode mode;
03123 {
03124 if (!TARGET_64BIT)
03125 return general_operand (op, mode);
03126 if (nonimmediate_operand (op, mode))
03127 return 1;
03128 return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
03129 }
03130
03131
03132
03133 int
03134 x86_64_nonmemory_operand (op, mode)
03135 rtx op;
03136 enum machine_mode mode;
03137 {
03138 if (!TARGET_64BIT)
03139 return nonmemory_operand (op, mode);
03140 if (register_operand (op, mode))
03141 return 1;
03142 return x86_64_sign_extended_value (op);
03143 }
03144
03145
03146
03147 int
03148 x86_64_movabs_operand (op, mode)
03149 rtx op;
03150 enum machine_mode mode;
03151 {
03152 if (!TARGET_64BIT || !flag_pic)
03153 return nonmemory_operand (op, mode);
03154 if (register_operand (op, mode) || x86_64_sign_extended_value (op))
03155 return 1;
03156 if (CONSTANT_P (op) && !symbolic_reference_mentioned_p (op))
03157 return 1;
03158 return 0;
03159 }
03160
03161
03162
03163
03164 int
03165 ix86_check_movabs (insn, opnum)
03166 rtx insn;
03167 int opnum;
03168 {
03169 rtx set, mem;
03170
03171 set = PATTERN (insn);
03172 if (GET_CODE (set) == PARALLEL)
03173 set = XVECEXP (set, 0, 0);
03174 if (GET_CODE (set) != SET)
03175 abort ();
03176 mem = XEXP (set, opnum);
03177 while (GET_CODE (mem) == SUBREG)
03178 mem = SUBREG_REG (mem);
03179 if (GET_CODE (mem) != MEM)
03180 abort ();
03181 return (volatile_ok || !MEM_VOLATILE_P (mem));
03182 }
03183
03184
03185
03186 int
03187 x86_64_szext_nonmemory_operand (op, mode)
03188 rtx op;
03189 enum machine_mode mode;
03190 {
03191 if (!TARGET_64BIT)
03192 return nonmemory_operand (op, mode);
03193 if (register_operand (op, mode))
03194 return 1;
03195 return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
03196 }
03197
03198
03199
03200 int
03201 x86_64_immediate_operand (op, mode)
03202 rtx op;
03203 enum machine_mode mode;
03204 {
03205 if (!TARGET_64BIT)
03206 return immediate_operand (op, mode);
03207 return x86_64_sign_extended_value (op);
03208 }
03209
03210
03211
03212 int
03213 x86_64_zext_immediate_operand (op, mode)
03214 rtx op;
03215 enum machine_mode mode ATTRIBUTE_UNUSED;
03216 {
03217 return x86_64_zero_extended_value (op);
03218 }
03219
03220
03221
03222 int
03223 const_int_1_operand (op, mode)
03224 rtx op;
03225 enum machine_mode mode ATTRIBUTE_UNUSED;
03226 {
03227 return (GET_CODE (op) == CONST_INT && INTVAL (op) == 1);
03228 }
03229
03230
03231
03232
03233
03234 int
03235 const_int_1_31_operand (op, mode)
03236 rtx op;
03237 enum machine_mode mode ATTRIBUTE_UNUSED;
03238 {
03239 return (GET_CODE (op) == CONST_INT && INTVAL (op) >= 1 && INTVAL (op) <= 31);
03240 }
03241
03242
03243
03244
03245 int
03246 symbolic_operand (op, mode)
03247 register rtx op;
03248 enum machine_mode mode ATTRIBUTE_UNUSED;
03249 {
03250 switch (GET_CODE (op))
03251 {
03252 case SYMBOL_REF:
03253 case LABEL_REF:
03254 return 1;
03255
03256 case CONST:
03257 op = XEXP (op, 0);
03258 if (GET_CODE (op) == SYMBOL_REF
03259 || GET_CODE (op) == LABEL_REF
03260 || (GET_CODE (op) == UNSPEC
03261 && (XINT (op, 1) == UNSPEC_GOT
03262 || XINT (op, 1) == UNSPEC_GOTOFF
03263 || XINT (op, 1) == UNSPEC_GOTPCREL)))
03264 return 1;
03265 if (GET_CODE (op) != PLUS
03266 || GET_CODE (XEXP (op, 1)) != CONST_INT)
03267 return 0;
03268
03269 op = XEXP (op, 0);
03270 if (GET_CODE (op) == SYMBOL_REF
03271 || GET_CODE (op) == LABEL_REF)
03272 return 1;
03273
03274 if (GET_CODE (op) != UNSPEC
03275 || XINT (op, 1) != UNSPEC_GOTOFF)
03276 return 0;
03277
03278 op = XVECEXP (op, 0, 0);
03279 if (GET_CODE (op) == SYMBOL_REF
03280 || GET_CODE (op) == LABEL_REF)
03281 return 1;
03282 return 0;
03283
03284 default:
03285 return 0;
03286 }
03287 }
03288
03289
03290
03291 int
03292 pic_symbolic_operand (op, mode)
03293 register rtx op;
03294 enum machine_mode mode ATTRIBUTE_UNUSED;
03295 {
03296 if (GET_CODE (op) != CONST)
03297 return 0;
03298 op = XEXP (op, 0);
03299 if (TARGET_64BIT)
03300 {
03301 if (GET_CODE (XEXP (op, 0)) == UNSPEC)
03302 return 1;
03303 }
03304 else
03305 {
03306 if (GET_CODE (op) == UNSPEC)
03307 return 1;
03308 if (GET_CODE (op) != PLUS
03309 || GET_CODE (XEXP (op, 1)) != CONST_INT)
03310 return 0;
03311 op = XEXP (op, 0);
03312 if (GET_CODE (op) == UNSPEC)
03313 return 1;
03314 }
03315 return 0;
03316 }
03317
03318
03319
03320 static int
03321 local_symbolic_operand (op, mode)
03322 rtx op;
03323 enum machine_mode mode ATTRIBUTE_UNUSED;
03324 {
03325 if (GET_CODE (op) == CONST
03326 && GET_CODE (XEXP (op, 0)) == PLUS
03327 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
03328 op = XEXP (XEXP (op, 0), 0);
03329
03330 if (GET_CODE (op) == LABEL_REF)
03331 return 1;
03332
03333 if (GET_CODE (op) != SYMBOL_REF)
03334 return 0;
03335
03336
03337
03338 if (CONSTANT_POOL_ADDRESS_P (op) || SYMBOL_REF_FLAG (op))
03339 return 1;
03340
03341
03342
03343
03344
03345
03346 if (strncmp (XSTR (op, 0), internal_label_prefix,
03347 internal_label_prefix_len) == 0)
03348 return 1;
03349
03350 return 0;
03351 }
03352
03353
03354
03355 int
03356 tls_symbolic_operand (op, mode)
03357 register rtx op;
03358 enum machine_mode mode ATTRIBUTE_UNUSED;
03359 {
03360 const char *symbol_str;
03361
03362 if (GET_CODE (op) != SYMBOL_REF)
03363 return 0;
03364 symbol_str = XSTR (op, 0);
03365
03366 if (symbol_str[0] != '%')
03367 return 0;
03368 return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;
03369 }
03370
03371 static int
03372 tls_symbolic_operand_1 (op, kind)
03373 rtx op;
03374 enum tls_model kind;
03375 {
03376 const char *symbol_str;
03377
03378 if (GET_CODE (op) != SYMBOL_REF)
03379 return 0;
03380 symbol_str = XSTR (op, 0);
03381
03382 return symbol_str[0] == '%' && symbol_str[1] == tls_model_chars[kind];
03383 }
03384
03385 int
03386 global_dynamic_symbolic_operand (op, mode)
03387 register rtx op;
03388 enum machine_mode mode ATTRIBUTE_UNUSED;
03389 {
03390 return tls_symbolic_operand_1 (op, TLS_MODEL_GLOBAL_DYNAMIC);
03391 }
03392
03393 int
03394 local_dynamic_symbolic_operand (op, mode)
03395 register rtx op;
03396 enum machine_mode mode ATTRIBUTE_UNUSED;
03397 {
03398 return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_DYNAMIC);
03399 }
03400
03401 int
03402 initial_exec_symbolic_operand (op, mode)
03403 register rtx op;
03404 enum machine_mode mode ATTRIBUTE_UNUSED;
03405 {
03406 return tls_symbolic_operand_1 (op, TLS_MODEL_INITIAL_EXEC);
03407 }
03408
03409 int
03410 local_exec_symbolic_operand (op, mode)
03411 register rtx op;
03412 enum machine_mode mode ATTRIBUTE_UNUSED;
03413 {
03414 return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_EXEC);
03415 }
03416
03417
03418
03419
03420
03421 int
03422 call_insn_operand (op, mode)
03423 rtx op;
03424 enum machine_mode mode ATTRIBUTE_UNUSED;
03425 {
03426
03427
03428 if (GET_CODE (op) == REG
03429 && (op == arg_pointer_rtx
03430 || op == frame_pointer_rtx
03431 || (REGNO (op) >= FIRST_PSEUDO_REGISTER
03432 && REGNO (op) <= LAST_VIRTUAL_REGISTER)))
03433 return 0;
03434
03435
03436
03437 if (GET_CODE (op) == CONST_INT)
03438 return 0;
03439
03440
03441 if (GET_CODE (op) == SYMBOL_REF)
03442 return 1;
03443
03444
03445 return general_operand (op, Pmode);
03446 }
03447
03448 int
03449 constant_call_address_operand (op, mode)
03450 rtx op;
03451 enum machine_mode mode ATTRIBUTE_UNUSED;
03452 {
03453 if (GET_CODE (op) == CONST
03454 && GET_CODE (XEXP (op, 0)) == PLUS
03455 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
03456 op = XEXP (XEXP (op, 0), 0);
03457 return GET_CODE (op) == SYMBOL_REF;
03458 }
03459
03460
03461
03462 int
03463 const0_operand (op, mode)
03464 register rtx op;
03465 enum machine_mode mode;
03466 {
03467 return op == CONST0_RTX (mode);
03468 }
03469
03470 int
03471 const1_operand (op, mode)
03472 register rtx op;
03473 enum machine_mode mode ATTRIBUTE_UNUSED;
03474 {
03475 return op == const1_rtx;
03476 }
03477
03478
03479
03480 int
03481 const248_operand (op, mode)
03482 register rtx op;
03483 enum machine_mode mode ATTRIBUTE_UNUSED;
03484 {
03485 return (GET_CODE (op) == CONST_INT
03486 && (INTVAL (op) == 2 || INTVAL (op) == 4 || INTVAL (op) == 8));
03487 }
03488
03489
03490
03491 int
03492 incdec_operand (op, mode)
03493 register rtx op;
03494 enum machine_mode mode ATTRIBUTE_UNUSED;
03495 {
03496
03497
03498 if (TARGET_PENTIUM4 && !optimize_size)
03499 return 0;
03500 return op == const1_rtx || op == constm1_rtx;
03501 }
03502
03503
03504
03505
03506 int
03507 shiftdi_operand (op, mode)
03508 rtx op;
03509 enum machine_mode mode ATTRIBUTE_UNUSED;
03510 {
03511 if (TARGET_64BIT)
03512 return nonimmediate_operand (op, mode);
03513 else
03514 return register_operand (op, mode);
03515 }
03516
03517
03518
03519
03520
03521
03522
03523
03524 int
03525 reg_no_sp_operand (op, mode)
03526 register rtx op;
03527 enum machine_mode mode;
03528 {
03529 rtx t = op;
03530 if (GET_CODE (t) == SUBREG)
03531 t = SUBREG_REG (t);
03532 if (t == stack_pointer_rtx || t == arg_pointer_rtx || t == frame_pointer_rtx)
03533 return 0;
03534
03535 return register_operand (op, mode);
03536 }
03537
03538 int
03539 mmx_reg_operand (op, mode)
03540 register rtx op;
03541 enum machine_mode mode ATTRIBUTE_UNUSED;
03542 {
03543 return MMX_REG_P (op);
03544 }
03545
03546
03547
03548
03549 int
03550 general_no_elim_operand (op, mode)
03551 register rtx op;
03552 enum machine_mode mode;
03553 {
03554 rtx t = op;
03555 if (GET_CODE (t) == SUBREG)
03556 t = SUBREG_REG (t);
03557 if (t == arg_pointer_rtx || t == frame_pointer_rtx
03558 || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
03559 || t == virtual_stack_dynamic_rtx)
03560 return 0;
03561 if (REG_P (t)
03562 && REGNO (t) >= FIRST_VIRTUAL_REGISTER
03563 && REGNO (t) <= LAST_VIRTUAL_REGISTER)
03564 return 0;
03565
03566 return general_operand (op, mode);
03567 }
03568
03569
03570
03571
03572 int
03573 nonmemory_no_elim_operand (op, mode)
03574 register rtx op;
03575 enum machine_mode mode;
03576 {
03577 rtx t = op;
03578 if (GET_CODE (t) == SUBREG)
03579 t = SUBREG_REG (t);
03580 if (t == arg_pointer_rtx || t == frame_pointer_rtx
03581 || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
03582 || t == virtual_stack_dynamic_rtx)
03583 return 0;
03584
03585 return GET_CODE (op) == CONST_INT || register_operand (op, mode);
03586 }
03587
03588
03589
03590
03591 int
03592 index_register_operand (op, mode)
03593 register rtx op;
03594 enum machine_mode mode;
03595 {
03596 rtx t = op;
03597 if (GET_CODE (t) == SUBREG)
03598 t = SUBREG_REG (t);
03599 if (!REG_P (t))
03600 return 0;
03601 if (t == arg_pointer_rtx
03602 || t == frame_pointer_rtx
03603 || t == virtual_incoming_args_rtx
03604 || t == virtual_stack_vars_rtx
03605 || t == virtual_stack_dynamic_rtx
03606 || REGNO (t) == STACK_POINTER_REGNUM)
03607 return 0;
03608
03609 return general_operand (op, mode);
03610 }
03611
03612
03613
03614 int
03615 q_regs_operand (op, mode)
03616 register rtx op;
03617 enum machine_mode mode;
03618 {
03619 if (mode != VOIDmode && GET_MODE (op) != mode)
03620 return 0;
03621 if (GET_CODE (op) == SUBREG)
03622 op = SUBREG_REG (op);
03623 return ANY_QI_REG_P (op);
03624 }
03625
03626
03627
03628 int
03629 non_q_regs_operand (op, mode)
03630 register rtx op;
03631 enum machine_mode mode;
03632 {
03633 if (mode != VOIDmode && GET_MODE (op) != mode)
03634 return 0;
03635 if (GET_CODE (op) == SUBREG)
03636 op = SUBREG_REG (op);
03637 return NON_QI_REG_P (op);
03638 }
03639
03640
03641 int
03642 vector_move_operand (op, mode)
03643 rtx op;
03644 enum machine_mode mode;
03645 {
03646 if (nonimmediate_operand (op, mode))
03647 return 1;
03648 if (GET_MODE (op) != mode && mode != VOIDmode)
03649 return 0;
03650 return (op == CONST0_RTX (GET_MODE (op)));
03651 }
03652
03653
03654
03655
03656 int
03657 no_seg_address_operand (op, mode)
03658 register rtx op;
03659 enum machine_mode mode;
03660 {
03661 struct ix86_address parts;
03662
03663 if (! address_operand (op, mode))
03664 return 0;
03665
03666 if (! ix86_decompose_address (op, &parts))
03667 abort ();
03668
03669 return parts.seg == SEG_DEFAULT;
03670 }
03671
03672
03673
03674 int
03675 sse_comparison_operator (op, mode)
03676 rtx op;
03677 enum machine_mode mode ATTRIBUTE_UNUSED;
03678 {
03679 enum rtx_code code = GET_CODE (op);
03680 switch (code)
03681 {
03682
03683 case EQ:
03684 case LT:
03685 case LE:
03686 case UNORDERED:
03687 case NE:
03688 case UNGE:
03689 case UNGT:
03690 case ORDERED:
03691 return 1;
03692
03693 case UNEQ:
03694 case UNLT:
03695 case UNLE:
03696 case LTGT:
03697 case GE:
03698 case GT:
03699 return !TARGET_IEEE_FP;
03700 default:
03701 return 0;
03702 }
03703 }
03704
03705 int
03706 ix86_comparison_operator (op, mode)
03707 register rtx op;
03708 enum machine_mode mode;
03709 {
03710 enum machine_mode inmode;
03711 enum rtx_code code = GET_CODE (op);
03712 if (mode != VOIDmode && GET_MODE (op) != mode)
03713 return 0;
03714 if (GET_RTX_CLASS (code) != '<')
03715 return 0;
03716 inmode = GET_MODE (XEXP (op, 0));
03717
03718 if (inmode == CCFPmode || inmode == CCFPUmode)
03719 {
03720 enum rtx_code second_code, bypass_code;
03721 ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
03722 return (bypass_code == NIL && second_code == NIL);
03723 }
03724 switch (code)
03725 {
03726 case EQ: case NE:
03727 return 1;
03728 case LT: case GE:
03729 if (inmode == CCmode || inmode == CCGCmode
03730 || inmode == CCGOCmode || inmode == CCNOmode)
03731 return 1;
03732 return 0;
03733 case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
03734 if (inmode == CCmode)
03735 return 1;
03736 return 0;
03737 case GT: case LE:
03738 if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
03739 return 1;
03740 return 0;
03741 default:
03742 return 0;
03743 }
03744 }
03745
03746
03747
03748 int
03749 fcmov_comparison_operator (op, mode)
03750 register rtx op;
03751 enum machine_mode mode;
03752 {
03753 enum machine_mode inmode;
03754 enum rtx_code code = GET_CODE (op);
03755 if (mode != VOIDmode && GET_MODE (op) != mode)
03756 return 0;
03757 if (GET_RTX_CLASS (code) != '<')
03758 return 0;
03759 inmode = GET_MODE (XEXP (op, 0));
03760 if (inmode == CCFPmode || inmode == CCFPUmode)
03761 {
03762 enum rtx_code second_code, bypass_code;
03763 ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
03764 if (bypass_code != NIL || second_code != NIL)
03765 return 0;
03766 code = ix86_fp_compare_code_to_integer (code);
03767 }
03768
03769 switch (code)
03770 {
03771 case LTU: case GTU: case LEU: case GEU:
03772 if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
03773 return 1;
03774 return 0;
03775 case ORDERED: case UNORDERED:
03776 case EQ: case NE:
03777 return 1;
03778 default:
03779 return 0;
03780 }
03781 }
03782
03783
03784
03785 int
03786 promotable_binary_operator (op, mode)
03787 register rtx op;
03788 enum machine_mode mode ATTRIBUTE_UNUSED;
03789 {
03790 switch (GET_CODE (op))
03791 {
03792 case MULT:
03793
03794
03795 return ix86_cpu > PROCESSOR_I486;
03796 case PLUS:
03797 case AND:
03798 case IOR:
03799 case XOR:
03800 case ASHIFT:
03801 return 1;
03802 default:
03803 return 0;
03804 }
03805 }
03806
03807
03808
03809
03810
03811 int
03812 cmp_fp_expander_operand (op, mode)
03813 register rtx op;
03814 enum machine_mode mode;
03815 {
03816 if (mode != VOIDmode && mode != GET_MODE (op))
03817 return 0;
03818 if (GET_CODE (op) == CONST_DOUBLE)
03819 return 1;
03820 return general_operand (op, mode);
03821 }
03822
03823
03824
03825 int
03826 ext_register_operand (op, mode)
03827 register rtx op;
03828 enum machine_mode mode ATTRIBUTE_UNUSED;
03829 {
03830 int regno;
03831 if ((!TARGET_64BIT || GET_MODE (op) != DImode)
03832 && GET_MODE (op) != SImode && GET_MODE (op) != HImode)
03833 return 0;
03834
03835 if (!register_operand (op, VOIDmode))
03836 return 0;
03837
03838
03839 regno = REG_P (op) ? REGNO (op) : REGNO (SUBREG_REG (op));
03840 return (regno > LAST_VIRTUAL_REGISTER || regno < 4);
03841 }
03842
03843
03844
03845
03846 int
03847 binary_fp_operator (op, mode)
03848 register rtx op;
03849 enum machine_mode mode;
03850 {
03851 if (mode != VOIDmode && mode != GET_MODE (op))
03852 return 0;
03853
03854 switch (GET_CODE (op))
03855 {
03856 case PLUS:
03857 case MINUS:
03858 case MULT:
03859 case DIV:
03860 return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
03861
03862 default:
03863 return 0;
03864 }
03865 }
03866
03867 int
03868 mult_operator (op, mode)
03869 register rtx op;
03870 enum machine_mode mode ATTRIBUTE_UNUSED;
03871 {
03872 return GET_CODE (op) == MULT;
03873 }
03874
03875 int
03876 div_operator (op, mode)
03877 register rtx op;
03878 enum machine_mode mode ATTRIBUTE_UNUSED;
03879 {
03880 return GET_CODE (op) == DIV;
03881 }
03882
03883 int
03884 arith_or_logical_operator (op, mode)
03885 rtx op;
03886 enum machine_mode mode;
03887 {
03888 return ((mode == VOIDmode || GET_MODE (op) == mode)
03889 && (GET_RTX_CLASS (GET_CODE (op)) == 'c'
03890 || GET_RTX_CLASS (GET_CODE (op)) == '2'));
03891 }
03892
03893
03894
03895 int
03896 memory_displacement_operand (op, mode)
03897 register rtx op;
03898 enum machine_mode mode;
03899 {
03900 struct ix86_address parts;
03901
03902 if (! memory_operand (op, mode))
03903 return 0;
03904
03905 if (! ix86_decompose_address (XEXP (op, 0), &parts))
03906 abort ();
03907
03908 return parts.disp != NULL_RTX;
03909 }
03910
03911
03912
03913
03914
03915
03916
03917 int
03918 cmpsi_operand (op, mode)
03919 rtx op;
03920 enum machine_mode mode;
03921 {
03922 if (nonimmediate_operand (op, mode))
03923 return 1;
03924
03925 if (GET_CODE (op) == AND
03926 && GET_MODE (op) == SImode
03927 && GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT
03928 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
03929 && GET_CODE (XEXP (XEXP (op, 0), 2)) == CONST_INT
03930 && INTVAL (XEXP (XEXP (op, 0), 1)) == 8
03931 && INTVAL (XEXP (XEXP (op, 0), 2)) == 8
03932 && GET_CODE (XEXP (op, 1)) == CONST_INT)
03933 return 1;
03934
03935 return 0;
03936 }
03937
03938
03939
03940
03941 int
03942 long_memory_operand (op, mode)
03943 register rtx op;
03944 enum machine_mode mode;
03945 {
03946 if (! memory_operand (op, mode))
03947 return 0;
03948
03949 return memory_address_length (op) != 0;
03950 }
03951
03952
03953
03954 int
03955 aligned_operand (op, mode)
03956 rtx op;
03957 enum machine_mode mode;
03958 {
03959 struct ix86_address parts;
03960
03961 if (!general_operand (op, mode))
03962 return 0;
03963
03964
03965 if (GET_CODE (op) != MEM)
03966 return 1;
03967
03968
03969 if (MEM_VOLATILE_P (op))
03970 return 0;
03971
03972 op = XEXP (op, 0);
03973
03974
03975 if (GET_CODE (op) == PRE_DEC
03976 || GET_CODE (op) == POST_INC)
03977 return 1;
03978
03979
03980 if (! ix86_decompose_address (op, &parts))
03981 abort ();
03982
03983 if (parts.base && GET_CODE (parts.base) == SUBREG)
03984 parts.base = SUBREG_REG (parts.base);
03985 if (parts.index && GET_CODE (parts.index) == SUBREG)
03986 parts.index = SUBREG_REG (parts.index);
03987
03988
03989 if (parts.index)
03990 {
03991 if (parts.scale < 4
03992 && REGNO_POINTER_ALIGN (REGNO (parts.index)) < 32)
03993 return 0;
03994 }
03995 if (parts.base)
03996 {
03997 if (REGNO_POINTER_ALIGN (REGNO (parts.base)) < 32)
03998 return 0;
03999 }
04000 if (parts.disp)
04001 {
04002 if (GET_CODE (parts.disp) != CONST_INT
04003 || (INTVAL (parts.disp) & 3) != 0)
04004 return 0;
04005 }
04006
04007
04008 return 1;
04009 }
04010
04011
04012
04013
04014
04015 int
04016 standard_80387_constant_p (x)
04017 rtx x;
04018 {
04019 if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x)))
04020 return -1;
04021
04022
04023
04024 if (x == CONST0_RTX (GET_MODE (x)))
04025 return 1;
04026 if (x == CONST1_RTX (GET_MODE (x)))
04027 return 2;
04028 return 0;
04029 }
04030
04031
04032
04033 int
04034 standard_sse_constant_p (x)
04035 rtx x;
04036 {
04037 if (x == const0_rtx)
04038 return 1;
04039 return (x == CONST0_RTX (GET_MODE (x)));
04040 }
04041
04042
04043
04044 int
04045 symbolic_reference_mentioned_p (op)
04046 rtx op;
04047 {
04048 register const char *fmt;
04049 register int i;
04050
04051 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
04052 return 1;
04053
04054 fmt = GET_RTX_FORMAT (GET_CODE (op));
04055 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
04056 {
04057 if (fmt[i] == 'E')
04058 {
04059 register int j;
04060
04061 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
04062 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
04063 return 1;
04064 }
04065
04066 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
04067 return 1;
04068 }
04069
04070 return 0;
04071 }
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085 int
04086 ix86_can_use_return_insn_p ()
04087 {
04088 struct ix86_frame frame;
04089
04090 #ifdef NON_SAVING_SETJMP
04091 if (NON_SAVING_SETJMP && current_function_calls_setjmp)
04092 return 0;
04093 #endif
04094
04095 if (! reload_completed || frame_pointer_needed)
04096 return 0;
04097
04098
04099
04100 if (current_function_pops_args
04101 && current_function_args_size >= 32768)
04102 return 0;
04103
04104 ix86_compute_frame_layout (&frame);
04105 return frame.to_allocate == 0 && frame.nregs == 0;
04106 }
04107
04108
04109 int
04110 x86_64_sign_extended_value (value)
04111 rtx value;
04112 {
04113 switch (GET_CODE (value))
04114 {
04115
04116
04117
04118 case CONST_INT:
04119 if (HOST_BITS_PER_WIDE_INT == 32)
04120 return 1;
04121 else
04122 {
04123 HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (value), DImode);
04124 return trunc_int_for_mode (val, SImode) == val;
04125 }
04126 break;
04127
04128
04129
04130
04131
04132 case SYMBOL_REF:
04133 return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL)
04134 && !tls_symbolic_operand (value, GET_MODE (value));
04135
04136
04137 case LABEL_REF:
04138 return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
04139 || ix86_cmodel == CM_KERNEL);
04140
04141
04142
04143 case CONST:
04144 if (GET_CODE (XEXP (value, 0)) == UNSPEC)
04145 switch (XINT (XEXP (value, 0), 1))
04146 {
04147 case UNSPEC_GOTPCREL:
04148 case UNSPEC_DTPOFF:
04149 case UNSPEC_GOTNTPOFF:
04150 case UNSPEC_NTPOFF:
04151 return 1;
04152 default:
04153 break;
04154 }
04155 if (GET_CODE (XEXP (value, 0)) == PLUS)
04156 {
04157 rtx op1 = XEXP (XEXP (value, 0), 0);
04158 rtx op2 = XEXP (XEXP (value, 0), 1);
04159 HOST_WIDE_INT offset;
04160
04161 if (ix86_cmodel == CM_LARGE)
04162 return 0;
04163 if (GET_CODE (op2) != CONST_INT)
04164 return 0;
04165 offset = trunc_int_for_mode (INTVAL (op2), DImode);
04166 switch (GET_CODE (op1))
04167 {
04168 case SYMBOL_REF:
04169
04170
04171
04172
04173 if (ix86_cmodel == CM_SMALL
04174 && offset < 16*1024*1024
04175 && trunc_int_for_mode (offset, SImode) == offset)
04176 return 1;
04177
04178
04179
04180
04181 if (ix86_cmodel == CM_KERNEL
04182 && offset > 0
04183 && trunc_int_for_mode (offset, SImode) == offset)
04184 return 1;
04185 break;
04186 case LABEL_REF:
04187
04188
04189 if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
04190 && offset < 16*1024*1024
04191 && trunc_int_for_mode (offset, SImode) == offset)
04192 return 1;
04193 if (ix86_cmodel == CM_KERNEL
04194 && offset > 0
04195 && trunc_int_for_mode (offset, SImode) == offset)
04196 return 1;
04197 break;
04198 case UNSPEC:
04199 switch (XINT (op1, 1))
04200 {
04201 case UNSPEC_DTPOFF:
04202 case UNSPEC_NTPOFF:
04203 if (offset > 0
04204 && trunc_int_for_mode (offset, SImode) == offset)
04205 return 1;
04206 }
04207 break;
04208 default:
04209 return 0;
04210 }
04211 }
04212 return 0;
04213 default:
04214 return 0;
04215 }
04216 }
04217
04218
04219 int
04220 x86_64_zero_extended_value (value)
04221 rtx value;
04222 {
04223 switch (GET_CODE (value))
04224 {
04225 case CONST_DOUBLE:
04226 if (HOST_BITS_PER_WIDE_INT == 32)
04227 return (GET_MODE (value) == VOIDmode
04228 && !CONST_DOUBLE_HIGH (value));
04229 else
04230 return 0;
04231 case CONST_INT:
04232 if (HOST_BITS_PER_WIDE_INT == 32)
04233 return INTVAL (value) >= 0;
04234 else
04235 return !(INTVAL (value) & ~(HOST_WIDE_INT) 0xffffffff);
04236 break;
04237
04238
04239
04240 case SYMBOL_REF:
04241 return (ix86_cmodel == CM_SMALL
04242 && !tls_symbolic_operand (value, GET_MODE (value)));
04243
04244
04245 case LABEL_REF:
04246 return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM;
04247
04248
04249
04250 case CONST:
04251 if (GET_CODE (XEXP (value, 0)) == PLUS)
04252 {
04253 rtx op1 = XEXP (XEXP (value, 0), 0);
04254 rtx op2 = XEXP (XEXP (value, 0), 1);
04255
04256 if (ix86_cmodel == CM_LARGE)
04257 return 0;
04258 switch (GET_CODE (op1))
04259 {
04260 case SYMBOL_REF:
04261 return 0;
04262
04263
04264
04265
04266 if (ix86_cmodel == CM_SMALL
04267 && GET_CODE (op2) == CONST_INT
04268 && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
04269 && (trunc_int_for_mode (INTVAL (op2), SImode)
04270 == INTVAL (op2)))
04271 return 1;
04272
04273
04274
04275
04276 break;
04277 case LABEL_REF:
04278
04279
04280 if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
04281 && GET_CODE (op2) == CONST_INT
04282 && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
04283 && (trunc_int_for_mode (INTVAL (op2), SImode)
04284 == INTVAL (op2)))
04285 return 1;
04286 break;
04287 default:
04288 return 0;
04289 }
04290 }
04291 return 0;
04292 default:
04293 return 0;
04294 }
04295 }
04296
04297
04298
04299
04300
04301 int
04302 ix86_frame_pointer_required ()
04303 {
04304
04305
04306 if (cfun->machine->accesses_prev_frame)
04307 return 1;
04308
04309
04310
04311 if (SUBTARGET_FRAME_POINTER_REQUIRED)
04312 return 1;
04313
04314
04315
04316
04317 if (TARGET_OMIT_LEAF_FRAME_POINTER
04318 && (!current_function_is_leaf))
04319 return 1;
04320
04321 if (current_function_profile)
04322 return 1;
04323
04324 return 0;
04325 }
04326
04327
04328
04329 void
04330 ix86_setup_frame_addresses ()
04331 {
04332 cfun->machine->accesses_prev_frame = 1;
04333 }
04334
04335 #if defined(HAVE_GAS_HIDDEN) && (defined(SUPPORTS_ONE_ONLY) && SUPPORTS_ONE_ONLY)
04336 # define USE_HIDDEN_LINKONCE 1
04337 #else
04338 # define USE_HIDDEN_LINKONCE 0
04339 #endif
04340
04341 static int pic_labels_used;
04342
04343
04344
04345
04346 static void
04347 get_pc_thunk_name (name, regno)
04348 char name[32];
04349 unsigned int regno;
04350 {
04351 if (USE_HIDDEN_LINKONCE)
04352 sprintf (name, "__i686.get_pc_thunk.%s", reg_names[regno]);
04353 else
04354 ASM_GENERATE_INTERNAL_LABEL (name, "LPR", regno);
04355 }
04356
04357
04358
04359
04360
04361 void
04362 ix86_asm_file_end (file)
04363 FILE *file;
04364 {
04365 rtx xops[2];
04366 int regno;
04367
04368 for (regno = 0; regno < 8; ++regno)
04369 {
04370 char name[32];
04371
04372 if (! ((pic_labels_used >> regno) & 1))
04373 continue;
04374
04375 get_pc_thunk_name (name, regno);
04376
04377 if (USE_HIDDEN_LINKONCE)
04378 {
04379 tree decl;
04380
04381 decl = build_decl (FUNCTION_DECL, get_identifier (name),
04382 error_mark_node);
04383 TREE_PUBLIC (decl) = 1;
04384 TREE_STATIC (decl) = 1;
04385 DECL_ONE_ONLY (decl) = 1;
04386
04387 (*targetm.asm_out.unique_section) (decl, 0);
04388 named_section (decl, NULL, 0);
04389
04390 (*targetm.asm_out.globalize_label) (file, name);
04391 fputs ("\t.hidden\t", file);
04392 assemble_name (file, name);
04393 fputc ('\n', file);
04394 ASM_DECLARE_FUNCTION_NAME (file, name, decl);
04395 }
04396 else
04397 {
04398 text_section ();
04399 ASM_OUTPUT_LABEL (file, name);
04400 }
04401
04402 xops[0] = gen_rtx_REG (SImode, regno);
04403 xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
04404 output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
04405 output_asm_insn ("ret", xops);
04406 }
04407
04408 #ifdef SUBTARGET_FILE_END
04409 SUBTARGET_FILE_END (file);
04410 #endif
04411 }
04412
04413
04414
04415 const char *
04416 output_set_got (dest)
04417 rtx dest;
04418 {
04419 rtx xops[3];
04420
04421 xops[0] = dest;
04422 xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
04423
04424 if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
04425 {
04426 xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
04427
04428 if (!flag_pic)
04429 output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
04430 else
04431 output_asm_insn ("call\t%a2", xops);
04432
04433 #if TARGET_MACHO
04434
04435
04436 ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
04437 #endif
04438 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
04439 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
04440
04441 if (flag_pic)
04442 output_asm_insn ("pop{l}\t%0", xops);
04443 }
04444 else
04445 {
04446 char name[32];
04447 get_pc_thunk_name (name, REGNO (dest));
04448 pic_labels_used |= 1 << REGNO (dest);
04449
04450 xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
04451 xops[2] = gen_rtx_MEM (QImode, xops[2]);
04452 output_asm_insn ("call\t%X2", xops);
04453 }
04454
04455 if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
04456 output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
04457 else if (!TARGET_MACHO)
04458 output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %a1+(.-%a2)}", xops);
04459
04460 return "";
04461 }
04462
04463
04464
04465 static rtx
04466 gen_push (arg)
04467 rtx arg;
04468 {
04469 return gen_rtx_SET (VOIDmode,
04470 gen_rtx_MEM (Pmode,
04471 gen_rtx_PRE_DEC (Pmode,
04472 stack_pointer_rtx)),
04473 arg);
04474 }
04475
04476
04477
04478
04479 static unsigned int
04480 ix86_select_alt_pic_regnum ()
04481 {
04482 if (current_function_is_leaf && !current_function_profile)
04483 {
04484 int i;
04485 for (i = 2; i >= 0; --i)
04486 if (!regs_ever_live[i])
04487 return i;
04488 }
04489
04490 return INVALID_REGNUM;
04491 }
04492
04493
04494 static int
04495 ix86_save_reg (regno, maybe_eh_return)
04496 unsigned int regno;
04497 int maybe_eh_return;
04498 {
04499 if (pic_offset_table_rtx
04500 && regno == REAL_PIC_OFFSET_TABLE_REGNUM
04501 && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
04502 || current_function_profile
04503 || current_function_calls_eh_return
04504 || current_function_uses_const_pool))
04505 {
04506 if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
04507 return 0;
04508 return 1;
04509 }
04510
04511 if (current_function_calls_eh_return && maybe_eh_return)
04512 {
04513 unsigned i;
04514 for (i = 0; ; i++)
04515 {
04516 unsigned test = EH_RETURN_DATA_REGNO (i);
04517 if (test == INVALID_REGNUM)
04518 break;
04519 if (test == regno)
04520 return 1;
04521 }
04522 }
04523
04524 return (regs_ever_live[regno]
04525 && !call_used_regs[regno]
04526 && !fixed_regs[regno]
04527 && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
04528 }
04529
04530
04531
04532 static int
04533 ix86_nsaved_regs ()
04534 {
04535 int nregs = 0;
04536 int regno;
04537
04538 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
04539 if (ix86_save_reg (regno, true))
04540 nregs++;
04541 return nregs;
04542 }
04543
04544
04545
04546
04547 HOST_WIDE_INT
04548 ix86_initial_elimination_offset (from, to)
04549 int from;
04550 int to;
04551 {
04552 struct ix86_frame frame;
04553 ix86_compute_frame_layout (&frame);
04554
04555 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
04556 return frame.hard_frame_pointer_offset;
04557 else if (from == FRAME_POINTER_REGNUM
04558 && to == HARD_FRAME_POINTER_REGNUM)
04559 return frame.hard_frame_pointer_offset - frame.frame_pointer_offset;
04560 else
04561 {
04562 if (to != STACK_POINTER_REGNUM)
04563 abort ();
04564 else if (from == ARG_POINTER_REGNUM)
04565 return frame.stack_pointer_offset;
04566 else if (from != FRAME_POINTER_REGNUM)
04567 abort ();
04568 else
04569 return frame.stack_pointer_offset - frame.frame_pointer_offset;
04570 }
04571 }
04572
04573
04574
04575 static void
04576 ix86_compute_frame_layout (frame)
04577 struct ix86_frame *frame;
04578 {
04579 HOST_WIDE_INT total_size;
04580 int stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT;
04581 int offset;
04582 int preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT;
04583 HOST_WIDE_INT size = get_frame_size ();
04584
04585 frame->nregs = ix86_nsaved_regs ();
04586 total_size = size;
04587
04588
04589 offset = frame_pointer_needed ? UNITS_PER_WORD * 2 : UNITS_PER_WORD;
04590
04591 frame->hard_frame_pointer_offset = offset;
04592
04593
04594
04595
04596
04597 if (size && !stack_alignment_needed)
04598 abort ();
04599 if (preferred_alignment < STACK_BOUNDARY / BITS_PER_UNIT)
04600 abort ();
04601 if (preferred_alignment > PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
04602 abort ();
04603 if (stack_alignment_needed > PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
04604 abort ();
04605
04606 if (stack_alignment_needed < STACK_BOUNDARY / BITS_PER_UNIT)
04607 stack_alignment_needed = STACK_BOUNDARY / BITS_PER_UNIT;
04608
04609
04610 offset += frame->nregs * UNITS_PER_WORD;
04611
04612
04613 if (ix86_save_varrargs_registers)
04614 {
04615 offset += X86_64_VARARGS_SIZE;
04616 frame->va_arg_size = X86_64_VARARGS_SIZE;
04617 }
04618 else
04619 frame->va_arg_size = 0;
04620
04621
04622 frame->padding1 = ((offset + stack_alignment_needed - 1)
04623 & -stack_alignment_needed) - offset;
04624
04625 offset += frame->padding1;
04626
04627
04628 frame->frame_pointer_offset = offset;
04629
04630 offset += size;
04631
04632
04633
04634 if (ACCUMULATE_OUTGOING_ARGS && !current_function_is_leaf)
04635 {
04636 offset += current_function_outgoing_args_size;
04637 frame->outgoing_arguments_size = current_function_outgoing_args_size;
04638 }
04639 else
04640 frame->outgoing_arguments_size = 0;
04641
04642
04643
04644 if (!current_function_is_leaf || current_function_calls_alloca)
04645 frame->padding2 = ((offset + preferred_alignment - 1)
04646 & -preferred_alignment) - offset;
04647 else
04648 frame->padding2 = 0;
04649
04650 offset += frame->padding2;
04651
04652
04653 frame->stack_pointer_offset = offset;
04654
04655
04656 frame->to_allocate =
04657 (size + frame->padding1 + frame->padding2
04658 + frame->outgoing_arguments_size + frame->va_arg_size);
04659
04660 if (TARGET_64BIT && TARGET_RED_ZONE && current_function_sp_is_unchanging
04661 && current_function_is_leaf)
04662 {
04663 frame->red_zone_size = frame->to_allocate;
04664 if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
04665 frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
04666 }
04667 else
04668 frame->red_zone_size = 0;
04669 frame->to_allocate -= frame->red_zone_size;
04670 frame->stack_pointer_offset -= frame->red_zone_size;
04671 #if 0
04672 fprintf (stderr, "nregs: %i\n", frame->nregs);
04673 fprintf (stderr, "size: %i\n", size);
04674 fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
04675 fprintf (stderr, "padding1: %i\n", frame->padding1);
04676 fprintf (stderr, "va_arg: %i\n", frame->va_arg_size);
04677 fprintf (stderr, "padding2: %i\n", frame->padding2);
04678 fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
04679 fprintf (stderr, "red_zone_size: %i\n", frame->red_zone_size);
04680 fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
04681 fprintf (stderr, "hard_frame_pointer_offset: %i\n",
04682 frame->hard_frame_pointer_offset);
04683 fprintf (stderr, "stack_pointer_offset: %i\n", frame->stack_pointer_offset);
04684 #endif
04685 }
04686
04687
04688
04689 static void
04690 ix86_emit_save_regs ()
04691 {
04692 register int regno;
04693 rtx insn;
04694
04695 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
04696 if (ix86_save_reg (regno, true))
04697 {
04698 insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
04699 RTX_FRAME_RELATED_P (insn) = 1;
04700 }
04701 }
04702
04703
04704
04705 static void
04706 ix86_emit_save_regs_using_mov (pointer, offset)
04707 rtx pointer;
04708 HOST_WIDE_INT offset;
04709 {
04710 int regno;
04711 rtx insn;
04712
04713 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04714 if (ix86_save_reg (regno, true))
04715 {
04716 insn = emit_move_insn (adjust_address (gen_rtx_MEM (Pmode, pointer),
04717 Pmode, offset),
04718 gen_rtx_REG (Pmode, regno));
04719 RTX_FRAME_RELATED_P (insn) = 1;
04720 offset += UNITS_PER_WORD;
04721 }
04722 }
04723
04724
04725
04726 void
04727 ix86_expand_prologue ()
04728 {
04729 rtx insn;
04730 bool pic_reg_used;
04731 struct ix86_frame frame;
04732 int use_mov = 0;
04733 HOST_WIDE_INT allocate;
04734
04735 if (!optimize_size)
04736 {
04737 use_fast_prologue_epilogue
04738 = !expensive_function_p (FAST_PROLOGUE_INSN_COUNT);
04739 if (TARGET_PROLOGUE_USING_MOVE)
04740 use_mov = use_fast_prologue_epilogue;
04741 }
04742 ix86_compute_frame_layout (&frame);
04743
04744
04745
04746
04747 if (frame_pointer_needed)
04748 {
04749 insn = emit_insn (gen_push (hard_frame_pointer_rtx));
04750 RTX_FRAME_RELATED_P (insn) = 1;
04751
04752 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
04753 RTX_FRAME_RELATED_P (insn) = 1;
04754 }
04755
04756 allocate = frame.to_allocate;
04757
04758
04759 if (allocate == 0 && frame.nregs <= 1)
04760 use_mov = 0;
04761
04762 if (!use_mov)
04763 ix86_emit_save_regs ();
04764 else
04765 allocate += frame.nregs * UNITS_PER_WORD;
04766
04767 if (allocate == 0)
04768 ;
04769 else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT)
04770 {
04771 insn = emit_insn (gen_pro_epilogue_adjust_stack
04772 (stack_pointer_rtx, stack_pointer_rtx,
04773 GEN_INT (-allocate)));
04774 RTX_FRAME_RELATED_P (insn) = 1;
04775 }
04776 else
04777 {
04778
04779
04780 rtx arg0, sym;
04781
04782 if (TARGET_64BIT)
04783 abort ();
04784
04785 arg0 = gen_rtx_REG (SImode, 0);
04786 emit_move_insn (arg0, GEN_INT (allocate));
04787
04788 sym = gen_rtx_MEM (FUNCTION_MODE,
04789 gen_rtx_SYMBOL_REF (Pmode, "_alloca"));
04790 insn = emit_call_insn (gen_call (sym, const0_rtx, constm1_rtx));
04791
04792 CALL_INSN_FUNCTION_USAGE (insn)
04793 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
04794 CALL_INSN_FUNCTION_USAGE (insn));
04795
04796
04797
04798 emit_insn (gen_blockage (const0_rtx));
04799 }
04800 if (use_mov)
04801 {
04802 if (!frame_pointer_needed || !frame.to_allocate)
04803 ix86_emit_save_regs_using_mov (stack_pointer_rtx, frame.to_allocate);
04804 else
04805 ix86_emit_save_regs_using_mov (hard_frame_pointer_rtx,
04806 -frame.nregs * UNITS_PER_WORD);
04807 }
04808
04809 #ifdef SUBTARGET_PROLOGUE
04810 SUBTARGET_PROLOGUE;
04811 #endif
04812
04813 pic_reg_used = false;
04814 if (pic_offset_table_rtx
04815 && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
04816 || current_function_profile))
04817 {
04818 unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum ();
04819
04820 if (alt_pic_reg_used != INVALID_REGNUM)
04821 REGNO (pic_offset_table_rtx) = alt_pic_reg_used;
04822
04823 pic_reg_used = true;
04824 }
04825
04826 if (pic_reg_used)
04827 {
04828 insn = emit_insn (gen_set_got (pic_offset_table_rtx));
04829
04830
04831
04832
04833
04834
04835
04836 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
04837 }
04838
04839
04840
04841 if (current_function_profile)
04842 emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx));
04843 }
04844
04845
04846
04847 static void
04848 ix86_emit_restore_regs_using_mov (pointer, offset, maybe_eh_return)
04849 rtx pointer;
04850 int offset;
04851 int maybe_eh_return;
04852 {
04853 int regno;
04854
04855 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04856 if (ix86_save_reg (regno, maybe_eh_return))
04857 {
04858 emit_move_insn (gen_rtx_REG (Pmode, regno),
04859 adjust_address (gen_rtx_MEM (Pmode, pointer),
04860 Pmode, offset));
04861 offset += UNITS_PER_WORD;
04862 }
04863 }
04864
04865
04866
04867 void
04868 ix86_expand_epilogue (style)
04869 int style;
04870 {
04871 int regno;
04872 int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
04873 struct ix86_frame frame;
04874 HOST_WIDE_INT offset;
04875
04876 ix86_compute_frame_layout (&frame);
04877
04878
04879
04880
04881
04882 offset = frame.nregs;
04883 if (current_function_calls_eh_return && style != 2)
04884 offset -= 2;
04885 offset *= -UNITS_PER_WORD;
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896
04897 if ((!sp_valid && frame.nregs <= 1)
04898 || (TARGET_EPILOGUE_USING_MOVE
04899 && use_fast_prologue_epilogue
04900 && (frame.nregs > 1 || frame.to_allocate))
04901 || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
04902 || (frame_pointer_needed && TARGET_USE_LEAVE
04903 && use_fast_prologue_epilogue && frame.nregs == 1)
04904 || current_function_calls_eh_return)
04905 {
04906
04907
04908
04909
04910
04911
04912 if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
04913 ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
04914 frame.to_allocate, style == 2);
04915 else
04916 ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
04917 offset, style == 2);
04918
04919
04920 if (style == 2)
04921 {
04922 rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
04923
04924 if (frame_pointer_needed)
04925 {
04926 tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
04927 tmp = plus_constant (tmp, UNITS_PER_WORD);
04928 emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
04929
04930 tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
04931 emit_move_insn (hard_frame_pointer_rtx, tmp);
04932
04933 emit_insn (gen_pro_epilogue_adjust_stack
04934 (stack_pointer_rtx, sa, const0_rtx));
04935 }
04936 else
04937 {
04938 tmp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, sa);
04939 tmp = plus_constant (tmp, (frame.to_allocate
04940 + frame.nregs * UNITS_PER_WORD));
04941 emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
04942 }
04943 }
04944 else if (!frame_pointer_needed)
04945 emit_insn (gen_pro_epilogue_adjust_stack
04946 (stack_pointer_rtx, stack_pointer_rtx,
04947 GEN_INT (frame.to_allocate
04948 + frame.nregs * UNITS_PER_WORD)));
04949
04950 else if (TARGET_USE_LEAVE || optimize_size || !use_fast_prologue_epilogue)
04951 emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
04952 else
04953 {
04954 emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
04955 hard_frame_pointer_rtx,
04956 const0_rtx));
04957 if (TARGET_64BIT)
04958 emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
04959 else
04960 emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
04961 }
04962 }
04963 else
04964 {
04965
04966
04967 if (!sp_valid)
04968 {
04969 if (!frame_pointer_needed)
04970 abort ();
04971 emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
04972 hard_frame_pointer_rtx,
04973 GEN_INT (offset)));
04974 }
04975 else if (frame.to_allocate)
04976 emit_insn (gen_pro_epilogue_adjust_stack
04977 (stack_pointer_rtx, stack_pointer_rtx,
04978 GEN_INT (frame.to_allocate)));
04979
04980 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04981 if (ix86_save_reg (regno, false))
04982 {
04983 if (TARGET_64BIT)
04984 emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
04985 else
04986 emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, regno)));
04987 }
04988 if (frame_pointer_needed)
04989 {
04990
04991
04992 if (TARGET_USE_LEAVE)
04993 emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
04994 else if (TARGET_64BIT)
04995 emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
04996 else
04997 emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
04998 }
04999 }
05000
05001
05002 if (style == 0)
05003 return;
05004
05005 if (current_function_pops_args && current_function_args_size)
05006 {
05007 rtx popc = GEN_INT (current_function_pops_args);
05008
05009
05010
05011
05012
05013 if (current_function_pops_args >= 65536)
05014 {
05015 rtx ecx = gen_rtx_REG (SImode, 2);
05016
05017
05018 if (TARGET_64BIT)
05019 abort ();
05020
05021 emit_insn (gen_popsi1 (ecx));
05022 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
05023 emit_jump_insn (gen_return_indirect_internal (ecx));
05024 }
05025 else
05026 emit_jump_insn (gen_return_pop_internal (popc));
05027 }
05028 else
05029 emit_jump_insn (gen_return_internal ());
05030 }
05031
05032
05033
05034 static void
05035 ix86_output_function_epilogue (file, size)
05036 FILE *file ATTRIBUTE_UNUSED;
05037 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
05038 {
05039 if (pic_offset_table_rtx)
05040 REGNO (pic_offset_table_rtx) = REAL_PIC_OFFSET_TABLE_REGNUM;
05041 }
05042
05043
05044
05045
05046
05047
05048 static int
05049 ix86_decompose_address (addr, out)
05050 register rtx addr;
05051 struct ix86_address *out;
05052 {
05053 rtx base = NULL_RTX;
05054 rtx index = NULL_RTX;
05055 rtx disp = NULL_RTX;
05056 HOST_WIDE_INT scale = 1;
05057 rtx scale_rtx = NULL_RTX;
05058 int retval = 1;
05059 enum ix86_address_seg seg = SEG_DEFAULT;
05060
05061 if (REG_P (addr) || GET_CODE (addr) == SUBREG)
05062 base = addr;
05063 else if (GET_CODE (addr) == PLUS)
05064 {
05065 rtx addends[4], op;
05066 int n = 0, i;
05067
05068 op = addr;
05069 do
05070 {
05071 if (n >= 4)
05072 return 0;
05073 addends[n++] = XEXP (op, 1);
05074 op = XEXP (op, 0);
05075 }
05076 while (GET_CODE (op) == PLUS);
05077 if (n >= 4)
05078 return 0;
05079 addends[n] = op;
05080
05081 for (i = 0; i <= n; ++i)
05082 {
05083 op = addends[i];
05084 switch (GET_CODE (op))
05085 {
05086 case MULT:
05087 if (index)
05088 return 0;
05089 index = XEXP (op, 0);
05090 scale_rtx = XEXP (op, 1);
05091 break;
05092
05093 case UNSPEC:
05094 if (XINT (op, 1) == UNSPEC_TP
05095 && TARGET_TLS_DIRECT_SEG_REFS
05096 && seg == SEG_DEFAULT)
05097 seg = TARGET_64BIT ? SEG_FS : SEG_GS;
05098 else
05099 return 0;
05100 break;
05101
05102 case REG:
05103 case SUBREG:
05104 if (!base)
05105 base = op;
05106 else if (!index)
05107 index = op;
05108 else
05109 return 0;
05110 break;
05111
05112 case CONST:
05113 case CONST_INT:
05114 case SYMBOL_REF:
05115 case LABEL_REF:
05116 if (disp)
05117 return 0;
05118 disp = op;
05119 break;
05120
05121 default:
05122 return 0;
05123 }
05124 }
05125 }
05126 else if (GET_CODE (addr) == MULT)
05127 {
05128 index = XEXP (addr, 0);
05129 scale_rtx = XEXP (addr, 1);
05130 }
05131 else if (GET_CODE (addr) == ASHIFT)
05132 {
05133 rtx tmp;
05134
05135
05136 index = XEXP (addr, 0);
05137 tmp = XEXP (addr, 1);
05138 if (GET_CODE (tmp) != CONST_INT)
05139 return 0;
05140 scale = INTVAL (tmp);
05141 if ((unsigned HOST_WIDE_INT) scale > 3)
05142 return 0;
05143 scale = 1 << scale;
05144 retval = -1;
05145 }
05146 else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP_MEM)
05147 {
05148 if (seg != SEG_DEFAULT)
05149 return 0;
05150 seg = TARGET_64BIT ? SEG_FS : SEG_GS;
05151 disp = const0_rtx;
05152 }
05153 else
05154 disp = addr;
05155
05156
05157 if (scale_rtx)
05158 {
05159 if (GET_CODE (scale_rtx) != CONST_INT)
05160 return 0;
05161 scale = INTVAL (scale_rtx);
05162 }
05163
05164
05165 if (base && index && scale == 1
05166 && (index == arg_pointer_rtx || index == frame_pointer_rtx
05167 || index == stack_pointer_rtx))
05168 {
05169 rtx tmp = base;
05170 base = index;
05171 index = tmp;
05172 }
05173
05174
05175 if ((base == hard_frame_pointer_rtx
05176 || base == frame_pointer_rtx
05177 || base == arg_pointer_rtx) && !disp)
05178 disp = const0_rtx;
05179
05180
05181
05182 if (ix86_cpu == PROCESSOR_K6 && !optimize_size
05183 && base && !index && !disp
05184 && REG_P (base)
05185 && REGNO_REG_CLASS (REGNO (base)) == SIREG)
05186 disp = const0_rtx;
05187
05188
05189 if (!base && index && scale && scale == 2)
05190 base = index, scale = 1;
05191
05192
05193 if (!base && !disp && index && scale != 1)
05194 disp = const0_rtx;
05195
05196 out->base = base;
05197 out->index = index;
05198 out->disp = disp;
05199 out->scale = scale;
05200 out->seg = seg;
05201
05202 return retval;
05203 }
05204
05205
05206
05207
05208
05209
05210 int
05211 ix86_address_cost (x)
05212 rtx x;
05213 {
05214 struct ix86_address parts;
05215 int cost = 1;
05216
05217 if (!ix86_decompose_address (x, &parts))
05218 abort ();
05219
05220 if (parts.base && GET_CODE (parts.base) == SUBREG)
05221 parts.base = SUBREG_REG (parts.base);
05222 if (parts.index && GET_CODE (parts.index) == SUBREG)
05223 parts.index = SUBREG_REG (parts.index);
05224
05225
05226 if (parts.disp && parts.disp != const0_rtx)
05227 cost--;
05228 if (parts.seg != SEG_DEFAULT)
05229 cost--;
05230
05231
05232 if ((parts.base
05233 && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER))
05234 || (parts.index
05235 && (!REG_P (parts.index)
05236 || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)))
05237 cost++;
05238
05239 if (parts.base
05240 && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER)
05241 && parts.index
05242 && (!REG_P (parts.index) || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)
05243 && parts.base != parts.index)
05244 cost++;
05245
05246
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261 if (TARGET_K6
05262 && ((!parts.disp && parts.base && parts.index && parts.scale != 1)
05263 || (parts.disp && !parts.base && parts.index && parts.scale != 1)
05264 || (!parts.disp && parts.base && parts.index && parts.scale == 1)))
05265 cost += 10;
05266
05267 return cost;
05268 }
05269
05270
05271
05272
05273
05274 rtx
05275 ix86_find_base_term (x)
05276 rtx x;
05277 {
05278 rtx term;
05279
05280 if (TARGET_64BIT)
05281 {
05282 if (GET_CODE (x) != CONST)
05283 return x;
05284 term = XEXP (x, 0);
05285 if (GET_CODE (term) == PLUS
05286 && (GET_CODE (XEXP (term, 1)) == CONST_INT
05287 || GET_CODE (XEXP (term, 1)) == CONST_DOUBLE))
05288 term = XEXP (term, 0);
05289 if (GET_CODE (term) != UNSPEC
05290 || XINT (term, 1) != UNSPEC_GOTPCREL)
05291 return x;
05292
05293 term = XVECEXP (term, 0, 0);
05294
05295 if (GET_CODE (term) != SYMBOL_REF
05296 && GET_CODE (term) != LABEL_REF)
05297 return x;
05298
05299 return term;
05300 }
05301
05302 if (GET_CODE (x) != PLUS
05303 || XEXP (x, 0) != pic_offset_table_rtx
05304 || GET_CODE (XEXP (x, 1)) != CONST)
05305 return x;
05306
05307 term = XEXP (XEXP (x, 1), 0);
05308
05309 if (GET_CODE (term) == PLUS && GET_CODE (XEXP (term, 1)) == CONST_INT)
05310 term = XEXP (term, 0);
05311
05312 if (GET_CODE (term) != UNSPEC
05313 || XINT (term, 1) != UNSPEC_GOTOFF)
05314 return x;
05315
05316 term = XVECEXP (term, 0, 0);
05317
05318 if (GET_CODE (term) != SYMBOL_REF
05319 && GET_CODE (term) != LABEL_REF)
05320 return x;
05321
05322 return term;
05323 }
05324
05325
05326
05327
05328 bool
05329 legitimate_constant_p (x)
05330 rtx x;
05331 {
05332 rtx inner;
05333
05334 switch (GET_CODE (x))
05335 {
05336 case SYMBOL_REF:
05337
05338 if (tls_symbolic_operand (x, Pmode))
05339 return false;
05340 break;
05341
05342 case CONST:
05343 inner = XEXP (x, 0);
05344
05345
05346
05347 if (GET_CODE (inner) == PLUS
05348 && tls_symbolic_operand (XEXP (inner, 0), Pmode))
05349 return false;
05350
05351
05352 if (GET_CODE (inner) == UNSPEC)
05353 switch (XINT (inner, 1))
05354 {
05355 case UNSPEC_TPOFF:
05356 return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
05357 default:
05358 return false;
05359 }
05360 break;
05361
05362 default:
05363 break;
05364 }
05365
05366
05367 return true;
05368 }
05369
05370
05371
05372
05373
05374 static bool
05375 ix86_cannot_force_const_mem (x)
05376 rtx x;
05377 {
05378 return !legitimate_constant_p (x);
05379 }
05380
05381
05382
05383 bool
05384 constant_address_p (x)
05385 rtx x;
05386 {
05387 switch (GET_CODE (x))
05388 {
05389 case LABEL_REF:
05390 case CONST_INT:
05391 return true;
05392
05393 case CONST_DOUBLE:
05394 return TARGET_64BIT;
05395
05396 case CONST:
05397
05398 if (TARGET_MACHO)
05399 return true;
05400
05401 case SYMBOL_REF:
05402 return !flag_pic && legitimate_constant_p (x);
05403
05404 default:
05405 return false;
05406 }
05407 }
05408
05409
05410
05411
05412
05413 bool
05414 legitimate_pic_operand_p (x)
05415 rtx x;
05416 {
05417 rtx inner;
05418
05419 switch (GET_CODE (x))
05420 {
05421 case CONST:
05422 inner = XEXP (x, 0);
05423
05424
05425 if (GET_CODE (inner) == UNSPEC)
05426 switch (XINT (inner, 1))
05427 {
05428 case UNSPEC_TPOFF:
05429 return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
05430 default:
05431 return false;
05432 }
05433
05434
05435 case SYMBOL_REF:
05436 case LABEL_REF:
05437 return legitimate_pic_address_disp_p (x);
05438
05439 default:
05440 return true;
05441 }
05442 }
05443
05444
05445
05446
05447 int
05448 legitimate_pic_address_disp_p (disp)
05449 register rtx disp;
05450 {
05451 bool saw_plus;
05452
05453
05454
05455 if (TARGET_64BIT)
05456 {
05457
05458 if (tls_symbolic_operand (disp, GET_MODE (disp)))
05459 return 0;
05460 if (GET_CODE (disp) == SYMBOL_REF
05461 && ix86_cmodel == CM_SMALL_PIC
05462 && (CONSTANT_POOL_ADDRESS_P (disp)
05463 || SYMBOL_REF_FLAG (disp)))
05464 return 1;
05465 if (GET_CODE (disp) == LABEL_REF)
05466 return 1;
05467 if (GET_CODE (disp) == CONST
05468 && GET_CODE (XEXP (disp, 0)) == PLUS)
05469 {
05470 rtx op0 = XEXP (XEXP (disp, 0), 0);
05471 rtx op1 = XEXP (XEXP (disp, 0), 1);
05472
05473
05474 if (tls_symbolic_operand (op0, GET_MODE (op0)))
05475 return 0;
05476
05477 if (((GET_CODE (op0) == SYMBOL_REF
05478 && ix86_cmodel == CM_SMALL_PIC
05479 && (CONSTANT_POOL_ADDRESS_P (op0)
05480 || SYMBOL_REF_FLAG (op0)))
05481 || GET_CODE (op0) == LABEL_REF)
05482 && GET_CODE (op1) == CONST_INT
05483 && INTVAL (op1) < 16*1024*1024
05484 && INTVAL (op1) >= -16*1024*1024)
05485 return 1;
05486 }
05487 }
05488 if (GET_CODE (disp) != CONST)
05489 return 0;
05490 disp = XEXP (disp, 0);
05491
05492 if (TARGET_64BIT)
05493 {
05494
05495
05496 if (GET_CODE (disp) != UNSPEC
05497 || XINT (disp, 1) != UNSPEC_GOTPCREL)
05498 return 0;
05499
05500 if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
05501 && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
05502 return 0;
05503 return 1;
05504 }
05505
05506 saw_plus = false;
05507 if (GET_CODE (disp) == PLUS)
05508 {
05509 if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
05510 return 0;
05511 disp = XEXP (disp, 0);
05512 saw_plus = true;
05513 }
05514
05515
05516 if (TARGET_MACHO && GET_CODE (disp) == MINUS)
05517 {
05518 if (GET_CODE (XEXP (disp, 0)) == LABEL_REF
05519 || GET_CODE (XEXP (disp, 0)) == SYMBOL_REF)
05520 if (GET_CODE (XEXP (disp, 1)) == SYMBOL_REF)
05521 {
05522 const char *sym_name = XSTR (XEXP (disp, 1), 0);
05523 if (strstr (sym_name, "$pb") != 0)
05524 return 1;
05525 }
05526 }
05527
05528 if (GET_CODE (disp) != UNSPEC)
05529 return 0;
05530
05531 switch (XINT (disp, 1))
05532 {
05533 case UNSPEC_GOT:
05534 if (saw_plus)
05535 return false;
05536 return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF;
05537 case UNSPEC_GOTOFF:
05538 return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
05539 case UNSPEC_GOTTPOFF:
05540 case UNSPEC_GOTNTPOFF:
05541 case UNSPEC_INDNTPOFF:
05542 if (saw_plus)
05543 return false;
05544 return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
05545 case UNSPEC_NTPOFF:
05546 return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
05547 case UNSPEC_DTPOFF:
05548 return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
05549 }
05550
05551 return 0;
05552 }
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562 int
05563 legitimate_address_p (mode, addr, strict)
05564 enum machine_mode mode;
05565 register rtx addr;
05566 int strict;
05567 {
05568 struct ix86_address parts;
05569 rtx base, index, disp;
05570 HOST_WIDE_INT scale;
05571 const char *reason = NULL;
05572 rtx reason_rtx = NULL_RTX;
05573
05574 if (TARGET_DEBUG_ADDR)
05575 {
05576 fprintf (stderr,
05577 "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
05578 GET_MODE_NAME (mode), strict);
05579 debug_rtx (addr);
05580 }
05581
05582 if (ix86_decompose_address (addr, &parts) <= 0)
05583 {
05584 reason = "decomposition failed";
05585 goto report_error;
05586 }
05587
05588 base = parts.base;
05589 index = parts.index;
05590 disp = parts.disp;
05591 scale = parts.scale;
05592
05593
05594
05595
05596
05597
05598
05599 if (base)
05600 {
05601 rtx reg;
05602 reason_rtx = base;
05603
05604 if (GET_CODE (base) == SUBREG)
05605 reg = SUBREG_REG (base);
05606 else
05607 reg = base;
05608
05609 if (GET_CODE (reg) != REG)
05610 {
05611 reason = "base is not a register";
05612 goto report_error;
05613 }
05614
05615 if (GET_MODE (base) != Pmode)
05616 {
05617 reason = "base is not in Pmode";
05618 goto report_error;
05619 }
05620
05621 if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
05622 || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg)))
05623 {
05624 reason = "base is not valid";
05625 goto report_error;
05626 }
05627 }
05628
05629
05630
05631
05632
05633
05634
05635 if (index)
05636 {
05637 rtx reg;
05638 reason_rtx = index;
05639
05640 if (GET_CODE (index) == SUBREG)
05641 reg = SUBREG_REG (index);
05642 else
05643 reg = index;
05644
05645 if (GET_CODE (reg) != REG)
05646 {
05647 reason = "index is not a register";
05648 goto report_error;
05649 }
05650
05651 if (GET_MODE (index) != Pmode)
05652 {
05653 reason = "index is not in Pmode";
05654 goto report_error;
05655 }
05656
05657 if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
05658 || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg)))
05659 {
05660 reason = "index is not valid";
05661 goto report_error;
05662 }
05663 }
05664
05665
05666 if (scale != 1)
05667 {
05668 reason_rtx = GEN_INT (scale);
05669 if (!index)
05670 {
05671 reason = "scale without index";
05672 goto report_error;
05673 }
05674
05675 if (scale != 2 && scale != 4 && scale != 8)
05676 {
05677 reason = "scale is not a valid multiplier";
05678 goto report_error;
05679 }
05680 }
05681
05682
05683 if (disp)
05684 {
05685 reason_rtx = disp;
05686
05687 if (GET_CODE (disp) == CONST
05688 && GET_CODE (XEXP (disp, 0)) == UNSPEC)
05689 switch (XINT (XEXP (disp, 0), 1))
05690 {
05691 case UNSPEC_GOT:
05692 case UNSPEC_GOTOFF:
05693 case UNSPEC_GOTPCREL:
05694 if (!flag_pic)
05695 abort ();
05696 goto is_legitimate_pic;
05697
05698 case UNSPEC_GOTTPOFF:
05699 case UNSPEC_GOTNTPOFF:
05700 case UNSPEC_INDNTPOFF:
05701 case UNSPEC_NTPOFF:
05702 case UNSPEC_DTPOFF:
05703 break;
05704
05705 default:
05706 reason = "invalid address unspec";
05707 goto report_error;
05708 }
05709
05710 else if (flag_pic && (SYMBOLIC_CONST (disp)
05711 #if TARGET_MACHO
05712 && !machopic_operand_p (disp)
05713 #endif
05714 ))
05715 {
05716 is_legitimate_pic:
05717 if (TARGET_64BIT && (index || base))
05718 {
05719
05720 if (GET_CODE (disp) != CONST
05721 || GET_CODE (XEXP (disp, 0)) != PLUS
05722 || GET_CODE (XEXP (XEXP (disp, 0), 0)) != UNSPEC
05723 || GET_CODE (XEXP (XEXP (disp, 0), 1)) != CONST_INT
05724 || (XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_DTPOFF
05725 && XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_NTPOFF))
05726 {
05727 reason = "non-constant pic memory reference";
05728 goto report_error;
05729 }
05730 }
05731 else if (! legitimate_pic_address_disp_p (disp))
05732 {
05733 reason = "displacement is an invalid pic construct";
05734 goto report_error;
05735 }
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757
05758 }
05759 else if (!CONSTANT_ADDRESS_P (disp))
05760 {
05761 reason = "displacement is not constant";
05762 goto report_error;
05763 }
05764 else if (TARGET_64BIT && !x86_64_sign_extended_value (disp))
05765 {
05766 reason = "displacement is out of range";
05767 goto report_error;
05768 }
05769 else if (!TARGET_64BIT && GET_CODE (disp) == CONST_DOUBLE)
05770 {
05771 reason = "displacement is a const_double";
05772 goto report_error;
05773 }
05774 }
05775
05776
05777 if (TARGET_DEBUG_ADDR)
05778 fprintf (stderr, "Success.\n");
05779 return TRUE;
05780
05781 report_error:
05782 if (TARGET_DEBUG_ADDR)
05783 {
05784 fprintf (stderr, "Error: %s\n", reason);
05785 debug_rtx (reason_rtx);
05786 }
05787 return FALSE;
05788 }
05789
05790
05791
05792 static HOST_WIDE_INT
05793 ix86_GOT_alias_set ()
05794 {
05795 static HOST_WIDE_INT set = -1;
05796 if (set == -1)
05797 set = new_alias_set ();
05798 return set;
05799 }
05800
05801
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816
05817
05818
05819 rtx
05820 legitimize_pic_address (orig, reg)
05821 rtx orig;
05822 rtx reg;
05823 {
05824 rtx addr = orig;
05825 rtx new = orig;
05826 rtx base;
05827
05828 #if TARGET_MACHO
05829 if (reg == 0)
05830 reg = gen_reg_rtx (Pmode);
05831
05832 return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
05833 #endif
05834
05835 if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
05836 new = addr;
05837 else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
05838 {
05839
05840
05841
05842 if (reload_in_progress)
05843 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
05844 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
05845 new = gen_rtx_CONST (Pmode, new);
05846 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
05847
05848 if (reg != 0)
05849 {
05850 emit_move_insn (reg, new);
05851 new = reg;
05852 }
05853 }
05854 else if (GET_CODE (addr) == SYMBOL_REF)
05855 {
05856 if (TARGET_64BIT)
05857 {
05858 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
05859 new = gen_rtx_CONST (Pmode, new);
05860 new = gen_rtx_MEM (Pmode, new);
05861 RTX_UNCHANGING_P (new) = 1;
05862 set_mem_alias_set (new, ix86_GOT_alias_set ());
05863
05864 if (reg == 0)
05865 reg = gen_reg_rtx (Pmode);
05866
05867
05868
05869 emit_insn (gen_movsi (reg, new));
05870 new = reg;
05871 }
05872 else
05873 {
05874
05875
05876
05877 if (reload_in_progress)
05878 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
05879 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
05880 new = gen_rtx_CONST (Pmode, new);
05881 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
05882 new = gen_rtx_MEM (Pmode, new);
05883 RTX_UNCHANGING_P (new) = 1;
05884 set_mem_alias_set (new, ix86_GOT_alias_set ());
05885
05886 if (reg == 0)
05887 reg = gen_reg_rtx (Pmode);
05888 emit_move_insn (reg, new);
05889 new = reg;
05890 }
05891 }
05892 else
05893 {
05894 if (GET_CODE (addr) == CONST)
05895 {
05896 addr = XEXP (addr, 0);
05897
05898
05899
05900
05901 if (GET_CODE (addr) == UNSPEC
05902 || (GET_CODE (addr) == PLUS
05903 && GET_CODE (XEXP (addr, 0)) == UNSPEC))
05904 return orig;
05905 if (GET_CODE (addr) != PLUS)
05906 abort ();
05907 }
05908 if (GET_CODE (addr) == PLUS)
05909 {
05910 rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
05911
05912
05913
05914 if (local_symbolic_operand (op0, Pmode)
05915 && GET_CODE (op1) == CONST_INT)
05916 {
05917 if (!TARGET_64BIT)
05918 {
05919 if (reload_in_progress)
05920 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
05921 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
05922 UNSPEC_GOTOFF);
05923 new = gen_rtx_PLUS (Pmode, new, op1);
05924 new = gen_rtx_CONST (Pmode, new);
05925 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
05926
05927 if (reg != 0)
05928 {
05929 emit_move_insn (reg, new);
05930 new = reg;
05931 }
05932 }
05933 else
05934 {
05935 if (INTVAL (op1) < -16*1024*1024
05936 || INTVAL (op1) >= 16*1024*1024)
05937 new = gen_rtx_PLUS (Pmode, op0, force_reg (Pmode, op1));
05938 }
05939 }
05940 else
05941 {
05942 base = legitimize_pic_address (XEXP (addr, 0), reg);
05943 new = legitimize_pic_address (XEXP (addr, 1),
05944 base == reg ? NULL_RTX : reg);
05945
05946 if (GET_CODE (new) == CONST_INT)
05947 new = plus_constant (base, INTVAL (new));
05948 else
05949 {
05950 if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
05951 {
05952 base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
05953 new = XEXP (new, 1);
05954 }
05955 new = gen_rtx_PLUS (Pmode, base, new);
05956 }
05957 }
05958 }
05959 }
05960 return new;
05961 }
05962
05963 static void
05964 ix86_encode_section_info (decl, first)
05965 tree decl;
05966 int first ATTRIBUTE_UNUSED;
05967 {
05968 bool local_p = (*targetm.binds_local_p) (decl);
05969 rtx rtl, symbol;
05970
05971 rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
05972 if (GET_CODE (rtl) != MEM)
05973 return;
05974 symbol = XEXP (rtl, 0);
05975 if (GET_CODE (symbol) != SYMBOL_REF)
05976 return;
05977
05978
05979
05980
05981 if (flag_pic)
05982 SYMBOL_REF_FLAG (symbol) = local_p;
05983
05984
05985
05986
05987
05988 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
05989 {
05990 const char *symbol_str;
05991 char *newstr;
05992 size_t len;
05993 enum tls_model kind = decl_tls_model (decl);
05994
05995 if (TARGET_64BIT && ! flag_pic)
05996 {
05997
05998
05999 switch (kind)
06000 {
06001 case TLS_MODEL_GLOBAL_DYNAMIC:
06002 kind = TLS_MODEL_INITIAL_EXEC; break;
06003 case TLS_MODEL_LOCAL_DYNAMIC:
06004 kind = TLS_MODEL_LOCAL_EXEC; break;
06005 default:
06006 break;
06007 }
06008 }
06009
06010 symbol_str = XSTR (symbol, 0);
06011
06012 if (symbol_str[0] == '%')
06013 {
06014 if (symbol_str[1] == tls_model_chars[kind])
06015 return;
06016 symbol_str += 2;
06017 }
06018 len = strlen (symbol_str) + 1;
06019 newstr = alloca (len + 2);
06020
06021 newstr[0] = '%';
06022 newstr[1] = tls_model_chars[kind];
06023 memcpy (newstr + 2, symbol_str, len);
06024
06025 XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
06026 }
06027 }
06028
06029
06030
06031 static const char *
06032 ix86_strip_name_encoding (str)
06033 const char *str;
06034 {
06035 if (str[0] == '%')
06036 str += 2;
06037 if (str [0] == '*')
06038 str += 1;
06039 return str;
06040 }
06041
06042
06043
06044 static rtx
06045 get_thread_pointer (to_reg)
06046 int to_reg;
06047 {
06048 rtx tp, reg, insn;
06049
06050 tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
06051 if (!to_reg)
06052 return tp;
06053
06054 reg = gen_reg_rtx (Pmode);
06055 insn = gen_rtx_SET (VOIDmode, reg, tp);
06056 insn = emit_insn (insn);
06057
06058 #if 0
06059
06060
06061
06062 if (flag_peephole2)
06063 {
06064 tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP_MEM);
06065 tp = gen_rtx_MEM (Pmode, tp);
06066 RTX_UNCHANGING_P (tp) = 1;
06067 set_mem_alias_set (tp, ix86_GOT_alias_set ());
06068 set_unique_reg_note (insn, REG_EQUAL, tp);
06069 }
06070 #endif
06071
06072 return reg;
06073 }
06074
06075
06076
06077
06078
06079 static rtx
06080 legitimize_tls_address (x, model, for_mov)
06081 rtx x;
06082 enum tls_model model;
06083 int for_mov;
06084 {
06085 rtx dest, base, off, pic;
06086 int type;
06087
06088 switch (model)
06089 {
06090 case TLS_MODEL_GLOBAL_DYNAMIC:
06091 dest = gen_reg_rtx (Pmode);
06092 if (TARGET_64BIT)
06093 {
06094 rtx rax = gen_rtx_REG (Pmode, 0), insns;
06095
06096 start_sequence ();
06097 emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
06098 insns = get_insns ();
06099 end_sequence ();
06100
06101 emit_libcall_block (insns, dest, rax, x);
06102 }
06103 else
06104 emit_insn (gen_tls_global_dynamic_32 (dest, x));
06105 break;
06106
06107 case TLS_MODEL_LOCAL_DYNAMIC:
06108 base = gen_reg_rtx (Pmode);
06109 if (TARGET_64BIT)
06110 {
06111 rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
06112
06113 start_sequence ();
06114 emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
06115 insns = get_insns ();
06116 end_sequence ();
06117
06118 note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
06119 note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
06120 emit_libcall_block (insns, base, rax, note);
06121 }
06122 else
06123 emit_insn (gen_tls_local_dynamic_base_32 (base));
06124
06125 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
06126 off = gen_rtx_CONST (Pmode, off);
06127
06128 return gen_rtx_PLUS (Pmode, base, off);
06129
06130 case TLS_MODEL_INITIAL_EXEC:
06131 if (TARGET_64BIT)
06132 {
06133 pic = NULL;
06134 type = UNSPEC_GOTNTPOFF;
06135 }
06136 else if (flag_pic)
06137 {
06138 if (reload_in_progress)
06139 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
06140 pic = pic_offset_table_rtx;
06141 type = TARGET_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
06142 }
06143 else if (!TARGET_GNU_TLS)
06144 {
06145 pic = gen_reg_rtx (Pmode);
06146 emit_insn (gen_set_got (pic));
06147 type = UNSPEC_GOTTPOFF;
06148 }
06149 else
06150 {
06151 pic = NULL;
06152 type = UNSPEC_INDNTPOFF;
06153 }
06154
06155 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
06156 off = gen_rtx_CONST (Pmode, off);
06157 if (pic)
06158 off = gen_rtx_PLUS (Pmode, pic, off);
06159 off = gen_rtx_MEM (Pmode, off);
06160 RTX_UNCHANGING_P (off) = 1;
06161 set_mem_alias_set (off, ix86_GOT_alias_set ());
06162
06163 if (TARGET_64BIT || TARGET_GNU_TLS)
06164 {
06165 base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
06166 off = force_reg (Pmode, off);
06167 return gen_rtx_PLUS (Pmode, base, off);
06168 }
06169 else
06170 {
06171 base = get_thread_pointer (true);
06172 dest = gen_reg_rtx (Pmode);
06173 emit_insn (gen_subsi3 (dest, base, off));
06174 }
06175 break;
06176
06177 case TLS_MODEL_LOCAL_EXEC:
06178 off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
06179 (TARGET_64BIT || TARGET_GNU_TLS
06180 ? UNSPEC_NTPOFF : UNSPEC_TPOFF));
06181 off = gen_rtx_CONST (Pmode, off);
06182
06183 if (TARGET_64BIT || TARGET_GNU_TLS)
06184 {
06185 base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
06186 return gen_rtx_PLUS (Pmode, base, off);
06187 }
06188 else
06189 {
06190 base = get_thread_pointer (true);
06191 dest = gen_reg_rtx (Pmode);
06192 emit_insn (gen_subsi3 (dest, base, off));
06193 }
06194 break;
06195
06196 default:
06197 abort ();
06198 }
06199
06200 return dest;
06201 }
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
06212
06213
06214
06215
06216
06217
06218
06219
06220
06221
06222
06223
06224 rtx
06225 legitimize_address (x, oldx, mode)
06226 register rtx x;
06227 register rtx oldx ATTRIBUTE_UNUSED;
06228 enum machine_mode mode;
06229 {
06230 int changed = 0;
06231 unsigned log;
06232
06233 if (TARGET_DEBUG_ADDR)
06234 {
06235 fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n",
06236 GET_MODE_NAME (mode));
06237 debug_rtx (x);
06238 }
06239
06240 log = tls_symbolic_operand (x, mode);
06241 if (log)
06242 return legitimize_tls_address (x, log, false);
06243
06244 if (flag_pic && SYMBOLIC_CONST (x))
06245 return legitimize_pic_address (x, 0);
06246
06247
06248 if (GET_CODE (x) == ASHIFT
06249 && GET_CODE (XEXP (x, 1)) == CONST_INT
06250 && (log = (unsigned) exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
06251 {
06252 changed = 1;
06253 x = gen_rtx_MULT (Pmode, force_reg (Pmode, XEXP (x, 0)),
06254 GEN_INT (1 << log));
06255 }
06256
06257 if (GET_CODE (x) == PLUS)
06258 {
06259
06260
06261 if (GET_CODE (XEXP (x, 0)) == ASHIFT
06262 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
06263 && (log = (unsigned) exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
06264 {
06265 changed = 1;
06266 XEXP (x, 0) = gen_rtx_MULT (Pmode,
06267 force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
06268 GEN_INT (1 << log));
06269 }
06270
06271 if (GET_CODE (XEXP (x, 1)) == ASHIFT
06272 && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
06273 && (log = (unsigned) exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
06274 {
06275 changed = 1;
06276 XEXP (x, 1) = gen_rtx_MULT (Pmode,
06277 force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
06278 GEN_INT (1 << log));
06279 }
06280
06281
06282 if (GET_CODE (XEXP (x, 1)) == MULT)
06283 {
06284 rtx tmp = XEXP (x, 0);
06285 XEXP (x, 0) = XEXP (x, 1);
06286 XEXP (x, 1) = tmp;
06287 changed = 1;
06288 }
06289
06290
06291
06292
06293
06294 if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
06295 {
06296 changed = 1;
06297 x = gen_rtx_PLUS (Pmode,
06298 gen_rtx_PLUS (Pmode, XEXP (x, 0),
06299 XEXP (XEXP (x, 1), 0)),
06300 XEXP (XEXP (x, 1), 1));
06301 }
06302
06303
06304
06305
06306 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
06307 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
06308 && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
06309 && CONSTANT_P (XEXP (x, 1)))
06310 {
06311 rtx constant;
06312 rtx other = NULL_RTX;
06313
06314 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
06315 {
06316 constant = XEXP (x, 1);
06317 other = XEXP (XEXP (XEXP (x, 0), 1), 1);
06318 }
06319 else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
06320 {
06321 constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
06322 other = XEXP (x, 1);
06323 }
06324 else
06325 constant = 0;
06326
06327 if (constant)
06328 {
06329 changed = 1;
06330 x = gen_rtx_PLUS (Pmode,
06331 gen_rtx_PLUS (Pmode, XEXP (XEXP (x, 0), 0),
06332 XEXP (XEXP (XEXP (x, 0), 1), 0)),
06333 plus_constant (other, INTVAL (constant)));
06334 }
06335 }
06336
06337 if (changed && legitimate_address_p (mode, x, FALSE))
06338 return x;
06339
06340 if (GET_CODE (XEXP (x, 0)) == MULT)
06341 {
06342 changed = 1;
06343 XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
06344 }
06345
06346 if (GET_CODE (XEXP (x, 1)) == MULT)
06347 {
06348 changed = 1;
06349 XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
06350 }
06351
06352 if (changed
06353 && GET_CODE (XEXP (x, 1)) == REG
06354 && GET_CODE (XEXP (x, 0)) == REG)
06355 return x;
06356
06357 if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
06358 {
06359 changed = 1;
06360 x = legitimize_pic_address (x, 0);
06361 }
06362
06363 if (changed && legitimate_address_p (mode, x, FALSE))
06364 return x;
06365
06366 if (GET_CODE (XEXP (x, 0)) == REG)
06367 {
06368 register rtx temp = gen_reg_rtx (Pmode);
06369 register rtx val = force_operand (XEXP (x, 1), temp);
06370 if (val != temp)
06371 emit_move_insn (temp, val);
06372
06373 XEXP (x, 1) = temp;
06374 return x;
06375 }
06376
06377 else if (GET_CODE (XEXP (x, 1)) == REG)
06378 {
06379 register rtx temp = gen_reg_rtx (Pmode);
06380 register rtx val = force_operand (XEXP (x, 0), temp);
06381 if (val != temp)
06382 emit_move_insn (temp, val);
06383
06384 XEXP (x, 0) = temp;
06385 return x;
06386 }
06387 }
06388
06389 return x;
06390 }
06391
06392
06393
06394
06395
06396
06397 static void
06398 output_pic_addr_const (file, x, code)
06399 FILE *file;
06400 rtx x;
06401 int code;
06402 {
06403 char buf[256];
06404
06405 switch (GET_CODE (x))
06406 {
06407 case PC:
06408 if (flag_pic)
06409 putc ('.', file);
06410 else
06411 abort ();
06412 break;
06413
06414 case SYMBOL_REF:
06415 assemble_name (file, XSTR (x, 0));
06416 if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_FLAG (x))
06417 fputs ("@PLT", file);
06418 break;
06419
06420 case LABEL_REF:
06421 x = XEXP (x, 0);
06422
06423 case CODE_LABEL:
06424 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
06425 assemble_name (asm_out_file, buf);
06426 break;
06427
06428 case CONST_INT:
06429 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
06430 break;
06431
06432 case CONST:
06433
06434
06435 output_pic_addr_const (file, XEXP (x, 0), code);
06436 break;
06437
06438 case CONST_DOUBLE:
06439 if (GET_MODE (x) == VOIDmode)
06440 {
06441
06442 if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
06443 fprintf (file, "0x%lx%08lx",
06444 (unsigned long) CONST_DOUBLE_HIGH (x),
06445 (unsigned long) CONST_DOUBLE_LOW (x));
06446 else
06447 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
06448 }
06449 else
06450
06451
06452 output_operand_lossage ("floating constant misused");
06453 break;
06454
06455 case PLUS:
06456
06457 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
06458 {
06459 output_pic_addr_const (file, XEXP (x, 0), code);
06460 putc ('+', file);
06461 output_pic_addr_const (file, XEXP (x, 1), code);
06462 }
06463 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
06464 {
06465 output_pic_addr_const (file, XEXP (x, 1), code);
06466 putc ('+', file);
06467 output_pic_addr_const (file, XEXP (x, 0), code);
06468 }
06469 else
06470 abort ();
06471 break;
06472
06473 case MINUS:
06474 if (!TARGET_MACHO)
06475 putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
06476 output_pic_addr_const (file, XEXP (x, 0), code);
06477 putc ('-', file);
06478 output_pic_addr_const (file, XEXP (x, 1), code);
06479 if (!TARGET_MACHO)
06480 putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
06481 break;
06482
06483 case UNSPEC:
06484 if (XVECLEN (x, 0) != 1)
06485 abort ();
06486 output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
06487 switch (XINT (x, 1))
06488 {
06489 case UNSPEC_GOT:
06490 fputs ("@GOT", file);
06491 break;
06492 case UNSPEC_GOTOFF:
06493 fputs ("@GOTOFF", file);
06494 break;
06495 case UNSPEC_GOTPCREL:
06496 fputs ("@GOTPCREL(%rip)", file);
06497 break;
06498 case UNSPEC_GOTTPOFF:
06499
06500 fputs ("@GOTTPOFF", file);
06501 break;
06502 case UNSPEC_TPOFF:
06503 fputs ("@TPOFF", file);
06504 break;
06505 case UNSPEC_NTPOFF:
06506 if (TARGET_64BIT)
06507 fputs ("@TPOFF", file);
06508 else
06509 fputs ("@NTPOFF", file);
06510 break;
06511 case UNSPEC_DTPOFF:
06512 fputs ("@DTPOFF", file);
06513 break;
06514 case UNSPEC_GOTNTPOFF:
06515 if (TARGET_64BIT)
06516 fputs ("@GOTTPOFF(%rip)", file);
06517 else
06518 fputs ("@GOTNTPOFF", file);
06519 break;
06520 case UNSPEC_INDNTPOFF:
06521 fputs ("@INDNTPOFF", file);
06522 break;
06523 default:
06524 output_operand_lossage ("invalid UNSPEC as operand");
06525 break;
06526 }
06527 break;
06528
06529 default:
06530 output_operand_lossage ("invalid expression as operand");
06531 }
06532 }
06533
06534
06535
06536
06537 void
06538 i386_dwarf_output_addr_const (file, x)
06539 FILE *file;
06540 rtx x;
06541 {
06542 #ifdef ASM_QUAD
06543 fprintf (file, "%s", TARGET_64BIT ? ASM_QUAD : ASM_LONG);
06544 #else
06545 if (TARGET_64BIT)
06546 abort ();
06547 fprintf (file, "%s", ASM_LONG);
06548 #endif
06549 if (flag_pic)
06550 output_pic_addr_const (file, x, '\0');
06551 else
06552 output_addr_const (file, x);
06553 fputc ('\n', file);
06554 }
06555
06556
06557
06558
06559 void
06560 i386_output_dwarf_dtprel (file, size, x)
06561 FILE *file;
06562 int size;
06563 rtx x;
06564 {
06565 fputs (ASM_LONG, file);
06566 output_addr_const (file, x);
06567 fputs ("@DTPOFF", file);
06568 switch (size)
06569 {
06570 case 4:
06571 break;
06572 case 8:
06573 fputs (", 0", file);
06574 break;
06575 default:
06576 abort ();
06577 }
06578 }
06579
06580
06581
06582
06583
06584 rtx
06585 i386_simplify_dwarf_addr (orig_x)
06586 rtx orig_x;
06587 {
06588 rtx x = orig_x, y;
06589
06590 if (GET_CODE (x) == MEM)
06591 x = XEXP (x, 0);
06592
06593 if (TARGET_64BIT)
06594 {
06595 if (GET_CODE (x) != CONST
06596 || GET_CODE (XEXP (x, 0)) != UNSPEC
06597 || XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
06598 || GET_CODE (orig_x) != MEM)
06599 return orig_x;
06600 return XVECEXP (XEXP (x, 0), 0, 0);
06601 }
06602
06603 if (GET_CODE (x) != PLUS
06604 || GET_CODE (XEXP (x, 1)) != CONST)
06605 return orig_x;
06606
06607 if (GET_CODE (XEXP (x, 0)) == REG
06608 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
06609
06610 y = NULL;
06611 else if (GET_CODE (XEXP (x, 0)) == PLUS)
06612 {
06613
06614 y = XEXP (x, 0);
06615 if (GET_CODE (XEXP (y, 0)) == REG
06616 && REGNO (XEXP (y, 0)) == PIC_OFFSET_TABLE_REGNUM)
06617 y = XEXP (y, 1);
06618 else if (GET_CODE (XEXP (y, 1)) == REG
06619 && REGNO (XEXP (y, 1)) == PIC_OFFSET_TABLE_REGNUM)
06620 y = XEXP (y, 0);
06621 else
06622 return orig_x;
06623 if (GET_CODE (y) != REG
06624 && GET_CODE (y) != MULT
06625 && GET_CODE (y) != ASHIFT)
06626 return orig_x;
06627 }
06628 else
06629 return orig_x;
06630
06631 x = XEXP (XEXP (x, 1), 0);
06632 if (GET_CODE (x) == UNSPEC
06633 && ((XINT (x, 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
06634 || (XINT (x, 1) == UNSPEC_GOTOFF && GET_CODE (orig_x) != MEM)))
06635 {
06636 if (y)
06637 return gen_rtx_PLUS (Pmode, y, XVECEXP (x, 0, 0));
06638 return XVECEXP (x, 0, 0);
06639 }
06640
06641 if (GET_CODE (x) == PLUS
06642 && GET_CODE (XEXP (x, 0)) == UNSPEC
06643 && GET_CODE (XEXP (x, 1)) == CONST_INT
06644 && ((XINT (XEXP (x, 0), 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
06645 || (XINT (XEXP (x, 0), 1) == UNSPEC_GOTOFF
06646 && GET_CODE (orig_x) != MEM)))
06647 {
06648 x = gen_rtx_PLUS (VOIDmode, XVECEXP (XEXP (x, 0), 0, 0), XEXP (x, 1));
06649 if (y)
06650 return gen_rtx_PLUS (Pmode, y, x);
06651 return x;
06652 }
06653
06654 return orig_x;
06655 }
06656
06657 static void
06658 put_condition_code (code, mode, reverse, fp, file)
06659 enum rtx_code code;
06660 enum machine_mode mode;
06661 int reverse, fp;
06662 FILE *file;
06663 {
06664 const char *suffix;
06665
06666 if (mode == CCFPmode || mode == CCFPUmode)
06667 {
06668 enum rtx_code second_code, bypass_code;
06669 ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
06670 if (bypass_code != NIL || second_code != NIL)
06671 abort ();
06672 code = ix86_fp_compare_code_to_integer (code);
06673 mode = CCmode;
06674 }
06675 if (reverse)
06676 code = reverse_condition (code);
06677
06678 switch (code)
06679 {
06680 case EQ:
06681 suffix = "e";
06682 break;
06683 case NE:
06684 suffix = "ne";
06685 break;
06686 case GT:
06687 if (mode != CCmode && mode != CCNOmode && mode != CCGCmode)
06688 abort ();
06689 suffix = "g";
06690 break;
06691 case GTU:
06692
06693
06694 if (mode != CCmode)
06695 abort ();
06696 suffix = fp ? "nbe" : "a";
06697 break;
06698 case LT:
06699 if (mode == CCNOmode || mode == CCGOCmode)
06700 suffix = "s";
06701 else if (mode == CCmode || mode == CCGCmode)
06702 suffix = "l";
06703 else
06704 abort ();
06705 break;
06706 case LTU:
06707 if (mode != CCmode)
06708 abort ();
06709 suffix = "b";
06710 break;
06711 case GE:
06712 if (mode == CCNOmode || mode == CCGOCmode)
06713 suffix = "ns";
06714 else if (mode == CCmode || mode == CCGCmode)
06715 suffix = "ge";
06716 else
06717 abort ();
06718 break;
06719 case GEU:
06720
06721 if (mode != CCmode)
06722 abort ();
06723 suffix = fp ? "nb" : "ae";
06724 break;
06725 case LE:
06726 if (mode != CCmode && mode != CCGCmode && mode != CCNOmode)
06727 abort ();
06728 suffix = "le";
06729 break;
06730 case LEU:
06731 if (mode != CCmode)
06732 abort ();
06733 suffix = "be";
06734 break;
06735 case UNORDERED:
06736 suffix = fp ? "u" : "p";
06737 break;
06738 case ORDERED:
06739 suffix = fp ? "nu" : "np";
06740 break;
06741 default:
06742 abort ();
06743 }
06744 fputs (suffix, file);
06745 }
06746
06747 void
06748 print_reg (x, code, file)
06749 rtx x;
06750 int code;
06751 FILE *file;
06752 {
06753 if (REGNO (x) == ARG_POINTER_REGNUM
06754 || REGNO (x) == FRAME_POINTER_REGNUM
06755 || REGNO (x) == FLAGS_REG
06756 || REGNO (x) == FPSR_REG)
06757 abort ();
06758
06759 if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
06760 putc ('%', file);
06761
06762 if (code == 'w' || MMX_REG_P (x))
06763 code = 2;
06764 else if (code == 'b')
06765 code = 1;
06766 else if (code == 'k')
06767 code = 4;
06768 else if (code == 'q')
06769 code = 8;
06770 else if (code == 'y')
06771 code = 3;
06772 else if (code == 'h')
06773 code = 0;
06774 else
06775 code = GET_MODE_SIZE (GET_MODE (x));
06776
06777
06778
06779 if (REX_INT_REG_P (x))
06780 {
06781 if (!TARGET_64BIT)
06782 abort ();
06783 switch (code)
06784 {
06785 case 0:
06786 error ("extended registers have no high halves");
06787 break;
06788 case 1:
06789 fprintf (file, "r%ib", REGNO (x) - FIRST_REX_INT_REG + 8);
06790 break;
06791 case 2:
06792 fprintf (file, "r%iw", REGNO (x) - FIRST_REX_INT_REG + 8);
06793 break;
06794 case 4:
06795 fprintf (file, "r%id", REGNO (x) - FIRST_REX_INT_REG + 8);
06796 break;
06797 case 8:
06798 fprintf (file, "r%i", REGNO (x) - FIRST_REX_INT_REG + 8);
06799 break;
06800 default:
06801 error ("unsupported operand size for extended register");
06802 break;
06803 }
06804 return;
06805 }
06806 switch (code)
06807 {
06808 case 3:
06809 if (STACK_TOP_P (x))
06810 {
06811 fputs ("st(0)", file);
06812 break;
06813 }
06814
06815 case 8:
06816 case 4:
06817 case 12:
06818 if (! ANY_FP_REG_P (x))
06819 putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
06820
06821 case 16:
06822 case 2:
06823 fputs (hi_reg_name[REGNO (x)], file);
06824 break;
06825 case 1:
06826 fputs (qi_reg_name[REGNO (x)], file);
06827 break;
06828 case 0:
06829 fputs (qi_high_reg_name[REGNO (x)], file);
06830 break;
06831 default:
06832 abort ();
06833 }
06834 }
06835
06836
06837
06838
06839
06840 static const char *
06841 get_some_local_dynamic_name ()
06842 {
06843 rtx insn;
06844
06845 if (cfun->machine->some_ld_name)
06846 return cfun->machine->some_ld_name;
06847
06848 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
06849 if (INSN_P (insn)
06850 && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
06851 return cfun->machine->some_ld_name;
06852
06853 abort ();
06854 }
06855
06856 static int
06857 get_some_local_dynamic_name_1 (px, data)
06858 rtx *px;
06859 void *data ATTRIBUTE_UNUSED;
06860 {
06861 rtx x = *px;
06862
06863 if (GET_CODE (x) == SYMBOL_REF
06864 && local_dynamic_symbolic_operand (x, Pmode))
06865 {
06866 cfun->machine->some_ld_name = XSTR (x, 0);
06867 return 1;
06868 }
06869
06870 return 0;
06871 }
06872
06873
06874
06875
06876
06877
06878
06879
06880
06881
06882
06883
06884
06885
06886
06887
06888
06889
06890
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900 void
06901 print_operand (file, x, code)
06902 FILE *file;
06903 rtx x;
06904 int code;
06905 {
06906 if (code)
06907 {
06908 switch (code)
06909 {
06910 case '*':
06911 if (ASSEMBLER_DIALECT == ASM_ATT)
06912 putc ('*', file);
06913 return;
06914
06915 case '&':
06916 assemble_name (file, get_some_local_dynamic_name ());
06917 return;
06918
06919 case 'A':
06920 if (ASSEMBLER_DIALECT == ASM_ATT)
06921 putc ('*', file);
06922 else if (ASSEMBLER_DIALECT == ASM_INTEL)
06923 {
06924
06925
06926 if (GET_CODE (x) != REG)
06927 {
06928 putc ('[', file);
06929 PRINT_OPERAND (file, x, 0);
06930 putc (']', file);
06931 return;
06932 }
06933 }
06934 else
06935 abort ();
06936
06937 PRINT_OPERAND (file, x, 0);
06938 return;
06939
06940
06941 case 'L':
06942 if (ASSEMBLER_DIALECT == ASM_ATT)
06943 putc ('l', file);
06944 return;
06945
06946 case 'W':
06947 if (ASSEMBLER_DIALECT == ASM_ATT)
06948 putc ('w', file);
06949 return;
06950
06951 case 'B':
06952 if (ASSEMBLER_DIALECT == ASM_ATT)
06953 putc ('b', file);
06954 return;
06955
06956 case 'Q':
06957 if (ASSEMBLER_DIALECT == ASM_ATT)
06958 putc ('l', file);
06959 return;
06960
06961 case 'S':
06962 if (ASSEMBLER_DIALECT == ASM_ATT)
06963 putc ('s', file);
06964 return;
06965
06966 case 'T':
06967 if (ASSEMBLER_DIALECT == ASM_ATT)
06968 putc ('t', file);
06969 return;
06970
06971 case 'z':
06972
06973
06974 if (STACK_REG_P (x))
06975 return;
06976
06977
06978 if (ASSEMBLER_DIALECT == ASM_INTEL)
06979 return;
06980
06981
06982 switch (GET_MODE_SIZE (GET_MODE (x)))
06983 {
06984 case 2:
06985 #ifdef HAVE_GAS_FILDS_FISTS
06986 putc ('s', file);
06987 #endif
06988 return;
06989
06990 case 4:
06991 if (GET_MODE (x) == SFmode)
06992 {
06993 putc ('s', file);
06994 return;
06995 }
06996 else
06997 putc ('l', file);
06998 return;
06999
07000 case 12:
07001 case 16:
07002 putc ('t', file);
07003 return;
07004
07005 case 8:
07006 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
07007 {
07008 #ifdef GAS_MNEMONICS
07009 putc ('q', file);
07010 #else
07011 putc ('l', file);
07012 putc ('l', file);
07013 #endif
07014 }
07015 else
07016 putc ('l', file);
07017 return;
07018
07019 default:
07020 abort ();
07021 }
07022
07023 case 'b':
07024 case 'w':
07025 case 'k':
07026 case 'q':
07027 case 'h':
07028 case 'y':
07029 case 'X':
07030 case 'P':
07031 break;
07032
07033 case 's':
07034 if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT)
07035 {
07036 PRINT_OPERAND (file, x, 0);
07037 putc (',', file);
07038 }
07039 return;
07040
07041 case 'D':
07042
07043
07044
07045 switch (GET_CODE (x))
07046 {
07047 case EQ:
07048 case UNEQ:
07049 fputs ("eq", file);
07050 break;
07051 case LT:
07052 case UNLT:
07053 fputs ("lt", file);
07054 break;
07055 case LE:
07056 case UNLE:
07057 fputs ("le", file);
07058 break;
07059 case UNORDERED:
07060 fputs ("unord", file);
07061 break;
07062 case NE:
07063 case LTGT:
07064 fputs ("neq", file);
07065 break;
07066 case UNGE:
07067 case GE:
07068 fputs ("nlt", file);
07069 break;
07070 case UNGT:
07071 case GT:
07072 fputs ("nle", file);
07073 break;
07074 case ORDERED:
07075 fputs ("ord", file);
07076 break;
07077 default:
07078 abort ();
07079 break;
07080 }
07081 return;
07082 case 'O':
07083 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
07084 if (ASSEMBLER_DIALECT == ASM_ATT)
07085 {
07086 switch (GET_MODE (x))
07087 {
07088 case HImode: putc ('w', file); break;
07089 case SImode:
07090 case SFmode: putc ('l', file); break;
07091 case DImode:
07092 case DFmode: putc ('q', file); break;
07093 default: abort ();
07094 }
07095 putc ('.', file);
07096 }
07097 #endif
07098 return;
07099 case 'C':
07100 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 0, file);
07101 return;
07102 case 'F':
07103 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
07104 if (ASSEMBLER_DIALECT == ASM_ATT)
07105 putc ('.', file);
07106 #endif
07107 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 1, file);
07108 return;
07109
07110
07111 case 'c':
07112
07113
07114 if (GET_RTX_CLASS (GET_CODE (x)) != '<')
07115 {
07116 output_operand_lossage ("operand is neither a constant nor a condition code, invalid operand code 'c'");
07117 return;
07118 }
07119 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 0, file);
07120 return;
07121 case 'f':
07122 #ifdef HAVE_AS_IX86_CMOV_SUN_SYNTAX
07123 if (ASSEMBLER_DIALECT == ASM_ATT)
07124 putc ('.', file);
07125 #endif
07126 put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
07127 return;
07128 case '+':
07129 {
07130 rtx x;
07131
07132 if (!optimize || optimize_size || !TARGET_BRANCH_PREDICTION_HINTS)
07133 return;
07134
07135 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
07136 if (x)
07137 {
07138 int pred_val = INTVAL (XEXP (x, 0));
07139
07140 if (pred_val < REG_BR_PROB_BASE * 45 / 100
07141 || pred_val > REG_BR_PROB_BASE * 55 / 100)
07142 {
07143 int taken = pred_val > REG_BR_PROB_BASE / 2;
07144 int cputaken = final_forward_branch_p (current_output_insn) == 0;
07145
07146
07147
07148 if (taken != cputaken)
07149 {
07150
07151
07152 if (taken)
07153 fputs ("ds ; ", file);
07154 else
07155 fputs ("cs ; ", file);
07156 }
07157 }
07158 }
07159 return;
07160 }
07161 default:
07162 #ifdef __MINGW32__
07163 {
07164 char str[50];
07165 sprintf (str, "invalid operand code `%c'", code);
07166 output_operand_lossage (str);
07167 }
07168 #else
07169 output_operand_lossage ("invalid operand code `%c'", code);
07170 #endif
07171 }
07172 }
07173
07174 if (GET_CODE (x) == REG)
07175 {
07176 PRINT_REG (x, code, file);
07177 }
07178
07179 else if (GET_CODE (x) == MEM)
07180 {
07181
07182 if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P')
07183 {
07184 const char * size;
07185 switch (GET_MODE_SIZE (GET_MODE (x)))
07186 {
07187 case 1: size = "BYTE"; break;
07188 case 2: size = "WORD"; break;
07189 case 4: size = "DWORD"; break;
07190 case 8: size = "QWORD"; break;
07191 case 12: size = "XWORD"; break;
07192 case 16: size = "XMMWORD"; break;
07193 default:
07194 abort ();
07195 }
07196
07197
07198 if (code == 'b')
07199 size = "BYTE";
07200 else if (code == 'w')
07201 size = "WORD";
07202 else if (code == 'k')
07203 size = "DWORD";
07204
07205 fputs (size, file);
07206 fputs (" PTR ", file);
07207 }
07208
07209 x = XEXP (x, 0);
07210 if (flag_pic && CONSTANT_ADDRESS_P (x))
07211 output_pic_addr_const (file, x, code);
07212
07213 else if (CONSTANT_ADDRESS_P (x) && code == 'P'
07214 && GET_CODE (x) != CONST_INT)
07215 output_addr_const (file, x);
07216 else if (this_is_asm_operands && ! address_operand (x, VOIDmode))
07217 output_operand_lossage ("invalid constraints for operand");
07218 else
07219 output_address (x);
07220 }
07221
07222 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
07223 {
07224 REAL_VALUE_TYPE r;
07225 long l;
07226
07227 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
07228 REAL_VALUE_TO_TARGET_SINGLE (r, l);
07229
07230 if (ASSEMBLER_DIALECT == ASM_ATT)
07231 putc ('$', file);
07232 fprintf (file, "0x%lx", l);
07233 }
07234
07235
07236 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
07237 {
07238 char dstr[30];
07239
07240 real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
07241 fprintf (file, "%s", dstr);
07242 }
07243
07244 else if (GET_CODE (x) == CONST_DOUBLE
07245 && (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode))
07246 {
07247 char dstr[30];
07248
07249 real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
07250 fprintf (file, "%s", dstr);
07251 }
07252
07253 else
07254 {
07255 if (code != 'P')
07256 {
07257 if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
07258 {
07259 if (ASSEMBLER_DIALECT == ASM_ATT)
07260 putc ('$', file);
07261 }
07262 else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
07263 || GET_CODE (x) == LABEL_REF)
07264 {
07265 if (ASSEMBLER_DIALECT == ASM_ATT)
07266 putc ('$', file);
07267 else
07268 fputs ("OFFSET FLAT:", file);
07269 }
07270 }
07271 if (GET_CODE (x) == CONST_INT)
07272 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
07273 else if (flag_pic)
07274 output_pic_addr_const (file, x, code);
07275 else
07276 output_addr_const (file, x);
07277 }
07278 }
07279
07280
07281
07282 void
07283 print_operand_address (file, addr)
07284 FILE *file;
07285 register rtx addr;
07286 {
07287 struct ix86_address parts;
07288 rtx base, index, disp;
07289 int scale;
07290
07291 if (! ix86_decompose_address (addr, &parts))
07292 abort ();
07293
07294 base = parts.base;
07295 index = parts.index;
07296 disp = parts.disp;
07297 scale = parts.scale;
07298
07299 switch (parts.seg)
07300 {
07301 case SEG_DEFAULT:
07302 break;
07303 case SEG_FS:
07304 if (USER_LABEL_PREFIX[0] == 0)
07305 putc ('%', file);
07306 fputs ("fs:", file);
07307 break;
07308 case SEG_GS:
07309 if (USER_LABEL_PREFIX[0] == 0)
07310 putc ('%', file);
07311 fputs ("gs:", file);
07312 break;
07313 default:
07314 abort ();
07315 }
07316
07317 if (!base && !index)
07318 {
07319
07320
07321 if (GET_CODE (disp) == CONST_INT)
07322 {
07323 if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT)
07324 {
07325 if (USER_LABEL_PREFIX[0] == 0)
07326 putc ('%', file);
07327 fputs ("ds:", file);
07328 }
07329 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
07330 }
07331 else if (flag_pic)
07332 output_pic_addr_const (file, disp, 0);
07333 else
07334 output_addr_const (file, disp);
07335
07336
07337 if (TARGET_64BIT
07338 && ((GET_CODE (disp) == SYMBOL_REF
07339 && ! tls_symbolic_operand (disp, GET_MODE (disp)))
07340 || GET_CODE (disp) == LABEL_REF
07341 || (GET_CODE (disp) == CONST
07342 && GET_CODE (XEXP (disp, 0)) == PLUS
07343 && (GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
07344 || GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
07345 && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)))
07346 fputs ("(%rip)", file);
07347 }
07348 else
07349 {
07350 if (ASSEMBLER_DIALECT == ASM_ATT)
07351 {
07352 if (disp)
07353 {
07354 if (flag_pic)
07355 output_pic_addr_const (file, disp, 0);
07356 else if (GET_CODE (disp) == LABEL_REF)
07357 output_asm_label (disp);
07358 else
07359 output_addr_const (file, disp);
07360 }
07361
07362 putc ('(', file);
07363 if (base)
07364 PRINT_REG (base, 0, file);
07365 if (index)
07366 {
07367 putc (',', file);
07368 PRINT_REG (index, 0, file);
07369 if (scale != 1)
07370 fprintf (file, ",%d", scale);
07371 }
07372 putc (')', file);
07373 }
07374 else
07375 {
07376 rtx offset = NULL_RTX;
07377
07378 if (disp)
07379 {
07380
07381 if (GET_CODE (disp) == CONST
07382 && GET_CODE (XEXP (disp, 0)) == PLUS
07383 && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
07384 {
07385 offset = XEXP (XEXP (disp, 0), 1);
07386 disp = gen_rtx_CONST (VOIDmode,
07387 XEXP (XEXP (disp, 0), 0));
07388 }
07389
07390 if (flag_pic)
07391 output_pic_addr_const (file, disp, 0);
07392 else if (GET_CODE (disp) == LABEL_REF)
07393 output_asm_label (disp);
07394 else if (GET_CODE (disp) == CONST_INT)
07395 offset = disp;
07396 else
07397 output_addr_const (file, disp);
07398 }
07399
07400 putc ('[', file);
07401 if (base)
07402 {
07403 PRINT_REG (base, 0, file);
07404 if (offset)
07405 {
07406 if (INTVAL (offset) >= 0)
07407 putc ('+', file);
07408 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (offset));
07409 }
07410 }
07411 else if (offset)
07412 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (offset));
07413 else
07414 putc ('0', file);
07415
07416 if (index)
07417 {
07418 putc ('+', file);
07419 PRINT_REG (index, 0, file);
07420 if (scale != 1)
07421 fprintf (file, "*%d", scale);
07422 }
07423 putc (']', file);
07424 }
07425 }
07426 }
07427
07428 bool
07429 output_addr_const_extra (file, x)
07430 FILE *file;
07431 rtx x;
07432 {
07433 rtx op;
07434
07435 if (GET_CODE (x) != UNSPEC)
07436 return false;
07437
07438 op = XVECEXP (x, 0, 0);
07439 switch (XINT (x, 1))
07440 {
07441 case UNSPEC_GOTTPOFF:
07442 output_addr_const (file, op);
07443
07444 fputs ("@GOTTPOFF", file);
07445 break;
07446 case UNSPEC_TPOFF:
07447 output_addr_const (file, op);
07448 fputs ("@TPOFF", file);
07449 break;
07450 case UNSPEC_NTPOFF:
07451 output_addr_const (file, op);
07452 if (TARGET_64BIT)
07453 fputs ("@TPOFF", file);
07454 else
07455 fputs ("@NTPOFF", file);
07456 break;
07457 case UNSPEC_DTPOFF:
07458 output_addr_const (file, op);
07459 fputs ("@DTPOFF", file);
07460 break;
07461 case UNSPEC_GOTNTPOFF:
07462 output_addr_const (file, op);
07463 if (TARGET_64BIT)
07464 fputs ("@GOTTPOFF(%rip)", file);
07465 else
07466 fputs ("@GOTNTPOFF", file);
07467 break;
07468 case UNSPEC_INDNTPOFF:
07469 output_addr_const (file, op);
07470 fputs ("@INDNTPOFF", file);
07471 break;
07472
07473 default:
07474 return false;
07475 }
07476
07477 return true;
07478 }
07479
07480
07481
07482
07483
07484
07485
07486 void
07487 split_di (operands, num, lo_half, hi_half)
07488 rtx operands[];
07489 int num;
07490 rtx lo_half[], hi_half[];
07491 {
07492 while (num--)
07493 {
07494 rtx op = operands[num];
07495
07496
07497
07498 if (GET_CODE (op) == MEM)
07499 {
07500 lo_half[num] = adjust_address (op, SImode, 0);
07501 hi_half[num] = adjust_address (op, SImode, 4);
07502 }
07503 else
07504 {
07505 lo_half[num] = simplify_gen_subreg (SImode, op,
07506 GET_MODE (op) == VOIDmode
07507 ? DImode : GET_MODE (op), 0);
07508 hi_half[num] = simplify_gen_subreg (SImode, op,
07509 GET_MODE (op) == VOIDmode
07510 ? DImode : GET_MODE (op), 4);
07511 }
07512 }
07513 }
07514
07515
07516
07517
07518
07519
07520 void
07521 split_ti (operands, num, lo_half, hi_half)
07522 rtx operands[];
07523 int num;
07524 rtx lo_half[], hi_half[];
07525 {
07526 while (num--)
07527 {
07528 rtx op = operands[num];
07529
07530
07531
07532 if (GET_CODE (op) == MEM)
07533 {
07534 lo_half[num] = adjust_address (op, DImode, 0);
07535 hi_half[num] = adjust_address (op, DImode, 8);
07536 }
07537 else
07538 {
07539 lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0);
07540 hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8);
07541 }
07542 }
07543 }
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553 #ifndef SYSV386_COMPAT
07554
07555
07556
07557
07558
07559 #define SYSV386_COMPAT 1
07560 #endif
07561
07562 const char *
07563 output_387_binary_op (insn, operands)
07564 rtx insn;
07565 rtx *operands;
07566 {
07567 static char buf[30];
07568 const char *p;
07569 const char *ssep;
07570 int is_sse = SSE_REG_P (operands[0]) | SSE_REG_P (operands[1]) | SSE_REG_P (operands[2]);
07571
07572 #ifdef ENABLE_CHECKING
07573
07574
07575 if (STACK_REG_P (operands[0])
07576 && ((REG_P (operands[1])
07577 && REGNO (operands[0]) == REGNO (operands[1])
07578 && (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM))
07579 || (REG_P (operands[2])
07580 && REGNO (operands[0]) == REGNO (operands[2])
07581 && (STACK_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)))
07582 && (STACK_TOP_P (operands[1]) || STACK_TOP_P (operands[2])))
07583 ;
07584 else if (!is_sse)
07585 abort ();
07586 #endif
07587
07588 switch (GET_CODE (operands[3]))
07589 {
07590 case PLUS:
07591 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
07592 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
07593 p = "fiadd";
07594 else
07595 p = "fadd";
07596 ssep = "add";
07597 break;
07598
07599 case MINUS:
07600 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
07601 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
07602 p = "fisub";
07603 else
07604 p = "fsub";
07605 ssep = "sub";
07606 break;
07607
07608 case MULT:
07609 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
07610 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
07611 p = "fimul";
07612 else
07613 p = "fmul";
07614 ssep = "mul";
07615 break;
07616
07617 case DIV:
07618 if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
07619 || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
07620 p = "fidiv";
07621 else
07622 p = "fdiv";
07623 ssep = "div";
07624 break;
07625
07626 default:
07627 abort ();
07628 }
07629
07630 if (is_sse)
07631 {
07632 strcpy (buf, ssep);
07633 if (GET_MODE (operands[0]) == SFmode)
07634 strcat (buf, "ss\t{%2, %0|%0, %2}");
07635 else
07636 strcat (buf, "sd\t{%2, %0|%0, %2}");
07637 return buf;
07638 }
07639 strcpy (buf, p);
07640
07641 switch (GET_CODE (operands[3]))
07642 {
07643 case MULT:
07644 case PLUS:
07645 if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
07646 {
07647 rtx temp = operands[2];
07648 operands[2] = operands[1];
07649 operands[1] = temp;
07650 }
07651
07652
07653
07654 if (GET_CODE (operands[2]) == MEM)
07655 {
07656 p = "%z2\t%2";
07657 break;
07658 }
07659
07660 if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
07661 {
07662 if (STACK_TOP_P (operands[0]))
07663
07664
07665
07666
07667
07668
07669
07670 p = "p\t{%0, %2|%2, %0}";
07671 else
07672 p = "p\t{%2, %0|%0, %2}";
07673 break;
07674 }
07675
07676 if (STACK_TOP_P (operands[0]))
07677 p = "\t{%y2, %0|%0, %y2}";
07678 else
07679 p = "\t{%2, %0|%0, %2}";
07680 break;
07681
07682 case MINUS:
07683 case DIV:
07684 if (GET_CODE (operands[1]) == MEM)
07685 {
07686 p = "r%z1\t%1";
07687 break;
07688 }
07689
07690 if (GET_CODE (operands[2]) == MEM)
07691 {
07692 p = "%z2\t%2";
07693 break;
07694 }
07695
07696 if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
07697 {
07698 #if SYSV386_COMPAT
07699
07700
07701
07702
07703
07704
07705 if (STACK_TOP_P (operands[0]))
07706 p = "{p\t%0, %2|rp\t%2, %0}";
07707 else
07708 p = "{rp\t%2, %0|p\t%0, %2}";
07709 #else
07710 if (STACK_TOP_P (operands[0]))
07711
07712 p = "rp\t{%0, %2|%2, %0}";
07713 else
07714 p = "p\t{%2, %0|%0, %2}";
07715 #endif
07716 break;
07717 }
07718
07719 if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
07720 {
07721 #if SYSV386_COMPAT
07722 if (STACK_TOP_P (operands[0]))
07723 p = "{rp\t%0, %1|p\t%1, %0}";
07724 else
07725 p = "{p\t%1, %0|rp\t%0, %1}";
07726 #else
07727 if (STACK_TOP_P (operands[0]))
07728 p = "p\t{%0, %1|%1, %0}";
07729 else
07730 p = "rp\t{%1, %0|%0, %1}";
07731 #endif
07732 break;
07733 }
07734
07735 if (STACK_TOP_P (operands[0]))
07736 {
07737 if (STACK_TOP_P (operands[1]))
07738 p = "\t{%y2, %0|%0, %y2}";
07739 else
07740 p = "r\t{%y1, %0|%0, %y1}";
07741 break;
07742 }
07743 else if (STACK_TOP_P (operands[1]))
07744 {
07745 #if SYSV386_COMPAT
07746 p = "{\t%1, %0|r\t%0, %1}";
07747 #else
07748 p = "r\t{%1, %0|%0, %1}";
07749 #endif
07750 }
07751 else
07752 {
07753 #if SYSV386_COMPAT
07754 p = "{r\t%2, %0|\t%0, %2}";
07755 #else
07756 p = "\t{%2, %0|%0, %2}";
07757 #endif
07758 }
07759 break;
07760
07761 default:
07762 abort ();
07763 }
07764
07765 strcat (buf, p);
07766 return buf;
07767 }
07768
07769
07770
07771
07772 void
07773 emit_i387_cw_initialization (normal, round_down)
07774 rtx normal, round_down;
07775 {
07776 rtx reg = gen_reg_rtx (HImode);
07777
07778 emit_insn (gen_x86_fnstcw_1 (normal));
07779 emit_move_insn (reg, normal);
07780 if (!TARGET_PARTIAL_REG_STALL && !optimize_size
07781 && !TARGET_64BIT)
07782 emit_insn (gen_movsi_insv_1 (reg, GEN_INT (0xc)));
07783 else
07784 emit_insn (gen_iorhi3 (reg, reg, GEN_INT (0xc00)));
07785 emit_move_insn (round_down, reg);
07786 }
07787
07788
07789
07790
07791
07792 const char *
07793 output_fix_trunc (insn, operands)
07794 rtx insn;
07795 rtx *operands;
07796 {
07797 int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
07798 int dimode_p = GET_MODE (operands[0]) == DImode;
07799
07800
07801
07802
07803 if (dimode_p && !stack_top_dies)
07804 output_asm_insn ("fld\t%y1", operands);
07805
07806 if (!STACK_TOP_P (operands[1]))
07807 abort ();
07808
07809 if (GET_CODE (operands[0]) != MEM)
07810 abort ();
07811
07812 output_asm_insn ("fldcw\t%3", operands);
07813 if (stack_top_dies || dimode_p)
07814 output_asm_insn ("fistp%z0\t%0", operands);
07815 else
07816 output_asm_insn ("fist%z0\t%0", operands);
07817 output_asm_insn ("fldcw\t%2", operands);
07818
07819 return "";
07820 }
07821
07822
07823
07824
07825
07826 const char *
07827 output_fp_compare (insn, operands, eflags_p, unordered_p)
07828 rtx insn;
07829 rtx *operands;
07830 int eflags_p, unordered_p;
07831 {
07832 int stack_top_dies;
07833 rtx cmp_op0 = operands[0];
07834 rtx cmp_op1 = operands[1];
07835 int is_sse = SSE_REG_P (operands[0]) | SSE_REG_P (operands[1]);
07836
07837 if (eflags_p == 2)
07838 {
07839 cmp_op0 = cmp_op1;
07840 cmp_op1 = operands[2];
07841 }
07842 if (is_sse)
07843 {
07844 if (GET_MODE (operands[0]) == SFmode)
07845 if (unordered_p)
07846 return "ucomiss\t{%1, %0|%0, %1}";
07847 else
07848 return "comiss\t{%1, %0|%0, %1}";
07849 else
07850 if (unordered_p)
07851 return "ucomisd\t{%1, %0|%0, %1}";
07852 else
07853 return "comisd\t{%1, %0|%0, %1}";
07854 }
07855
07856 if (! STACK_TOP_P (cmp_op0))
07857 abort ();
07858
07859 stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
07860
07861 if (STACK_REG_P (cmp_op1)
07862 && stack_top_dies
07863 && find_regno_note (insn, REG_DEAD, REGNO (cmp_op1))
07864 && REGNO (cmp_op1) != FIRST_STACK_REG)
07865 {
07866
07867
07868
07869
07870 if (eflags_p == 1)
07871 {
07872
07873
07874 if (unordered_p)
07875 output_asm_insn ("fucomip\t{%y1, %0|%0, %y1}", operands);
07876 else
07877 output_asm_insn ("fcomip\t{%y1, %0|%0, %y1}", operands);
07878 return "fstp\t%y0";
07879 }
07880 else
07881 {
07882 if (eflags_p == 2)
07883 {
07884 if (unordered_p)
07885 return "fucompp\n\tfnstsw\t%0";
07886 else
07887 return "fcompp\n\tfnstsw\t%0";
07888 }
07889 else
07890 {
07891 if (unordered_p)
07892 return "fucompp";
07893 else
07894 return "fcompp";
07895 }
07896 }
07897 }
07898 else
07899 {
07900
07901
07902 static const char * const alt[24] =
07903 {
07904 "fcom%z1\t%y1",
07905 "fcomp%z1\t%y1",
07906 "fucom%z1\t%y1",
07907 "fucomp%z1\t%y1",
07908
07909 "ficom%z1\t%y1",
07910 "ficomp%z1\t%y1",
07911 NULL,
07912 NULL,
07913
07914 "fcomi\t{%y1, %0|%0, %y1}",
07915 "fcomip\t{%y1, %0|%0, %y1}",
07916 "fucomi\t{%y1, %0|%0, %y1}",
07917 "fucomip\t{%y1, %0|%0, %y1}",
07918
07919 NULL,
07920 NULL,
07921 NULL,
07922 NULL,
07923
07924 "fcom%z2\t%y2\n\tfnstsw\t%0",
07925 "fcomp%z2\t%y2\n\tfnstsw\t%0",
07926 "fucom%z2\t%y2\n\tfnstsw\t%0",
07927 "fucomp%z2\t%y2\n\tfnstsw\t%0",
07928
07929 "ficom%z2\t%y2\n\tfnstsw\t%0",
07930 "ficomp%z2\t%y2\n\tfnstsw\t%0",
07931 NULL,
07932 NULL
07933 };
07934
07935 int mask;
07936 const char *ret;
07937
07938 mask = eflags_p << 3;
07939 mask |= (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT) << 2;
07940 mask |= unordered_p << 1;
07941 mask |= stack_top_dies;
07942
07943 if (mask >= 24)
07944 abort ();
07945 ret = alt[mask];
07946 if (ret == NULL)
07947 abort ();
07948
07949 return ret;
07950 }
07951 }
07952
07953 void
07954 ix86_output_addr_vec_elt (file, value)
07955 FILE *file;
07956 int value;
07957 {
07958 const char *directive = ASM_LONG;
07959
07960 if (TARGET_64BIT)
07961 {
07962 #ifdef ASM_QUAD
07963 directive = ASM_QUAD;
07964 #else
07965 abort ();
07966 #endif
07967 }
07968
07969 fprintf (file, "%s%s%d\n", directive, LPREFIX, value);
07970 }
07971
07972 void
07973 ix86_output_addr_diff_elt (file, value, rel)
07974 FILE *file;
07975 int value, rel;
07976 {
07977 if (TARGET_64BIT)
07978 fprintf (file, "%s%s%d-%s%d\n",
07979 ASM_LONG, LPREFIX, value, LPREFIX, rel);
07980 else if (HAVE_AS_GOTOFF_IN_DATA)
07981 fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
07982 #if TARGET_MACHO
07983 else if (TARGET_MACHO)
07984 fprintf (file, "%s%s%d-%s\n", ASM_LONG, LPREFIX, value,
07985 machopic_function_base_name () + 1);
07986 #endif
07987 else
07988 asm_fprintf (file, "%s%U%s+[.-%s%d]\n",
07989 ASM_LONG, GOT_SYMBOL_NAME, LPREFIX, value);
07990 }
07991
07992
07993
07994
07995 void
07996 ix86_expand_clear (dest)
07997 rtx dest;
07998 {
07999 rtx tmp;
08000
08001
08002 if (!reload_completed)
08003 abort ();
08004
08005
08006 if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
08007 dest = gen_rtx_REG (SImode, REGNO (dest));
08008
08009 tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
08010
08011
08012 if (reload_completed && (!TARGET_USE_MOV0 || optimize_size))
08013 {
08014 rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, 17));
08015 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
08016 }
08017
08018 emit_insn (tmp);
08019 }
08020
08021
08022
08023
08024 static rtx
08025 maybe_get_pool_constant (x)
08026 rtx x;
08027 {
08028 x = XEXP (x, 0);
08029
08030 if (flag_pic && ! TARGET_64BIT)
08031 {
08032 if (GET_CODE (x) != PLUS)
08033 return NULL_RTX;
08034 if (XEXP (x, 0) != pic_offset_table_rtx)
08035 return NULL_RTX;
08036 x = XEXP (x, 1);
08037 if (GET_CODE (x) != CONST)
08038 return NULL_RTX;
08039 x = XEXP (x, 0);
08040 if (GET_CODE (x) != UNSPEC)
08041 return NULL_RTX;
08042 if (XINT (x, 1) != UNSPEC_GOTOFF)
08043 return NULL_RTX;
08044 x = XVECEXP (x, 0, 0);
08045 }
08046
08047 if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
08048 return get_pool_constant (x);
08049
08050 return NULL_RTX;
08051 }
08052
08053 void
08054 ix86_expand_move (mode, operands)
08055 enum machine_mode mode;
08056 rtx operands[];
08057 {
08058 int strict = (reload_in_progress || reload_completed);
08059 rtx op0, op1;
08060 enum tls_model model;
08061
08062 op0 = operands[0];
08063 op1 = operands[1];
08064
08065 model = tls_symbolic_operand (op1, Pmode);
08066 if (model)
08067 {
08068 op1 = legitimize_tls_address (op1, model, true);
08069 op1 = force_operand (op1, op0);
08070 if (op1 == op0)
08071 return;
08072 }
08073
08074 if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
08075 {
08076 #if TARGET_MACHO
08077 if (MACHOPIC_PURE)
08078 {
08079 rtx temp = ((reload_in_progress
08080 || ((op0 && GET_CODE (op0) == REG)
08081 && mode == Pmode))
08082 ? op0 : gen_reg_rtx (Pmode));
08083 op1 = machopic_indirect_data_reference (op1, temp);
08084 op1 = machopic_legitimize_pic_address (op1, mode,
08085 temp == op1 ? 0 : temp);
08086 }
08087 else
08088 {
08089 if (MACHOPIC_INDIRECT)
08090 op1 = machopic_indirect_data_reference (op1, 0);
08091 }
08092 if (op0 != op1)
08093 {
08094 insn = gen_rtx_SET (VOIDmode, op0, op1);
08095 emit_insn (insn);
08096 }
08097 return;
08098 #endif
08099 if (GET_CODE (op0) == MEM)
08100 op1 = force_reg (Pmode, op1);
08101 else
08102 {
08103 rtx temp = op0;
08104 if (GET_CODE (temp) != REG)
08105 temp = gen_reg_rtx (Pmode);
08106 temp = legitimize_pic_address (op1, temp);
08107 if (temp == op0)
08108 return;
08109 op1 = temp;
08110 }
08111 }
08112 else
08113 {
08114 if (GET_CODE (op0) == MEM
08115 && (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
08116 || !push_operand (op0, mode))
08117 && GET_CODE (op1) == MEM)
08118 op1 = force_reg (mode, op1);
08119
08120 if (push_operand (op0, mode)
08121 && ! general_no_elim_operand (op1, mode))
08122 op1 = copy_to_mode_reg (mode, op1);
08123
08124
08125
08126 if (TARGET_64BIT && mode == DImode
08127 && immediate_operand (op1, mode)
08128 && !x86_64_zero_extended_value (op1)
08129 && !register_operand (op0, mode)
08130 && optimize && !reload_completed && !reload_in_progress)
08131 op1 = copy_to_mode_reg (mode, op1);
08132
08133 if (FLOAT_MODE_P (mode))
08134 {
08135
08136
08137
08138
08139 if (strict)
08140 ;
08141 else if (GET_CODE (op1) == CONST_DOUBLE)
08142 {
08143 op1 = validize_mem (force_const_mem (mode, op1));
08144 if (!register_operand (op0, mode))
08145 {
08146 rtx temp = gen_reg_rtx (mode);
08147 emit_insn (gen_rtx_SET (VOIDmode, temp, op1));
08148 emit_move_insn (op0, temp);
08149 return;
08150 }
08151 }
08152 }
08153 }
08154
08155 emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
08156 }
08157
08158 void
08159 ix86_expand_vector_move (mode, operands)
08160 enum machine_mode mode;
08161 rtx operands[];
08162 {
08163
08164
08165
08166
08167 if ((reload_in_progress | reload_completed) == 0
08168 && register_operand (operands[0], mode)
08169 && CONSTANT_P (operands[1]) && operands[1] != CONST0_RTX (mode))
08170 {
08171 operands[1] = force_const_mem (mode, operands[1]);
08172 emit_move_insn (operands[0], operands[1]);
08173 return;
08174 }
08175
08176
08177 if (!no_new_pseudos
08178 && !register_operand (operands[0], mode)
08179 && !register_operand (operands[1], mode))
08180 {
08181 rtx temp = force_reg (GET_MODE (operands[1]), operands[1]);
08182 emit_move_insn (operands[0], temp);
08183 return;
08184 }
08185
08186 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
08187 }
08188
08189
08190
08191
08192
08193 void
08194 ix86_expand_binary_operator (code, mode, operands)
08195 enum rtx_code code;
08196 enum machine_mode mode;
08197 rtx operands[];
08198 {
08199 int matching_memory;
08200 rtx src1, src2, dst, op, clob;
08201
08202 dst = operands[0];
08203 src1 = operands[1];
08204 src2 = operands[2];
08205
08206
08207 if (GET_RTX_CLASS (code) == 'c'
08208 && (rtx_equal_p (dst, src2)
08209 || immediate_operand (src1, mode)))
08210 {
08211 rtx temp = src1;
08212 src1 = src2;
08213 src2 = temp;
08214 }
08215
08216
08217
08218 matching_memory = 0;
08219 if (GET_CODE (dst) == MEM)
08220 {
08221 if (rtx_equal_p (dst, src1))
08222 matching_memory = 1;
08223 else if (GET_RTX_CLASS (code) == 'c'
08224 && rtx_equal_p (dst, src2))
08225 matching_memory = 2;
08226 else
08227 dst = gen_reg_rtx (mode);
08228 }
08229
08230
08231 if (GET_CODE (src1) == MEM && GET_CODE (src2) == MEM)
08232 {
08233 if (matching_memory != 2)
08234 src2 = force_reg (mode, src2);
08235 else
08236 src1 = force_reg (mode, src1);
08237 }
08238
08239
08240
08241 if ((CONSTANT_P (src1)
08242 || (!matching_memory && GET_CODE (src1) == MEM))
08243 && GET_RTX_CLASS (code) != 'c')
08244 src1 = force_reg (mode, src1);
08245
08246
08247 if (optimize && ! no_new_pseudos)
08248 {
08249 if (GET_CODE (dst) == MEM)
08250 dst = gen_reg_rtx (mode);
08251 if (GET_CODE (src1) == MEM)
08252 src1 = force_reg (mode, src1);
08253 if (GET_CODE (src2) == MEM)
08254 src2 = force_reg (mode, src2);
08255 }
08256
08257
08258
08259 op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, mode, src1, src2));
08260 if (reload_in_progress)
08261 {
08262
08263
08264 if (code != PLUS)
08265 abort ();
08266 emit_insn (op);
08267 }
08268 else
08269 {
08270 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
08271 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
08272 }
08273
08274
08275 if (dst != operands[0])
08276 emit_move_insn (operands[0], dst);
08277 }
08278
08279
08280
08281
08282 int
08283 ix86_binary_operator_ok (code, mode, operands)
08284 enum rtx_code code;
08285 enum machine_mode mode ATTRIBUTE_UNUSED;
08286 rtx operands[3];
08287 {
08288
08289 if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
08290 return 0;
08291
08292 if (CONSTANT_P (operands[1]) && GET_RTX_CLASS (code) != 'c')
08293 return 0;
08294
08295 if (GET_CODE (operands[0]) == MEM
08296 && ! (rtx_equal_p (operands[0], operands[1])
08297 || (GET_RTX_CLASS (code) == 'c'
08298 && rtx_equal_p (operands[0], operands[2]))))
08299 return 0;
08300
08301
08302 if (GET_CODE (operands[1]) == MEM
08303 && GET_RTX_CLASS (code) != 'c'
08304 && ! rtx_equal_p (operands[0], operands[1]))
08305 return 0;
08306 return 1;
08307 }
08308
08309
08310
08311
08312
08313 void
08314 ix86_expand_unary_operator (code, mode, operands)
08315 enum rtx_code code;
08316 enum machine_mode mode;
08317 rtx operands[];
08318 {
08319 int matching_memory;
08320 rtx src, dst, op, clob;
08321
08322 dst = operands[0];
08323 src = operands[1];
08324
08325
08326
08327 matching_memory = 0;
08328 if (GET_CODE (dst) == MEM)
08329 {
08330 if (rtx_equal_p (dst, src))
08331 matching_memory = 1;
08332 else
08333 dst = gen_reg_rtx (mode);
08334 }
08335
08336
08337 if (!matching_memory && GET_CODE (src) == MEM)
08338 src = force_reg (mode, src);
08339
08340
08341 if (optimize && ! no_new_pseudos)
08342 {
08343 if (GET_CODE (dst) == MEM)
08344 dst = gen_reg_rtx (mode);
08345 if (GET_CODE (src) == MEM)
08346 src = force_reg (mode, src);
08347 }
08348
08349
08350
08351 op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_e (code, mode, src));
08352 if (reload_in_progress || code == NOT)
08353 {
08354
08355
08356 if (code != NOT)
08357 abort ();
08358 emit_insn (op);
08359 }
08360 else
08361 {
08362 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
08363 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
08364 }
08365
08366
08367 if (dst != operands[0])
08368 emit_move_insn (operands[0], dst);
08369 }
08370
08371
08372
08373
08374 int
08375 ix86_unary_operator_ok (code, mode, operands)
08376 enum rtx_code code ATTRIBUTE_UNUSED;
08377 enum machine_mode mode ATTRIBUTE_UNUSED;
08378 rtx operands[2] ATTRIBUTE_UNUSED;
08379 {
08380
08381 if ((GET_CODE (operands[0]) == MEM
08382 || GET_CODE (operands[1]) == MEM)
08383 && ! rtx_equal_p (operands[0], operands[1]))
08384 return FALSE;
08385 return TRUE;
08386 }
08387
08388
08389
08390
08391
08392 int
08393 ix86_match_ccmode (insn, req_mode)
08394 rtx insn;
08395 enum machine_mode req_mode;
08396 {
08397 rtx set;
08398 enum machine_mode set_mode;
08399
08400 set = PATTERN (insn);
08401 if (GET_CODE (set) == PARALLEL)
08402 set = XVECEXP (set, 0, 0);
08403 if (GET_CODE (set) != SET)
08404 abort ();
08405 if (GET_CODE (SET_SRC (set)) != COMPARE)
08406 abort ();
08407
08408 set_mode = GET_MODE (SET_DEST (set));
08409 switch (set_mode)
08410 {
08411 case CCNOmode:
08412 if (req_mode != CCNOmode
08413 && (req_mode != CCmode
08414 || XEXP (SET_SRC (set), 1) != const0_rtx))
08415 return 0;
08416 break;
08417 case CCmode:
08418 if (req_mode == CCGCmode)
08419 return 0;
08420
08421 case CCGCmode:
08422 if (req_mode == CCGOCmode || req_mode == CCNOmode)
08423 return 0;
08424
08425 case CCGOCmode:
08426 if (req_mode == CCZmode)
08427 return 0;
08428
08429 case CCZmode:
08430 break;
08431
08432 default:
08433 abort ();
08434 }
08435
08436 return (GET_MODE (SET_SRC (set)) == set_mode);
08437 }
08438
08439
08440
08441 static rtx
08442 ix86_expand_int_compare (code, op0, op1)
08443 enum rtx_code code;
08444 rtx op0, op1;
08445 {
08446 enum machine_mode cmpmode;
08447 rtx tmp, flags;
08448
08449 cmpmode = SELECT_CC_MODE (code, op0, op1);
08450 flags = gen_rtx_REG (cmpmode, FLAGS_REG);
08451
08452
08453
08454 tmp = gen_rtx_COMPARE (cmpmode, op0, op1);
08455 emit_insn (gen_rtx_SET (VOIDmode, flags, tmp));
08456
08457
08458
08459 return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
08460 }
08461
08462
08463
08464
08465 enum machine_mode
08466 ix86_fp_compare_mode (code)
08467 enum rtx_code code ATTRIBUTE_UNUSED;
08468 {
08469
08470
08471
08472
08473
08474 return TARGET_IEEE_FP ? CCFPUmode : CCFPmode;
08475 }
08476
08477 enum machine_mode
08478 ix86_cc_mode (code, op0, op1)
08479 enum rtx_code code;
08480 rtx op0, op1;
08481 {
08482 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
08483 return ix86_fp_compare_mode (code);
08484 switch (code)
08485 {
08486
08487 case EQ:
08488 case NE:
08489 return CCZmode;
08490
08491 case GEU:
08492 case GTU:
08493 case LTU:
08494 case LEU:
08495 return CCmode;
08496
08497
08498 case GE:
08499 case LT:
08500 if (op1 == const0_rtx)
08501 return CCGOCmode;
08502 else
08503
08504 return CCGCmode;
08505
08506
08507
08508
08509 case GT:
08510 case LE:
08511 if (op1 == const0_rtx)
08512 return CCNOmode;
08513 else
08514 return CCGCmode;
08515
08516
08517 case USE:
08518 return CCmode;
08519 default:
08520 abort ();
08521 }
08522 }
08523
08524
08525
08526 int
08527 ix86_use_fcomi_compare (code)
08528 enum rtx_code code ATTRIBUTE_UNUSED;
08529 {
08530 enum rtx_code swapped_code = swap_condition (code);
08531 return ((ix86_fp_comparison_cost (code) == ix86_fp_comparison_fcomi_cost (code))
08532 || (ix86_fp_comparison_cost (swapped_code)
08533 == ix86_fp_comparison_fcomi_cost (swapped_code)));
08534 }
08535
08536
08537
08538
08539
08540 static enum rtx_code
08541 ix86_prepare_fp_compare_args (code, pop0, pop1)
08542 enum rtx_code code;
08543 rtx *pop0, *pop1;
08544 {
08545 enum machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
08546 rtx op0 = *pop0, op1 = *pop1;
08547 enum machine_mode op_mode = GET_MODE (op0);
08548 int is_sse = SSE_REG_P (op0) | SSE_REG_P (op1);
08549
08550
08551
08552
08553
08554 if (!is_sse
08555 && (fpcmp_mode == CCFPUmode
08556 || op_mode == XFmode
08557 || op_mode == TFmode
08558 || ix86_use_fcomi_compare (code)))
08559 {
08560 op0 = force_reg (op_mode, op0);
08561 op1 = force_reg (op_mode, op1);
08562 }
08563 else
08564 {
08565
08566
08567
08568
08569 if (standard_80387_constant_p (op0) == 0
08570 || (GET_CODE (op0) == MEM
08571 && ! (standard_80387_constant_p (op1) == 0
08572 || GET_CODE (op1) == MEM)))
08573 {
08574 rtx tmp;
08575 tmp = op0, op0 = op1, op1 = tmp;
08576 code = swap_condition (code);
08577 }
08578
08579 if (GET_CODE (op0) != REG)
08580 op0 = force_reg (op_mode, op0);
08581
08582 if (CONSTANT_P (op1))
08583 {
08584 if (standard_80387_constant_p (op1))
08585 op1 = force_reg (op_mode, op1);
08586 else
08587 op1 = validize_mem (force_const_mem (op_mode, op1));
08588 }
08589 }
08590
08591
08592 if (ix86_fp_comparison_cost (code)
08593 > ix86_fp_comparison_cost (swap_condition (code))
08594 && (GET_CODE (op1) == REG || !no_new_pseudos))
08595 {
08596 rtx tmp;
08597 tmp = op0, op0 = op1, op1 = tmp;
08598 code = swap_condition (code);
08599 if (GET_CODE (op0) != REG)
08600 op0 = force_reg (op_mode, op0);
08601 }
08602
08603 *pop0 = op0;
08604 *pop1 = op1;
08605 return code;
08606 }
08607
08608
08609
08610
08611 static enum rtx_code
08612 ix86_fp_compare_code_to_integer (code)
08613 enum rtx_code code;
08614 {
08615 switch (code)
08616 {
08617 case GT:
08618 return GTU;
08619 case GE:
08620 return GEU;
08621 case ORDERED:
08622 case UNORDERED:
08623 return code;
08624 break;
08625 case UNEQ:
08626 return EQ;
08627 break;
08628 case UNLT:
08629 return LTU;
08630 break;
08631 case UNLE:
08632 return LEU;
08633 break;
08634 case LTGT:
08635 return NE;
08636 break;
08637 default:
08638 return UNKNOWN;
08639 }
08640 }
08641
08642
08643
08644
08645
08646
08647 static void
08648 ix86_fp_comparison_codes (code, bypass_code, first_code, second_code)
08649 enum rtx_code code, *bypass_code, *first_code, *second_code;
08650 {
08651 *first_code = code;
08652 *bypass_code = NIL;
08653 *second_code = NIL;
08654
08655
08656
08657
08658
08659
08660
08661
08662
08663 switch (code)
08664 {
08665 case GT:
08666 case GE:
08667 case ORDERED:
08668 case UNORDERED:
08669 case UNEQ:
08670 case UNLT:
08671 case UNLE:
08672 case LTGT:
08673 break;
08674 case LT:
08675 *first_code = UNLT;
08676 *bypass_code = UNORDERED;
08677 break;
08678 case LE:
08679 *first_code = UNLE;
08680 *bypass_code = UNORDERED;
08681 break;
08682 case EQ:
08683 *first_code = UNEQ;
08684 *bypass_code = UNORDERED;
08685 break;
08686 case NE:
08687 *first_code = LTGT;
08688 *second_code = UNORDERED;
08689 break;
08690 case UNGE:
08691 *first_code = GE;
08692 *second_code = UNORDERED;
08693 break;
08694 case UNGT:
08695 *first_code = GT;
08696 *second_code = UNORDERED;
08697 break;
08698 default:
08699 abort ();
08700 }
08701 if (!TARGET_IEEE_FP)
08702 {
08703 *second_code = NIL;
08704 *bypass_code = NIL;
08705 }
08706 }
08707
08708
08709
08710
08711
08712 static int
08713 ix86_fp_comparison_arithmetics_cost (code)
08714 enum rtx_code code;
08715 {
08716 if (!TARGET_IEEE_FP)
08717 return 4;
08718
08719 switch (code)
08720 {
08721 case UNLE:
08722 case UNLT:
08723 case LTGT:
08724 case GT:
08725 case GE:
08726 case UNORDERED:
08727 case ORDERED:
08728 case UNEQ:
08729 return 4;
08730 break;
08731 case LT:
08732 case NE:
08733 case EQ:
08734 case UNGE:
08735 return 5;
08736 break;
08737 case LE:
08738 case UNGT:
08739 return 6;
08740 break;
08741 default:
08742 abort ();
08743 }
08744 }
08745
08746
08747
08748 static int
08749 ix86_fp_comparison_fcomi_cost (code)
08750 enum rtx_code code;
08751 {
08752 enum rtx_code bypass_code, first_code, second_code;
08753
08754
08755 if (!TARGET_CMOVE)
08756 return 1024;
08757 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
08758 return (bypass_code != NIL || second_code != NIL) + 2;
08759 }
08760
08761
08762
08763 static int
08764 ix86_fp_comparison_sahf_cost (code)
08765 enum rtx_code code;
08766 {
08767 enum rtx_code bypass_code, first_code, second_code;
08768
08769
08770 if (!TARGET_USE_SAHF && !optimize_size)
08771 return 1024;
08772 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
08773 return (bypass_code != NIL || second_code != NIL) + 3;
08774 }
08775
08776
08777
08778 static int
08779 ix86_fp_comparison_cost (code)
08780 enum rtx_code code;
08781 {
08782 int fcomi_cost, sahf_cost, arithmetics_cost = 1024;
08783 int min;
08784
08785 fcomi_cost = ix86_fp_comparison_fcomi_cost (code);
08786 sahf_cost = ix86_fp_comparison_sahf_cost (code);
08787
08788 min = arithmetics_cost = ix86_fp_comparison_arithmetics_cost (code);
08789 if (min > sahf_cost)
08790 min = sahf_cost;
08791 if (min > fcomi_cost)
08792 min = fcomi_cost;
08793 return min;
08794 }
08795
08796
08797
08798 static rtx
08799 ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
08800 enum rtx_code code;
08801 rtx op0, op1, scratch;
08802 rtx *second_test;
08803 rtx *bypass_test;
08804 {
08805 enum machine_mode fpcmp_mode, intcmp_mode;
08806 rtx tmp, tmp2;
08807 int cost = ix86_fp_comparison_cost (code);
08808 enum rtx_code bypass_code, first_code, second_code;
08809
08810 fpcmp_mode = ix86_fp_compare_mode (code);
08811 code = ix86_prepare_fp_compare_args (code, &op0, &op1);
08812
08813 if (second_test)
08814 *second_test = NULL_RTX;
08815 if (bypass_test)
08816 *bypass_test = NULL_RTX;
08817
08818 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
08819
08820
08821 if ((bypass_code == NIL || bypass_test)
08822 && (second_code == NIL || second_test)
08823 && ix86_fp_comparison_arithmetics_cost (code) > cost)
08824 {
08825 if (TARGET_CMOVE)
08826 {
08827 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
08828 tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG),
08829 tmp);
08830 emit_insn (tmp);
08831 }
08832 else
08833 {
08834 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
08835 tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
08836 if (!scratch)
08837 scratch = gen_reg_rtx (HImode);
08838 emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
08839 emit_insn (gen_x86_sahf_1 (scratch));
08840 }
08841
08842
08843 intcmp_mode = fpcmp_mode;
08844 code = first_code;
08845 if (bypass_code != NIL)
08846 *bypass_test = gen_rtx_fmt_ee (bypass_code, VOIDmode,
08847 gen_rtx_REG (intcmp_mode, FLAGS_REG),
08848 const0_rtx);
08849 if (second_code != NIL)
08850 *second_test = gen_rtx_fmt_ee (second_code, VOIDmode,
08851 gen_rtx_REG (intcmp_mode, FLAGS_REG),
08852 const0_rtx);
08853 }
08854 else
08855 {
08856
08857 tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
08858 tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
08859 if (!scratch)
08860 scratch = gen_reg_rtx (HImode);
08861 emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
08862
08863
08864
08865
08866
08867
08868 intcmp_mode = CCNOmode;
08869 switch (code)
08870 {
08871 case GT:
08872 case UNGT:
08873 if (code == GT || !TARGET_IEEE_FP)
08874 {
08875 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
08876 code = EQ;
08877 }
08878 else
08879 {
08880 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08881 emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
08882 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
08883 intcmp_mode = CCmode;
08884 code = GEU;
08885 }
08886 break;
08887 case LT:
08888 case UNLT:
08889 if (code == LT && TARGET_IEEE_FP)
08890 {
08891 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08892 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01)));
08893 intcmp_mode = CCmode;
08894 code = EQ;
08895 }
08896 else
08897 {
08898 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
08899 code = NE;
08900 }
08901 break;
08902 case GE:
08903 case UNGE:
08904 if (code == GE || !TARGET_IEEE_FP)
08905 {
08906 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
08907 code = EQ;
08908 }
08909 else
08910 {
08911 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08912 emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
08913 GEN_INT (0x01)));
08914 code = NE;
08915 }
08916 break;
08917 case LE:
08918 case UNLE:
08919 if (code == LE && TARGET_IEEE_FP)
08920 {
08921 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08922 emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
08923 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
08924 intcmp_mode = CCmode;
08925 code = LTU;
08926 }
08927 else
08928 {
08929 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
08930 code = NE;
08931 }
08932 break;
08933 case EQ:
08934 case UNEQ:
08935 if (code == EQ && TARGET_IEEE_FP)
08936 {
08937 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08938 emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
08939 intcmp_mode = CCmode;
08940 code = EQ;
08941 }
08942 else
08943 {
08944 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
08945 code = NE;
08946 break;
08947 }
08948 break;
08949 case NE:
08950 case LTGT:
08951 if (code == NE && TARGET_IEEE_FP)
08952 {
08953 emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
08954 emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
08955 GEN_INT (0x40)));
08956 code = NE;
08957 }
08958 else
08959 {
08960 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
08961 code = EQ;
08962 }
08963 break;
08964
08965 case UNORDERED:
08966 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
08967 code = NE;
08968 break;
08969 case ORDERED:
08970 emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
08971 code = EQ;
08972 break;
08973
08974 default:
08975 abort ();
08976 }
08977 }
08978
08979
08980
08981 return gen_rtx_fmt_ee (code, VOIDmode,
08982 gen_rtx_REG (intcmp_mode, FLAGS_REG),
08983 const0_rtx);
08984 }
08985
08986 rtx
08987 ix86_expand_compare (code, second_test, bypass_test)
08988 enum rtx_code code;
08989 rtx *second_test, *bypass_test;
08990 {
08991 rtx op0, op1, ret;
08992 op0 = ix86_compare_op0;
08993 op1 = ix86_compare_op1;
08994
08995 if (second_test)
08996 *second_test = NULL_RTX;
08997 if (bypass_test)
08998 *bypass_test = NULL_RTX;
08999
09000 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
09001 ret = ix86_expand_fp_compare (code, op0, op1, NULL_RTX,
09002 second_test, bypass_test);
09003 else
09004 ret = ix86_expand_int_compare (code, op0, op1);
09005
09006 return ret;
09007 }
09008
09009
09010 bool
09011 ix86_fp_jump_nontrivial_p (code)
09012 enum rtx_code code;
09013 {
09014 enum rtx_code bypass_code, first_code, second_code;
09015 if (!TARGET_CMOVE)
09016 return true;
09017 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
09018 return bypass_code != NIL || second_code != NIL;
09019 }
09020
09021 void
09022 ix86_expand_branch (code, label)
09023 enum rtx_code code;
09024 rtx label;
09025 {
09026 rtx tmp;
09027
09028 switch (GET_MODE (ix86_compare_op0))
09029 {
09030 case QImode:
09031 case HImode:
09032 case SImode:
09033 simple:
09034 tmp = ix86_expand_compare (code, NULL, NULL);
09035 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
09036 gen_rtx_LABEL_REF (VOIDmode, label),
09037 pc_rtx);
09038 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
09039 return;
09040
09041 case SFmode:
09042 case DFmode:
09043 case XFmode:
09044 case TFmode:
09045 {
09046 rtvec vec;
09047 int use_fcomi;
09048 enum rtx_code bypass_code, first_code, second_code;
09049
09050 code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0,
09051 &ix86_compare_op1);
09052
09053 ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
09054
09055
09056
09057
09058 if (bypass_code == NIL && second_code == NIL
09059 && TARGET_CMOVE)
09060 {
09061 ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1,
09062 gen_rtx_LABEL_REF (VOIDmode, label),
09063 pc_rtx, NULL_RTX);
09064 }
09065 else
09066 {
09067 tmp = gen_rtx_fmt_ee (code, VOIDmode,
09068 ix86_compare_op0, ix86_compare_op1);
09069 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
09070 gen_rtx_LABEL_REF (VOIDmode, label),
09071 pc_rtx);
09072 tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
09073
09074 use_fcomi = ix86_use_fcomi_compare (code);
09075 vec = rtvec_alloc (3 + !use_fcomi);
09076 RTVEC_ELT (vec, 0) = tmp;
09077 RTVEC_ELT (vec, 1)
09078 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
09079 RTVEC_ELT (vec, 2)
09080 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
09081 if (! use_fcomi)
09082 RTVEC_ELT (vec, 3)
09083 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
09084
09085 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
09086 }
09087 return;
09088 }
09089
09090 case DImode:
09091 if (TARGET_64BIT)
09092 goto simple;
09093
09094 {
09095 rtx lo[2], hi[2], label2;
09096 enum rtx_code code1, code2, code3;
09097
09098 if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
09099 {
09100 tmp = ix86_compare_op0;
09101 ix86_compare_op0 = ix86_compare_op1;
09102 ix86_compare_op1 = tmp;
09103 code = swap_condition (code);
09104 }
09105 split_di (&ix86_compare_op0, 1, lo+0, hi+0);
09106 split_di (&ix86_compare_op1, 1, lo+1, hi+1);
09107
09108
09109
09110
09111
09112 if ((code == EQ || code == NE)
09113 && (!optimize_size
09114 || hi[1] == const0_rtx || lo[1] == const0_rtx))
09115 {
09116 rtx xor0, xor1;
09117
09118 xor1 = hi[0];
09119 if (hi[1] != const0_rtx)
09120 xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
09121 NULL_RTX, 0, OPTAB_WIDEN);
09122
09123 xor0 = lo[0];
09124 if (lo[1] != const0_rtx)
09125 xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
09126 NULL_RTX, 0, OPTAB_WIDEN);
09127
09128 tmp = expand_binop (SImode, ior_optab, xor1, xor0,
09129 NULL_RTX, 0, OPTAB_WIDEN);
09130
09131 ix86_compare_op0 = tmp;
09132 ix86_compare_op1 = const0_rtx;
09133 ix86_expand_branch (code, label);
09134 return;
09135 }
09136
09137
09138
09139
09140
09141 if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx)
09142 switch (code)
09143 {
09144 case LT: case LTU: case GE: case GEU:
09145 ix86_compare_op0 = hi[0];
09146 ix86_compare_op1 = hi[1];
09147 ix86_expand_branch (code, label);
09148 return;
09149 default:
09150 break;
09151 }
09152
09153
09154
09155 label2 = gen_label_rtx ();
09156
09157 code1 = code;
09158 code2 = swap_condition (code);
09159 code3 = unsigned_condition (code);
09160
09161 switch (code)
09162 {
09163 case LT: case GT: case LTU: case GTU:
09164 break;
09165
09166 case LE: code1 = LT; code2 = GT; break;
09167 case GE: code1 = GT; code2 = LT; break;
09168 case LEU: code1 = LTU; code2 = GTU; break;
09169 case GEU: code1 = GTU; code2 = LTU; break;
09170
09171 case EQ: code1 = NIL; code2 = NE; break;
09172 case NE: code2 = NIL; break;
09173
09174 default:
09175 abort ();
09176 }
09177
09178
09179
09180
09181
09182
09183
09184
09185
09186 ix86_compare_op0 = hi[0];
09187 ix86_compare_op1 = hi[1];
09188
09189 if (code1 != NIL)
09190 ix86_expand_branch (code1, label);
09191 if (code2 != NIL)
09192 ix86_expand_branch (code2, label2);
09193
09194 ix86_compare_op0 = lo[0];
09195 ix86_compare_op1 = lo[1];
09196 ix86_expand_branch (code3, label);
09197
09198 if (code2 != NIL)
09199 emit_label (label2);
09200 return;
09201 }
09202
09203 default:
09204 abort ();
09205 }
09206 }
09207
09208
09209 void
09210 ix86_split_fp_branch (code, op1, op2, target1, target2, tmp)
09211 enum rtx_code code;
09212 rtx op1, op2, target1, target2, tmp;
09213 {
09214 rtx second, bypass;
09215 rtx label = NULL_RTX;
09216 rtx condition;
09217 int bypass_probability = -1, second_probability = -1, probability = -1;
09218 rtx i;
09219
09220 if (target2 != pc_rtx)
09221 {
09222 rtx tmp = target2;
09223 code = reverse_condition_maybe_unordered (code);
09224 target2 = target1;
09225 target1 = tmp;
09226 }
09227
09228 condition = ix86_expand_fp_compare (code, op1, op2,
09229 tmp, &second, &bypass);
09230
09231 if (split_branch_probability >= 0)
09232 {
09233
09234
09235
09236 probability = split_branch_probability;
09237
09238
09239
09240
09241 if (bypass)
09242 bypass_probability = 1;
09243 if (second)
09244 second_probability = 1;
09245 }
09246 if (bypass != NULL_RTX)
09247 {
09248 label = gen_label_rtx ();
09249 i = emit_jump_insn (gen_rtx_SET
09250 (VOIDmode, pc_rtx,
09251 gen_rtx_IF_THEN_ELSE (VOIDmode,
09252 bypass,
09253 gen_rtx_LABEL_REF (VOIDmode,
09254 label),
09255 pc_rtx)));
09256 if (bypass_probability >= 0)
09257 REG_NOTES (i)
09258 = gen_rtx_EXPR_LIST (REG_BR_PROB,
09259 GEN_INT (bypass_probability),
09260 REG_NOTES (i));
09261 }
09262 i = emit_jump_insn (gen_rtx_SET
09263 (VOIDmode, pc_rtx,
09264 gen_rtx_IF_THEN_ELSE (VOIDmode,
09265 condition, target1, target2)));
09266 if (probability >= 0)
09267 REG_NOTES (i)
09268 = gen_rtx_EXPR_LIST (REG_BR_PROB,
09269 GEN_INT (probability),
09270 REG_NOTES (i));
09271 if (second != NULL_RTX)
09272 {
09273 i = emit_jump_insn (gen_rtx_SET
09274 (VOIDmode, pc_rtx,
09275 gen_rtx_IF_THEN_ELSE (VOIDmode, second, target1,
09276 target2)));
09277 if (second_probability >= 0)
09278 REG_NOTES (i)
09279 = gen_rtx_EXPR_LIST (REG_BR_PROB,
09280 GEN_INT (second_probability),
09281 REG_NOTES (i));
09282 }
09283 if (label != NULL_RTX)
09284 emit_label (label);
09285 }
09286
09287 int
09288 ix86_expand_setcc (code, dest)
09289 enum rtx_code code;
09290 rtx dest;
09291 {
09292 rtx ret, tmp, tmpreg;
09293 rtx second_test, bypass_test;
09294
09295 if (GET_MODE (ix86_compare_op0) == DImode
09296 && !TARGET_64BIT)
09297 return 0;
09298
09299 if (GET_MODE (dest) != QImode)
09300 abort ();
09301
09302 ret = ix86_expand_compare (code, &second_test, &bypass_test);
09303 PUT_MODE (ret, QImode);
09304
09305 tmp = dest;
09306 tmpreg = dest;
09307
09308 emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
09309 if (bypass_test || second_test)
09310 {
09311 rtx test = second_test;
09312 int bypass = 0;
09313 rtx tmp2 = gen_reg_rtx (QImode);
09314 if (bypass_test)
09315 {
09316 if (second_test)
09317 abort ();
09318 test = bypass_test;
09319 bypass = 1;
09320 PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test)));
09321 }
09322 PUT_MODE (test, QImode);
09323 emit_insn (gen_rtx_SET (VOIDmode, tmp2, test));
09324
09325 if (bypass)
09326 emit_insn (gen_andqi3 (tmp, tmpreg, tmp2));
09327 else
09328 emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
09329 }
09330
09331 return 1;
09332 }
09333
09334 int
09335 ix86_expand_int_movcc (operands)
09336 rtx operands[];
09337 {
09338 enum rtx_code code = GET_CODE (operands[1]), compare_code;
09339 rtx compare_seq, compare_op;
09340 rtx second_test, bypass_test;
09341 enum machine_mode mode = GET_MODE (operands[0]);
09342
09343
09344
09345
09346
09347 if ((code == LEU || code == GTU)
09348 && GET_CODE (ix86_compare_op1) == CONST_INT
09349 && mode != HImode
09350 && INTVAL (ix86_compare_op1) != -1
09351
09352
09353 && (!TARGET_64BIT
09354 || GET_MODE (ix86_compare_op0) != DImode
09355 || INTVAL (ix86_compare_op1) != 0x7fffffff)
09356 && GET_CODE (operands[2]) == CONST_INT
09357 && GET_CODE (operands[3]) == CONST_INT)
09358 {
09359 if (code == LEU)
09360 code = LTU;
09361 else
09362 code = GEU;
09363 ix86_compare_op1 = gen_int_mode (INTVAL (ix86_compare_op1) + 1,
09364 GET_MODE (ix86_compare_op0));
09365 }
09366
09367 start_sequence ();
09368 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
09369 compare_seq = get_insns ();
09370 end_sequence ();
09371
09372 compare_code = GET_CODE (compare_op);
09373
09374
09375
09376
09377 if (mode != HImode
09378 && (mode != DImode || TARGET_64BIT)
09379 && GET_CODE (operands[2]) == CONST_INT
09380 && GET_CODE (operands[3]) == CONST_INT)
09381 {
09382 rtx out = operands[0];
09383 HOST_WIDE_INT ct = INTVAL (operands[2]);
09384 HOST_WIDE_INT cf = INTVAL (operands[3]);
09385 HOST_WIDE_INT diff;
09386
09387 if ((compare_code == LTU || compare_code == GEU)
09388 && !second_test && !bypass_test)
09389 {
09390
09391 rtx tmp = out;
09392
09393
09394 if (compare_code == LTU)
09395 {
09396 HOST_WIDE_INT tmp = ct;
09397 ct = cf;
09398 cf = tmp;
09399 compare_code = reverse_condition (compare_code);
09400 code = reverse_condition (code);
09401 }
09402 diff = ct - cf;
09403
09404 if (reg_overlap_mentioned_p (out, ix86_compare_op0)
09405 || reg_overlap_mentioned_p (out, ix86_compare_op1))
09406 tmp = gen_reg_rtx (mode);
09407
09408 emit_insn (compare_seq);
09409 if (mode == DImode)
09410 emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp));
09411 else
09412 emit_insn (gen_x86_movsicc_0_m1 (tmp));
09413
09414 if (diff == 1)
09415 {
09416
09417
09418
09419
09420
09421
09422
09423 if (ct)
09424 tmp = expand_simple_binop (mode, PLUS,
09425 tmp, GEN_INT (ct),
09426 tmp, 1, OPTAB_DIRECT);
09427 }
09428 else if (cf == -1)
09429 {
09430
09431
09432
09433
09434
09435
09436
09437 tmp = expand_simple_binop (mode, IOR,
09438 tmp, GEN_INT (ct),
09439 tmp, 1, OPTAB_DIRECT);
09440 }
09441 else if (diff == -1 && ct)
09442 {
09443
09444
09445
09446
09447
09448
09449
09450
09451 tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
09452 if (cf)
09453 tmp = expand_simple_binop (mode, PLUS,
09454 tmp, GEN_INT (cf),
09455 tmp, 1, OPTAB_DIRECT);
09456 }
09457 else
09458 {
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468
09469 if (cf == 0)
09470 {
09471 cf = ct;
09472 ct = 0;
09473 tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
09474 }
09475
09476 tmp = expand_simple_binop (mode, AND,
09477 tmp,
09478 gen_int_mode (cf - ct, mode),
09479 tmp, 1, OPTAB_DIRECT);
09480 if (ct)
09481 tmp = expand_simple_binop (mode, PLUS,
09482 tmp, GEN_INT (ct),
09483 tmp, 1, OPTAB_DIRECT);
09484 }
09485
09486 if (tmp != out)
09487 emit_move_insn (out, tmp);
09488
09489 return 1;
09490 }
09491
09492 diff = ct - cf;
09493 if (diff < 0)
09494 {
09495 HOST_WIDE_INT tmp;
09496 tmp = ct, ct = cf, cf = tmp;
09497 diff = -diff;
09498 if (FLOAT_MODE_P (GET_MODE (ix86_compare_op0)))
09499 {
09500
09501
09502
09503
09504 compare_code = reverse_condition_maybe_unordered (compare_code);
09505 code = reverse_condition_maybe_unordered (code);
09506 }
09507 else
09508 {
09509 compare_code = reverse_condition (compare_code);
09510 code = reverse_condition (code);
09511 }
09512 }
09513
09514 compare_code = NIL;
09515 if (GET_MODE_CLASS (GET_MODE (ix86_compare_op0)) == MODE_INT
09516 && GET_CODE (ix86_compare_op1) == CONST_INT)
09517 {
09518 if (ix86_compare_op1 == const0_rtx
09519 && (code == LT || code == GE))
09520 compare_code = code;
09521 else if (ix86_compare_op1 == constm1_rtx)
09522 {
09523 if (code == LE)
09524 compare_code = LT;
09525 else if (code == GT)
09526 compare_code = GE;
09527 }
09528 }
09529
09530
09531 if (compare_code != NIL
09532 && GET_MODE (ix86_compare_op0) == GET_MODE (out)
09533 && (cf == -1 || ct == -1))
09534 {
09535
09536
09537
09538 if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
09539 || diff == 3 || diff == 5 || diff == 9)
09540 || (compare_code == LT && ct == -1)
09541 || (compare_code == GE && cf == -1))
09542 {
09543
09544
09545
09546
09547
09548 if (ct != -1)
09549 {
09550 cf = ct;
09551 ct = -1;
09552 code = reverse_condition (code);
09553 }
09554
09555 out = emit_store_flag (out, code, ix86_compare_op0,
09556 ix86_compare_op1, VOIDmode, 0, -1);
09557
09558 out = expand_simple_binop (mode, IOR,
09559 out, GEN_INT (cf),
09560 out, 1, OPTAB_DIRECT);
09561 if (out != operands[0])
09562 emit_move_insn (operands[0], out);
09563
09564 return 1;
09565 }
09566 }
09567
09568 if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
09569 || diff == 3 || diff == 5 || diff == 9)
09570 && (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
09571 {
09572
09573
09574
09575
09576
09577
09578
09579
09580
09581
09582
09583 rtx tmp;
09584 int nops;
09585
09586 out = emit_store_flag (out, code, ix86_compare_op0,
09587 ix86_compare_op1, VOIDmode, 0, 1);
09588
09589 nops = 0;
09590
09591
09592 if (diff == 1)
09593 tmp = copy_rtx (out);
09594 else
09595 {
09596 rtx out1;
09597 out1 = copy_rtx (out);
09598 tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
09599 nops++;
09600 if (diff & 1)
09601 {
09602 tmp = gen_rtx_PLUS (mode, tmp, out1);
09603 nops++;
09604 }
09605 }
09606 if (cf != 0)
09607 {
09608 tmp = gen_rtx_PLUS (mode, tmp, GEN_INT (cf));
09609 nops++;
09610 }
09611 if (tmp != out
09612 && (GET_CODE (tmp) != SUBREG || SUBREG_REG (tmp) != out))
09613 {
09614 if (nops == 1)
09615 out = force_operand (tmp, copy_rtx (out));
09616 else
09617 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (out), copy_rtx (tmp)));
09618 }
09619 if (out != operands[0])
09620 emit_move_insn (operands[0], copy_rtx (out));
09621
09622 return 1;
09623 }
09624
09625
09626
09627
09628
09629
09630
09631
09632
09633
09634
09635
09636
09637
09638
09639
09640
09641
09642
09643
09644 if (!optimize_size && !TARGET_CMOVE)
09645 {
09646 if (cf == 0)
09647 {
09648 cf = ct;
09649 ct = 0;
09650 if (FLOAT_MODE_P (GET_MODE (ix86_compare_op0)))
09651
09652
09653
09654
09655 code = reverse_condition_maybe_unordered (code);
09656 else
09657 {
09658 code = reverse_condition (code);
09659 if (compare_code != NIL)
09660 compare_code = reverse_condition (compare_code);
09661 }
09662 }
09663
09664 if (compare_code != NIL)
09665 {
09666
09667
09668
09669
09670
09671
09672
09673
09674
09675
09676
09677
09678 if (compare_code == GE || !cf)
09679 {
09680 code = reverse_condition (code);
09681 compare_code = LT;
09682 }
09683 else
09684 {
09685 HOST_WIDE_INT tmp = cf;
09686 cf = ct;
09687 ct = tmp;
09688 }
09689
09690 out = emit_store_flag (out, code, ix86_compare_op0,
09691 ix86_compare_op1, VOIDmode, 0, -1);
09692 }
09693 else
09694 {
09695 out = emit_store_flag (out, code, ix86_compare_op0,
09696 ix86_compare_op1, VOIDmode, 0, 1);
09697
09698 out = expand_simple_binop (mode, PLUS, out, constm1_rtx,
09699 out, 1, OPTAB_DIRECT);
09700 }
09701
09702 out = expand_simple_binop (mode, AND, out,
09703 gen_int_mode (cf - ct, mode),
09704 out, 1, OPTAB_DIRECT);
09705 if (ct)
09706 out = expand_simple_binop (mode, PLUS, out, GEN_INT (ct),
09707 out, 1, OPTAB_DIRECT);
09708 if (out != operands[0])
09709 emit_move_insn (operands[0], out);
09710
09711 return 1;
09712 }
09713 }
09714
09715 if (!TARGET_CMOVE)
09716 {
09717
09718
09719 optab op;
09720 rtx var, orig_out, out, tmp;
09721
09722 if (optimize_size)
09723 return 0;
09724
09725
09726
09727
09728 if (GET_CODE (operands[2]) == CONST_INT)
09729 {
09730 var = operands[3];
09731 if (INTVAL (operands[2]) == 0)
09732 operands[3] = constm1_rtx, op = and_optab;
09733 else if (INTVAL (operands[2]) == -1)
09734 operands[3] = const0_rtx, op = ior_optab;
09735 else
09736 return 0;
09737 }
09738 else if (GET_CODE (operands[3]) == CONST_INT)
09739 {
09740 var = operands[2];
09741 if (INTVAL (operands[3]) == 0)
09742 operands[2] = constm1_rtx, op = and_optab;
09743 else if (INTVAL (operands[3]) == -1)
09744 operands[2] = const0_rtx, op = ior_optab;
09745 else
09746 return 0;
09747 }
09748 else
09749 return 0;
09750
09751 orig_out = operands[0];
09752 tmp = gen_reg_rtx (mode);
09753 operands[0] = tmp;
09754
09755
09756 if (ix86_expand_int_movcc (operands) == 0)
09757 return 0;
09758
09759
09760 out = expand_binop (mode, op, var, tmp, orig_out, 0,
09761 OPTAB_WIDEN);
09762 if (out != orig_out)
09763 emit_move_insn (orig_out, out);
09764
09765 return 1;
09766 }
09767
09768
09769
09770
09771
09772
09773
09774
09775
09776
09777
09778
09779 if (! nonimmediate_operand (operands[2], mode))
09780 operands[2] = force_reg (mode, operands[2]);
09781 if (! nonimmediate_operand (operands[3], mode))
09782 operands[3] = force_reg (mode, operands[3]);
09783
09784 if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
09785 {
09786 rtx tmp = gen_reg_rtx (mode);
09787 emit_move_insn (tmp, operands[3]);
09788 operands[3] = tmp;
09789 }
09790 if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
09791 {
09792 rtx tmp = gen_reg_rtx (mode);
09793 emit_move_insn (tmp, operands[2]);
09794 operands[2] = tmp;
09795 }
09796 if (! register_operand (operands[2], VOIDmode)
09797 && ! register_operand (operands[3], VOIDmode))
09798 operands[2] = force_reg (mode, operands[2]);
09799
09800 emit_insn (compare_seq);
09801 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09802 gen_rtx_IF_THEN_ELSE (mode,
09803 compare_op, operands[2],
09804 operands[3])));
09805 if (bypass_test)
09806 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09807 gen_rtx_IF_THEN_ELSE (mode,
09808 bypass_test,
09809 operands[3],
09810 operands[0])));
09811 if (second_test)
09812 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09813 gen_rtx_IF_THEN_ELSE (mode,
09814 second_test,
09815 operands[2],
09816 operands[0])));
09817
09818 return 1;
09819 }
09820
09821 int
09822 ix86_expand_fp_movcc (operands)
09823 rtx operands[];
09824 {
09825 enum rtx_code code;
09826 rtx tmp;
09827 rtx compare_op, second_test, bypass_test;
09828
09829
09830
09831 if (((TARGET_SSE_MATH && GET_MODE (operands[0]) == SFmode)
09832 || (TARGET_SSE2 && TARGET_SSE_MATH && GET_MODE (operands[0]) == DFmode))
09833 && GET_MODE (ix86_compare_op0) == GET_MODE (operands[0])
09834
09835 && (!TARGET_IEEE_FP
09836 || (GET_CODE (operands[1]) != LTGT && GET_CODE (operands[1]) != UNEQ))
09837
09838 && (!REG_P (operands[0])
09839 || SSE_REG_P (operands[0])
09840 || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
09841 {
09842 rtx op0 = ix86_compare_op0, op1 = ix86_compare_op1;
09843 code = GET_CODE (operands[1]);
09844
09845
09846
09847 if (rtx_equal_p (operands[2], op1))
09848 {
09849 rtx tmp = op0;
09850 op0 = op1;
09851 op1 = tmp;
09852 code = reverse_condition_maybe_unordered (code);
09853 }
09854 if (rtx_equal_p (operands[2], op0) && rtx_equal_p (operands[3], op1))
09855 {
09856
09857 if (code == LT)
09858 {
09859 operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
09860 if (memory_operand (op0, VOIDmode))
09861 op0 = force_reg (GET_MODE (operands[0]), op0);
09862 if (GET_MODE (operands[0]) == SFmode)
09863 emit_insn (gen_minsf3 (operands[0], op0, op1));
09864 else
09865 emit_insn (gen_mindf3 (operands[0], op0, op1));
09866 return 1;
09867 }
09868
09869 if (code == GT)
09870 {
09871 operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
09872 if (memory_operand (op0, VOIDmode))
09873 op0 = force_reg (GET_MODE (operands[0]), op0);
09874 if (GET_MODE (operands[0]) == SFmode)
09875 emit_insn (gen_maxsf3 (operands[0], op0, op1));
09876 else
09877 emit_insn (gen_maxdf3 (operands[0], op0, op1));
09878 return 1;
09879 }
09880 }
09881
09882
09883
09884
09885 if (!sse_comparison_operator (operands[1], VOIDmode)
09886 || (rtx_equal_p (operands[0], ix86_compare_op1) && !TARGET_IEEE_FP))
09887 {
09888 rtx tmp = ix86_compare_op0;
09889 ix86_compare_op0 = ix86_compare_op1;
09890 ix86_compare_op1 = tmp;
09891 operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
09892 VOIDmode, ix86_compare_op0,
09893 ix86_compare_op1);
09894 }
09895
09896
09897
09898 if ((rtx_equal_p (operands[0], operands[3])
09899 && (!TARGET_IEEE_FP || GET_CODE (operands[1]) != EQ))
09900 || (GET_CODE (operands[1]) == NE && TARGET_IEEE_FP))
09901 {
09902 rtx tmp = operands[2];
09903 operands[2] = operands[3];
09904 operands[3] = tmp;
09905 operands[1] = gen_rtx_fmt_ee (reverse_condition_maybe_unordered
09906 (GET_CODE (operands[1])),
09907 VOIDmode, ix86_compare_op0,
09908 ix86_compare_op1);
09909 }
09910 if (GET_MODE (operands[0]) == SFmode)
09911 emit_insn (gen_sse_movsfcc (operands[0], operands[1],
09912 operands[2], operands[3],
09913 ix86_compare_op0, ix86_compare_op1));
09914 else
09915 emit_insn (gen_sse_movdfcc (operands[0], operands[1],
09916 operands[2], operands[3],
09917 ix86_compare_op0, ix86_compare_op1));
09918 return 1;
09919 }
09920
09921
09922
09923
09924 code = GET_CODE (operands[1]);
09925 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
09926
09927
09928
09929
09930 if (!fcmov_comparison_operator (compare_op, VOIDmode))
09931 {
09932 if (second_test != NULL || bypass_test != NULL)
09933 abort ();
09934 tmp = gen_reg_rtx (QImode);
09935 ix86_expand_setcc (code, tmp);
09936 code = NE;
09937 ix86_compare_op0 = tmp;
09938 ix86_compare_op1 = const0_rtx;
09939 compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
09940 }
09941 if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
09942 {
09943 tmp = gen_reg_rtx (GET_MODE (operands[0]));
09944 emit_move_insn (tmp, operands[3]);
09945 operands[3] = tmp;
09946 }
09947 if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
09948 {
09949 tmp = gen_reg_rtx (GET_MODE (operands[0]));
09950 emit_move_insn (tmp, operands[2]);
09951 operands[2] = tmp;
09952 }
09953
09954 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09955 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
09956 compare_op,
09957 operands[2],
09958 operands[3])));
09959 if (bypass_test)
09960 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09961 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
09962 bypass_test,
09963 operands[3],
09964 operands[0])));
09965 if (second_test)
09966 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
09967 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
09968 second_test,
09969 operands[2],
09970 operands[0])));
09971
09972 return 1;
09973 }
09974
09975
09976
09977
09978
09979
09980 static int
09981 ix86_split_to_parts (operand, parts, mode)
09982 rtx operand;
09983 rtx *parts;
09984 enum machine_mode mode;
09985 {
09986 int size;
09987
09988 if (!TARGET_64BIT)
09989 size = mode == TFmode ? 3 : (GET_MODE_SIZE (mode) / 4);
09990 else
09991 size = (GET_MODE_SIZE (mode) + 4) / 8;
09992
09993 if (GET_CODE (operand) == REG && MMX_REGNO_P (REGNO (operand)))
09994 abort ();
09995 if (size < 2 || size > 3)
09996 abort ();
09997
09998
09999
10000 if (GET_CODE (operand) == MEM && RTX_UNCHANGING_P (operand))
10001 {
10002 rtx tmp = maybe_get_pool_constant (operand);
10003 if (tmp)
10004 operand = tmp;
10005 }
10006
10007 if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
10008 {
10009
10010 if (! push_operand (operand, VOIDmode))
10011 abort ();
10012
10013 operand = copy_rtx (operand);
10014 PUT_MODE (operand, Pmode);
10015 parts[0] = parts[1] = parts[2] = operand;
10016 }
10017 else if (!TARGET_64BIT)
10018 {
10019 if (mode == DImode)
10020 split_di (&operand, 1, &parts[0], &parts[1]);
10021 else
10022 {
10023 if (REG_P (operand))
10024 {
10025 if (!reload_completed)
10026 abort ();
10027 parts[0] = gen_rtx_REG (SImode, REGNO (operand) + 0);
10028 parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
10029 if (size == 3)
10030 parts[2] = gen_rtx_REG (SImode, REGNO (operand) + 2);
10031 }
10032 else if (offsettable_memref_p (operand))
10033 {
10034 operand = adjust_address (operand, SImode, 0);
10035 parts[0] = operand;
10036 parts[1] = adjust_address (operand, SImode, 4);
10037 if (size == 3)
10038 parts[2] = adjust_address (operand, SImode, 8);
10039 }
10040 else if (GET_CODE (operand) == CONST_DOUBLE)
10041 {
10042 REAL_VALUE_TYPE r;
10043 long l[4];
10044
10045 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
10046 switch (mode)
10047 {
10048 case XFmode:
10049 case TFmode:
10050 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
10051 parts[2] = gen_int_mode (l[2], SImode);
10052 break;
10053 case DFmode:
10054 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
10055 break;
10056 default:
10057 abort ();
10058 }
10059 parts[1] = gen_int_mode (l[1], SImode);
10060 parts[0] = gen_int_mode (l[0], SImode);
10061 }
10062 else
10063 abort ();
10064 }
10065 }
10066 else
10067 {
10068 if (mode == TImode)
10069 split_ti (&operand, 1, &parts[0], &parts[1]);
10070 if (mode == XFmode || mode == TFmode)
10071 {
10072 if (REG_P (operand))
10073 {
10074 if (!reload_completed)
10075 abort ();
10076 parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
10077 parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
10078 }
10079 else if (offsettable_memref_p (operand))
10080 {
10081 operand = adjust_address (operand, DImode, 0);
10082 parts[0] = operand;
10083 parts[1] = adjust_address (operand, SImode, 8);
10084 }
10085 else if (GET_CODE (operand) == CONST_DOUBLE)
10086 {
10087 REAL_VALUE_TYPE r;
10088 long l[3];
10089
10090 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
10091 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
10092
10093 if (HOST_BITS_PER_WIDE_INT >= 64)
10094 parts[0]
10095 = gen_int_mode
10096 ((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1))
10097 + ((((HOST_WIDE_INT) l[1]) << 31) << 1),
10098 DImode);
10099 else
10100 parts[0] = immed_double_const (l[0], l[1], DImode);
10101 parts[1] = gen_int_mode (l[2], SImode);
10102 }
10103 else
10104 abort ();
10105 }
10106 }
10107
10108 return size;
10109 }
10110
10111
10112
10113
10114
10115
10116 void
10117 ix86_split_long_move (operands)
10118 rtx operands[];
10119 {
10120 rtx part[2][3];
10121 int nparts;
10122 int push = 0;
10123 int collisions = 0;
10124 enum machine_mode mode = GET_MODE (operands[0]);
10125
10126
10127
10128
10129 if (GET_MODE_SIZE (GET_MODE (operands[0])) == 8 && TARGET_64BIT)
10130 {
10131
10132
10133
10134 if (GET_CODE (operands[1]) == MEM
10135 && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
10136 && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
10137 operands[1] = get_pool_constant (XEXP (operands[1], 0));
10138 if (push_operand (operands[0], VOIDmode))
10139 {
10140 operands[0] = copy_rtx (operands[0]);
10141 PUT_MODE (operands[0], Pmode);
10142 }
10143 else
10144 operands[0] = gen_lowpart (DImode, operands[0]);
10145 operands[1] = gen_lowpart (DImode, operands[1]);
10146 emit_move_insn (operands[0], operands[1]);
10147 return;
10148 }
10149
10150
10151 if (push_operand (operands[0], VOIDmode))
10152 push = 1;
10153 else if (GET_CODE (operands[0]) == MEM
10154 && ! offsettable_memref_p (operands[0]))
10155 abort ();
10156
10157 nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands[0]));
10158 ix86_split_to_parts (operands[0], part[0], GET_MODE (operands[0]));
10159
10160
10161 if (push && GET_CODE (operands[1]) == MEM
10162 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
10163 {
10164 if (nparts == 3)
10165 part[1][1] = change_address (part[1][1], GET_MODE (part[1][1]),
10166 XEXP (part[1][2], 0));
10167 part[1][0] = change_address (part[1][0], GET_MODE (part[1][0]),
10168 XEXP (part[1][1], 0));
10169 }
10170
10171
10172
10173 if (REG_P (part[0][0]) && GET_CODE (part[1][0]) == MEM)
10174 {
10175 if (reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0)))
10176 collisions++;
10177 if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
10178 collisions++;
10179 if (nparts == 3
10180 && reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
10181 collisions++;
10182
10183
10184 if (collisions == 1 && nparts == 3
10185 && reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
10186 {
10187 rtx tmp;
10188 tmp = part[0][1]; part[0][1] = part[0][2]; part[0][2] = tmp;
10189 tmp = part[1][1]; part[1][1] = part[1][2]; part[1][2] = tmp;
10190 }
10191
10192
10193
10194 else if (collisions > 1)
10195 {
10196 rtx base;
10197
10198 collisions = 1;
10199
10200 base = part[0][nparts - 1];
10201
10202
10203
10204 if (GET_MODE (base) != Pmode)
10205 base = gen_rtx_REG (Pmode, REGNO (base));
10206
10207 emit_insn (gen_rtx_SET (VOIDmode, base, XEXP (part[1][0], 0)));
10208 part[1][0] = replace_equiv_address (part[1][0], base);
10209 part[1][1] = replace_equiv_address (part[1][1],
10210 plus_constant (base, UNITS_PER_WORD));
10211 if (nparts == 3)
10212 part[1][2] = replace_equiv_address (part[1][2],
10213 plus_constant (base, 8));
10214 }
10215 }
10216
10217 if (push)
10218 {
10219 if (!TARGET_64BIT)
10220 {
10221 if (nparts == 3)
10222 {
10223
10224
10225
10226 if (mode == TFmode && !TARGET_64BIT)
10227 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
10228 GEN_INT (-4)));
10229 emit_move_insn (part[0][2], part[1][2]);
10230 }
10231 }
10232 else
10233 {
10234
10235
10236
10237
10238 if (GET_MODE (part[1][1]) == SImode)
10239 {
10240 if (GET_CODE (part[1][1]) == MEM)
10241 part[1][1] = adjust_address (part[1][1], DImode, 0);
10242 else if (REG_P (part[1][1]))
10243 part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
10244 else
10245 abort ();
10246 if (GET_MODE (part[1][0]) == SImode)
10247 part[1][0] = part[1][1];
10248 }
10249 }
10250 emit_move_insn (part[0][1], part[1][1]);
10251 emit_move_insn (part[0][0], part[1][0]);
10252 return;
10253 }
10254
10255
10256 if ((REG_P (part[0][0])
10257 && REG_P (part[1][1])
10258 && (REGNO (part[0][0]) == REGNO (part[1][1])
10259 || (nparts == 3
10260 && REGNO (part[0][0]) == REGNO (part[1][2]))))
10261 || (collisions > 0
10262 && reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
10263 {
10264 if (nparts == 3)
10265 {
10266 operands[2] = part[0][2];
10267 operands[3] = part[0][1];
10268 operands[4] = part[0][0];
10269 operands[5] = part[1][2];
10270 operands[6] = part[1][1];
10271 operands[7] = part[1][0];
10272 }
10273 else
10274 {
10275 operands[2] = part[0][1];
10276 operands[3] = part[0][0];
10277 operands[5] = part[1][1];
10278 operands[6] = part[1][0];
10279 }
10280 }
10281 else
10282 {
10283 if (nparts == 3)
10284 {
10285 operands[2] = part[0][0];
10286 operands[3] = part[0][1];
10287 operands[4] = part[0][2];
10288 operands[5] = part[1][0];
10289 operands[6] = part[1][1];
10290 operands[7] = part[1][2];
10291 }
10292 else
10293 {
10294 operands[2] = part[0][0];
10295 operands[3] = part[0][1];
10296 operands[5] = part[1][0];
10297 operands[6] = part[1][1];
10298 }
10299 }
10300 emit_move_insn (operands[2], operands[5]);
10301 emit_move_insn (operands[3], operands[6]);
10302 if (nparts == 3)
10303 emit_move_insn (operands[4], operands[7]);
10304
10305 return;
10306 }
10307
10308 void
10309 ix86_split_ashldi (operands, scratch)
10310 rtx *operands, scratch;
10311 {
10312 rtx low[2], high[2];
10313 int count;
10314
10315 if (GET_CODE (operands[2]) == CONST_INT)
10316 {
10317 split_di (operands, 2, low, high);
10318 count = INTVAL (operands[2]) & 63;
10319
10320 if (count >= 32)
10321 {
10322 emit_move_insn (high[0], low[1]);
10323 emit_move_insn (low[0], const0_rtx);
10324
10325 if (count > 32)
10326 emit_insn (gen_ashlsi3 (high[0], high[0], GEN_INT (count - 32)));
10327 }
10328 else
10329 {
10330 if (!rtx_equal_p (operands[0], operands[1]))
10331 emit_move_insn (operands[0], operands[1]);
10332 emit_insn (gen_x86_shld_1 (high[0], low[0], GEN_INT (count)));
10333 emit_insn (gen_ashlsi3 (low[0], low[0], GEN_INT (count)));
10334 }
10335 }
10336 else
10337 {
10338 if (!rtx_equal_p (operands[0], operands[1]))
10339 emit_move_insn (operands[0], operands[1]);
10340
10341 split_di (operands, 1, low, high);
10342
10343 emit_insn (gen_x86_shld_1 (high[0], low[0], operands[2]));
10344 emit_insn (gen_ashlsi3 (low[0], low[0], operands[2]));
10345
10346 if (TARGET_CMOVE && (! no_new_pseudos || scratch))
10347 {
10348 if (! no_new_pseudos)
10349 scratch = force_reg (SImode, const0_rtx);
10350 else
10351 emit_move_insn (scratch, const0_rtx);
10352
10353 emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2],
10354 scratch));
10355 }
10356 else
10357 emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2]));
10358 }
10359 }
10360
10361 void
10362 ix86_split_ashrdi (operands, scratch)
10363 rtx *operands, scratch;
10364 {
10365 rtx low[2], high[2];
10366 int count;
10367
10368 if (GET_CODE (operands[2]) == CONST_INT)
10369 {
10370 split_di (operands, 2, low, high);
10371 count = INTVAL (operands[2]) & 63;
10372
10373 if (count >= 32)
10374 {
10375 emit_move_insn (low[0], high[1]);
10376
10377 if (! reload_completed)
10378 emit_insn (gen_ashrsi3 (high[0], low[0], GEN_INT (31)));
10379 else
10380 {
10381 emit_move_insn (high[0], low[0]);
10382 emit_insn (gen_ashrsi3 (high[0], high[0], GEN_INT (31)));
10383 }
10384
10385 if (count > 32)
10386 emit_insn (gen_ashrsi3 (low[0], low[0], GEN_INT (count - 32)));
10387 }
10388 else
10389 {
10390 if (!rtx_equal_p (operands[0], operands[1]))
10391 emit_move_insn (operands[0], operands[1]);
10392 emit_insn (gen_x86_shrd_1 (low[0], high[0], GEN_INT (count)));
10393 emit_insn (gen_ashrsi3 (high[0], high[0], GEN_INT (count)));
10394 }
10395 }
10396 else
10397 {
10398 if (!rtx_equal_p (operands[0], operands[1]))
10399 emit_move_insn (operands[0], operands[1]);
10400
10401 split_di (operands, 1, low, high);
10402
10403 emit_insn (gen_x86_shrd_1 (low[0], high[0], operands[2]));
10404 emit_insn (gen_ashrsi3 (high[0], high[0], operands[2]));
10405
10406 if (TARGET_CMOVE && (! no_new_pseudos || scratch))
10407 {
10408 if (! no_new_pseudos)
10409 scratch = gen_reg_rtx (SImode);
10410 emit_move_insn (scratch, high[0]);
10411 emit_insn (gen_ashrsi3 (scratch, scratch, GEN_INT (31)));
10412 emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
10413 scratch));
10414 }
10415 else
10416 emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2]));
10417 }
10418 }
10419
10420 void
10421 ix86_split_lshrdi (operands, scratch)
10422 rtx *operands, scratch;
10423 {
10424 rtx low[2], high[2];
10425 int count;
10426
10427 if (GET_CODE (operands[2]) == CONST_INT)
10428 {
10429 split_di (operands, 2, low, high);
10430 count = INTVAL (operands[2]) & 63;
10431
10432 if (count >= 32)
10433 {
10434 emit_move_insn (low[0], high[1]);
10435 emit_move_insn (high[0], const0_rtx);
10436
10437 if (count > 32)
10438 emit_insn (gen_lshrsi3 (low[0], low[0], GEN_INT (count - 32)));
10439 }
10440 else
10441 {
10442 if (!rtx_equal_p (operands[0], operands[1]))
10443 emit_move_insn (operands[0], operands[1]);
10444 emit_insn (gen_x86_shrd_1 (low[0], high[0], GEN_INT (count)));
10445 emit_insn (gen_lshrsi3 (high[0], high[0], GEN_INT (count)));
10446 }
10447 }
10448 else
10449 {
10450 if (!rtx_equal_p (operands[0], operands[1]))
10451 emit_move_insn (operands[0], operands[1]);
10452
10453 split_di (operands, 1, low, high);
10454
10455 emit_insn (gen_x86_shrd_1 (low[0], high[0], operands[2]));
10456 emit_insn (gen_lshrsi3 (high[0], high[0], operands[2]));
10457
10458
10459 if (TARGET_CMOVE && (! no_new_pseudos || scratch))
10460 {
10461 if (! no_new_pseudos)
10462 scratch = force_reg (SImode, const0_rtx);
10463 else
10464 emit_move_insn (scratch, const0_rtx);
10465
10466 emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
10467 scratch));
10468 }
10469 else
10470 emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2]));
10471 }
10472 }
10473
10474
10475
10476 static rtx
10477 ix86_expand_aligntest (variable, value)
10478 rtx variable;
10479 int value;
10480 {
10481 rtx label = gen_label_rtx ();
10482 rtx tmpcount = gen_reg_rtx (GET_MODE (variable));
10483 if (GET_MODE (variable) == DImode)
10484 emit_insn (gen_anddi3 (tmpcount, variable, GEN_INT (value)));
10485 else
10486 emit_insn (gen_andsi3 (tmpcount, variable, GEN_INT (value)));
10487 emit_cmp_and_jump_insns (tmpcount, const0_rtx, EQ, 0, GET_MODE (variable),
10488 1, label);
10489 return label;
10490 }
10491
10492
10493 static void
10494 ix86_adjust_counter (countreg, value)
10495 rtx countreg;
10496 HOST_WIDE_INT value;
10497 {
10498 if (GET_MODE (countreg) == DImode)
10499 emit_insn (gen_adddi3 (countreg, countreg, GEN_INT (-value)));
10500 else
10501 emit_insn (gen_addsi3 (countreg, countreg, GEN_INT (-value)));
10502 }
10503
10504
10505 rtx
10506 ix86_zero_extend_to_Pmode (exp)
10507 rtx exp;
10508 {
10509 rtx r;
10510 if (GET_MODE (exp) == VOIDmode)
10511 return force_reg (Pmode, exp);
10512 if (GET_MODE (exp) == Pmode)
10513 return copy_to_mode_reg (Pmode, exp);
10514 r = gen_reg_rtx (Pmode);
10515 emit_insn (gen_zero_extendsidi2 (r, exp));
10516 return r;
10517 }
10518
10519
10520
10521 int
10522 ix86_expand_movstr (dst, src, count_exp, align_exp)
10523 rtx dst, src, count_exp, align_exp;
10524 {
10525 rtx srcreg, destreg, countreg;
10526 enum machine_mode counter_mode;
10527 HOST_WIDE_INT align = 0;
10528 unsigned HOST_WIDE_INT count = 0;
10529 rtx insns;
10530
10531 start_sequence ();
10532
10533 if (GET_CODE (align_exp) == CONST_INT)
10534 align = INTVAL (align_exp);
10535
10536
10537 if (!TARGET_ALIGN_STRINGOPS)
10538 align = 64;
10539
10540 if (GET_CODE (count_exp) == CONST_INT)
10541 count = INTVAL (count_exp);
10542
10543
10544
10545
10546 if (!TARGET_64BIT || GET_MODE (count_exp) == SImode
10547 || x86_64_zero_extended_value (count_exp))
10548 counter_mode = SImode;
10549 else
10550 counter_mode = DImode;
10551
10552 if (counter_mode != SImode && counter_mode != DImode)
10553 abort ();
10554
10555 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
10556 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
10557
10558 emit_insn (gen_cld ());
10559
10560
10561
10562
10563 if ((!optimize || optimize_size) && (count == 0 || (count & 0x03)))
10564 {
10565 countreg = ix86_zero_extend_to_Pmode (count_exp);
10566 if (TARGET_64BIT)
10567 emit_insn (gen_rep_movqi_rex64 (destreg, srcreg, countreg,
10568 destreg, srcreg, countreg));
10569 else
10570 emit_insn (gen_rep_movqi (destreg, srcreg, countreg,
10571 destreg, srcreg, countreg));
10572 }
10573
10574
10575
10576
10577
10578 else if (count != 0
10579 && (align >= 8
10580 || (!TARGET_PENTIUMPRO && !TARGET_64BIT && align >= 4)
10581 || optimize_size || count < (unsigned int) 64))
10582 {
10583 int size = TARGET_64BIT && !optimize_size ? 8 : 4;
10584 if (count & ~(size - 1))
10585 {
10586 countreg = copy_to_mode_reg (counter_mode,
10587 GEN_INT ((count >> (size == 4 ? 2 : 3))
10588 & (TARGET_64BIT ? -1 : 0x3fffffff)));
10589 countreg = ix86_zero_extend_to_Pmode (countreg);
10590 if (size == 4)
10591 {
10592 if (TARGET_64BIT)
10593 emit_insn (gen_rep_movsi_rex64 (destreg, srcreg, countreg,
10594 destreg, srcreg, countreg));
10595 else
10596 emit_insn (gen_rep_movsi (destreg, srcreg, countreg,
10597 destreg, srcreg, countreg));
10598 }
10599 else
10600 emit_insn (gen_rep_movdi_rex64 (destreg, srcreg, countreg,
10601 destreg, srcreg, countreg));
10602 }
10603 if (size == 8 && (count & 0x04))
10604 emit_insn (gen_strmovsi (destreg, srcreg));
10605 if (count & 0x02)
10606 emit_insn (gen_strmovhi (destreg, srcreg));
10607 if (count & 0x01)
10608 emit_insn (gen_strmovqi (destreg, srcreg));
10609 }
10610
10611
10612
10613
10614
10615 else
10616 {
10617 rtx countreg2;
10618 rtx label = NULL;
10619 int desired_alignment = (TARGET_PENTIUMPRO
10620 && (count == 0 || count >= (unsigned int) 260)
10621 ? 8 : UNITS_PER_WORD);
10622
10623
10624
10625
10626 if (!TARGET_INLINE_ALL_STRINGOPS && align < UNITS_PER_WORD)
10627 {
10628 end_sequence ();
10629 return 0;
10630 }
10631
10632 if (TARGET_SINGLE_STRINGOP)
10633 emit_insn (gen_cld ());
10634
10635 countreg2 = gen_reg_rtx (Pmode);
10636 countreg = copy_to_mode_reg (counter_mode, count_exp);
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651 if (count == 0 && align < desired_alignment)
10652 {
10653 label = gen_label_rtx ();
10654 emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
10655 LEU, 0, counter_mode, 1, label);
10656 }
10657 if (align <= 1)
10658 {
10659 rtx label = ix86_expand_aligntest (destreg, 1);
10660 emit_insn (gen_strmovqi (destreg, srcreg));
10661 ix86_adjust_counter (countreg, 1);
10662 emit_label (label);
10663 LABEL_NUSES (label) = 1;
10664 }
10665 if (align <= 2)
10666 {
10667 rtx label = ix86_expand_aligntest (destreg, 2);
10668 emit_insn (gen_strmovhi (destreg, srcreg));
10669 ix86_adjust_counter (countreg, 2);
10670 emit_label (label);
10671 LABEL_NUSES (label) = 1;
10672 }
10673 if (align <= 4 && desired_alignment > 4)
10674 {
10675 rtx label = ix86_expand_aligntest (destreg, 4);
10676 emit_insn (gen_strmovsi (destreg, srcreg));
10677 ix86_adjust_counter (countreg, 4);
10678 emit_label (label);
10679 LABEL_NUSES (label) = 1;
10680 }
10681
10682 if (label && desired_alignment > 4 && !TARGET_64BIT)
10683 {
10684 emit_label (label);
10685 LABEL_NUSES (label) = 1;
10686 label = NULL_RTX;
10687 }
10688 if (!TARGET_SINGLE_STRINGOP)
10689 emit_insn (gen_cld ());
10690 if (TARGET_64BIT)
10691 {
10692 emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
10693 GEN_INT (3)));
10694 emit_insn (gen_rep_movdi_rex64 (destreg, srcreg, countreg2,
10695 destreg, srcreg, countreg2));
10696 }
10697 else
10698 {
10699 emit_insn (gen_lshrsi3 (countreg2, countreg, GEN_INT (2)));
10700 emit_insn (gen_rep_movsi (destreg, srcreg, countreg2,
10701 destreg, srcreg, countreg2));
10702 }
10703
10704 if (label)
10705 {
10706 emit_label (label);
10707 LABEL_NUSES (label) = 1;
10708 }
10709 if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
10710 emit_insn (gen_strmovsi (destreg, srcreg));
10711 if ((align <= 4 || count == 0) && TARGET_64BIT)
10712 {
10713 rtx label = ix86_expand_aligntest (countreg, 4);
10714 emit_insn (gen_strmovsi (destreg, srcreg));
10715 emit_label (label);
10716 LABEL_NUSES (label) = 1;
10717 }
10718 if (align > 2 && count != 0 && (count & 2))
10719 emit_insn (gen_strmovhi (destreg, srcreg));
10720 if (align <= 2 || count == 0)
10721 {
10722 rtx label = ix86_expand_aligntest (countreg, 2);
10723 emit_insn (gen_strmovhi (destreg, srcreg));
10724 emit_label (label);
10725 LABEL_NUSES (label) = 1;
10726 }
10727 if (align > 1 && count != 0 && (count & 1))
10728 emit_insn (gen_strmovqi (destreg, srcreg));
10729 if (align <= 1 || count == 0)
10730 {
10731 rtx label = ix86_expand_aligntest (countreg, 1);
10732 emit_insn (gen_strmovqi (destreg, srcreg));
10733 emit_label (label);
10734 LABEL_NUSES (label) = 1;
10735 }
10736 }
10737
10738 insns = get_insns ();
10739 end_sequence ();
10740
10741 ix86_set_move_mem_attrs (insns, dst, src, destreg, srcreg);
10742 emit_insn (insns);
10743 return 1;
10744 }
10745
10746
10747
10748 int
10749 ix86_expand_clrstr (src, count_exp, align_exp)
10750 rtx src, count_exp, align_exp;
10751 {
10752 rtx destreg, zeroreg, countreg;
10753 enum machine_mode counter_mode;
10754 HOST_WIDE_INT align = 0;
10755 unsigned HOST_WIDE_INT count = 0;
10756
10757 if (GET_CODE (align_exp) == CONST_INT)
10758 align = INTVAL (align_exp);
10759
10760
10761 if (!TARGET_ALIGN_STRINGOPS)
10762 align = 32;
10763
10764 if (GET_CODE (count_exp) == CONST_INT)
10765 count = INTVAL (count_exp);
10766
10767
10768
10769 if (!TARGET_64BIT || GET_MODE (count_exp) == SImode
10770 || x86_64_zero_extended_value (count_exp))
10771 counter_mode = SImode;
10772 else
10773 counter_mode = DImode;
10774
10775 destreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
10776
10777 emit_insn (gen_cld ());
10778
10779
10780
10781
10782 if ((!optimize || optimize_size) && (count == 0 || (count & 0x03)))
10783 {
10784 countreg = ix86_zero_extend_to_Pmode (count_exp);
10785 zeroreg = copy_to_mode_reg (QImode, const0_rtx);
10786 if (TARGET_64BIT)
10787 emit_insn (gen_rep_stosqi_rex64 (destreg, countreg, zeroreg,
10788 destreg, countreg));
10789 else
10790 emit_insn (gen_rep_stosqi (destreg, countreg, zeroreg,
10791 destreg, countreg));
10792 }
10793 else if (count != 0
10794 && (align >= 8
10795 || (!TARGET_PENTIUMPRO && !TARGET_64BIT && align >= 4)
10796 || optimize_size || count < (unsigned int) 64))
10797 {
10798 int size = TARGET_64BIT && !optimize_size ? 8 : 4;
10799 zeroreg = copy_to_mode_reg (size == 4 ? SImode : DImode, const0_rtx);
10800 if (count & ~(size - 1))
10801 {
10802 countreg = copy_to_mode_reg (counter_mode,
10803 GEN_INT ((count >> (size == 4 ? 2 : 3))
10804 & (TARGET_64BIT ? -1 : 0x3fffffff)));
10805 countreg = ix86_zero_extend_to_Pmode (countreg);
10806 if (size == 4)
10807 {
10808 if (TARGET_64BIT)
10809 emit_insn (gen_rep_stossi_rex64 (destreg, countreg, zeroreg,
10810 destreg, countreg));
10811 else
10812 emit_insn (gen_rep_stossi (destreg, countreg, zeroreg,
10813 destreg, countreg));
10814 }
10815 else
10816 emit_insn (gen_rep_stosdi_rex64 (destreg, countreg, zeroreg,
10817 destreg, countreg));
10818 }
10819 if (size == 8 && (count & 0x04))
10820 emit_insn (gen_strsetsi (destreg,
10821 gen_rtx_SUBREG (SImode, zeroreg, 0)));
10822 if (count & 0x02)
10823 emit_insn (gen_strsethi (destreg,
10824 gen_rtx_SUBREG (HImode, zeroreg, 0)));
10825 if (count & 0x01)
10826 emit_insn (gen_strsetqi (destreg,
10827 gen_rtx_SUBREG (QImode, zeroreg, 0)));
10828 }
10829 else
10830 {
10831 rtx countreg2;
10832 rtx label = NULL;
10833
10834 int desired_alignment = (TARGET_PENTIUMPRO
10835 && (count == 0 || count >= (unsigned int) 260)
10836 ? 8 : UNITS_PER_WORD);
10837
10838
10839
10840
10841 if (!TARGET_INLINE_ALL_STRINGOPS && align < UNITS_PER_WORD)
10842 return 0;
10843
10844 if (TARGET_SINGLE_STRINGOP)
10845 emit_insn (gen_cld ());
10846
10847 countreg2 = gen_reg_rtx (Pmode);
10848 countreg = copy_to_mode_reg (counter_mode, count_exp);
10849 zeroreg = copy_to_mode_reg (Pmode, const0_rtx);
10850
10851 if (count == 0 && align < desired_alignment)
10852 {
10853 label = gen_label_rtx ();
10854 emit_cmp_and_jump_insns (countreg, GEN_INT (desired_alignment - 1),
10855 LEU, 0, counter_mode, 1, label);
10856 }
10857 if (align <= 1)
10858 {
10859 rtx label = ix86_expand_aligntest (destreg, 1);
10860 emit_insn (gen_strsetqi (destreg,
10861 gen_rtx_SUBREG (QImode, zeroreg, 0)));
10862 ix86_adjust_counter (countreg, 1);
10863 emit_label (label);
10864 LABEL_NUSES (label) = 1;
10865 }
10866 if (align <= 2)
10867 {
10868 rtx label = ix86_expand_aligntest (destreg, 2);
10869 emit_insn (gen_strsethi (destreg,
10870 gen_rtx_SUBREG (HImode, zeroreg, 0)));
10871 ix86_adjust_counter (countreg, 2);
10872 emit_label (label);
10873 LABEL_NUSES (label) = 1;
10874 }
10875 if (align <= 4 && desired_alignment > 4)
10876 {
10877 rtx label = ix86_expand_aligntest (destreg, 4);
10878 emit_insn (gen_strsetsi (destreg, (TARGET_64BIT
10879 ? gen_rtx_SUBREG (SImode, zeroreg, 0)
10880 : zeroreg)));
10881 ix86_adjust_counter (countreg, 4);
10882 emit_label (label);
10883 LABEL_NUSES (label) = 1;
10884 }
10885
10886 if (label && desired_alignment > 4 && !TARGET_64BIT)
10887 {
10888 emit_label (label);
10889 LABEL_NUSES (label) = 1;
10890 label = NULL_RTX;
10891 }
10892
10893 if (!TARGET_SINGLE_STRINGOP)
10894 emit_insn (gen_cld ());
10895 if (TARGET_64BIT)
10896 {
10897 emit_insn (gen_lshrdi3 (countreg2, ix86_zero_extend_to_Pmode (countreg),
10898 GEN_INT (3)));
10899 emit_insn (gen_rep_stosdi_rex64 (destreg, countreg2, zeroreg,
10900 destreg, countreg2));
10901 }
10902 else
10903 {
10904 emit_insn (gen_lshrsi3 (countreg2, countreg, GEN_INT (2)));
10905 emit_insn (gen_rep_stossi (destreg, countreg2, zeroreg,
10906 destreg, countreg2));
10907 }
10908 if (label)
10909 {
10910 emit_label (label);
10911 LABEL_NUSES (label) = 1;
10912 }
10913
10914 if (TARGET_64BIT && align > 4 && count != 0 && (count & 4))
10915 emit_insn (gen_strsetsi (destreg,
10916 gen_rtx_SUBREG (SImode, zeroreg, 0)));
10917 if (TARGET_64BIT && (align <= 4 || count == 0))
10918 {
10919 rtx label = ix86_expand_aligntest (countreg, 4);
10920 emit_insn (gen_strsetsi (destreg,
10921 gen_rtx_SUBREG (SImode, zeroreg, 0)));
10922 emit_label (label);
10923 LABEL_NUSES (label) = 1;
10924 }
10925 if (align > 2 && count != 0 && (count & 2))
10926 emit_insn (gen_strsethi (destreg,
10927 gen_rtx_SUBREG (HImode, zeroreg, 0)));
10928 if (align <= 2 || count == 0)
10929 {
10930 rtx label = ix86_expand_aligntest (countreg, 2);
10931 emit_insn (gen_strsethi (destreg,
10932 gen_rtx_SUBREG (HImode, zeroreg, 0)));
10933 emit_label (label);
10934 LABEL_NUSES (label) = 1;
10935 }
10936 if (align > 1 && count != 0 && (count & 1))
10937 emit_insn (gen_strsetqi (destreg,
10938 gen_rtx_SUBREG (QImode, zeroreg, 0)));
10939 if (align <= 1 || count == 0)
10940 {
10941 rtx label = ix86_expand_aligntest (countreg, 1);
10942 emit_insn (gen_strsetqi (destreg,
10943 gen_rtx_SUBREG (QImode, zeroreg, 0)));
10944 emit_label (label);
10945 LABEL_NUSES (label) = 1;
10946 }
10947 }
10948 return 1;
10949 }
10950
10951 int
10952 ix86_expand_strlen (out, src, eoschar, align)
10953 rtx out, src, eoschar, align;
10954 {
10955 rtx addr, scratch1, scratch2, scratch3, scratch4;
10956
10957
10958
10959
10960 if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
10961 && !TARGET_INLINE_ALL_STRINGOPS
10962 && !optimize_size
10963 && (GET_CODE (align) != CONST_INT || INTVAL (align) < 4))
10964 return 0;
10965
10966 addr = force_reg (Pmode, XEXP (src, 0));
10967 scratch1 = gen_reg_rtx (Pmode);
10968
10969 if (TARGET_UNROLL_STRLEN && eoschar == const0_rtx && optimize > 1
10970 && !optimize_size)
10971 {
10972
10973
10974
10975
10976
10977
10978
10979
10980 emit_move_insn (out, addr);
10981
10982 ix86_expand_strlensi_unroll_1 (out, align);
10983
10984
10985
10986
10987 if (TARGET_64BIT)
10988 emit_insn (gen_subdi3 (out, out, addr));
10989 else
10990 emit_insn (gen_subsi3 (out, out, addr));
10991 }
10992 else
10993 {
10994 scratch2 = gen_reg_rtx (Pmode);
10995 scratch3 = gen_reg_rtx (Pmode);
10996 scratch4 = force_reg (Pmode, constm1_rtx);
10997
10998 emit_move_insn (scratch3, addr);
10999 eoschar = force_reg (QImode, eoschar);
11000
11001 emit_insn (gen_cld ());
11002 if (TARGET_64BIT)
11003 {
11004 emit_insn (gen_strlenqi_rex_1 (scratch1, scratch3, eoschar,
11005 align, scratch4, scratch3));
11006 emit_insn (gen_one_cmpldi2 (scratch2, scratch1));
11007 emit_insn (gen_adddi3 (out, scratch2, constm1_rtx));
11008 }
11009 else
11010 {
11011 emit_insn (gen_strlenqi_1 (scratch1, scratch3, eoschar,
11012 align, scratch4, scratch3));
11013 emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
11014 emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
11015 }
11016 }
11017 return 1;
11018 }
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031 static void
11032 ix86_expand_strlensi_unroll_1 (out, align_rtx)
11033 rtx out, align_rtx;
11034 {
11035 int align;
11036 rtx tmp;
11037 rtx align_2_label = NULL_RTX;
11038 rtx align_3_label = NULL_RTX;
11039 rtx align_4_label = gen_label_rtx ();
11040 rtx end_0_label = gen_label_rtx ();
11041 rtx mem;
11042 rtx tmpreg = gen_reg_rtx (SImode);
11043 rtx scratch = gen_reg_rtx (SImode);
11044
11045 align = 0;
11046 if (GET_CODE (align_rtx) == CONST_INT)
11047 align = INTVAL (align_rtx);
11048
11049
11050
11051
11052 if (align < 4)
11053 {
11054 rtx scratch1 = gen_reg_rtx (Pmode);
11055 emit_move_insn (scratch1, out);
11056
11057 if (align != 2)
11058 {
11059 align_3_label = gen_label_rtx ();
11060 align_2_label = gen_label_rtx ();
11061
11062
11063 align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (3),
11064 NULL_RTX, 0, OPTAB_WIDEN);
11065
11066 emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
11067 Pmode, 1, align_4_label);
11068 emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), EQ, NULL,
11069 Pmode, 1, align_2_label);
11070 emit_cmp_and_jump_insns (align_rtx, GEN_INT (2), GTU, NULL,
11071 Pmode, 1, align_3_label);
11072 }
11073 else
11074 {
11075
11076
11077
11078 align_rtx = expand_binop (Pmode, and_optab, scratch1, GEN_INT (2),
11079 NULL_RTX, 0, OPTAB_WIDEN);
11080
11081 emit_cmp_and_jump_insns (align_rtx, const0_rtx, EQ, NULL,
11082 Pmode, 1, align_4_label);
11083 }
11084
11085 mem = gen_rtx_MEM (QImode, out);
11086
11087
11088
11089
11090 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL,
11091 QImode, 1, end_0_label);
11092
11093
11094 if (TARGET_64BIT)
11095 emit_insn (gen_adddi3 (out, out, const1_rtx));
11096 else
11097 emit_insn (gen_addsi3 (out, out, const1_rtx));
11098
11099
11100 if (align != 2)
11101 {
11102 emit_label (align_2_label);
11103
11104 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
11105 end_0_label);
11106
11107 if (TARGET_64BIT)
11108 emit_insn (gen_adddi3 (out, out, const1_rtx));
11109 else
11110 emit_insn (gen_addsi3 (out, out, const1_rtx));
11111
11112 emit_label (align_3_label);
11113 }
11114
11115 emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
11116 end_0_label);
11117
11118 if (TARGET_64BIT)
11119 emit_insn (gen_adddi3 (out, out, const1_rtx));
11120 else
11121 emit_insn (gen_addsi3 (out, out, const1_rtx));
11122 }
11123
11124
11125
11126
11127 emit_label (align_4_label);
11128
11129 mem = gen_rtx_MEM (SImode, out);
11130 emit_move_insn (scratch, mem);
11131 if (TARGET_64BIT)
11132 emit_insn (gen_adddi3 (out, out, GEN_INT (4)));
11133 else
11134 emit_insn (gen_addsi3 (out, out, GEN_INT (4)));
11135
11136
11137
11138
11139 emit_insn (gen_addsi3 (tmpreg, scratch, GEN_INT (-0x01010101)));
11140 emit_insn (gen_one_cmplsi2 (scratch, scratch));
11141 emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
11142 emit_insn (gen_andsi3 (tmpreg, tmpreg,
11143 gen_int_mode (0x80808080, SImode)));
11144 emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
11145 align_4_label);
11146
11147 if (TARGET_CMOVE)
11148 {
11149 rtx reg = gen_reg_rtx (SImode);
11150 rtx reg2 = gen_reg_rtx (Pmode);
11151 emit_move_insn (reg, tmpreg);
11152 emit_insn (gen_lshrsi3 (reg, reg, GEN_INT (16)));
11153
11154
11155 emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
11156 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11157 tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
11158 emit_insn (gen_rtx_SET (VOIDmode, tmpreg,
11159 gen_rtx_IF_THEN_ELSE (SImode, tmp,
11160 reg,
11161 tmpreg)));
11162
11163 emit_insn (gen_rtx_SET (SImode, reg2,
11164 gen_rtx_PLUS (Pmode, out, GEN_INT (2))));
11165
11166 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11167 tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
11168 emit_insn (gen_rtx_SET (VOIDmode, out,
11169 gen_rtx_IF_THEN_ELSE (Pmode, tmp,
11170 reg2,
11171 out)));
11172
11173 }
11174 else
11175 {
11176 rtx end_2_label = gen_label_rtx ();
11177
11178
11179 emit_insn (gen_testsi_ccno_1 (tmpreg, GEN_INT (0x8080)));
11180 tmp = gen_rtx_REG (CCNOmode, FLAGS_REG);
11181 tmp = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
11182 tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
11183 gen_rtx_LABEL_REF (VOIDmode, end_2_label),
11184 pc_rtx);
11185 tmp = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
11186 JUMP_LABEL (tmp) = end_2_label;
11187
11188
11189 emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
11190 if (TARGET_64BIT)
11191 emit_insn (gen_adddi3 (out, out, GEN_INT (2)));
11192 else
11193 emit_insn (gen_addsi3 (out, out, GEN_INT (2)));
11194
11195 emit_label (end_2_label);
11196
11197 }
11198
11199
11200 tmpreg = gen_lowpart (QImode, tmpreg);
11201 emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg));
11202 if (TARGET_64BIT)
11203 emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3)));
11204 else
11205 emit_insn (gen_subsi3_carry (out, out, GEN_INT (3)));
11206
11207 emit_label (end_0_label);
11208 }
11209
11210 void
11211 ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
11212 rtx retval, fnaddr, callarg1, callarg2, pop;
11213 {
11214 rtx use = NULL, call;
11215
11216 if (pop == const0_rtx)
11217 pop = NULL;
11218 if (TARGET_64BIT && pop)
11219 abort ();
11220
11221 #if TARGET_MACHO
11222 if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
11223 fnaddr = machopic_indirect_call_target (fnaddr);
11224 #else
11225
11226 if (! TARGET_64BIT && flag_pic
11227 && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
11228 && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
11229 use_reg (&use, pic_offset_table_rtx);
11230
11231 if (TARGET_64BIT && INTVAL (callarg2) >= 0)
11232 {
11233 rtx al = gen_rtx_REG (QImode, 0);
11234 emit_move_insn (al, callarg2);
11235 use_reg (&use, al);
11236 }
11237 #endif
11238
11239 if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
11240 {
11241 fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
11242 fnaddr = gen_rtx_MEM (QImode, fnaddr);
11243 }
11244
11245 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
11246 if (retval)
11247 call = gen_rtx_SET (VOIDmode, retval, call);
11248 if (pop)
11249 {
11250 pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
11251 pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
11252 call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
11253 }
11254
11255 call = emit_call_insn (call);
11256 if (use)
11257 CALL_INSN_FUNCTION_USAGE (call) = use;
11258 }
11259
11260
11261
11262
11263
11264
11265 static struct machine_function *
11266 ix86_init_machine_status ()
11267 {
11268 return ggc_alloc_cleared (sizeof (struct machine_function));
11269 }
11270
11271
11272
11273
11274
11275
11276
11277 rtx
11278 assign_386_stack_local (mode, n)
11279 enum machine_mode mode;
11280 int n;
11281 {
11282 if (n < 0 || n >= MAX_386_STACK_LOCALS)
11283 abort ();
11284
11285 if (ix86_stack_locals[(int) mode][n] == NULL_RTX)
11286 ix86_stack_locals[(int) mode][n]
11287 = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
11288
11289 return ix86_stack_locals[(int) mode][n];
11290 }
11291
11292
11293
11294 static GTY(()) rtx ix86_tls_symbol;
11295 rtx
11296 ix86_tls_get_addr ()
11297 {
11298
11299 if (!ix86_tls_symbol)
11300 {
11301 ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
11302 (TARGET_GNU_TLS && !TARGET_64BIT)
11303 ? "___tls_get_addr"
11304 : "__tls_get_addr");
11305 }
11306
11307 return ix86_tls_symbol;
11308 }
11309
11310
11311
11312
11313 static int
11314 memory_address_length (addr)
11315 rtx addr;
11316 {
11317 struct ix86_address parts;
11318 rtx base, index, disp;
11319 int len;
11320
11321 if (GET_CODE (addr) == PRE_DEC
11322 || GET_CODE (addr) == POST_INC
11323 || GET_CODE (addr) == PRE_MODIFY
11324 || GET_CODE (addr) == POST_MODIFY)
11325 return 0;
11326
11327 if (! ix86_decompose_address (addr, &parts))
11328 abort ();
11329
11330 base = parts.base;
11331 index = parts.index;
11332 disp = parts.disp;
11333 len = 0;
11334
11335
11336
11337
11338
11339
11340 if (base && !index && !disp)
11341 {
11342
11343
11344 if (addr == stack_pointer_rtx
11345 || addr == arg_pointer_rtx
11346 || addr == frame_pointer_rtx
11347 || addr == hard_frame_pointer_rtx)
11348 len = 1;
11349 }
11350
11351
11352 else if (disp && !base && !index)
11353 len = 4;
11354
11355 else
11356 {
11357
11358 if (disp)
11359 {
11360 if (GET_CODE (disp) == CONST_INT
11361 && CONST_OK_FOR_LETTER_P (INTVAL (disp), 'K')
11362 && base)
11363 len = 1;
11364 else
11365 len = 4;
11366 }
11367
11368 else if (base == hard_frame_pointer_rtx)
11369 len = 1;
11370
11371
11372 if (index
11373
11374 || base == stack_pointer_rtx
11375 || base == arg_pointer_rtx
11376 || base == frame_pointer_rtx)
11377 len += 1;
11378 }
11379
11380 return len;
11381 }
11382
11383
11384
11385 int
11386 ix86_attr_length_immediate_default (insn, shortform)
11387 rtx insn;
11388 int shortform;
11389 {
11390 int len = 0;
11391 int i;
11392 extract_insn_cached (insn);
11393 for (i = recog_data.n_operands - 1; i >= 0; --i)
11394 if (CONSTANT_P (recog_data.operand[i]))
11395 {
11396 if (len)
11397 abort ();
11398 if (shortform
11399 && GET_CODE (recog_data.operand[i]) == CONST_INT
11400 && CONST_OK_FOR_LETTER_P (INTVAL (recog_data.operand[i]), 'K'))
11401 len = 1;
11402 else
11403 {
11404 switch (get_attr_mode (insn))
11405 {
11406 case MODE_QI:
11407 len+=1;
11408 break;
11409 case MODE_HI:
11410 len+=2;
11411 break;
11412 case MODE_SI:
11413 len+=4;
11414 break;
11415
11416 case MODE_DI:
11417 len+=4;
11418 break;
11419 default:
11420 fatal_insn ("unknown insn mode", insn);
11421 }
11422 }
11423 }
11424 return len;
11425 }
11426
11427 int
11428 ix86_attr_length_address_default (insn)
11429 rtx insn;
11430 {
11431 int i;
11432
11433 if (get_attr_type (insn) == TYPE_LEA)
11434 {
11435 rtx set = PATTERN (insn);
11436 if (GET_CODE (set) == SET)
11437 ;
11438 else if (GET_CODE (set) == PARALLEL
11439 && GET_CODE (XVECEXP (set, 0, 0)) == SET)
11440 set = XVECEXP (set, 0, 0);
11441 else
11442 {
11443 #ifdef ENABLE_CHECKING
11444 abort ();
11445 #endif
11446 return 0;
11447 }
11448
11449 return memory_address_length (SET_SRC (set));
11450 }
11451
11452 extract_insn_cached (insn);
11453 for (i = recog_data.n_operands - 1; i >= 0; --i)
11454 if (GET_CODE (recog_data.operand[i]) == MEM)
11455 {
11456 return memory_address_length (XEXP (recog_data.operand[i], 0));
11457 break;
11458 }
11459 return 0;
11460 }
11461
11462
11463
11464 static int
11465 ix86_issue_rate ()
11466 {
11467 switch (ix86_cpu)
11468 {
11469 case PROCESSOR_PENTIUM:
11470 case PROCESSOR_K6:
11471 return 2;
11472
11473 case PROCESSOR_PENTIUMPRO:
11474 case PROCESSOR_PENTIUM4:
11475 case PROCESSOR_ATHLON:
11476 return 3;
11477
11478 default:
11479 return 1;
11480 }
11481 }
11482
11483
11484
11485
11486 static int
11487 ix86_flags_dependant (insn, dep_insn, insn_type)
11488 rtx insn, dep_insn;
11489 enum attr_type insn_type;
11490 {
11491 rtx set, set2;
11492
11493
11494 if (insn_type != TYPE_SETCC
11495 && insn_type != TYPE_ICMOV
11496 && insn_type != TYPE_FCMOV
11497 && insn_type != TYPE_IBR)
11498 return 0;
11499
11500 if ((set = single_set (dep_insn)) != 0)
11501 {
11502 set = SET_DEST (set);
11503 set2 = NULL_RTX;
11504 }
11505 else if (GET_CODE (PATTERN (dep_insn)) == PARALLEL
11506 && XVECLEN (PATTERN (dep_insn), 0) == 2
11507 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 0)) == SET
11508 && GET_CODE (XVECEXP (PATTERN (dep_insn), 0, 1)) == SET)
11509 {
11510 set = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
11511 set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
11512 }
11513 else
11514 return 0;
11515
11516 if (GET_CODE (set) != REG || REGNO (set) != FLAGS_REG)
11517 return 0;
11518
11519
11520
11521 if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
11522 return 0;
11523
11524 if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
11525 return 0;
11526
11527 return 1;
11528 }
11529
11530
11531
11532
11533 static int
11534 ix86_agi_dependant (insn, dep_insn, insn_type)
11535 rtx insn, dep_insn;
11536 enum attr_type insn_type;
11537 {
11538 rtx addr;
11539
11540 if (insn_type == TYPE_LEA
11541 && TARGET_PENTIUM)
11542 {
11543 addr = PATTERN (insn);
11544 if (GET_CODE (addr) == SET)
11545 ;
11546 else if (GET_CODE (addr) == PARALLEL
11547 && GET_CODE (XVECEXP (addr, 0, 0)) == SET)
11548 addr = XVECEXP (addr, 0, 0);
11549 else
11550 abort ();
11551 addr = SET_SRC (addr);
11552 }
11553 else
11554 {
11555 int i;
11556 extract_insn_cached (insn);
11557 for (i = recog_data.n_operands - 1; i >= 0; --i)
11558 if (GET_CODE (recog_data.operand[i]) == MEM)
11559 {
11560 addr = XEXP (recog_data.operand[i], 0);
11561 goto found;
11562 }
11563 return 0;
11564 found:;
11565 }
11566
11567 return modified_in_p (addr, dep_insn);
11568 }
11569
11570 static int
11571 ix86_adjust_cost (insn, link, dep_insn, cost)
11572 rtx insn, link, dep_insn;
11573 int cost;
11574 {
11575 enum attr_type insn_type, dep_insn_type;
11576 enum attr_memory memory, dep_memory;
11577 rtx set, set2;
11578 int dep_insn_code_number;
11579
11580
11581 if (REG_NOTE_KIND (link) != 0)
11582 return 0;
11583
11584 dep_insn_code_number = recog_memoized (dep_insn);
11585
11586
11587 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
11588 return cost;
11589
11590 insn_type = get_attr_type (insn);
11591 dep_insn_type = get_attr_type (dep_insn);
11592
11593 switch (ix86_cpu)
11594 {
11595 case PROCESSOR_PENTIUM:
11596
11597 if (ix86_agi_dependant (insn, dep_insn, insn_type))
11598 cost += 1;
11599
11600
11601 if (ix86_flags_dependant (insn, dep_insn, insn_type))
11602 cost = 0;
11603
11604
11605 if (insn_type == TYPE_FMOV
11606 && get_attr_memory (insn) == MEMORY_STORE
11607 && !ix86_agi_dependant (insn, dep_insn, insn_type))
11608 cost += 1;
11609 break;
11610
11611 case PROCESSOR_PENTIUMPRO:
11612 memory = get_attr_memory (insn);
11613 dep_memory = get_attr_memory (dep_insn);
11614
11615
11616
11617 if (dep_insn_type != TYPE_IMOV
11618 && dep_insn_type != TYPE_FMOV
11619 && (dep_memory == MEMORY_LOAD || dep_memory == MEMORY_BOTH))
11620 cost += 1;
11621
11622
11623 if (get_attr_fp_int_src (dep_insn))
11624 cost += 5;
11625
11626
11627 if (insn_type == TYPE_FMOV
11628 && (set = single_set (dep_insn)) != NULL_RTX
11629 && (set2 = single_set (insn)) != NULL_RTX
11630 && rtx_equal_p (SET_DEST (set), SET_SRC (set2))
11631 && GET_CODE (SET_DEST (set2)) == MEM)
11632 cost += 1;
11633
11634
11635
11636
11637 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
11638 && !ix86_agi_dependant (insn, dep_insn, insn_type))
11639 {
11640
11641
11642 if (dep_insn_type == TYPE_IMOV
11643 || dep_insn_type == TYPE_FMOV)
11644 cost = 1;
11645 else if (cost > 1)
11646 cost--;
11647 }
11648 break;
11649
11650 case PROCESSOR_K6:
11651 memory = get_attr_memory (insn);
11652 dep_memory = get_attr_memory (dep_insn);
11653
11654
11655 if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
11656 && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
11657 return 1;
11658
11659
11660
11661 if (dep_memory == MEMORY_LOAD || dep_memory == MEMORY_BOTH)
11662 cost += (dep_insn_type != TYPE_IMOV) ? 2 : 1;
11663
11664
11665 if (get_attr_fp_int_src (dep_insn))
11666 cost += 5;
11667
11668
11669
11670
11671 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
11672 && !ix86_agi_dependant (insn, dep_insn, insn_type))
11673 {
11674
11675
11676 if (dep_insn_type == TYPE_IMOV
11677 || dep_insn_type == TYPE_FMOV)
11678 cost = 1;
11679 else if (cost > 2)
11680 cost -= 2;
11681 else
11682 cost = 1;
11683 }
11684 break;
11685
11686 case PROCESSOR_ATHLON:
11687 memory = get_attr_memory (insn);
11688 dep_memory = get_attr_memory (dep_insn);
11689
11690 if (dep_memory == MEMORY_LOAD || dep_memory == MEMORY_BOTH)
11691 {
11692 if (dep_insn_type == TYPE_IMOV || dep_insn_type == TYPE_FMOV)
11693 cost += 2;
11694 else
11695 cost += 3;
11696 }
11697
11698
11699
11700 if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
11701 && !ix86_agi_dependant (insn, dep_insn, insn_type))
11702 {
11703
11704
11705 if (dep_insn_type == TYPE_IMOV
11706 || dep_insn_type == TYPE_FMOV)
11707 cost = 0;
11708 else if (cost >= 3)
11709 cost -= 3;
11710 else
11711 cost = 0;
11712 }
11713
11714 default:
11715 break;
11716 }
11717
11718 return cost;
11719 }
11720
11721 static union
11722 {
11723 struct ppro_sched_data
11724 {
11725 rtx decode[3];
11726 int issued_this_cycle;
11727 } ppro;
11728 } ix86_sched_data;
11729
11730 static enum attr_ppro_uops
11731 ix86_safe_ppro_uops (insn)
11732 rtx insn;
11733 {
11734 if (recog_memoized (insn) >= 0)
11735 return get_attr_ppro_uops (insn);
11736 else
11737 return PPRO_UOPS_MANY;
11738 }
11739
11740 static void
11741 ix86_dump_ppro_packet (dump)
11742 FILE *dump;
11743 {
11744 if (ix86_sched_data.ppro.decode[0])
11745 {
11746 fprintf (dump, "PPRO packet: %d",
11747 INSN_UID (ix86_sched_data.ppro.decode[0]));
11748 if (ix86_sched_data.ppro.decode[1])
11749 fprintf (dump, " %d", INSN_UID (ix86_sched_data.ppro.decode[1]));
11750 if (ix86_sched_data.ppro.decode[2])
11751 fprintf (dump, " %d", INSN_UID (ix86_sched_data.ppro.decode[2]));
11752 fputc ('\n', dump);
11753 }
11754 }
11755
11756
11757
11758 static void
11759 ix86_sched_init (dump, sched_verbose, veclen)
11760 FILE *dump ATTRIBUTE_UNUSED;
11761 int sched_verbose ATTRIBUTE_UNUSED;
11762 int veclen ATTRIBUTE_UNUSED;
11763 {
11764 memset (&ix86_sched_data, 0, sizeof (ix86_sched_data));
11765 }
11766
11767
11768
11769 static void
11770 ix86_reorder_insn (insnp, slot)
11771 rtx *insnp, *slot;
11772 {
11773 if (insnp != slot)
11774 {
11775 rtx insn = *insnp;
11776 do
11777 insnp[0] = insnp[1];
11778 while (++insnp != slot);
11779 *insnp = insn;
11780 }
11781 }
11782
11783 static void
11784 ix86_sched_reorder_ppro (ready, e_ready)
11785 rtx *ready;
11786 rtx *e_ready;
11787 {
11788 rtx decode[3];
11789 enum attr_ppro_uops cur_uops;
11790 int issued_this_cycle;
11791 rtx *insnp;
11792 int i;
11793
11794
11795
11796
11797
11798
11799
11800 memcpy (decode, ix86_sched_data.ppro.decode, sizeof (decode));
11801 issued_this_cycle = 0;
11802
11803 insnp = e_ready;
11804 cur_uops = ix86_safe_ppro_uops (*insnp);
11805
11806
11807
11808 if (decode[0] == NULL)
11809 {
11810 if (cur_uops == PPRO_UOPS_MANY)
11811 {
11812 decode[0] = *insnp;
11813 goto ppro_done;
11814 }
11815
11816
11817 while (cur_uops != PPRO_UOPS_FEW)
11818 {
11819 if (insnp == ready)
11820 break;
11821 cur_uops = ix86_safe_ppro_uops (*--insnp);
11822 }
11823
11824
11825 if (cur_uops == PPRO_UOPS_FEW)
11826 ix86_reorder_insn (insnp, e_ready);
11827
11828
11829 issued_this_cycle = 1;
11830 decode[0] = *e_ready--;
11831 }
11832
11833
11834 for (i = 1; i < 3; ++i)
11835 if (decode[i] == NULL)
11836 {
11837 if (ready > e_ready)
11838 goto ppro_done;
11839
11840 insnp = e_ready;
11841 cur_uops = ix86_safe_ppro_uops (*insnp);
11842 while (cur_uops != PPRO_UOPS_ONE)
11843 {
11844 if (insnp == ready)
11845 break;
11846 cur_uops = ix86_safe_ppro_uops (*--insnp);
11847 }
11848
11849
11850 if (cur_uops == PPRO_UOPS_ONE)
11851 {
11852 ix86_reorder_insn (insnp, e_ready);
11853 decode[i] = *e_ready--;
11854 issued_this_cycle++;
11855 continue;
11856 }
11857
11858
11859
11860 }
11861
11862 ppro_done:
11863 if (issued_this_cycle == 0)
11864 issued_this_cycle = 1;
11865 ix86_sched_data.ppro.issued_this_cycle = issued_this_cycle;
11866 }
11867
11868
11869
11870 static int
11871 ix86_sched_reorder (dump, sched_verbose, ready, n_readyp, clock_var)
11872 FILE *dump ATTRIBUTE_UNUSED;
11873 int sched_verbose ATTRIBUTE_UNUSED;
11874 rtx *ready;
11875 int *n_readyp;
11876 int clock_var ATTRIBUTE_UNUSED;
11877 {
11878 int n_ready = *n_readyp;
11879 rtx *e_ready = ready + n_ready - 1;
11880
11881
11882
11883
11884 if (n_ready < 2)
11885 {
11886 ix86_sched_data.ppro.issued_this_cycle = 1;
11887 goto out;
11888 }
11889
11890 switch (ix86_cpu)
11891 {
11892 default:
11893 break;
11894
11895 case PROCESSOR_PENTIUMPRO:
11896 ix86_sched_reorder_ppro (ready, e_ready);
11897 break;
11898 }
11899
11900 out:
11901 return ix86_issue_rate ();
11902 }
11903
11904
11905
11906
11907 static int
11908 ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
11909 FILE *dump;
11910 int sched_verbose;
11911 rtx insn;
11912 int can_issue_more;
11913 {
11914 int i;
11915 switch (ix86_cpu)
11916 {
11917 default:
11918 return can_issue_more - 1;
11919
11920 case PROCESSOR_PENTIUMPRO:
11921 {
11922 enum attr_ppro_uops uops = ix86_safe_ppro_uops (insn);
11923
11924 if (uops == PPRO_UOPS_MANY)
11925 {
11926 if (sched_verbose)
11927 ix86_dump_ppro_packet (dump);
11928 ix86_sched_data.ppro.decode[0] = insn;
11929 ix86_sched_data.ppro.decode[1] = NULL;
11930 ix86_sched_data.ppro.decode[2] = NULL;
11931 if (sched_verbose)
11932 ix86_dump_ppro_packet (dump);
11933 ix86_sched_data.ppro.decode[0] = NULL;
11934 }
11935 else if (uops == PPRO_UOPS_FEW)
11936 {
11937 if (sched_verbose)
11938 ix86_dump_ppro_packet (dump);
11939 ix86_sched_data.ppro.decode[0] = insn;
11940 ix86_sched_data.ppro.decode[1] = NULL;
11941 ix86_sched_data.ppro.decode[2] = NULL;
11942 }
11943 else
11944 {
11945 for (i = 0; i < 3; ++i)
11946 if (ix86_sched_data.ppro.decode[i] == NULL)
11947 {
11948 ix86_sched_data.ppro.decode[i] = insn;
11949 break;
11950 }
11951 if (i == 3)
11952 abort ();
11953 if (i == 2)
11954 {
11955 if (sched_verbose)
11956 ix86_dump_ppro_packet (dump);
11957 ix86_sched_data.ppro.decode[0] = NULL;
11958 ix86_sched_data.ppro.decode[1] = NULL;
11959 ix86_sched_data.ppro.decode[2] = NULL;
11960 }
11961 }
11962 }
11963 return --ix86_sched_data.ppro.issued_this_cycle;
11964 }
11965 }
11966
11967 static int
11968 ia32_use_dfa_pipeline_interface ()
11969 {
11970 if (ix86_cpu == PROCESSOR_PENTIUM)
11971 return 1;
11972 return 0;
11973 }
11974
11975
11976
11977
11978
11979 static int
11980 ia32_multipass_dfa_lookahead ()
11981 {
11982 if (ix86_cpu == PROCESSOR_PENTIUM)
11983 return 2;
11984 else
11985 return 0;
11986 }
11987
11988
11989
11990
11991
11992
11993 void
11994 ix86_set_move_mem_attrs (insns, dstref, srcref, dstreg, srcreg)
11995 rtx insns;
11996 rtx dstref, srcref, dstreg, srcreg;
11997 {
11998 rtx insn;
11999
12000 for (insn = insns; insn != 0 ; insn = NEXT_INSN (insn))
12001 if (INSN_P (insn))
12002 ix86_set_move_mem_attrs_1 (PATTERN (insn), dstref, srcref,
12003 dstreg, srcreg);
12004 }
12005
12006
12007
12008
12009 static void
12010 ix86_set_move_mem_attrs_1 (x, dstref, srcref, dstreg, srcreg)
12011 rtx x;
12012 rtx dstref, srcref, dstreg, srcreg;
12013 {
12014 enum rtx_code code = GET_CODE (x);
12015 const char *format_ptr = GET_RTX_FORMAT (code);
12016 int i, j;
12017
12018 if (code == MEM && XEXP (x, 0) == dstreg)
12019 MEM_COPY_ATTRIBUTES (x, dstref);
12020 else if (code == MEM && XEXP (x, 0) == srcreg)
12021 MEM_COPY_ATTRIBUTES (x, srcref);
12022
12023 for (i = 0; i < GET_RTX_LENGTH (code); i++, format_ptr++)
12024 {
12025 if (*format_ptr == 'e')
12026 ix86_set_move_mem_attrs_1 (XEXP (x, i), dstref, srcref,
12027 dstreg, srcreg);
12028 else if (*format_ptr == 'E')
12029 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
12030 ix86_set_move_mem_attrs_1 (XVECEXP (x, i, j), dstref, srcref,
12031 dstreg, srcreg);
12032 }
12033 }
12034
12035
12036
12037
12038
12039
12040
12041 int
12042 ix86_constant_alignment (exp, align)
12043 tree exp;
12044 int align;
12045 {
12046 if (TREE_CODE (exp) == REAL_CST)
12047 {
12048 if (TYPE_MODE (TREE_TYPE (exp)) == DFmode && align < 64)
12049 return 64;
12050 else if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (exp))) && align < 128)
12051 return 128;
12052 }
12053 else if (TREE_CODE (exp) == STRING_CST && TREE_STRING_LENGTH (exp) >= 31
12054 && align < 256)
12055 return 256;
12056
12057 return align;
12058 }
12059
12060
12061
12062
12063
12064
12065 int
12066 ix86_data_alignment (type, align)
12067 tree type;
12068 int align;
12069 {
12070 if (AGGREGATE_TYPE_P (type)
12071 && TYPE_SIZE (type)
12072 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
12073 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 256
12074 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 256)
12075 return 256;
12076
12077
12078
12079 if (TARGET_64BIT)
12080 {
12081 if (AGGREGATE_TYPE_P (type)
12082 && TYPE_SIZE (type)
12083 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
12084 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 128
12085 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
12086 return 128;
12087 }
12088
12089 if (TREE_CODE (type) == ARRAY_TYPE)
12090 {
12091 if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
12092 return 64;
12093 if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
12094 return 128;
12095 }
12096 else if (TREE_CODE (type) == COMPLEX_TYPE)
12097 {
12098
12099 if (TYPE_MODE (type) == DCmode && align < 64)
12100 return 64;
12101 if (TYPE_MODE (type) == XCmode && align < 128)
12102 return 128;
12103 }
12104 else if ((TREE_CODE (type) == RECORD_TYPE
12105 || TREE_CODE (type) == UNION_TYPE
12106 || TREE_CODE (type) == QUAL_UNION_TYPE)
12107 && TYPE_FIELDS (type))
12108 {
12109 if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
12110 return 64;
12111 if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
12112 return 128;
12113 }
12114 else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
12115 || TREE_CODE (type) == INTEGER_TYPE)
12116 {
12117 if (TYPE_MODE (type) == DFmode && align < 64)
12118 return 64;
12119 if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
12120 return 128;
12121 }
12122
12123 return align;
12124 }
12125
12126
12127
12128
12129
12130
12131 int
12132 ix86_local_alignment (type, align)
12133 tree type;
12134 int align;
12135 {
12136
12137
12138 if (TARGET_64BIT)
12139 {
12140 if (AGGREGATE_TYPE_P (type)
12141 && TYPE_SIZE (type)
12142 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
12143 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16
12144 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 128)
12145 return 128;
12146 }
12147 if (TREE_CODE (type) == ARRAY_TYPE)
12148 {
12149 if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
12150 return 64;
12151 if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
12152 return 128;
12153 }
12154 else if (TREE_CODE (type) == COMPLEX_TYPE)
12155 {
12156 if (TYPE_MODE (type) == DCmode && align < 64)
12157 return 64;
12158 if (TYPE_MODE (type) == XCmode && align < 128)
12159 return 128;
12160 }
12161 else if ((TREE_CODE (type) == RECORD_TYPE
12162 || TREE_CODE (type) == UNION_TYPE
12163 || TREE_CODE (type) == QUAL_UNION_TYPE)
12164 && TYPE_FIELDS (type))
12165 {
12166 if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
12167 return 64;
12168 if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
12169 return 128;
12170 }
12171 else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
12172 || TREE_CODE (type) == INTEGER_TYPE)
12173 {
12174
12175 if (TYPE_MODE (type) == DFmode && align < 64)
12176 return 64;
12177 if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
12178 return 128;
12179 }
12180 return align;
12181 }
12182
12183
12184
12185
12186 void
12187 x86_initialize_trampoline (tramp, fnaddr, cxt)
12188 rtx tramp, fnaddr, cxt;
12189 {
12190 if (!TARGET_64BIT)
12191 {
12192
12193 rtx disp = expand_binop (SImode, sub_optab, fnaddr,
12194 plus_constant (tramp, 10),
12195 NULL_RTX, 1, OPTAB_DIRECT);
12196 emit_move_insn (gen_rtx_MEM (QImode, tramp),
12197 gen_int_mode (0xb9, QImode));
12198 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 1)), cxt);
12199 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 5)),
12200 gen_int_mode (0xe9, QImode));
12201 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 6)), disp);
12202 }
12203 else
12204 {
12205 int offset = 0;
12206
12207
12208
12209 if (x86_64_zero_extended_value (fnaddr))
12210 {
12211 fnaddr = copy_to_mode_reg (DImode, fnaddr);
12212 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
12213 gen_int_mode (0xbb41, HImode));
12214 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, offset + 2)),
12215 gen_lowpart (SImode, fnaddr));
12216 offset += 6;
12217 }
12218 else
12219 {
12220 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
12221 gen_int_mode (0xbb49, HImode));
12222 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
12223 fnaddr);
12224 offset += 10;
12225 }
12226
12227 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
12228 gen_int_mode (0xba49, HImode));
12229 emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
12230 cxt);
12231 offset += 10;
12232
12233 emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
12234 gen_int_mode (0xff49, HImode));
12235 emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, offset+2)),
12236 gen_int_mode (0xe3, QImode));
12237 offset += 3;
12238 if (offset > TRAMPOLINE_SIZE)
12239 abort ();
12240 }
12241
12242 #ifdef TRANSFER_FROM_TRAMPOLINE
12243 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
12244 LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
12245 #endif
12246 }
12247
12248 #define def_builtin(MASK, NAME, TYPE, CODE) \
12249 do { \
12250 if ((MASK) & target_flags \
12251 && (!((MASK) & MASK_64BIT) || TARGET_64BIT)) \
12252 builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
12253 NULL, NULL_TREE); \
12254 } while (0)
12255
12256 struct builtin_description
12257 {
12258 const unsigned int mask;
12259 const enum insn_code icode;
12260 const char *const name;
12261 const enum ix86_builtins code;
12262 const enum rtx_code comparison;
12263 const unsigned int flag;
12264 };
12265
12266 static const struct builtin_description bdesc_comi[] =
12267 {
12268 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, UNEQ, 0 },
12269 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, UNLT, 0 },
12270 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, UNLE, 0 },
12271 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, GT, 0 },
12272 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, GE, 0 },
12273 { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, LTGT, 0 },
12274 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, UNEQ, 0 },
12275 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, UNLT, 0 },
12276 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, UNLE, 0 },
12277 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, GT, 0 },
12278 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, GE, 0 },
12279 { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, LTGT, 0 },
12280 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdeq", IX86_BUILTIN_COMIEQSD, UNEQ, 0 },
12281 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdlt", IX86_BUILTIN_COMILTSD, UNLT, 0 },
12282 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdle", IX86_BUILTIN_COMILESD, UNLE, 0 },
12283 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdgt", IX86_BUILTIN_COMIGTSD, GT, 0 },
12284 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdge", IX86_BUILTIN_COMIGESD, GE, 0 },
12285 { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdneq", IX86_BUILTIN_COMINEQSD, LTGT, 0 },
12286 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdeq", IX86_BUILTIN_UCOMIEQSD, UNEQ, 0 },
12287 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdlt", IX86_BUILTIN_UCOMILTSD, UNLT, 0 },
12288 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdle", IX86_BUILTIN_UCOMILESD, UNLE, 0 },
12289 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdgt", IX86_BUILTIN_UCOMIGTSD, GT, 0 },
12290 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdge", IX86_BUILTIN_UCOMIGESD, GE, 0 },
12291 { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, LTGT, 0 },
12292 };
12293
12294 static const struct builtin_description bdesc_2arg[] =
12295 {
12296
12297 { MASK_SSE, CODE_FOR_addv4sf3, "__builtin_ia32_addps", IX86_BUILTIN_ADDPS, 0, 0 },
12298 { MASK_SSE, CODE_FOR_subv4sf3, "__builtin_ia32_subps", IX86_BUILTIN_SUBPS, 0, 0 },
12299 { MASK_SSE, CODE_FOR_mulv4sf3, "__builtin_ia32_mulps", IX86_BUILTIN_MULPS, 0, 0 },
12300 { MASK_SSE, CODE_FOR_divv4sf3, "__builtin_ia32_divps", IX86_BUILTIN_DIVPS, 0, 0 },
12301 { MASK_SSE, CODE_FOR_vmaddv4sf3, "__builtin_ia32_addss", IX86_BUILTIN_ADDSS, 0, 0 },
12302 { MASK_SSE, CODE_FOR_vmsubv4sf3, "__builtin_ia32_subss", IX86_BUILTIN_SUBSS, 0, 0 },
12303 { MASK_SSE, CODE_FOR_vmmulv4sf3, "__builtin_ia32_mulss", IX86_BUILTIN_MULSS, 0, 0 },
12304 { MASK_SSE, CODE_FOR_vmdivv4sf3, "__builtin_ia32_divss", IX86_BUILTIN_DIVSS, 0, 0 },
12305
12306 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpeqps", IX86_BUILTIN_CMPEQPS, EQ, 0 },
12307 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpltps", IX86_BUILTIN_CMPLTPS, LT, 0 },
12308 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpleps", IX86_BUILTIN_CMPLEPS, LE, 0 },
12309 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgtps", IX86_BUILTIN_CMPGTPS, LT, 1 },
12310 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgeps", IX86_BUILTIN_CMPGEPS, LE, 1 },
12311 { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpunordps", IX86_BUILTIN_CMPUNORDPS, UNORDERED, 0 },
12312 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpneqps", IX86_BUILTIN_CMPNEQPS, EQ, 0 },
12313 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnltps", IX86_BUILTIN_CMPNLTPS, LT, 0 },
12314 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnleps", IX86_BUILTIN_CMPNLEPS, LE, 0 },
12315 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngtps", IX86_BUILTIN_CMPNGTPS, LT, 1 },
12316 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngeps", IX86_BUILTIN_CMPNGEPS, LE, 1 },
12317 { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpordps", IX86_BUILTIN_CMPORDPS, UNORDERED, 0 },
12318 { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpeqss", IX86_BUILTIN_CMPEQSS, EQ, 0 },
12319 { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpltss", IX86_BUILTIN_CMPLTSS, LT, 0 },
12320 { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpless", IX86_BUILTIN_CMPLESS, LE, 0 },
12321 { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpunordss", IX86_BUILTIN_CMPUNORDSS, UNORDERED, 0 },
12322 { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpneqss", IX86_BUILTIN_CMPNEQSS, EQ, 0 },
12323 { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnltss", IX86_BUILTIN_CMPNLTSS, LT, 0 },
12324 { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnless", IX86_BUILTIN_CMPNLESS, LE, 0 },
12325 { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpordss", IX86_BUILTIN_CMPORDSS, UNORDERED, 0 },
12326
12327 { MASK_SSE, CODE_FOR_sminv4sf3, "__builtin_ia32_minps", IX86_BUILTIN_MINPS, 0, 0 },
12328 { MASK_SSE, CODE_FOR_smaxv4sf3, "__builtin_ia32_maxps", IX86_BUILTIN_MAXPS, 0, 0 },
12329 { MASK_SSE, CODE_FOR_vmsminv4sf3, "__builtin_ia32_minss", IX86_BUILTIN_MINSS, 0, 0 },
12330 { MASK_SSE, CODE_FOR_vmsmaxv4sf3, "__builtin_ia32_maxss", IX86_BUILTIN_MAXSS, 0, 0 },
12331
12332 { MASK_SSE, CODE_FOR_sse_andv4sf3, "__builtin_ia32_andps", IX86_BUILTIN_ANDPS, 0, 0 },
12333 { MASK_SSE, CODE_FOR_sse_nandv4sf3, "__builtin_ia32_andnps", IX86_BUILTIN_ANDNPS, 0, 0 },
12334 { MASK_SSE, CODE_FOR_sse_iorv4sf3, "__builtin_ia32_orps", IX86_BUILTIN_ORPS, 0, 0 },
12335 { MASK_SSE, CODE_FOR_sse_xorv4sf3, "__builtin_ia32_xorps", IX86_BUILTIN_XORPS, 0, 0 },
12336
12337 { MASK_SSE, CODE_FOR_sse_movss, "__builtin_ia32_movss", IX86_BUILTIN_MOVSS, 0, 0 },
12338 { MASK_SSE, CODE_FOR_sse_movhlps, "__builtin_ia32_movhlps", IX86_BUILTIN_MOVHLPS, 0, 0 },
12339 { MASK_SSE, CODE_FOR_sse_movlhps, "__builtin_ia32_movlhps", IX86_BUILTIN_MOVLHPS, 0, 0 },
12340 { MASK_SSE, CODE_FOR_sse_unpckhps, "__builtin_ia32_unpckhps", IX86_BUILTIN_UNPCKHPS, 0, 0 },
12341 { MASK_SSE, CODE_FOR_sse_unpcklps, "__builtin_ia32_unpcklps", IX86_BUILTIN_UNPCKLPS, 0, 0 },
12342
12343
12344 { MASK_MMX, CODE_FOR_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, 0, 0 },
12345 { MASK_MMX, CODE_FOR_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, 0, 0 },
12346 { MASK_MMX, CODE_FOR_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, 0, 0 },
12347 { MASK_MMX, CODE_FOR_mmx_adddi3, "__builtin_ia32_paddq", IX86_BUILTIN_PADDQ, 0, 0 },
12348 { MASK_MMX, CODE_FOR_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, 0, 0 },
12349 { MASK_MMX, CODE_FOR_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, 0, 0 },
12350 { MASK_MMX, CODE_FOR_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, 0, 0 },
12351 { MASK_MMX, CODE_FOR_mmx_subdi3, "__builtin_ia32_psubq", IX86_BUILTIN_PSUBQ, 0, 0 },
12352
12353 { MASK_MMX, CODE_FOR_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, 0, 0 },
12354 { MASK_MMX, CODE_FOR_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, 0, 0 },
12355 { MASK_MMX, CODE_FOR_sssubv8qi3, "__builtin_ia32_psubsb", IX86_BUILTIN_PSUBSB, 0, 0 },
12356 { MASK_MMX, CODE_FOR_sssubv4hi3, "__builtin_ia32_psubsw", IX86_BUILTIN_PSUBSW, 0, 0 },
12357 { MASK_MMX, CODE_FOR_usaddv8qi3, "__builtin_ia32_paddusb", IX86_BUILTIN_PADDUSB, 0, 0 },
12358 { MASK_MMX, CODE_FOR_usaddv4hi3, "__builtin_ia32_paddusw", IX86_BUILTIN_PADDUSW, 0, 0 },
12359 { MASK_MMX, CODE_FOR_ussubv8qi3, "__builtin_ia32_psubusb", IX86_BUILTIN_PSUBUSB, 0, 0 },
12360 { MASK_MMX, CODE_FOR_ussubv4hi3, "__builtin_ia32_psubusw", IX86_BUILTIN_PSUBUSW, 0, 0 },
12361
12362 { MASK_MMX, CODE_FOR_mulv4hi3, "__builtin_ia32_pmullw", IX86_BUILTIN_PMULLW, 0, 0 },
12363 { MASK_MMX, CODE_FOR_smulv4hi3_highpart, "__builtin_ia32_pmulhw", IX86_BUILTIN_PMULHW, 0, 0 },
12364 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_umulv4hi3_highpart, "__builtin_ia32_pmulhuw", IX86_BUILTIN_PMULHUW, 0, 0 },
12365
12366 { MASK_MMX, CODE_FOR_mmx_anddi3, "__builtin_ia32_pand", IX86_BUILTIN_PAND, 0, 0 },
12367 { MASK_MMX, CODE_FOR_mmx_nanddi3, "__builtin_ia32_pandn", IX86_BUILTIN_PANDN, 0, 0 },
12368 { MASK_MMX, CODE_FOR_mmx_iordi3, "__builtin_ia32_por", IX86_BUILTIN_POR, 0, 0 },
12369 { MASK_MMX, CODE_FOR_mmx_xordi3, "__builtin_ia32_pxor", IX86_BUILTIN_PXOR, 0, 0 },
12370
12371 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv8qi3, "__builtin_ia32_pavgb", IX86_BUILTIN_PAVGB, 0, 0 },
12372 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv4hi3, "__builtin_ia32_pavgw", IX86_BUILTIN_PAVGW, 0, 0 },
12373
12374 { MASK_MMX, CODE_FOR_eqv8qi3, "__builtin_ia32_pcmpeqb", IX86_BUILTIN_PCMPEQB, 0, 0 },
12375 { MASK_MMX, CODE_FOR_eqv4hi3, "__builtin_ia32_pcmpeqw", IX86_BUILTIN_PCMPEQW, 0, 0 },
12376 { MASK_MMX, CODE_FOR_eqv2si3, "__builtin_ia32_pcmpeqd", IX86_BUILTIN_PCMPEQD, 0, 0 },
12377 { MASK_MMX, CODE_FOR_gtv8qi3, "__builtin_ia32_pcmpgtb", IX86_BUILTIN_PCMPGTB, 0, 0 },
12378 { MASK_MMX, CODE_FOR_gtv4hi3, "__builtin_ia32_pcmpgtw", IX86_BUILTIN_PCMPGTW, 0, 0 },
12379 { MASK_MMX, CODE_FOR_gtv2si3, "__builtin_ia32_pcmpgtd", IX86_BUILTIN_PCMPGTD, 0, 0 },
12380
12381 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_umaxv8qi3, "__builtin_ia32_pmaxub", IX86_BUILTIN_PMAXUB, 0, 0 },
12382 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_smaxv4hi3, "__builtin_ia32_pmaxsw", IX86_BUILTIN_PMAXSW, 0, 0 },
12383 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_uminv8qi3, "__builtin_ia32_pminub", IX86_BUILTIN_PMINUB, 0, 0 },
12384 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_sminv4hi3, "__builtin_ia32_pminsw", IX86_BUILTIN_PMINSW, 0, 0 },
12385
12386 { MASK_MMX, CODE_FOR_mmx_punpckhbw, "__builtin_ia32_punpckhbw", IX86_BUILTIN_PUNPCKHBW, 0, 0 },
12387 { MASK_MMX, CODE_FOR_mmx_punpckhwd, "__builtin_ia32_punpckhwd", IX86_BUILTIN_PUNPCKHWD, 0, 0 },
12388 { MASK_MMX, CODE_FOR_mmx_punpckhdq, "__builtin_ia32_punpckhdq", IX86_BUILTIN_PUNPCKHDQ, 0, 0 },
12389 { MASK_MMX, CODE_FOR_mmx_punpcklbw, "__builtin_ia32_punpcklbw", IX86_BUILTIN_PUNPCKLBW, 0, 0 },
12390 { MASK_MMX, CODE_FOR_mmx_punpcklwd, "__builtin_ia32_punpcklwd", IX86_BUILTIN_PUNPCKLWD, 0, 0 },
12391 { MASK_MMX, CODE_FOR_mmx_punpckldq, "__builtin_ia32_punpckldq", IX86_BUILTIN_PUNPCKLDQ, 0, 0 },
12392
12393
12394 { MASK_MMX, CODE_FOR_mmx_packsswb, 0, IX86_BUILTIN_PACKSSWB, 0, 0 },
12395 { MASK_MMX, CODE_FOR_mmx_packssdw, 0, IX86_BUILTIN_PACKSSDW, 0, 0 },
12396 { MASK_MMX, CODE_FOR_mmx_packuswb, 0, IX86_BUILTIN_PACKUSWB, 0, 0 },
12397
12398 { MASK_SSE, CODE_FOR_cvtpi2ps, 0, IX86_BUILTIN_CVTPI2PS, 0, 0 },
12399 { MASK_SSE, CODE_FOR_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 },
12400 { MASK_SSE | MASK_64BIT, CODE_FOR_cvtsi2ssq, 0, IX86_BUILTIN_CVTSI642SS, 0, 0 },
12401
12402 { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 },
12403 { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 },
12404 { MASK_MMX, CODE_FOR_ashlv2si3, 0, IX86_BUILTIN_PSLLD, 0, 0 },
12405 { MASK_MMX, CODE_FOR_ashlv2si3, 0, IX86_BUILTIN_PSLLDI, 0, 0 },
12406 { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQ, 0, 0 },
12407 { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQI, 0, 0 },
12408
12409 { MASK_MMX, CODE_FOR_lshrv4hi3, 0, IX86_BUILTIN_PSRLW, 0, 0 },
12410 { MASK_MMX, CODE_FOR_lshrv4hi3, 0, IX86_BUILTIN_PSRLWI, 0, 0 },
12411 { MASK_MMX, CODE_FOR_lshrv2si3, 0, IX86_BUILTIN_PSRLD, 0, 0 },
12412 { MASK_MMX, CODE_FOR_lshrv2si3, 0, IX86_BUILTIN_PSRLDI, 0, 0 },
12413 { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQ, 0, 0 },
12414 { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQI, 0, 0 },
12415
12416 { MASK_MMX, CODE_FOR_ashrv4hi3, 0, IX86_BUILTIN_PSRAW, 0, 0 },
12417 { MASK_MMX, CODE_FOR_ashrv4hi3, 0, IX86_BUILTIN_PSRAWI, 0, 0 },
12418 { MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRAD, 0, 0 },
12419 { MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRADI, 0, 0 },
12420
12421 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_psadbw, 0, IX86_BUILTIN_PSADBW, 0, 0 },
12422 { MASK_MMX, CODE_FOR_mmx_pmaddwd, 0, IX86_BUILTIN_PMADDWD, 0, 0 },
12423
12424
12425 { MASK_SSE2, CODE_FOR_addv2df3, "__builtin_ia32_addpd", IX86_BUILTIN_ADDPD, 0, 0 },
12426 { MASK_SSE2, CODE_FOR_subv2df3, "__builtin_ia32_subpd", IX86_BUILTIN_SUBPD, 0, 0 },
12427 { MASK_SSE2, CODE_FOR_mulv2df3, "__builtin_ia32_mulpd", IX86_BUILTIN_MULPD, 0, 0 },
12428 { MASK_SSE2, CODE_FOR_divv2df3, "__builtin_ia32_divpd", IX86_BUILTIN_DIVPD, 0, 0 },
12429 { MASK_SSE2, CODE_FOR_vmaddv2df3, "__builtin_ia32_addsd", IX86_BUILTIN_ADDSD, 0, 0 },
12430 { MASK_SSE2, CODE_FOR_vmsubv2df3, "__builtin_ia32_subsd", IX86_BUILTIN_SUBSD, 0, 0 },
12431 { MASK_SSE2, CODE_FOR_vmmulv2df3, "__builtin_ia32_mulsd", IX86_BUILTIN_MULSD, 0, 0 },
12432 { MASK_SSE2, CODE_FOR_vmdivv2df3, "__builtin_ia32_divsd", IX86_BUILTIN_DIVSD, 0, 0 },
12433
12434 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpeqpd", IX86_BUILTIN_CMPEQPD, EQ, 0 },
12435 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpltpd", IX86_BUILTIN_CMPLTPD, LT, 0 },
12436 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmplepd", IX86_BUILTIN_CMPLEPD, LE, 0 },
12437 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpgtpd", IX86_BUILTIN_CMPGTPD, LT, 1 },
12438 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpgepd", IX86_BUILTIN_CMPGEPD, LE, 1 },
12439 { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpunordpd", IX86_BUILTIN_CMPUNORDPD, UNORDERED, 0 },
12440 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpneqpd", IX86_BUILTIN_CMPNEQPD, EQ, 0 },
12441 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpnltpd", IX86_BUILTIN_CMPNLTPD, LT, 0 },
12442 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpnlepd", IX86_BUILTIN_CMPNLEPD, LE, 0 },
12443 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpngtpd", IX86_BUILTIN_CMPNGTPD, LT, 1 },
12444 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpngepd", IX86_BUILTIN_CMPNGEPD, LE, 1 },
12445 { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpordpd", IX86_BUILTIN_CMPORDPD, UNORDERED, 0 },
12446 { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpeqsd", IX86_BUILTIN_CMPEQSD, EQ, 0 },
12447 { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpltsd", IX86_BUILTIN_CMPLTSD, LT, 0 },
12448 { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmplesd", IX86_BUILTIN_CMPLESD, LE, 0 },
12449 { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpunordsd", IX86_BUILTIN_CMPUNORDSD, UNORDERED, 0 },
12450 { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpneqsd", IX86_BUILTIN_CMPNEQSD, EQ, 0 },
12451 { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnltsd", IX86_BUILTIN_CMPNLTSD, LT, 0 },
12452 { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnlesd", IX86_BUILTIN_CMPNLESD, LE, 0 },
12453 { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpordsd", IX86_BUILTIN_CMPORDSD, UNORDERED, 0 },
12454
12455 { MASK_SSE2, CODE_FOR_sminv2df3, "__builtin_ia32_minpd", IX86_BUILTIN_MINPD, 0, 0 },
12456 { MASK_SSE2, CODE_FOR_smaxv2df3, "__builtin_ia32_maxpd", IX86_BUILTIN_MAXPD, 0, 0 },
12457 { MASK_SSE2, CODE_FOR_vmsminv2df3, "__builtin_ia32_minsd", IX86_BUILTIN_MINSD, 0, 0 },
12458 { MASK_SSE2, CODE_FOR_vmsmaxv2df3, "__builtin_ia32_maxsd", IX86_BUILTIN_MAXSD, 0, 0 },
12459
12460 { MASK_SSE2, CODE_FOR_sse2_andv2df3, "__builtin_ia32_andpd", IX86_BUILTIN_ANDPD, 0, 0 },
12461 { MASK_SSE2, CODE_FOR_sse2_nandv2df3, "__builtin_ia32_andnpd", IX86_BUILTIN_ANDNPD, 0, 0 },
12462 { MASK_SSE2, CODE_FOR_sse2_iorv2df3, "__builtin_ia32_orpd", IX86_BUILTIN_ORPD, 0, 0 },
12463 { MASK_SSE2, CODE_FOR_sse2_xorv2df3, "__builtin_ia32_xorpd", IX86_BUILTIN_XORPD, 0, 0 },
12464
12465 { MASK_SSE2, CODE_FOR_sse2_movsd, "__builtin_ia32_movsd", IX86_BUILTIN_MOVSD, 0, 0 },
12466 { MASK_SSE2, CODE_FOR_sse2_unpckhpd, "__builtin_ia32_unpckhpd", IX86_BUILTIN_UNPCKHPD, 0, 0 },
12467 { MASK_SSE2, CODE_FOR_sse2_unpcklpd, "__builtin_ia32_unpcklpd", IX86_BUILTIN_UNPCKLPD, 0, 0 },
12468
12469
12470 { MASK_SSE2, CODE_FOR_addv16qi3, "__builtin_ia32_paddb128", IX86_BUILTIN_PADDB128, 0, 0 },
12471 { MASK_SSE2, CODE_FOR_addv8hi3, "__builtin_ia32_paddw128", IX86_BUILTIN_PADDW128, 0, 0 },
12472 { MASK_SSE2, CODE_FOR_addv4si3, "__builtin_ia32_paddd128", IX86_BUILTIN_PADDD128, 0, 0 },
12473 { MASK_SSE2, CODE_FOR_addv2di3, "__builtin_ia32_paddq128", IX86_BUILTIN_PADDQ128, 0, 0 },
12474 { MASK_SSE2, CODE_FOR_subv16qi3, "__builtin_ia32_psubb128", IX86_BUILTIN_PSUBB128, 0, 0 },
12475 { MASK_SSE2, CODE_FOR_subv8hi3, "__builtin_ia32_psubw128", IX86_BUILTIN_PSUBW128, 0, 0 },
12476 { MASK_SSE2, CODE_FOR_subv4si3, "__builtin_ia32_psubd128", IX86_BUILTIN_PSUBD128, 0, 0 },
12477 { MASK_SSE2, CODE_FOR_subv2di3, "__builtin_ia32_psubq128", IX86_BUILTIN_PSUBQ128, 0, 0 },
12478
12479 { MASK_MMX, CODE_FOR_ssaddv16qi3, "__builtin_ia32_paddsb128", IX86_BUILTIN_PADDSB128, 0, 0 },
12480 { MASK_MMX, CODE_FOR_ssaddv8hi3, "__builtin_ia32_paddsw128", IX86_BUILTIN_PADDSW128, 0, 0 },
12481 { MASK_MMX, CODE_FOR_sssubv16qi3, "__builtin_ia32_psubsb128", IX86_BUILTIN_PSUBSB128, 0, 0 },
12482 { MASK_MMX, CODE_FOR_sssubv8hi3, "__builtin_ia32_psubsw128", IX86_BUILTIN_PSUBSW128, 0, 0 },
12483 { MASK_MMX, CODE_FOR_usaddv16qi3, "__builtin_ia32_paddusb128", IX86_BUILTIN_PADDUSB128, 0, 0 },
12484 { MASK_MMX, CODE_FOR_usaddv8hi3, "__builtin_ia32_paddusw128", IX86_BUILTIN_PADDUSW128, 0, 0 },
12485 { MASK_MMX, CODE_FOR_ussubv16qi3, "__builtin_ia32_psubusb128", IX86_BUILTIN_PSUBUSB128, 0, 0 },
12486 { MASK_MMX, CODE_FOR_ussubv8hi3, "__builtin_ia32_psubusw128", IX86_BUILTIN_PSUBUSW128, 0, 0 },
12487
12488 { MASK_SSE2, CODE_FOR_mulv8hi3, "__builtin_ia32_pmullw128", IX86_BUILTIN_PMULLW128, 0, 0 },
12489 { MASK_SSE2, CODE_FOR_smulv8hi3_highpart, "__builtin_ia32_pmulhw128", IX86_BUILTIN_PMULHW128, 0, 0 },
12490 { MASK_SSE2, CODE_FOR_sse2_umulsidi3, "__builtin_ia32_pmuludq", IX86_BUILTIN_PMULUDQ, 0, 0 },
12491 { MASK_SSE2, CODE_FOR_sse2_umulv2siv2di3, "__builtin_ia32_pmuludq128", IX86_BUILTIN_PMULUDQ128, 0, 0 },
12492
12493 { MASK_SSE2, CODE_FOR_sse2_andv2di3, "__builtin_ia32_pand128", IX86_BUILTIN_PAND128, 0, 0 },
12494 { MASK_SSE2, CODE_FOR_sse2_nandv2di3, "__builtin_ia32_pandn128", IX86_BUILTIN_PANDN128, 0, 0 },
12495 { MASK_SSE2, CODE_FOR_sse2_iorv2di3, "__builtin_ia32_por128", IX86_BUILTIN_POR128, 0, 0 },
12496 { MASK_SSE2, CODE_FOR_sse2_xorv2di3, "__builtin_ia32_pxor128", IX86_BUILTIN_PXOR128, 0, 0 },
12497
12498 { MASK_SSE2, CODE_FOR_sse2_uavgv16qi3, "__builtin_ia32_pavgb128", IX86_BUILTIN_PAVGB128, 0, 0 },
12499 { MASK_SSE2, CODE_FOR_sse2_uavgv8hi3, "__builtin_ia32_pavgw128", IX86_BUILTIN_PAVGW128, 0, 0 },
12500
12501 { MASK_SSE2, CODE_FOR_eqv16qi3, "__builtin_ia32_pcmpeqb128", IX86_BUILTIN_PCMPEQB128, 0, 0 },
12502 { MASK_SSE2, CODE_FOR_eqv8hi3, "__builtin_ia32_pcmpeqw128", IX86_BUILTIN_PCMPEQW128, 0, 0 },
12503 { MASK_SSE2, CODE_FOR_eqv4si3, "__builtin_ia32_pcmpeqd128", IX86_BUILTIN_PCMPEQD128, 0, 0 },
12504 { MASK_SSE2, CODE_FOR_gtv16qi3, "__builtin_ia32_pcmpgtb128", IX86_BUILTIN_PCMPGTB128, 0, 0 },
12505 { MASK_SSE2, CODE_FOR_gtv8hi3, "__builtin_ia32_pcmpgtw128", IX86_BUILTIN_PCMPGTW128, 0, 0 },
12506 { MASK_SSE2, CODE_FOR_gtv4si3, "__builtin_ia32_pcmpgtd128", IX86_BUILTIN_PCMPGTD128, 0, 0 },
12507
12508 { MASK_SSE2, CODE_FOR_umaxv16qi3, "__builtin_ia32_pmaxub128", IX86_BUILTIN_PMAXUB128, 0, 0 },
12509 { MASK_SSE2, CODE_FOR_smaxv8hi3, "__builtin_ia32_pmaxsw128", IX86_BUILTIN_PMAXSW128, 0, 0 },
12510 { MASK_SSE2, CODE_FOR_uminv16qi3, "__builtin_ia32_pminub128", IX86_BUILTIN_PMINUB128, 0, 0 },
12511 { MASK_SSE2, CODE_FOR_sminv8hi3, "__builtin_ia32_pminsw128", IX86_BUILTIN_PMINSW128, 0, 0 },
12512
12513 { MASK_SSE2, CODE_FOR_sse2_punpckhbw, "__builtin_ia32_punpckhbw128", IX86_BUILTIN_PUNPCKHBW128, 0, 0 },
12514 { MASK_SSE2, CODE_FOR_sse2_punpckhwd, "__builtin_ia32_punpckhwd128", IX86_BUILTIN_PUNPCKHWD128, 0, 0 },
12515 { MASK_SSE2, CODE_FOR_sse2_punpckhdq, "__builtin_ia32_punpckhdq128", IX86_BUILTIN_PUNPCKHDQ128, 0, 0 },
12516 { MASK_SSE2, CODE_FOR_sse2_punpckhqdq, "__builtin_ia32_punpckhqdq128", IX86_BUILTIN_PUNPCKHQDQ128, 0, 0 },
12517 { MASK_SSE2, CODE_FOR_sse2_punpcklbw, "__builtin_ia32_punpcklbw128", IX86_BUILTIN_PUNPCKLBW128, 0, 0 },
12518 { MASK_SSE2, CODE_FOR_sse2_punpcklwd, "__builtin_ia32_punpcklwd128", IX86_BUILTIN_PUNPCKLWD128, 0, 0 },
12519 { MASK_SSE2, CODE_FOR_sse2_punpckldq, "__builtin_ia32_punpckldq128", IX86_BUILTIN_PUNPCKLDQ128, 0, 0 },
12520 { MASK_SSE2, CODE_FOR_sse2_punpcklqdq, "__builtin_ia32_punpcklqdq128", IX86_BUILTIN_PUNPCKLQDQ128, 0, 0 },
12521
12522 { MASK_SSE2, CODE_FOR_sse2_packsswb, "__builtin_ia32_packsswb128", IX86_BUILTIN_PACKSSWB128, 0, 0 },
12523 { MASK_SSE2, CODE_FOR_sse2_packssdw, "__builtin_ia32_packssdw128", IX86_BUILTIN_PACKSSDW128, 0, 0 },
12524 { MASK_SSE2, CODE_FOR_sse2_packuswb, "__builtin_ia32_packuswb128", IX86_BUILTIN_PACKUSWB128, 0, 0 },
12525
12526 { MASK_SSE2, CODE_FOR_umulv8hi3_highpart, "__builtin_ia32_pmulhuw128", IX86_BUILTIN_PMULHUW128, 0, 0 },
12527 { MASK_SSE2, CODE_FOR_sse2_psadbw, 0, IX86_BUILTIN_PSADBW128, 0, 0 },
12528
12529 { MASK_SSE2, CODE_FOR_ashlv8hi3_ti, 0, IX86_BUILTIN_PSLLW128, 0, 0 },
12530 { MASK_SSE2, CODE_FOR_ashlv8hi3, 0, IX86_BUILTIN_PSLLWI128, 0, 0 },
12531 { MASK_SSE2, CODE_FOR_ashlv4si3_ti, 0, IX86_BUILTIN_PSLLD128, 0, 0 },
12532 { MASK_SSE2, CODE_FOR_ashlv4si3, 0, IX86_BUILTIN_PSLLDI128, 0, 0 },
12533 { MASK_SSE2, CODE_FOR_ashlv2di3_ti, 0, IX86_BUILTIN_PSLLQ128, 0, 0 },
12534 { MASK_SSE2, CODE_FOR_ashlv2di3, 0, IX86_BUILTIN_PSLLQI128, 0, 0 },
12535
12536 { MASK_SSE2, CODE_FOR_lshrv8hi3_ti, 0, IX86_BUILTIN_PSRLW128, 0, 0 },
12537 { MASK_SSE2, CODE_FOR_lshrv8hi3, 0, IX86_BUILTIN_PSRLWI128, 0, 0 },
12538 { MASK_SSE2, CODE_FOR_lshrv4si3_ti, 0, IX86_BUILTIN_PSRLD128, 0, 0 },
12539 { MASK_SSE2, CODE_FOR_lshrv4si3, 0, IX86_BUILTIN_PSRLDI128, 0, 0 },
12540 { MASK_SSE2, CODE_FOR_lshrv2di3_ti, 0, IX86_BUILTIN_PSRLQ128, 0, 0 },
12541 { MASK_SSE2, CODE_FOR_lshrv2di3, 0, IX86_BUILTIN_PSRLQI128, 0, 0 },
12542
12543 { MASK_SSE2, CODE_FOR_ashrv8hi3_ti, 0, IX86_BUILTIN_PSRAW128, 0, 0 },
12544 { MASK_SSE2, CODE_FOR_ashrv8hi3, 0, IX86_BUILTIN_PSRAWI128, 0, 0 },
12545 { MASK_SSE2, CODE_FOR_ashrv4si3_ti, 0, IX86_BUILTIN_PSRAD128, 0, 0 },
12546 { MASK_SSE2, CODE_FOR_ashrv4si3, 0, IX86_BUILTIN_PSRADI128, 0, 0 },
12547
12548 { MASK_SSE2, CODE_FOR_sse2_pmaddwd, 0, IX86_BUILTIN_PMADDWD128, 0, 0 },
12549
12550 { MASK_SSE2, CODE_FOR_cvtsi2sd, 0, IX86_BUILTIN_CVTSI2SD, 0, 0 },
12551 { MASK_SSE2 | MASK_64BIT, CODE_FOR_cvtsi2sdq, 0, IX86_BUILTIN_CVTSI642SD, 0, 0 },
12552 { MASK_SSE2, CODE_FOR_cvtsd2ss, 0, IX86_BUILTIN_CVTSD2SS, 0, 0 },
12553 { MASK_SSE2, CODE_FOR_cvtss2sd, 0, IX86_BUILTIN_CVTSS2SD, 0, 0 },
12554
12555
12556 { MASK_PNI, CODE_FOR_addsubv4sf3, "__builtin_ia32_addsubps", IX86_BUILTIN_ADDSUBPS, 0, 0 },
12557 { MASK_PNI, CODE_FOR_addsubv2df3, "__builtin_ia32_addsubpd", IX86_BUILTIN_ADDSUBPD, 0, 0 },
12558 { MASK_PNI, CODE_FOR_haddv4sf3, "__builtin_ia32_haddps", IX86_BUILTIN_HADDPS, 0, 0 },
12559 { MASK_PNI, CODE_FOR_haddv2df3, "__builtin_ia32_haddpd", IX86_BUILTIN_HADDPD, 0, 0 },
12560 { MASK_PNI, CODE_FOR_hsubv4sf3, "__builtin_ia32_hsubps", IX86_BUILTIN_HSUBPS, 0, 0 },
12561 { MASK_PNI, CODE_FOR_hsubv2df3, "__builtin_ia32_hsubpd", IX86_BUILTIN_HSUBPD, 0, 0 }
12562 };
12563
12564 static const struct builtin_description bdesc_1arg[] =
12565 {
12566 { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB, 0, 0 },
12567 { MASK_SSE, CODE_FOR_sse_movmskps, 0, IX86_BUILTIN_MOVMSKPS, 0, 0 },
12568
12569 { MASK_SSE, CODE_FOR_sqrtv4sf2, 0, IX86_BUILTIN_SQRTPS, 0, 0 },
12570 { MASK_SSE, CODE_FOR_rsqrtv4sf2, 0, IX86_BUILTIN_RSQRTPS, 0, 0 },
12571 { MASK_SSE, CODE_FOR_rcpv4sf2, 0, IX86_BUILTIN_RCPPS, 0, 0 },
12572
12573 { MASK_SSE, CODE_FOR_cvtps2pi, 0, IX86_BUILTIN_CVTPS2PI, 0, 0 },
12574 { MASK_SSE, CODE_FOR_cvtss2si, 0, IX86_BUILTIN_CVTSS2SI, 0, 0 },
12575 { MASK_SSE | MASK_64BIT, CODE_FOR_cvtss2siq, 0, IX86_BUILTIN_CVTSS2SI64, 0, 0 },
12576 { MASK_SSE, CODE_FOR_cvttps2pi, 0, IX86_BUILTIN_CVTTPS2PI, 0, 0 },
12577 { MASK_SSE, CODE_FOR_cvttss2si, 0, IX86_BUILTIN_CVTTSS2SI, 0, 0 },
12578 { MASK_SSE | MASK_64BIT, CODE_FOR_cvttss2siq, 0, IX86_BUILTIN_CVTTSS2SI64, 0, 0 },
12579
12580 { MASK_SSE2, CODE_FOR_sse2_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB128, 0, 0 },
12581 { MASK_SSE2, CODE_FOR_sse2_movmskpd, 0, IX86_BUILTIN_MOVMSKPD, 0, 0 },
12582 { MASK_SSE2, CODE_FOR_sse2_movq2dq, 0, IX86_BUILTIN_MOVQ2DQ, 0, 0 },
12583 { MASK_SSE2, CODE_FOR_sse2_movdq2q, 0, IX86_BUILTIN_MOVDQ2Q, 0, 0 },
12584
12585 { MASK_SSE2, CODE_FOR_sqrtv2df2, 0, IX86_BUILTIN_SQRTPD, 0, 0 },
12586
12587 { MASK_SSE2, CODE_FOR_cvtdq2pd, 0, IX86_BUILTIN_CVTDQ2PD, 0, 0 },
12588 { MASK_SSE2, CODE_FOR_cvtdq2ps, 0, IX86_BUILTIN_CVTDQ2PS, 0, 0 },
12589
12590 { MASK_SSE2, CODE_FOR_cvtpd2dq, 0, IX86_BUILTIN_CVTPD2DQ, 0, 0 },
12591 { MASK_SSE2, CODE_FOR_cvtpd2pi, 0, IX86_BUILTIN_CVTPD2PI, 0, 0 },
12592 { MASK_SSE2, CODE_FOR_cvtpd2ps, 0, IX86_BUILTIN_CVTPD2PS, 0, 0 },
12593 { MASK_SSE2, CODE_FOR_cvttpd2dq, 0, IX86_BUILTIN_CVTTPD2DQ, 0, 0 },
12594 { MASK_SSE2, CODE_FOR_cvttpd2pi, 0, IX86_BUILTIN_CVTTPD2PI, 0, 0 },
12595
12596 { MASK_SSE2, CODE_FOR_cvtpi2pd, 0, IX86_BUILTIN_CVTPI2PD, 0, 0 },
12597
12598 { MASK_SSE2, CODE_FOR_cvtsd2si, 0, IX86_BUILTIN_CVTSD2SI, 0, 0 },
12599 { MASK_SSE2, CODE_FOR_cvttsd2si, 0, IX86_BUILTIN_CVTTSD2SI, 0, 0 },
12600 { MASK_SSE2 | MASK_64BIT, CODE_FOR_cvtsd2siq, 0, IX86_BUILTIN_CVTSD2SI64, 0, 0 },
12601 { MASK_SSE2 | MASK_64BIT, CODE_FOR_cvttsd2siq, 0, IX86_BUILTIN_CVTTSD2SI64, 0, 0 },
12602
12603 { MASK_SSE2, CODE_FOR_cvtps2dq, 0, IX86_BUILTIN_CVTPS2DQ, 0, 0 },
12604 { MASK_SSE2, CODE_FOR_cvtps2pd, 0, IX86_BUILTIN_CVTPS2PD, 0, 0 },
12605 { MASK_SSE2, CODE_FOR_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 },
12606
12607 { MASK_SSE2, CODE_FOR_sse2_movq, 0, IX86_BUILTIN_MOVQ, 0, 0 },
12608
12609
12610 { MASK_PNI, CODE_FOR_movshdup, 0, IX86_BUILTIN_MOVSHDUP, 0, 0 },
12611 { MASK_PNI, CODE_FOR_movsldup, 0, IX86_BUILTIN_MOVSLDUP, 0, 0 },
12612 { MASK_PNI, CODE_FOR_movddup, 0, IX86_BUILTIN_MOVDDUP, 0, 0 }
12613 };
12614
12615 void
12616 ix86_init_builtins ()
12617 {
12618 if (TARGET_MMX)
12619 ix86_init_mmx_sse_builtins ();
12620 }
12621
12622
12623
12624
12625 static void
12626 ix86_init_mmx_sse_builtins ()
12627 {
12628 const struct builtin_description * d;
12629 size_t i;
12630
12631 tree pchar_type_node = build_pointer_type (char_type_node);
12632 tree pcchar_type_node = build_pointer_type (
12633 build_type_variant (char_type_node, 1, 0));
12634 tree pfloat_type_node = build_pointer_type (float_type_node);
12635 tree pcfloat_type_node = build_pointer_type (
12636 build_type_variant (float_type_node, 1, 0));
12637 tree pv2si_type_node = build_pointer_type (V2SI_type_node);
12638 tree pv2di_type_node = build_pointer_type (V2DI_type_node);
12639 tree pdi_type_node = build_pointer_type (long_long_unsigned_type_node);
12640
12641
12642 tree int_ftype_v4sf_v4sf
12643 = build_function_type_list (integer_type_node,
12644 V4SF_type_node, V4SF_type_node, NULL_TREE);
12645 tree v4si_ftype_v4sf_v4sf
12646 = build_function_type_list (V4SI_type_node,
12647 V4SF_type_node, V4SF_type_node, NULL_TREE);
12648
12649 tree int_ftype_v4sf
12650 = build_function_type_list (integer_type_node,
12651 V4SF_type_node, NULL_TREE);
12652 tree int64_ftype_v4sf
12653 = build_function_type_list (long_long_integer_type_node,
12654 V4SF_type_node, NULL_TREE);
12655 tree int_ftype_v8qi
12656 = build_function_type_list (integer_type_node, V8QI_type_node, NULL_TREE);
12657 tree v4sf_ftype_v4sf_int
12658 = build_function_type_list (V4SF_type_node,
12659 V4SF_type_node, integer_type_node, NULL_TREE);
12660 tree v4sf_ftype_v4sf_int64
12661 = build_function_type_list (V4SF_type_node,
12662 V4SF_type_node, long_long_integer_type_node,
12663 NULL_TREE);
12664 tree v4sf_ftype_v4sf_v2si
12665 = build_function_type_list (V4SF_type_node,
12666 V4SF_type_node, V2SI_type_node, NULL_TREE);
12667 tree int_ftype_v4hi_int
12668 = build_function_type_list (integer_type_node,
12669 V4HI_type_node, integer_type_node, NULL_TREE);
12670 tree v4hi_ftype_v4hi_int_int
12671 = build_function_type_list (V4HI_type_node, V4HI_type_node,
12672 integer_type_node, integer_type_node,
12673 NULL_TREE);
12674
12675 tree v8qi_ftype_v4hi_v4hi
12676 = build_function_type_list (V8QI_type_node,
12677 V4HI_type_node, V4HI_type_node, NULL_TREE);
12678 tree v4hi_ftype_v2si_v2si
12679 = build_function_type_list (V4HI_type_node,
12680 V2SI_type_node, V2SI_type_node, NULL_TREE);
12681 tree v4sf_ftype_v4sf_v4sf_int
12682 = build_function_type_list (V4SF_type_node,
12683 V4SF_type_node, V4SF_type_node,
12684 integer_type_node, NULL_TREE);
12685 tree v2si_ftype_v4hi_v4hi
12686 = build_function_type_list (V2SI_type_node,
12687 V4HI_type_node, V4HI_type_node, NULL_TREE);
12688 tree v4hi_ftype_v4hi_int
12689 = build_function_type_list (V4HI_type_node,
12690 V4HI_type_node, integer_type_node, NULL_TREE);
12691 tree v4hi_ftype_v4hi_di
12692 = build_function_type_list (V4HI_type_node,
12693 V4HI_type_node, long_long_unsigned_type_node,
12694 NULL_TREE);
12695 tree v2si_ftype_v2si_di
12696 = build_function_type_list (V2SI_type_node,
12697 V2SI_type_node, long_long_unsigned_type_node,
12698 NULL_TREE);
12699 tree void_ftype_void
12700 = build_function_type (void_type_node, void_list_node);
12701 tree void_ftype_unsigned
12702 = build_function_type_list (void_type_node, unsigned_type_node, NULL_TREE);
12703 tree void_ftype_unsigned_unsigned
12704 = build_function_type_list (void_type_node, unsigned_type_node,
12705 unsigned_type_node, NULL_TREE);
12706 tree void_ftype_pcvoid_unsigned_unsigned
12707 = build_function_type_list (void_type_node, const_ptr_type_node,
12708 unsigned_type_node, unsigned_type_node,
12709 NULL_TREE);
12710 tree unsigned_ftype_void
12711 = build_function_type (unsigned_type_node, void_list_node);
12712 tree di_ftype_void
12713 = build_function_type (long_long_unsigned_type_node, void_list_node);
12714 tree v4sf_ftype_void
12715 = build_function_type (V4SF_type_node, void_list_node);
12716 tree v2si_ftype_v4sf
12717 = build_function_type_list (V2SI_type_node, V4SF_type_node, NULL_TREE);
12718
12719 tree void_ftype_v8qi_v8qi_pchar
12720 = build_function_type_list (void_type_node,
12721 V8QI_type_node, V8QI_type_node,
12722 pchar_type_node, NULL_TREE);
12723 tree v4sf_ftype_pcfloat
12724 = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
12725
12726 tree v4sf_ftype_v4sf_pv2si
12727 = build_function_type_list (V4SF_type_node,
12728 V4SF_type_node, pv2si_type_node, NULL_TREE);
12729 tree void_ftype_pv2si_v4sf
12730 = build_function_type_list (void_type_node,
12731 pv2si_type_node, V4SF_type_node, NULL_TREE);
12732 tree void_ftype_pfloat_v4sf
12733 = build_function_type_list (void_type_node,
12734 pfloat_type_node, V4SF_type_node, NULL_TREE);
12735 tree void_ftype_pdi_di
12736 = build_function_type_list (void_type_node,
12737 pdi_type_node, long_long_unsigned_type_node,
12738 NULL_TREE);
12739 tree void_ftype_pv2di_v2di
12740 = build_function_type_list (void_type_node,
12741 pv2di_type_node, V2DI_type_node, NULL_TREE);
12742
12743 tree v4sf_ftype_v4sf
12744 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
12745
12746
12747 tree v4sf_ftype_v4sf_v4sf
12748 = build_function_type_list (V4SF_type_node,
12749 V4SF_type_node, V4SF_type_node, NULL_TREE);
12750 tree v8qi_ftype_v8qi_v8qi
12751 = build_function_type_list (V8QI_type_node,
12752 V8QI_type_node, V8QI_type_node, NULL_TREE);
12753 tree v4hi_ftype_v4hi_v4hi
12754 = build_function_type_list (V4HI_type_node,
12755 V4HI_type_node, V4HI_type_node, NULL_TREE);
12756 tree v2si_ftype_v2si_v2si
12757 = build_function_type_list (V2SI_type_node,
12758 V2SI_type_node, V2SI_type_node, NULL_TREE);
12759 tree di_ftype_di_di
12760 = build_function_type_list (long_long_unsigned_type_node,
12761 long_long_unsigned_type_node,
12762 long_long_unsigned_type_node, NULL_TREE);
12763
12764 tree v2si_ftype_v2sf
12765 = build_function_type_list (V2SI_type_node, V2SF_type_node, NULL_TREE);
12766 tree v2sf_ftype_v2si
12767 = build_function_type_list (V2SF_type_node, V2SI_type_node, NULL_TREE);
12768 tree v2si_ftype_v2si
12769 = build_function_type_list (V2SI_type_node, V2SI_type_node, NULL_TREE);
12770 tree v2sf_ftype_v2sf
12771 = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
12772 tree v2sf_ftype_v2sf_v2sf
12773 = build_function_type_list (V2SF_type_node,
12774 V2SF_type_node, V2SF_type_node, NULL_TREE);
12775 tree v2si_ftype_v2sf_v2sf
12776 = build_function_type_list (V2SI_type_node,
12777 V2SF_type_node, V2SF_type_node, NULL_TREE);
12778 tree pint_type_node = build_pointer_type (integer_type_node);
12779 tree pcint_type_node = build_pointer_type (
12780 build_type_variant (integer_type_node, 1, 0));
12781 tree pdouble_type_node = build_pointer_type (double_type_node);
12782 tree pcdouble_type_node = build_pointer_type (
12783 build_type_variant (double_type_node, 1, 0));
12784 tree int_ftype_v2df_v2df
12785 = build_function_type_list (integer_type_node,
12786 V2DF_type_node, V2DF_type_node, NULL_TREE);
12787
12788 tree ti_ftype_void
12789 = build_function_type (intTI_type_node, void_list_node);
12790 tree v2di_ftype_void
12791 = build_function_type (V2DI_type_node, void_list_node);
12792 tree ti_ftype_ti_ti
12793 = build_function_type_list (intTI_type_node,
12794 intTI_type_node, intTI_type_node, NULL_TREE);
12795 tree void_ftype_pcvoid
12796 = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
12797 tree v2di_ftype_di
12798 = build_function_type_list (V2DI_type_node,
12799 long_long_unsigned_type_node, NULL_TREE);
12800 tree di_ftype_v2di
12801 = build_function_type_list (long_long_unsigned_type_node,
12802 V2DI_type_node, NULL_TREE);
12803 tree v4sf_ftype_v4si
12804 = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
12805 tree v4si_ftype_v4sf
12806 = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
12807 tree v2df_ftype_v4si
12808 = build_function_type_list (V2DF_type_node, V4SI_type_node, NULL_TREE);
12809 tree v4si_ftype_v2df
12810 = build_function_type_list (V4SI_type_node, V2DF_type_node, NULL_TREE);
12811 tree v2si_ftype_v2df
12812 = build_function_type_list (V2SI_type_node, V2DF_type_node, NULL_TREE);
12813 tree v4sf_ftype_v2df
12814 = build_function_type_list (V4SF_type_node, V2DF_type_node, NULL_TREE);
12815 tree v2df_ftype_v2si
12816 = build_function_type_list (V2DF_type_node, V2SI_type_node, NULL_TREE);
12817 tree v2df_ftype_v4sf
12818 = build_function_type_list (V2DF_type_node, V4SF_type_node, NULL_TREE);
12819 tree int_ftype_v2df
12820 = build_function_type_list (integer_type_node, V2DF_type_node, NULL_TREE);
12821 tree int64_ftype_v2df
12822 = build_function_type_list (long_long_integer_type_node,
12823 V2DF_type_node, NULL_TREE);
12824 tree v2df_ftype_v2df_int
12825 = build_function_type_list (V2DF_type_node,
12826 V2DF_type_node, integer_type_node, NULL_TREE);
12827 tree v2df_ftype_v2df_int64
12828 = build_function_type_list (V2DF_type_node,
12829 V2DF_type_node, long_long_integer_type_node,
12830 NULL_TREE);
12831 tree v4sf_ftype_v4sf_v2df
12832 = build_function_type_list (V4SF_type_node,
12833 V4SF_type_node, V2DF_type_node, NULL_TREE);
12834 tree v2df_ftype_v2df_v4sf
12835 = build_function_type_list (V2DF_type_node,
12836 V2DF_type_node, V4SF_type_node, NULL_TREE);
12837 tree v2df_ftype_v2df_v2df_int
12838 = build_function_type_list (V2DF_type_node,
12839 V2DF_type_node, V2DF_type_node,
12840 integer_type_node,
12841 NULL_TREE);
12842 tree v2df_ftype_v2df_pv2si
12843 = build_function_type_list (V2DF_type_node,
12844 V2DF_type_node, pv2si_type_node, NULL_TREE);
12845 tree void_ftype_pv2si_v2df
12846 = build_function_type_list (void_type_node,
12847 pv2si_type_node, V2DF_type_node, NULL_TREE);
12848 tree void_ftype_pdouble_v2df
12849 = build_function_type_list (void_type_node,
12850 pdouble_type_node, V2DF_type_node, NULL_TREE);
12851 tree void_ftype_pint_int
12852 = build_function_type_list (void_type_node,
12853 pint_type_node, integer_type_node, NULL_TREE);
12854 tree void_ftype_v16qi_v16qi_pchar
12855 = build_function_type_list (void_type_node,
12856 V16QI_type_node, V16QI_type_node,
12857 pchar_type_node, NULL_TREE);
12858 tree v2df_ftype_pcdouble
12859 = build_function_type_list (V2DF_type_node, pcdouble_type_node, NULL_TREE);
12860 tree v2df_ftype_v2df_v2df
12861 = build_function_type_list (V2DF_type_node,
12862 V2DF_type_node, V2DF_type_node, NULL_TREE);
12863 tree v16qi_ftype_v16qi_v16qi
12864 = build_function_type_list (V16QI_type_node,
12865 V16QI_type_node, V16QI_type_node, NULL_TREE);
12866 tree v8hi_ftype_v8hi_v8hi
12867 = build_function_type_list (V8HI_type_node,
12868 V8HI_type_node, V8HI_type_node, NULL_TREE);
12869 tree v4si_ftype_v4si_v4si
12870 = build_function_type_list (V4SI_type_node,
12871 V4SI_type_node, V4SI_type_node, NULL_TREE);
12872 tree v2di_ftype_v2di_v2di
12873 = build_function_type_list (V2DI_type_node,
12874 V2DI_type_node, V2DI_type_node, NULL_TREE);
12875 tree v2di_ftype_v2df_v2df
12876 = build_function_type_list (V2DI_type_node,
12877 V2DF_type_node, V2DF_type_node, NULL_TREE);
12878 tree v2df_ftype_v2df
12879 = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
12880 tree v2df_ftype_double
12881 = build_function_type_list (V2DF_type_node, double_type_node, NULL_TREE);
12882 tree v2df_ftype_double_double
12883 = build_function_type_list (V2DF_type_node,
12884 double_type_node, double_type_node, NULL_TREE);
12885 tree int_ftype_v8hi_int
12886 = build_function_type_list (integer_type_node,
12887 V8HI_type_node, integer_type_node, NULL_TREE);
12888 tree v8hi_ftype_v8hi_int_int
12889 = build_function_type_list (V8HI_type_node,
12890 V8HI_type_node, integer_type_node,
12891 integer_type_node, NULL_TREE);
12892 tree v2di_ftype_v2di_int
12893 = build_function_type_list (V2DI_type_node,
12894 V2DI_type_node, integer_type_node, NULL_TREE);
12895 tree v4si_ftype_v4si_int
12896 = build_function_type_list (V4SI_type_node,
12897 V4SI_type_node, integer_type_node, NULL_TREE);
12898 tree v8hi_ftype_v8hi_int
12899 = build_function_type_list (V8HI_type_node,
12900 V8HI_type_node, integer_type_node, NULL_TREE);
12901 tree v8hi_ftype_v8hi_v2di
12902 = build_function_type_list (V8HI_type_node,
12903 V8HI_type_node, V2DI_type_node, NULL_TREE);
12904 tree v4si_ftype_v4si_v2di
12905 = build_function_type_list (V4SI_type_node,
12906 V4SI_type_node, V2DI_type_node, NULL_TREE);
12907 tree v4si_ftype_v8hi_v8hi
12908 = build_function_type_list (V4SI_type_node,
12909 V8HI_type_node, V8HI_type_node, NULL_TREE);
12910 #ifdef KEY // New type
12911 tree v4hi_ftype_v8qi_v8qi
12912 = build_function_type_list (V4HI_type_node,
12913 V8QI_type_node, V8QI_type_node, NULL_TREE);
12914 #else
12915 tree di_ftype_v8qi_v8qi
12916 = build_function_type_list (long_long_unsigned_type_node,
12917 V8QI_type_node, V8QI_type_node, NULL_TREE);
12918 #endif
12919 tree v2di_ftype_v16qi_v16qi
12920 = build_function_type_list (V2DI_type_node,
12921 V16QI_type_node, V16QI_type_node, NULL_TREE);
12922 tree int_ftype_v16qi
12923 = build_function_type_list (integer_type_node, V16QI_type_node, NULL_TREE);
12924 tree v16qi_ftype_pcchar
12925 = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
12926 tree void_ftype_pchar_v16qi
12927 = build_function_type_list (void_type_node,
12928 pchar_type_node, V16QI_type_node, NULL_TREE);
12929 tree v4si_ftype_pcint
12930 = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
12931 tree void_ftype_pcint_v4si
12932 = build_function_type_list (void_type_node,
12933 pcint_type_node, V4SI_type_node, NULL_TREE);
12934 tree v2di_ftype_v2di
12935 = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE);
12936
12937
12938
12939 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
12940 {
12941
12942
12943 enum machine_mode mode;
12944 tree type;
12945
12946 if (d->name == 0)
12947 continue;
12948 mode = insn_data[d->icode].operand[1].mode;
12949
12950 switch (mode)
12951 {
12952 case V16QImode:
12953 type = v16qi_ftype_v16qi_v16qi;
12954 break;
12955 case V8HImode:
12956 type = v8hi_ftype_v8hi_v8hi;
12957 break;
12958 case V4SImode:
12959 type = v4si_ftype_v4si_v4si;
12960 break;
12961 case V2DImode:
12962 type = v2di_ftype_v2di_v2di;
12963 break;
12964 case V2DFmode:
12965 type = v2df_ftype_v2df_v2df;
12966 break;
12967 case TImode:
12968 type = ti_ftype_ti_ti;
12969 break;
12970 case V4SFmode:
12971 type = v4sf_ftype_v4sf_v4sf;
12972 break;
12973 case V8QImode:
12974 type = v8qi_ftype_v8qi_v8qi;
12975 break;
12976 case V4HImode:
12977 type = v4hi_ftype_v4hi_v4hi;
12978 break;
12979 case V2SImode:
12980 type = v2si_ftype_v2si_v2si;
12981 break;
12982 case DImode:
12983 type = di_ftype_di_di;
12984 break;
12985
12986 default:
12987 abort ();
12988 }
12989
12990
12991 if (d->icode == CODE_FOR_maskcmpv4sf3
12992 || d->icode == CODE_FOR_maskncmpv4sf3
12993 || d->icode == CODE_FOR_vmmaskcmpv4sf3
12994 || d->icode == CODE_FOR_vmmaskncmpv4sf3)
12995 type = v4si_ftype_v4sf_v4sf;
12996
12997 if (d->icode == CODE_FOR_maskcmpv2df3
12998 || d->icode == CODE_FOR_maskncmpv2df3
12999 || d->icode == CODE_FOR_vmmaskcmpv2df3
13000 || d->icode == CODE_FOR_vmmaskncmpv2df3)
13001 type = v2di_ftype_v2df_v2df;
13002
13003 def_builtin (d->mask, d->name, type, d->code);
13004 }
13005
13006
13007 def_builtin (MASK_MMX, "__builtin_ia32_mmx_zero", di_ftype_void, IX86_BUILTIN_MMX_ZERO);
13008 def_builtin (MASK_MMX, "__builtin_ia32_emms", void_ftype_void, IX86_BUILTIN_EMMS);
13009 def_builtin (MASK_MMX, "__builtin_ia32_psllw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSLLW);
13010 def_builtin (MASK_MMX, "__builtin_ia32_pslld", v2si_ftype_v2si_di, IX86_BUILTIN_PSLLD);
13011 def_builtin (MASK_MMX, "__builtin_ia32_psllq", di_ftype_di_di, IX86_BUILTIN_PSLLQ);
13012
13013 def_builtin (MASK_MMX, "__builtin_ia32_psrlw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSRLW);
13014 def_builtin (MASK_MMX, "__builtin_ia32_psrld", v2si_ftype_v2si_di, IX86_BUILTIN_PSRLD);
13015 def_builtin (MASK_MMX, "__builtin_ia32_psrlq", di_ftype_di_di, IX86_BUILTIN_PSRLQ);
13016
13017 def_builtin (MASK_MMX, "__builtin_ia32_psraw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSRAW);
13018 def_builtin (MASK_MMX, "__builtin_ia32_psrad", v2si_ftype_v2si_di, IX86_BUILTIN_PSRAD);
13019
13020 def_builtin (MASK_MMX, "__builtin_ia32_pshufw", v4hi_ftype_v4hi_int, IX86_BUILTIN_PSHUFW);
13021 def_builtin (MASK_MMX, "__builtin_ia32_pmaddwd", v2si_ftype_v4hi_v4hi, IX86_BUILTIN_PMADDWD);
13022
13023
13024 for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
13025 if (d->mask == MASK_SSE2)
13026 def_builtin (d->mask, d->name, int_ftype_v2df_v2df, d->code);
13027 else
13028 def_builtin (d->mask, d->name, int_ftype_v4sf_v4sf, d->code);
13029
13030 def_builtin (MASK_MMX, "__builtin_ia32_packsswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKSSWB);
13031 def_builtin (MASK_MMX, "__builtin_ia32_packssdw", v4hi_ftype_v2si_v2si, IX86_BUILTIN_PACKSSDW);
13032 def_builtin (MASK_MMX, "__builtin_ia32_packuswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKUSWB);
13033
13034 def_builtin (MASK_SSE, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
13035 def_builtin (MASK_SSE, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
13036 def_builtin (MASK_SSE, "__builtin_ia32_cvtpi2ps", v4sf_ftype_v4sf_v2si, IX86_BUILTIN_CVTPI2PS);
13037 def_builtin (MASK_SSE, "__builtin_ia32_cvtps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTPS2PI);
13038 def_builtin (MASK_SSE, "__builtin_ia32_cvtsi2ss", v4sf_ftype_v4sf_int, IX86_BUILTIN_CVTSI2SS);
13039 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvtsi642ss", v4sf_ftype_v4sf_int64, IX86_BUILTIN_CVTSI642SS);
13040 def_builtin (MASK_SSE, "__builtin_ia32_cvtss2si", int_ftype_v4sf, IX86_BUILTIN_CVTSS2SI);
13041 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvtss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTSS2SI64);
13042 def_builtin (MASK_SSE, "__builtin_ia32_cvttps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTTPS2PI);
13043 def_builtin (MASK_SSE, "__builtin_ia32_cvttss2si", int_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI);
13044 def_builtin (MASK_SSE | MASK_64BIT, "__builtin_ia32_cvttss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI64);
13045
13046 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pextrw", int_ftype_v4hi_int, IX86_BUILTIN_PEXTRW);
13047 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pinsrw", v4hi_ftype_v4hi_int_int, IX86_BUILTIN_PINSRW);
13048
13049 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ);
13050
13051 def_builtin (MASK_SSE, "__builtin_ia32_loadaps", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADAPS);
13052 def_builtin (MASK_SSE, "__builtin_ia32_loadups", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADUPS);
13053 def_builtin (MASK_SSE, "__builtin_ia32_loadss", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADSS);
13054 def_builtin (MASK_SSE, "__builtin_ia32_storeaps", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREAPS);
13055 def_builtin (MASK_SSE, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS);
13056 def_builtin (MASK_SSE, "__builtin_ia32_storess", void_ftype_pfloat_v4sf, IX86_BUILTIN_STORESS);
13057
13058 def_builtin (MASK_SSE, "__builtin_ia32_loadhps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADHPS);
13059 def_builtin (MASK_SSE, "__builtin_ia32_loadlps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADLPS);
13060 def_builtin (MASK_SSE, "__builtin_ia32_storehps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STOREHPS);
13061 def_builtin (MASK_SSE, "__builtin_ia32_storelps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STORELPS);
13062
13063 def_builtin (MASK_SSE, "__builtin_ia32_movmskps", int_ftype_v4sf, IX86_BUILTIN_MOVMSKPS);
13064 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pmovmskb", int_ftype_v8qi, IX86_BUILTIN_PMOVMSKB);
13065 def_builtin (MASK_SSE, "__builtin_ia32_movntps", void_ftype_pfloat_v4sf, IX86_BUILTIN_MOVNTPS);
13066 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_movntq", void_ftype_pdi_di, IX86_BUILTIN_MOVNTQ);
13067
13068 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_sfence", void_ftype_void, IX86_BUILTIN_SFENCE);
13069
13070 #ifdef KEY // Fix inconsistent return type
13071 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_psadbw", v4hi_ftype_v8qi_v8qi, IX86_BUILTIN_PSADBW);
13072 #else
13073 def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_psadbw", di_ftype_v8qi_v8qi, IX86_BUILTIN_PSADBW);
13074 #endif
13075
13076 def_builtin (MASK_SSE, "__builtin_ia32_rcpps", v4sf_ftype_v4sf, IX86_BUILTIN_RCPPS);
13077 def_builtin (MASK_SSE, "__builtin_ia32_rcpss", v4sf_ftype_v4sf, IX86_BUILTIN_RCPSS);
13078 def_builtin (MASK_SSE, "__builtin_ia32_rsqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTPS);
13079 def_builtin (MASK_SSE, "__builtin_ia32_rsqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTSS);
13080 def_builtin (MASK_SSE, "__builtin_ia32_sqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTPS);
13081 def_builtin (MASK_SSE, "__builtin_ia32_sqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTSS);
13082
13083 def_builtin (MASK_SSE, "__builtin_ia32_shufps", v4sf_ftype_v4sf_v4sf_int, IX86_BUILTIN_SHUFPS);
13084
13085
13086 def_builtin (MASK_3DNOW, "__builtin_ia32_femms", void_ftype_void, IX86_BUILTIN_FEMMS);
13087 def_builtin (MASK_3DNOW, "__builtin_ia32_pavgusb", v8qi_ftype_v8qi_v8qi, IX86_BUILTIN_PAVGUSB);
13088 def_builtin (MASK_3DNOW, "__builtin_ia32_pf2id", v2si_ftype_v2sf, IX86_BUILTIN_PF2ID);
13089 def_builtin (MASK_3DNOW, "__builtin_ia32_pfacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFACC);
13090 def_builtin (MASK_3DNOW, "__builtin_ia32_pfadd", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFADD);
13091 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpeq", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPEQ);
13092 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpge", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPGE);
13093 def_builtin (MASK_3DNOW, "__builtin_ia32_pfcmpgt", v2si_ftype_v2sf_v2sf, IX86_BUILTIN_PFCMPGT);
13094 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmax", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMAX);
13095 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmin", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMIN);
13096 def_builtin (MASK_3DNOW, "__builtin_ia32_pfmul", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFMUL);
13097 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcp", v2sf_ftype_v2sf, IX86_BUILTIN_PFRCP);
13098 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcpit1", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRCPIT1);
13099 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrcpit2", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRCPIT2);
13100 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrsqrt", v2sf_ftype_v2sf, IX86_BUILTIN_PFRSQRT);
13101 def_builtin (MASK_3DNOW, "__builtin_ia32_pfrsqit1", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFRSQIT1);
13102 def_builtin (MASK_3DNOW, "__builtin_ia32_pfsub", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFSUB);
13103 def_builtin (MASK_3DNOW, "__builtin_ia32_pfsubr", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFSUBR);
13104 def_builtin (MASK_3DNOW, "__builtin_ia32_pi2fd", v2sf_ftype_v2si, IX86_BUILTIN_PI2FD);
13105 def_builtin (MASK_3DNOW, "__builtin_ia32_pmulhrw", v4hi_ftype_v4hi_v4hi, IX86_BUILTIN_PMULHRW);
13106
13107
13108 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pf2iw", v2si_ftype_v2sf, IX86_BUILTIN_PF2IW);
13109 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pfnacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFNACC);
13110 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pfpnacc", v2sf_ftype_v2sf_v2sf, IX86_BUILTIN_PFPNACC);
13111 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pi2fw", v2sf_ftype_v2si, IX86_BUILTIN_PI2FW);
13112 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsf", v2sf_ftype_v2sf, IX86_BUILTIN_PSWAPDSF);
13113 def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsi", v2si_ftype_v2si, IX86_BUILTIN_PSWAPDSI);
13114
13115 def_builtin (MASK_SSE, "__builtin_ia32_setzerops", v4sf_ftype_void, IX86_BUILTIN_SSE_ZERO);
13116
13117
13118 def_builtin (MASK_SSE2, "__builtin_ia32_pextrw128", int_ftype_v8hi_int, IX86_BUILTIN_PEXTRW128);
13119 def_builtin (MASK_SSE2, "__builtin_ia32_pinsrw128", v8hi_ftype_v8hi_int_int, IX86_BUILTIN_PINSRW128);
13120
13121 def_builtin (MASK_SSE2, "__builtin_ia32_maskmovdqu", void_ftype_v16qi_v16qi_pchar, IX86_BUILTIN_MASKMOVDQU);
13122 def_builtin (MASK_SSE2, "__builtin_ia32_movq2dq", v2di_ftype_di, IX86_BUILTIN_MOVQ2DQ);
13123 def_builtin (MASK_SSE2, "__builtin_ia32_movdq2q", di_ftype_v2di, IX86_BUILTIN_MOVDQ2Q);
13124
13125 def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADAPD);
13126 def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADUPD);
13127 def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADSD);
13128 def_builtin (MASK_SSE2, "__builtin_ia32_storeapd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREAPD);
13129 def_builtin (MASK_SSE2, "__builtin_ia32_storeupd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREUPD);
13130 def_builtin (MASK_SSE2, "__builtin_ia32_storesd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORESD);
13131
13132 def_builtin (MASK_SSE2, "__builtin_ia32_loadhpd", v2df_ftype_v2df_pv2si, IX86_BUILTIN_LOADHPD);
13133 def_builtin (MASK_SSE2, "__builtin_ia32_loadlpd", v2df_ftype_v2df_pv2si, IX86_BUILTIN_LOADLPD);
13134 def_builtin (MASK_SSE2, "__builtin_ia32_storehpd", void_ftype_pv2si_v2df, IX86_BUILTIN_STOREHPD);
13135 def_builtin (MASK_SSE2, "__builtin_ia32_storelpd", void_ftype_pv2si_v2df, IX86_BUILTIN_STORELPD);
13136
13137 def_builtin (MASK_SSE2, "__builtin_ia32_movmskpd", int_ftype_v2df, IX86_BUILTIN_MOVMSKPD);
13138 def_builtin (MASK_SSE2, "__builtin_ia32_pmovmskb128", int_ftype_v16qi, IX86_BUILTIN_PMOVMSKB128);
13139 def_builtin (MASK_SSE2, "__builtin_ia32_movnti", void_ftype_pint_int, IX86_BUILTIN_MOVNTI);
13140 def_builtin (MASK_SSE2, "__builtin_ia32_movntpd", void_ftype_pdouble_v2df, IX86_BUILTIN_MOVNTPD);
13141 def_builtin (MASK_SSE2, "__builtin_ia32_movntdq", void_ftype_pv2di_v2di, IX86_BUILTIN_MOVNTDQ);
13142
13143 def_builtin (MASK_SSE2, "__builtin_ia32_pshufd", v4si_ftype_v4si_int, IX86_BUILTIN_PSHUFD);
13144 def_builtin (MASK_SSE2, "__builtin_ia32_pshuflw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFLW);
13145 def_builtin (MASK_SSE2, "__builtin_ia32_pshufhw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFHW);
13146 def_builtin (MASK_SSE2, "__builtin_ia32_psadbw128", v2di_ftype_v16qi_v16qi, IX86_BUILTIN_PSADBW128);
13147
13148 def_builtin (MASK_SSE2, "__builtin_ia32_sqrtpd", v2df_ftype_v2df, IX86_BUILTIN_SQRTPD);
13149 def_builtin (MASK_SSE2, "__builtin_ia32_sqrtsd", v2df_ftype_v2df, IX86_BUILTIN_SQRTSD);
13150
13151 def_builtin (MASK_SSE2, "__builtin_ia32_shufpd", v2df_ftype_v2df_v2df_int, IX86_BUILTIN_SHUFPD);
13152
13153 def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2pd", v2df_ftype_v4si, IX86_BUILTIN_CVTDQ2PD);
13154 def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2ps", v4sf_ftype_v4si, IX86_BUILTIN_CVTDQ2PS);
13155
13156 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTPD2DQ);
13157 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTPD2PI);
13158 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2ps", v4sf_ftype_v2df, IX86_BUILTIN_CVTPD2PS);
13159 def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTTPD2DQ);
13160 def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTTPD2PI);
13161
13162 def_builtin (MASK_SSE2, "__builtin_ia32_cvtpi2pd", v2df_ftype_v2si, IX86_BUILTIN_CVTPI2PD);
13163
13164 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2si", int_ftype_v2df, IX86_BUILTIN_CVTSD2SI);
13165 def_builtin (MASK_SSE2, "__builtin_ia32_cvttsd2si", int_ftype_v2df, IX86_BUILTIN_CVTTSD2SI);
13166 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvtsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTSD2SI64);
13167 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvttsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTTSD2SI64);
13168
13169 def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTPS2DQ);
13170 def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2pd", v2df_ftype_v4sf, IX86_BUILTIN_CVTPS2PD);
13171 def_builtin (MASK_SSE2, "__builtin_ia32_cvttps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTTPS2DQ);
13172
13173 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsi2sd", v2df_ftype_v2df_int, IX86_BUILTIN_CVTSI2SD);
13174 def_builtin (MASK_SSE2 | MASK_64BIT, "__builtin_ia32_cvtsi642sd", v2df_ftype_v2df_int64, IX86_BUILTIN_CVTSI642SD);
13175 def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2ss", v4sf_ftype_v4sf_v2df, IX86_BUILTIN_CVTSD2SS);
13176 def_builtin (MASK_SSE2, "__builtin_ia32_cvtss2sd", v2df_ftype_v2df_v4sf, IX86_BUILTIN_CVTSS2SD);
13177
13178 def_builtin (MASK_SSE2, "__builtin_ia32_setpd1", v2df_ftype_double, IX86_BUILTIN_SETPD1);
13179 def_builtin (MASK_SSE2, "__builtin_ia32_setpd", v2df_ftype_double_double, IX86_BUILTIN_SETPD);
13180 def_builtin (MASK_SSE2, "__builtin_ia32_setzeropd", ti_ftype_void, IX86_BUILTIN_CLRPD);
13181 def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pcdouble, IX86_BUILTIN_LOADPD1);
13182 def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADRPD);
13183 def_builtin (MASK_SSE2, "__builtin_ia32_storepd1", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREPD1);
13184 def_builtin (MASK_SSE2, "__builtin_ia32_storerpd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORERPD);
13185
13186 def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pcvoid, IX86_BUILTIN_CLFLUSH);
13187 def_builtin (MASK_SSE2, "__builtin_ia32_lfence", void_ftype_void, IX86_BUILTIN_LFENCE);
13188 def_builtin (MASK_SSE2, "__builtin_ia32_mfence", void_ftype_void, IX86_BUILTIN_MFENCE);
13189
13190 def_builtin (MASK_SSE2, "__builtin_ia32_loaddqa", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQA);
13191 def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQU);
13192 def_builtin (MASK_SSE2, "__builtin_ia32_loadd", v4si_ftype_pcint, IX86_BUILTIN_LOADD);
13193 def_builtin (MASK_SSE2, "__builtin_ia32_storedqa", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQA);
13194 def_builtin (MASK_SSE2, "__builtin_ia32_storedqu", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQU);
13195 def_builtin (MASK_SSE2, "__builtin_ia32_stored", void_ftype_pcint_v4si, IX86_BUILTIN_STORED);
13196 def_builtin (MASK_SSE2, "__builtin_ia32_movq", v2di_ftype_v2di, IX86_BUILTIN_MOVQ);
13197
13198 def_builtin (MASK_SSE, "__builtin_ia32_setzero128", v2di_ftype_void, IX86_BUILTIN_CLRTI);
13199
13200 def_builtin (MASK_SSE2, "__builtin_ia32_psllw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSLLW128);
13201 def_builtin (MASK_SSE2, "__builtin_ia32_pslld128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSLLD128);
13202 def_builtin (MASK_SSE2, "__builtin_ia32_psllq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSLLQ128);
13203
13204 def_builtin (MASK_SSE2, "__builtin_ia32_psrlw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSRLW128);
13205 def_builtin (MASK_SSE2, "__builtin_ia32_psrld128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSRLD128);
13206 def_builtin (MASK_SSE2, "__builtin_ia32_psrlq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSRLQ128);
13207
13208 def_builtin (MASK_SSE2, "__builtin_ia32_psraw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSRAW128);
13209 def_builtin (MASK_SSE2, "__builtin_ia32_psrad128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSRAD128);
13210
13211 def_builtin (MASK_SSE2, "__builtin_ia32_pslldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLDQI128);
13212 def_builtin (MASK_SSE2, "__builtin_ia32_psllwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSLLWI128);
13213 def_builtin (MASK_SSE2, "__builtin_ia32_pslldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSLLDI128);
13214 def_builtin (MASK_SSE2, "__builtin_ia32_psllqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLQI128);
13215
13216 def_builtin (MASK_SSE2, "__builtin_ia32_psrldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLDQI128);
13217 def_builtin (MASK_SSE2, "__builtin_ia32_psrlwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRLWI128);
13218 def_builtin (MASK_SSE2, "__builtin_ia32_psrldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRLDI128);
13219 def_builtin (MASK_SSE2, "__builtin_ia32_psrlqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLQI128);
13220
13221 def_builtin (MASK_SSE2, "__builtin_ia32_psrawi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRAWI128);
13222 def_builtin (MASK_SSE2, "__builtin_ia32_psradi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRADI128);
13223
13224 def_builtin (MASK_SSE2, "__builtin_ia32_pmaddwd128", v4si_ftype_v8hi_v8hi, IX86_BUILTIN_PMADDWD128);
13225
13226
13227 def_builtin (MASK_PNI, "__builtin_ia32_monitor",
13228 void_ftype_pcvoid_unsigned_unsigned,
13229 IX86_BUILTIN_MONITOR);
13230 def_builtin (MASK_PNI, "__builtin_ia32_mwait",
13231 void_ftype_unsigned_unsigned,
13232 IX86_BUILTIN_MWAIT);
13233 def_builtin (MASK_PNI, "__builtin_ia32_movshdup",
13234 v4sf_ftype_v4sf,
13235 IX86_BUILTIN_MOVSHDUP);
13236 def_builtin (MASK_PNI, "__builtin_ia32_movsldup",
13237 v4sf_ftype_v4sf,
13238 IX86_BUILTIN_MOVSLDUP);
13239 def_builtin (MASK_PNI, "__builtin_ia32_lddqu",
13240 v16qi_ftype_pcchar, IX86_BUILTIN_LDDQU);
13241 def_builtin (MASK_PNI, "__builtin_ia32_loadddup",
13242 v2df_ftype_pcdouble, IX86_BUILTIN_LOADDDUP);
13243 def_builtin (MASK_PNI, "__builtin_ia32_movddup",
13244 v2df_ftype_v2df, IX86_BUILTIN_MOVDDUP);
13245 }
13246
13247
13248
13249
13250 static rtx
13251 safe_vector_operand (x, mode)
13252 rtx x;
13253 enum machine_mode mode;
13254 {
13255 if (x != const0_rtx)
13256 return x;
13257 x = gen_reg_rtx (mode);
13258
13259 if (VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode))
13260 emit_insn (gen_mmx_clrdi (mode == DImode ? x
13261 : gen_rtx_SUBREG (DImode, x, 0)));
13262 else
13263 emit_insn (gen_sse_clrv4sf (mode == V4SFmode ? x
13264 : gen_rtx_SUBREG (V4SFmode, x, 0)));
13265 return x;
13266 }
13267
13268
13269
13270 static rtx
13271 ix86_expand_binop_builtin (icode, arglist, target)
13272 enum insn_code icode;
13273 tree arglist;
13274 rtx target;
13275 {
13276 rtx pat;
13277 tree arg0 = TREE_VALUE (arglist);
13278 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13279 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13280 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13281 enum machine_mode tmode = insn_data[icode].operand[0].mode;
13282 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
13283 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
13284
13285 if (VECTOR_MODE_P (mode0))
13286 op0 = safe_vector_operand (op0, mode0);
13287 if (VECTOR_MODE_P (mode1))
13288 op1 = safe_vector_operand (op1, mode1);
13289
13290 if (! target
13291 || GET_MODE (target) != tmode
13292 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13293 target = gen_reg_rtx (tmode);
13294
13295 if (GET_MODE (op1) == SImode && mode1 == TImode)
13296 {
13297 rtx x = gen_reg_rtx (V4SImode);
13298 emit_insn (gen_sse2_loadd (x, op1));
13299 op1 = gen_lowpart (TImode, x);
13300 }
13301
13302
13303
13304 if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
13305 abort ();
13306
13307 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13308 op0 = copy_to_mode_reg (mode0, op0);
13309 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
13310 op1 = copy_to_mode_reg (mode1, op1);
13311
13312
13313
13314
13315 if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
13316 op0 = copy_to_mode_reg (mode0, op0);
13317
13318 pat = GEN_FCN (icode) (target, op0, op1);
13319 if (! pat)
13320 return 0;
13321 emit_insn (pat);
13322 return target;
13323 }
13324
13325
13326
13327 static rtx
13328 ix86_expand_store_builtin (icode, arglist)
13329 enum insn_code icode;
13330 tree arglist;
13331 {
13332 rtx pat;
13333 tree arg0 = TREE_VALUE (arglist);
13334 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13335 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13336 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13337 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
13338 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
13339
13340 if (VECTOR_MODE_P (mode1))
13341 op1 = safe_vector_operand (op1, mode1);
13342
13343 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
13344 op1 = copy_to_mode_reg (mode1, op1);
13345
13346 pat = GEN_FCN (icode) (op0, op1);
13347 if (pat)
13348 emit_insn (pat);
13349 return 0;
13350 }
13351
13352
13353
13354 static rtx
13355 ix86_expand_unop_builtin (icode, arglist, target, do_load)
13356 enum insn_code icode;
13357 tree arglist;
13358 rtx target;
13359 int do_load;
13360 {
13361 rtx pat;
13362 tree arg0 = TREE_VALUE (arglist);
13363 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13364 enum machine_mode tmode = insn_data[icode].operand[0].mode;
13365 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
13366
13367 if (! target
13368 || GET_MODE (target) != tmode
13369 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13370 target = gen_reg_rtx (tmode);
13371 if (do_load)
13372 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
13373 else
13374 {
13375 if (VECTOR_MODE_P (mode0))
13376 op0 = safe_vector_operand (op0, mode0);
13377
13378 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13379 op0 = copy_to_mode_reg (mode0, op0);
13380 }
13381
13382 pat = GEN_FCN (icode) (target, op0);
13383 if (! pat)
13384 return 0;
13385 emit_insn (pat);
13386 return target;
13387 }
13388
13389
13390
13391
13392 static rtx
13393 ix86_expand_unop1_builtin (icode, arglist, target)
13394 enum insn_code icode;
13395 tree arglist;
13396 rtx target;
13397 {
13398 rtx pat;
13399 tree arg0 = TREE_VALUE (arglist);
13400 rtx op1, op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13401 enum machine_mode tmode = insn_data[icode].operand[0].mode;
13402 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
13403
13404 if (! target
13405 || GET_MODE (target) != tmode
13406 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13407 target = gen_reg_rtx (tmode);
13408
13409 if (VECTOR_MODE_P (mode0))
13410 op0 = safe_vector_operand (op0, mode0);
13411
13412 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13413 op0 = copy_to_mode_reg (mode0, op0);
13414
13415 op1 = op0;
13416 if (! (*insn_data[icode].operand[2].predicate) (op1, mode0))
13417 op1 = copy_to_mode_reg (mode0, op1);
13418
13419 pat = GEN_FCN (icode) (target, op0, op1);
13420 if (! pat)
13421 return 0;
13422 emit_insn (pat);
13423 return target;
13424 }
13425
13426
13427
13428 static rtx
13429 ix86_expand_sse_compare (d, arglist, target)
13430 const struct builtin_description *d;
13431 tree arglist;
13432 rtx target;
13433 {
13434 rtx pat;
13435 tree arg0 = TREE_VALUE (arglist);
13436 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13437 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13438 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13439 rtx op2;
13440 enum machine_mode tmode = insn_data[d->icode].operand[0].mode;
13441 enum machine_mode mode0 = insn_data[d->icode].operand[1].mode;
13442 enum machine_mode mode1 = insn_data[d->icode].operand[2].mode;
13443 enum rtx_code comparison = d->comparison;
13444
13445 if (VECTOR_MODE_P (mode0))
13446 op0 = safe_vector_operand (op0, mode0);
13447 if (VECTOR_MODE_P (mode1))
13448 op1 = safe_vector_operand (op1, mode1);
13449
13450
13451
13452 if (d->flag)
13453 {
13454 rtx tmp = gen_reg_rtx (mode1);
13455 emit_move_insn (tmp, op1);
13456 op1 = op0;
13457 op0 = tmp;
13458 }
13459
13460 if (! target
13461 || GET_MODE (target) != tmode
13462 || ! (*insn_data[d->icode].operand[0].predicate) (target, tmode))
13463 target = gen_reg_rtx (tmode);
13464
13465 if (! (*insn_data[d->icode].operand[1].predicate) (op0, mode0))
13466 op0 = copy_to_mode_reg (mode0, op0);
13467 if (! (*insn_data[d->icode].operand[2].predicate) (op1, mode1))
13468 op1 = copy_to_mode_reg (mode1, op1);
13469
13470 op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
13471 pat = GEN_FCN (d->icode) (target, op0, op1, op2);
13472 if (! pat)
13473 return 0;
13474 emit_insn (pat);
13475 return target;
13476 }
13477
13478
13479
13480 static rtx
13481 ix86_expand_sse_comi (d, arglist, target)
13482 const struct builtin_description *d;
13483 tree arglist;
13484 rtx target;
13485 {
13486 rtx pat;
13487 tree arg0 = TREE_VALUE (arglist);
13488 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13489 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13490 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13491 rtx op2;
13492 enum machine_mode mode0 = insn_data[d->icode].operand[0].mode;
13493 enum machine_mode mode1 = insn_data[d->icode].operand[1].mode;
13494 enum rtx_code comparison = d->comparison;
13495
13496 if (VECTOR_MODE_P (mode0))
13497 op0 = safe_vector_operand (op0, mode0);
13498 if (VECTOR_MODE_P (mode1))
13499 op1 = safe_vector_operand (op1, mode1);
13500
13501
13502
13503 if (d->flag)
13504 {
13505 rtx tmp = op1;
13506 op1 = op0;
13507 op0 = tmp;
13508 }
13509
13510 target = gen_reg_rtx (SImode);
13511 emit_move_insn (target, const0_rtx);
13512 target = gen_rtx_SUBREG (QImode, target, 0);
13513
13514 if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
13515 op0 = copy_to_mode_reg (mode0, op0);
13516 if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
13517 op1 = copy_to_mode_reg (mode1, op1);
13518
13519 op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
13520 pat = GEN_FCN (d->icode) (op0, op1);
13521 if (! pat)
13522 return 0;
13523 emit_insn (pat);
13524 emit_insn (gen_rtx_SET (VOIDmode,
13525 gen_rtx_STRICT_LOW_PART (VOIDmode, target),
13526 gen_rtx_fmt_ee (comparison, QImode,
13527 SET_DEST (pat),
13528 const0_rtx)));
13529
13530 return SUBREG_REG (target);
13531 }
13532
13533
13534
13535
13536
13537
13538
13539 rtx
13540 ix86_expand_builtin (exp, target, subtarget, mode, ignore)
13541 tree exp;
13542 rtx target;
13543 rtx subtarget ATTRIBUTE_UNUSED;
13544 enum machine_mode mode ATTRIBUTE_UNUSED;
13545 int ignore ATTRIBUTE_UNUSED;
13546 {
13547 const struct builtin_description *d;
13548 size_t i;
13549 enum insn_code icode;
13550 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
13551 tree arglist = TREE_OPERAND (exp, 1);
13552 tree arg0, arg1, arg2;
13553 rtx op0, op1, op2, pat;
13554 enum machine_mode tmode, mode0, mode1, mode2;
13555 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
13556
13557 switch (fcode)
13558 {
13559 case IX86_BUILTIN_EMMS:
13560 emit_insn (gen_emms ());
13561 return 0;
13562
13563 case IX86_BUILTIN_SFENCE:
13564 emit_insn (gen_sfence ());
13565 return 0;
13566
13567 case IX86_BUILTIN_PEXTRW:
13568 case IX86_BUILTIN_PEXTRW128:
13569 icode = (fcode == IX86_BUILTIN_PEXTRW
13570 ? CODE_FOR_mmx_pextrw
13571 : CODE_FOR_sse2_pextrw);
13572 arg0 = TREE_VALUE (arglist);
13573 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13574 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13575 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13576 tmode = insn_data[icode].operand[0].mode;
13577 mode0 = insn_data[icode].operand[1].mode;
13578 mode1 = insn_data[icode].operand[2].mode;
13579
13580 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13581 op0 = copy_to_mode_reg (mode0, op0);
13582 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
13583 {
13584
13585 error ("selector must be an immediate");
13586 return gen_reg_rtx (tmode);
13587 }
13588 if (target == 0
13589 || GET_MODE (target) != tmode
13590 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13591 target = gen_reg_rtx (tmode);
13592 pat = GEN_FCN (icode) (target, op0, op1);
13593 if (! pat)
13594 return 0;
13595 emit_insn (pat);
13596 return target;
13597
13598 case IX86_BUILTIN_PINSRW:
13599 case IX86_BUILTIN_PINSRW128:
13600 icode = (fcode == IX86_BUILTIN_PINSRW
13601 ? CODE_FOR_mmx_pinsrw
13602 : CODE_FOR_sse2_pinsrw);
13603 arg0 = TREE_VALUE (arglist);
13604 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13605 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
13606 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13607 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13608 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
13609 tmode = insn_data[icode].operand[0].mode;
13610 mode0 = insn_data[icode].operand[1].mode;
13611 mode1 = insn_data[icode].operand[2].mode;
13612 mode2 = insn_data[icode].operand[3].mode;
13613
13614 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13615 op0 = copy_to_mode_reg (mode0, op0);
13616 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
13617 op1 = copy_to_mode_reg (mode1, op1);
13618 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
13619 {
13620
13621 error ("selector must be an immediate");
13622 return const0_rtx;
13623 }
13624 if (target == 0
13625 || GET_MODE (target) != tmode
13626 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13627 target = gen_reg_rtx (tmode);
13628 pat = GEN_FCN (icode) (target, op0, op1, op2);
13629 if (! pat)
13630 return 0;
13631 emit_insn (pat);
13632 return target;
13633
13634 case IX86_BUILTIN_MASKMOVQ:
13635 case IX86_BUILTIN_MASKMOVDQU:
13636 icode = (fcode == IX86_BUILTIN_MASKMOVQ
13637 ? (TARGET_64BIT ? CODE_FOR_mmx_maskmovq_rex : CODE_FOR_mmx_maskmovq)
13638 : (TARGET_64BIT ? CODE_FOR_sse2_maskmovdqu_rex64
13639 : CODE_FOR_sse2_maskmovdqu));
13640
13641 arg1 = TREE_VALUE (arglist);
13642 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
13643 arg0 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
13644 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13645 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13646 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
13647 mode0 = insn_data[icode].operand[0].mode;
13648 mode1 = insn_data[icode].operand[1].mode;
13649 mode2 = insn_data[icode].operand[2].mode;
13650
13651 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
13652 op0 = copy_to_mode_reg (mode0, op0);
13653 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
13654 op1 = copy_to_mode_reg (mode1, op1);
13655 if (! (*insn_data[icode].operand[2].predicate) (op2, mode2))
13656 op2 = copy_to_mode_reg (mode2, op2);
13657 pat = GEN_FCN (icode) (op0, op1, op2);
13658 if (! pat)
13659 return 0;
13660 emit_insn (pat);
13661 return 0;
13662
13663 case IX86_BUILTIN_SQRTSS:
13664 return ix86_expand_unop1_builtin (CODE_FOR_vmsqrtv4sf2, arglist, target);
13665 case IX86_BUILTIN_RSQRTSS:
13666 return ix86_expand_unop1_builtin (CODE_FOR_vmrsqrtv4sf2, arglist, target);
13667 case IX86_BUILTIN_RCPSS:
13668 return ix86_expand_unop1_builtin (CODE_FOR_vmrcpv4sf2, arglist, target);
13669
13670 case IX86_BUILTIN_LOADAPS:
13671 return ix86_expand_unop_builtin (CODE_FOR_sse_movaps, arglist, target, 1);
13672
13673 case IX86_BUILTIN_LOADUPS:
13674 return ix86_expand_unop_builtin (CODE_FOR_sse_movups, arglist, target, 1);
13675
13676 case IX86_BUILTIN_STOREAPS:
13677 return ix86_expand_store_builtin (CODE_FOR_sse_movaps, arglist);
13678
13679 case IX86_BUILTIN_STOREUPS:
13680 return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist);
13681
13682 case IX86_BUILTIN_LOADSS:
13683 return ix86_expand_unop_builtin (CODE_FOR_sse_loadss, arglist, target, 1);
13684
13685 case IX86_BUILTIN_STORESS:
13686 return ix86_expand_store_builtin (CODE_FOR_sse_storess, arglist);
13687
13688 case IX86_BUILTIN_LOADHPS:
13689 case IX86_BUILTIN_LOADLPS:
13690 case IX86_BUILTIN_LOADHPD:
13691 case IX86_BUILTIN_LOADLPD:
13692 icode = (fcode == IX86_BUILTIN_LOADHPS ? CODE_FOR_sse_movhps
13693 : fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_movlps
13694 : fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_movhpd
13695 : CODE_FOR_sse2_movlpd);
13696 arg0 = TREE_VALUE (arglist);
13697 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13698 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13699 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13700 tmode = insn_data[icode].operand[0].mode;
13701 mode0 = insn_data[icode].operand[1].mode;
13702 mode1 = insn_data[icode].operand[2].mode;
13703
13704 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13705 op0 = copy_to_mode_reg (mode0, op0);
13706 op1 = gen_rtx_MEM (mode1, copy_to_mode_reg (Pmode, op1));
13707 if (target == 0
13708 || GET_MODE (target) != tmode
13709 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13710 target = gen_reg_rtx (tmode);
13711 pat = GEN_FCN (icode) (target, op0, op1);
13712 if (! pat)
13713 return 0;
13714 emit_insn (pat);
13715 return target;
13716
13717 case IX86_BUILTIN_STOREHPS:
13718 case IX86_BUILTIN_STORELPS:
13719 case IX86_BUILTIN_STOREHPD:
13720 case IX86_BUILTIN_STORELPD:
13721 icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_movhps
13722 : fcode == IX86_BUILTIN_STORELPS ? CODE_FOR_sse_movlps
13723 : fcode == IX86_BUILTIN_STOREHPD ? CODE_FOR_sse2_movhpd
13724 : CODE_FOR_sse2_movlpd);
13725 arg0 = TREE_VALUE (arglist);
13726 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13727 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13728 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13729 mode0 = insn_data[icode].operand[1].mode;
13730 mode1 = insn_data[icode].operand[2].mode;
13731
13732 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
13733 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
13734 op1 = copy_to_mode_reg (mode1, op1);
13735
13736 pat = GEN_FCN (icode) (op0, op0, op1);
13737 if (! pat)
13738 return 0;
13739 emit_insn (pat);
13740 return 0;
13741
13742 case IX86_BUILTIN_MOVNTPS:
13743 return ix86_expand_store_builtin (CODE_FOR_sse_movntv4sf, arglist);
13744 case IX86_BUILTIN_MOVNTQ:
13745 return ix86_expand_store_builtin (CODE_FOR_sse_movntdi, arglist);
13746
13747 case IX86_BUILTIN_LDMXCSR:
13748 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
13749 target = assign_386_stack_local (SImode, 0);
13750 emit_move_insn (target, op0);
13751 emit_insn (gen_ldmxcsr (target));
13752 return 0;
13753
13754 case IX86_BUILTIN_STMXCSR:
13755 target = assign_386_stack_local (SImode, 0);
13756 emit_insn (gen_stmxcsr (target));
13757 return copy_to_mode_reg (SImode, target);
13758
13759 case IX86_BUILTIN_SHUFPS:
13760 case IX86_BUILTIN_SHUFPD:
13761 icode = (fcode == IX86_BUILTIN_SHUFPS
13762 ? CODE_FOR_sse_shufps
13763 : CODE_FOR_sse2_shufpd);
13764 arg0 = TREE_VALUE (arglist);
13765 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13766 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
13767 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13768 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13769 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
13770 tmode = insn_data[icode].operand[0].mode;
13771 mode0 = insn_data[icode].operand[1].mode;
13772 mode1 = insn_data[icode].operand[2].mode;
13773 mode2 = insn_data[icode].operand[3].mode;
13774
13775 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
13776 op0 = copy_to_mode_reg (mode0, op0);
13777 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
13778 op1 = copy_to_mode_reg (mode1, op1);
13779 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
13780 {
13781
13782 error ("mask must be an immediate");
13783 return gen_reg_rtx (tmode);
13784 }
13785 if (target == 0
13786 || GET_MODE (target) != tmode
13787 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13788 target = gen_reg_rtx (tmode);
13789 pat = GEN_FCN (icode) (target, op0, op1, op2);
13790 if (! pat)
13791 return 0;
13792 emit_insn (pat);
13793 return target;
13794
13795 case IX86_BUILTIN_PSHUFW:
13796 case IX86_BUILTIN_PSHUFD:
13797 case IX86_BUILTIN_PSHUFHW:
13798 case IX86_BUILTIN_PSHUFLW:
13799 icode = ( fcode == IX86_BUILTIN_PSHUFHW ? CODE_FOR_sse2_pshufhw
13800 : fcode == IX86_BUILTIN_PSHUFLW ? CODE_FOR_sse2_pshuflw
13801 : fcode == IX86_BUILTIN_PSHUFD ? CODE_FOR_sse2_pshufd
13802 : CODE_FOR_mmx_pshufw);
13803 arg0 = TREE_VALUE (arglist);
13804 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13805 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13806 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13807 tmode = insn_data[icode].operand[0].mode;
13808 mode1 = insn_data[icode].operand[1].mode;
13809 mode2 = insn_data[icode].operand[2].mode;
13810
13811 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
13812 op0 = copy_to_mode_reg (mode1, op0);
13813 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
13814 {
13815
13816 error ("mask must be an immediate");
13817 return const0_rtx;
13818 }
13819 if (target == 0
13820 || GET_MODE (target) != tmode
13821 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
13822 target = gen_reg_rtx (tmode);
13823 pat = GEN_FCN (icode) (target, op0, op1);
13824 if (! pat)
13825 return 0;
13826 emit_insn (pat);
13827 return target;
13828
13829 case IX86_BUILTIN_PSLLDQI128:
13830 case IX86_BUILTIN_PSRLDQI128:
13831 icode = ( fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3
13832 : CODE_FOR_sse2_lshrti3);
13833 arg0 = TREE_VALUE (arglist);
13834 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13835 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
13836 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
13837 tmode = insn_data[icode].operand[0].mode;
13838 mode1 = insn_data[icode].operand[1].mode;
13839 mode2 = insn_data[icode].operand[2].mode;
13840
13841 if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
13842 {
13843 op0 = copy_to_reg (op0);
13844 op0 = simplify_gen_subreg (mode1, op0, GET_MODE (op0), 0);
13845 }
13846 if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
13847 {
13848 error ("shift must be an immediate");
13849 return const0_rtx;
13850 }
13851 target = gen_reg_rtx (V2DImode);
13852 pat = GEN_FCN (icode) (simplify_gen_subreg (tmode, target, V2DImode, 0), op0, op1);
13853 if (! pat)
13854 return 0;
13855 emit_insn (pat);
13856 return target;
13857
13858 case IX86_BUILTIN_FEMMS:
13859 emit_insn (gen_femms ());
13860 return NULL_RTX;
13861
13862 case IX86_BUILTIN_PAVGUSB:
13863 return ix86_expand_binop_builtin (CODE_FOR_pavgusb, arglist, target);
13864
13865 case IX86_BUILTIN_PF2ID:
13866 return ix86_expand_unop_builtin (CODE_FOR_pf2id, arglist, target, 0);
13867
13868 case IX86_BUILTIN_PFACC:
13869 return ix86_expand_binop_builtin (CODE_FOR_pfacc, arglist, target);
13870
13871 case IX86_BUILTIN_PFADD:
13872 return ix86_expand_binop_builtin (CODE_FOR_addv2sf3, arglist, target);
13873
13874 case IX86_BUILTIN_PFCMPEQ:
13875 return ix86_expand_binop_builtin (CODE_FOR_eqv2sf3, arglist, target);
13876
13877 case IX86_BUILTIN_PFCMPGE:
13878 return ix86_expand_binop_builtin (CODE_FOR_gev2sf3, arglist, target);
13879
13880 case IX86_BUILTIN_PFCMPGT:
13881 return ix86_expand_binop_builtin (CODE_FOR_gtv2sf3, arglist, target);
13882
13883 case IX86_BUILTIN_PFMAX:
13884 return ix86_expand_binop_builtin (CODE_FOR_pfmaxv2sf3, arglist, target);
13885
13886 case IX86_BUILTIN_PFMIN:
13887 return ix86_expand_binop_builtin (CODE_FOR_pfminv2sf3, arglist, target);
13888
13889 case IX86_BUILTIN_PFMUL:
13890 return ix86_expand_binop_builtin (CODE_FOR_mulv2sf3, arglist, target);
13891
13892 case IX86_BUILTIN_PFRCP:
13893 return ix86_expand_unop_builtin (CODE_FOR_pfrcpv2sf2, arglist, target, 0);
13894
13895 case IX86_BUILTIN_PFRCPIT1:
13896 return ix86_expand_binop_builtin (CODE_FOR_pfrcpit1v2sf3, arglist, target);
13897
13898 case IX86_BUILTIN_PFRCPIT2:
13899 return ix86_expand_binop_builtin (CODE_FOR_pfrcpit2v2sf3, arglist, target);
13900
13901 case IX86_BUILTIN_PFRSQIT1:
13902 return ix86_expand_binop_builtin (CODE_FOR_pfrsqit1v2sf3, arglist, target);
13903
13904 case IX86_BUILTIN_PFRSQRT:
13905 return ix86_expand_unop_builtin (CODE_FOR_pfrsqrtv2sf2, arglist, target, 0);
13906
13907 case IX86_BUILTIN_PFSUB:
13908 return ix86_expand_binop_builtin (CODE_FOR_subv2sf3, arglist, target);
13909
13910 case IX86_BUILTIN_PFSUBR:
13911 return ix86_expand_binop_builtin (CODE_FOR_subrv2sf3, arglist, target);
13912
13913 case IX86_BUILTIN_PI2FD:
13914 return ix86_expand_unop_builtin (CODE_FOR_floatv2si2, arglist, target, 0);
13915
13916 case IX86_BUILTIN_PMULHRW:
13917 return ix86_expand_binop_builtin (CODE_FOR_pmulhrwv4hi3, arglist, target);
13918
13919 case IX86_BUILTIN_PF2IW:
13920 return ix86_expand_unop_builtin (CODE_FOR_pf2iw, arglist, target, 0);
13921
13922 case IX86_BUILTIN_PFNACC:
13923 return ix86_expand_binop_builtin (CODE_FOR_pfnacc, arglist, target);
13924
13925 case IX86_BUILTIN_PFPNACC:
13926 return ix86_expand_binop_builtin (CODE_FOR_pfpnacc, arglist, target);
13927
13928 case IX86_BUILTIN_PI2FW:
13929 return ix86_expand_unop_builtin (CODE_FOR_pi2fw, arglist, target, 0);
13930
13931 case IX86_BUILTIN_PSWAPDSI:
13932 return ix86_expand_unop_builtin (CODE_FOR_pswapdv2si2, arglist, target, 0);
13933
13934 case IX86_BUILTIN_PSWAPDSF:
13935 return ix86_expand_unop_builtin (CODE_FOR_pswapdv2sf2, arglist, target, 0);
13936
13937 case IX86_BUILTIN_SSE_ZERO:
13938 target = gen_reg_rtx (V4SFmode);
13939 emit_insn (gen_sse_clrv4sf (target));
13940 return target;
13941
13942 case IX86_BUILTIN_MMX_ZERO:
13943 target = gen_reg_rtx (DImode);
13944 emit_insn (gen_mmx_clrdi (target));
13945 return target;
13946
13947 case IX86_BUILTIN_CLRTI:
13948 target = gen_reg_rtx (V2DImode);
13949 emit_insn (gen_sse2_clrti (simplify_gen_subreg (TImode, target, V2DImode, 0)));
13950 return target;
13951
13952
13953 case IX86_BUILTIN_SQRTSD:
13954 return ix86_expand_unop1_builtin (CODE_FOR_vmsqrtv2df2, arglist, target);
13955 case IX86_BUILTIN_LOADAPD:
13956 return ix86_expand_unop_builtin (CODE_FOR_sse2_movapd, arglist, target, 1);
13957 case IX86_BUILTIN_LOADUPD:
13958 return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, arglist, target, 1);
13959
13960 case IX86_BUILTIN_STOREAPD:
13961 return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
13962 case IX86_BUILTIN_STOREUPD:
13963 return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, arglist);
13964
13965 case IX86_BUILTIN_LOADSD:
13966 return ix86_expand_unop_builtin (CODE_FOR_sse2_loadsd, arglist, target, 1);
13967
13968 case IX86_BUILTIN_STORESD:
13969 return ix86_expand_store_builtin (CODE_FOR_sse2_storesd, arglist);
13970
13971 case IX86_BUILTIN_SETPD1:
13972 target = assign_386_stack_local (DFmode, 0);
13973 arg0 = TREE_VALUE (arglist);
13974 emit_move_insn (adjust_address (target, DFmode, 0),
13975 expand_expr (arg0, NULL_RTX, VOIDmode, 0));
13976 op0 = gen_reg_rtx (V2DFmode);
13977 emit_insn (gen_sse2_loadsd (op0, adjust_address (target, V2DFmode, 0)));
13978 emit_insn (gen_sse2_shufpd (op0, op0, op0, GEN_INT (0)));
13979 return op0;
13980
13981 case IX86_BUILTIN_SETPD:
13982 target = assign_386_stack_local (V2DFmode, 0);
13983 arg0 = TREE_VALUE (arglist);
13984 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
13985 emit_move_insn (adjust_address (target, DFmode, 0),
13986 expand_expr (arg0, NULL_RTX, VOIDmode, 0));
13987 emit_move_insn (adjust_address (target, DFmode, 8),
13988 expand_expr (arg1, NULL_RTX, VOIDmode, 0));
13989 op0 = gen_reg_rtx (V2DFmode);
13990 emit_insn (gen_sse2_movapd (op0, target));
13991 return op0;
13992
13993 case IX86_BUILTIN_LOADRPD:
13994 target = ix86_expand_unop_builtin (CODE_FOR_sse2_movapd, arglist,
13995 gen_reg_rtx (V2DFmode), 1);
13996 emit_insn (gen_sse2_shufpd (target, target, target, GEN_INT (1)));
13997 return target;
13998
13999 case IX86_BUILTIN_LOADPD1:
14000 target = ix86_expand_unop_builtin (CODE_FOR_sse2_loadsd, arglist,
14001 gen_reg_rtx (V2DFmode), 1);
14002 emit_insn (gen_sse2_shufpd (target, target, target, const0_rtx));
14003 return target;
14004
14005 case IX86_BUILTIN_STOREPD1:
14006 return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
14007 case IX86_BUILTIN_STORERPD:
14008 return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
14009
14010 case IX86_BUILTIN_CLRPD:
14011 target = gen_reg_rtx (V2DFmode);
14012 emit_insn (gen_sse_clrv2df (target));
14013 return target;
14014
14015 case IX86_BUILTIN_MFENCE:
14016 emit_insn (gen_sse2_mfence ());
14017 return 0;
14018 case IX86_BUILTIN_LFENCE:
14019 emit_insn (gen_sse2_lfence ());
14020 return 0;
14021
14022 case IX86_BUILTIN_CLFLUSH:
14023 arg0 = TREE_VALUE (arglist);
14024 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
14025 icode = CODE_FOR_sse2_clflush;
14026 if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
14027 op0 = copy_to_mode_reg (Pmode, op0);
14028
14029 emit_insn (gen_sse2_clflush (op0));
14030 return 0;
14031
14032 case IX86_BUILTIN_MOVNTPD:
14033 return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, arglist);
14034 case IX86_BUILTIN_MOVNTDQ:
14035 return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, arglist);
14036 case IX86_BUILTIN_MOVNTI:
14037 return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist);
14038
14039 case IX86_BUILTIN_LOADDQA:
14040 return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqa, arglist, target, 1);
14041 case IX86_BUILTIN_LOADDQU:
14042 return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1);
14043 case IX86_BUILTIN_LOADD:
14044 return ix86_expand_unop_builtin (CODE_FOR_sse2_loadd, arglist, target, 1);
14045
14046 case IX86_BUILTIN_STOREDQA:
14047 return ix86_expand_store_builtin (CODE_FOR_sse2_movdqa, arglist);
14048 case IX86_BUILTIN_STOREDQU:
14049 return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist);
14050 case IX86_BUILTIN_STORED:
14051 return ix86_expand_store_builtin (CODE_FOR_sse2_stored, arglist);
14052
14053 case IX86_BUILTIN_MONITOR:
14054 arg0 = TREE_VALUE (arglist);
14055 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
14056 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
14057 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
14058 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
14059 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
14060 if (!REG_P (op0))
14061 op0 = copy_to_mode_reg (SImode, op0);
14062 if (!REG_P (op1))
14063 op1 = copy_to_mode_reg (SImode, op1);
14064 if (!REG_P (op2))
14065 op2 = copy_to_mode_reg (SImode, op2);
14066 emit_insn (gen_monitor (op0, op1, op2));
14067 return 0;
14068
14069 case IX86_BUILTIN_MWAIT:
14070 arg0 = TREE_VALUE (arglist);
14071 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
14072 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
14073 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
14074 if (!REG_P (op0))
14075 op0 = copy_to_mode_reg (SImode, op0);
14076 if (!REG_P (op1))
14077 op1 = copy_to_mode_reg (SImode, op1);
14078 emit_insn (gen_mwait (op0, op1));
14079 return 0;
14080
14081 case IX86_BUILTIN_LOADDDUP:
14082 return ix86_expand_unop_builtin (CODE_FOR_loadddup, arglist, target, 1);
14083
14084 case IX86_BUILTIN_LDDQU:
14085 return ix86_expand_unop_builtin (CODE_FOR_lddqu, arglist, target,
14086 1);
14087
14088 default:
14089 break;
14090 }
14091
14092 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
14093 if (d->code == fcode)
14094 {
14095
14096 if (d->icode == CODE_FOR_maskcmpv4sf3
14097 || d->icode == CODE_FOR_vmmaskcmpv4sf3
14098 || d->icode == CODE_FOR_maskncmpv4sf3
14099 || d->icode == CODE_FOR_vmmaskncmpv4sf3
14100 || d->icode == CODE_FOR_maskcmpv2df3
14101 || d->icode == CODE_FOR_vmmaskcmpv2df3
14102 || d->icode == CODE_FOR_maskncmpv2df3
14103 || d->icode == CODE_FOR_vmmaskncmpv2df3)
14104 return ix86_expand_sse_compare (d, arglist, target);
14105
14106 return ix86_expand_binop_builtin (d->icode, arglist, target);
14107 }
14108
14109 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
14110 if (d->code == fcode)
14111 return ix86_expand_unop_builtin (d->icode, arglist, target, 0);
14112
14113 for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
14114 if (d->code == fcode)
14115 return ix86_expand_sse_comi (d, arglist, target);
14116
14117
14118 return 0;
14119 }
14120
14121
14122
14123 rtx
14124 ix86_force_to_memory (mode, operand)
14125 enum machine_mode mode;
14126 rtx operand;
14127 {
14128 rtx result;
14129 if (!reload_completed)
14130 abort ();
14131 if (TARGET_64BIT && TARGET_RED_ZONE)
14132 {
14133 result = gen_rtx_MEM (mode,
14134 gen_rtx_PLUS (Pmode,
14135 stack_pointer_rtx,
14136 GEN_INT (-RED_ZONE_SIZE)));
14137 emit_move_insn (result, operand);
14138 }
14139 else if (TARGET_64BIT && !TARGET_RED_ZONE)
14140 {
14141 switch (mode)
14142 {
14143 case HImode:
14144 case SImode:
14145 operand = gen_lowpart (DImode, operand);
14146
14147 case DImode:
14148 emit_insn (
14149 gen_rtx_SET (VOIDmode,
14150 gen_rtx_MEM (DImode,
14151 gen_rtx_PRE_DEC (DImode,
14152 stack_pointer_rtx)),
14153 operand));
14154 break;
14155 default:
14156 abort ();
14157 }
14158 result = gen_rtx_MEM (mode, stack_pointer_rtx);
14159 }
14160 else
14161 {
14162 switch (mode)
14163 {
14164 case DImode:
14165 {
14166 rtx operands[2];
14167 split_di (&operand, 1, operands, operands + 1);
14168 emit_insn (
14169 gen_rtx_SET (VOIDmode,
14170 gen_rtx_MEM (SImode,
14171 gen_rtx_PRE_DEC (Pmode,
14172 stack_pointer_rtx)),
14173 operands[1]));
14174 emit_insn (
14175 gen_rtx_SET (VOIDmode,
14176 gen_rtx_MEM (SImode,
14177 gen_rtx_PRE_DEC (Pmode,
14178 stack_pointer_rtx)),
14179 operands[0]));
14180 }
14181 break;
14182 case HImode:
14183
14184 if (!TARGET_PARTIAL_REG_STALL)
14185 operand = gen_lowpart (SImode, operand);
14186
14187 case SImode:
14188 emit_insn (
14189 gen_rtx_SET (VOIDmode,
14190 gen_rtx_MEM (GET_MODE (operand),
14191 gen_rtx_PRE_DEC (SImode,
14192 stack_pointer_rtx)),
14193 operand));
14194 break;
14195 default:
14196 abort ();
14197 }
14198 result = gen_rtx_MEM (mode, stack_pointer_rtx);
14199 }
14200 return result;
14201 }
14202
14203
14204 void
14205 ix86_free_from_memory (mode)
14206 enum machine_mode mode;
14207 {
14208 if (!TARGET_64BIT || !TARGET_RED_ZONE)
14209 {
14210 int size;
14211
14212 if (mode == DImode || TARGET_64BIT)
14213 size = 8;
14214 else if (mode == HImode && TARGET_PARTIAL_REG_STALL)
14215 size = 2;
14216 else
14217 size = 4;
14218
14219
14220 emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
14221 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
14222 GEN_INT (size))));
14223 }
14224 }
14225
14226
14227
14228
14229
14230 enum reg_class
14231 ix86_preferred_reload_class (x, class)
14232 rtx x;
14233 enum reg_class class;
14234 {
14235 if (GET_CODE (x) == CONST_VECTOR && x != CONST0_RTX (GET_MODE (x)))
14236 return NO_REGS;
14237 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
14238 {
14239
14240 if (SSE_CLASS_P (class))
14241 return NO_REGS;
14242
14243 if (MAYBE_FLOAT_CLASS_P (class) && standard_80387_constant_p (x))
14244 {
14245
14246 if (MAYBE_SSE_CLASS_P (class))
14247 return (reg_class_subset_p (class, GENERAL_REGS)
14248 ? GENERAL_REGS : FLOAT_REGS);
14249 else
14250 return class;
14251 }
14252
14253 if (reg_class_subset_p (class, GENERAL_REGS))
14254 return GENERAL_REGS;
14255
14256 if (MAYBE_FLOAT_CLASS_P (class) || MAYBE_SSE_CLASS_P (class))
14257 return NO_REGS;
14258 }
14259 if (MAYBE_MMX_CLASS_P (class) && CONSTANT_P (x))
14260 return NO_REGS;
14261 if (GET_MODE (x) == QImode && ! reg_class_subset_p (class, Q_REGS))
14262 return Q_REGS;
14263 return class;
14264 }
14265
14266
14267
14268
14269
14270
14271
14272
14273
14274
14275
14276 int
14277 ix86_secondary_memory_needed (class1, class2, mode, strict)
14278 enum reg_class class1, class2;
14279 enum machine_mode mode;
14280 int strict;
14281 {
14282 if (MAYBE_FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class1)
14283 || MAYBE_FLOAT_CLASS_P (class2) != FLOAT_CLASS_P (class2)
14284 || MAYBE_SSE_CLASS_P (class1) != SSE_CLASS_P (class1)
14285 || MAYBE_SSE_CLASS_P (class2) != SSE_CLASS_P (class2)
14286 || MAYBE_MMX_CLASS_P (class1) != MMX_CLASS_P (class1)
14287 || MAYBE_MMX_CLASS_P (class2) != MMX_CLASS_P (class2))
14288 {
14289 if (strict)
14290 abort ();
14291 else
14292 return 1;
14293 }
14294 return (FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class2)
14295 || (SSE_CLASS_P (class1) != SSE_CLASS_P (class2)
14296 && (mode) != SImode)
14297 || (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
14298 && (mode) != SImode));
14299 }
14300
14301
14302
14303
14304
14305
14306 int
14307 ix86_register_move_cost (mode, class1, class2)
14308 enum machine_mode mode;
14309 enum reg_class class1, class2;
14310 {
14311
14312
14313
14314
14315 if (ix86_secondary_memory_needed (class1, class2, mode, 0))
14316 {
14317 int cost = 1;
14318
14319 cost += MAX (MEMORY_MOVE_COST (mode, class1, 0),
14320 MEMORY_MOVE_COST (mode, class1, 1));
14321 cost += MAX (MEMORY_MOVE_COST (mode, class2, 0),
14322 MEMORY_MOVE_COST (mode, class2, 1));
14323
14324
14325
14326
14327 if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode))
14328 cost += 20;
14329
14330
14331
14332 if ((MMX_CLASS_P (class1) && MAYBE_FLOAT_CLASS_P (class2))
14333 || (MMX_CLASS_P (class2) && MAYBE_FLOAT_CLASS_P (class1)))
14334 cost += 20;
14335
14336 return cost;
14337 }
14338
14339
14340 if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
14341 || SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
14342 return ix86_cost->mmxsse_to_integer;
14343 if (MAYBE_FLOAT_CLASS_P (class1))
14344 return ix86_cost->fp_move;
14345 if (MAYBE_SSE_CLASS_P (class1))
14346 return ix86_cost->sse_move;
14347 if (MAYBE_MMX_CLASS_P (class1))
14348 return ix86_cost->mmx_move;
14349 return 2;
14350 }
14351
14352
14353 int
14354 ix86_hard_regno_mode_ok (regno, mode)
14355 int regno;
14356 enum machine_mode mode;
14357 {
14358
14359 if (CC_REGNO_P (regno))
14360 return GET_MODE_CLASS (mode) == MODE_CC;
14361 if (GET_MODE_CLASS (mode) == MODE_CC
14362 || GET_MODE_CLASS (mode) == MODE_RANDOM
14363 || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
14364 return 0;
14365 if (FP_REGNO_P (regno))
14366 return VALID_FP_MODE_P (mode);
14367 if (SSE_REGNO_P (regno))
14368 return (TARGET_SSE ? VALID_SSE_REG_MODE (mode) : 0);
14369 if (MMX_REGNO_P (regno))
14370 return (TARGET_MMX
14371 ? VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode) : 0);
14372
14373
14374 if (!VALID_INT_MODE_P (mode) && !VALID_FP_MODE_P (mode))
14375 return 0;
14376
14377
14378 if (regno < 4 || mode != QImode || TARGET_64BIT)
14379 return 1;
14380 return reload_in_progress || reload_completed || !TARGET_PARTIAL_REG_STALL;
14381 }
14382
14383
14384
14385
14386
14387
14388
14389
14390
14391
14392
14393
14394 int
14395 ix86_memory_move_cost (mode, class, in)
14396 enum machine_mode mode;
14397 enum reg_class class;
14398 int in;
14399 {
14400 if (FLOAT_CLASS_P (class))
14401 {
14402 int index;
14403 switch (mode)
14404 {
14405 case SFmode:
14406 index = 0;
14407 break;
14408 case DFmode:
14409 index = 1;
14410 break;
14411 case XFmode:
14412 case TFmode:
14413 index = 2;
14414 break;
14415 default:
14416 return 100;
14417 }
14418 return in ? ix86_cost->fp_load [index] : ix86_cost->fp_store [index];
14419 }
14420 if (SSE_CLASS_P (class))
14421 {
14422 int index;
14423 switch (GET_MODE_SIZE (mode))
14424 {
14425 case 4:
14426 index = 0;
14427 break;
14428 case 8:
14429 index = 1;
14430 break;
14431 case 16:
14432 index = 2;
14433 break;
14434 default:
14435 return 100;
14436 }
14437 return in ? ix86_cost->sse_load [index] : ix86_cost->sse_store [index];
14438 }
14439 if (MMX_CLASS_P (class))
14440 {
14441 int index;
14442 switch (GET_MODE_SIZE (mode))
14443 {
14444 case 4:
14445 index = 0;
14446 break;
14447 case 8:
14448 index = 1;
14449 break;
14450 default:
14451 return 100;
14452 }
14453 return in ? ix86_cost->mmx_load [index] : ix86_cost->mmx_store [index];
14454 }
14455 switch (GET_MODE_SIZE (mode))
14456 {
14457 case 1:
14458 if (in)
14459 return (Q_CLASS_P (class) ? ix86_cost->int_load[0]
14460 : ix86_cost->movzbl_load);
14461 else
14462 return (Q_CLASS_P (class) ? ix86_cost->int_store[0]
14463 : ix86_cost->int_store[0] + 4);
14464 break;
14465 case 2:
14466 return in ? ix86_cost->int_load[1] : ix86_cost->int_store[1];
14467 default:
14468
14469 if (mode == TFmode)
14470 mode = XFmode;
14471 return ((in ? ix86_cost->int_load[2] : ix86_cost->int_store[2])
14472 * ((int) GET_MODE_SIZE (mode)
14473 + UNITS_PER_WORD -1 ) / UNITS_PER_WORD);
14474 }
14475 }
14476
14477 #if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
14478 static void
14479 ix86_svr3_asm_out_constructor (symbol, priority)
14480 rtx symbol;
14481 int priority ATTRIBUTE_UNUSED;
14482 {
14483 init_section ();
14484 fputs ("\tpushl $", asm_out_file);
14485 assemble_name (asm_out_file, XSTR (symbol, 0));
14486 fputc ('\n', asm_out_file);
14487 }
14488 #endif
14489
14490 #if TARGET_MACHO
14491
14492 static int current_machopic_label_num;
14493
14494
14495
14496
14497 void
14498 machopic_output_stub (file, symb, stub)
14499 FILE *file;
14500 const char *symb, *stub;
14501 {
14502 unsigned int length;
14503 char *binder_name, *symbol_name, lazy_ptr_name[32];
14504 int label = ++current_machopic_label_num;
14505
14506
14507 symb = (*targetm.strip_name_encoding) (symb);
14508
14509 length = strlen (stub);
14510 binder_name = alloca (length + 32);
14511 GEN_BINDER_NAME_FOR_STUB (binder_name, stub, length);
14512
14513 length = strlen (symb);
14514 symbol_name = alloca (length + 32);
14515 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
14516
14517 sprintf (lazy_ptr_name, "L%d$lz", label);
14518
14519 if (MACHOPIC_PURE)
14520 machopic_picsymbol_stub_section ();
14521 else
14522 machopic_symbol_stub_section ();
14523
14524 fprintf (file, "%s:\n", stub);
14525 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
14526
14527 if (MACHOPIC_PURE)
14528 {
14529 fprintf (file, "\tcall LPC$%d\nLPC$%d:\tpopl %%eax\n", label, label);
14530 fprintf (file, "\tmovl %s-LPC$%d(%%eax),%%edx\n", lazy_ptr_name, label);
14531 fprintf (file, "\tjmp %%edx\n");
14532 }
14533 else
14534 fprintf (file, "\tjmp *%s\n", lazy_ptr_name);
14535
14536 fprintf (file, "%s:\n", binder_name);
14537
14538 if (MACHOPIC_PURE)
14539 {
14540 fprintf (file, "\tlea %s-LPC$%d(%%eax),%%eax\n", lazy_ptr_name, label);
14541 fprintf (file, "\tpushl %%eax\n");
14542 }
14543 else
14544 fprintf (file, "\t pushl $%s\n", lazy_ptr_name);
14545
14546 fprintf (file, "\tjmp dyld_stub_binding_helper\n");
14547
14548 machopic_lazy_symbol_ptr_section ();
14549 fprintf (file, "%s:\n", lazy_ptr_name);
14550 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
14551 fprintf (file, "\t.long %s\n", binder_name);
14552 }
14553 #endif
14554
14555
14556
14557 void
14558 x86_order_regs_for_local_alloc ()
14559 {
14560 int pos = 0;
14561 int i;
14562
14563
14564 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
14565 if (GENERAL_REGNO_P (i) && call_used_regs[i])
14566 reg_alloc_order [pos++] = i;
14567
14568
14569 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
14570 if (GENERAL_REGNO_P (i) && !call_used_regs[i])
14571 reg_alloc_order [pos++] = i;
14572
14573
14574
14575 if (!TARGET_SSE_MATH)
14576 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
14577 reg_alloc_order [pos++] = i;
14578
14579
14580 for (i = FIRST_SSE_REG; i <= LAST_SSE_REG; i++)
14581 reg_alloc_order [pos++] = i;
14582 for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)
14583 reg_alloc_order [pos++] = i;
14584
14585
14586 if (TARGET_SSE_MATH)
14587 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
14588 reg_alloc_order [pos++] = i;
14589
14590 for (i = FIRST_MMX_REG; i <= LAST_MMX_REG; i++)
14591 reg_alloc_order [pos++] = i;
14592
14593
14594
14595 while (pos < FIRST_PSEUDO_REGISTER)
14596 reg_alloc_order [pos++] = 0;
14597 }
14598
14599
14600
14601
14602 static rtx
14603 x86_this_parameter (function)
14604 tree function;
14605 {
14606 tree type = TREE_TYPE (function);
14607
14608 if (TARGET_64BIT)
14609 {
14610 int n = aggregate_value_p (TREE_TYPE (type)) != 0;
14611 return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
14612 }
14613
14614 if (ix86_fntype_regparm (type) > 0)
14615 {
14616 tree parm;
14617
14618 parm = TYPE_ARG_TYPES (type);
14619
14620
14621 for (; parm; parm = TREE_CHAIN (parm))
14622 if (TREE_VALUE (parm) == void_type_node)
14623 break;
14624
14625 if (parm)
14626 return gen_rtx_REG (SImode, 0);
14627 }
14628
14629 if (aggregate_value_p (TREE_TYPE (type)))
14630 return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
14631 else
14632 return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
14633 }
14634
14635
14636
14637 static bool
14638 x86_can_output_mi_thunk (thunk, delta, vcall_offset, function)
14639 tree thunk ATTRIBUTE_UNUSED;
14640 HOST_WIDE_INT delta ATTRIBUTE_UNUSED;
14641 HOST_WIDE_INT vcall_offset;
14642 tree function;
14643 {
14644
14645 if (TARGET_64BIT)
14646 return true;
14647
14648
14649 if (ix86_fntype_regparm (TREE_TYPE (function)) < 3)
14650 return true;
14651
14652
14653 if (vcall_offset)
14654 return false;
14655
14656
14657 if (flag_pic && !(*targetm.binds_local_p) (function))
14658 return false;
14659
14660
14661 return true;
14662 }
14663
14664
14665
14666
14667
14668
14669
14670 static void
14671 x86_output_mi_thunk (file, thunk, delta, vcall_offset, function)
14672 FILE *file ATTRIBUTE_UNUSED;
14673 tree thunk ATTRIBUTE_UNUSED;
14674 HOST_WIDE_INT delta;
14675 HOST_WIDE_INT vcall_offset;
14676 tree function;
14677 {
14678 rtx xops[3];
14679 rtx this = x86_this_parameter (function);
14680 rtx this_reg, tmp;
14681
14682
14683
14684 if (REG_P (this))
14685 this_reg = this;
14686 else if (vcall_offset)
14687 {
14688
14689 xops[0] = this;
14690 xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
14691 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
14692 }
14693 else
14694 this_reg = NULL_RTX;
14695
14696
14697 if (delta)
14698 {
14699 xops[0] = GEN_INT (delta);
14700 xops[1] = this_reg ? this_reg : this;
14701 if (TARGET_64BIT)
14702 {
14703 if (!x86_64_general_operand (xops[0], DImode))
14704 {
14705 tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 );
14706 xops[1] = tmp;
14707 output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
14708 xops[0] = tmp;
14709 xops[1] = this;
14710 }
14711 output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
14712 }
14713 else
14714 output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
14715 }
14716
14717
14718 if (vcall_offset)
14719 {
14720 if (TARGET_64BIT)
14721 tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 );
14722 else
14723 tmp = gen_rtx_REG (SImode, 2 );
14724
14725 xops[0] = gen_rtx_MEM (Pmode, this_reg);
14726 xops[1] = tmp;
14727 if (TARGET_64BIT)
14728 output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
14729 else
14730 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
14731
14732
14733 xops[0] = gen_rtx_MEM (Pmode, plus_constant (tmp, vcall_offset));
14734 if (TARGET_64BIT && !memory_operand (xops[0], Pmode))
14735 {
14736 rtx tmp2 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 );
14737 xops[0] = GEN_INT (vcall_offset);
14738 xops[1] = tmp2;
14739 output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
14740 xops[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tmp, tmp2));
14741 }
14742 xops[1] = this_reg;
14743 if (TARGET_64BIT)
14744 output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
14745 else
14746 output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
14747 }
14748
14749
14750 if (this_reg && this_reg != this)
14751 {
14752 xops[0] = this_reg;
14753 xops[1] = this;
14754 output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
14755 }
14756
14757 xops[0] = XEXP (DECL_RTL (function), 0);
14758 if (TARGET_64BIT)
14759 {
14760 if (!flag_pic || (*targetm.binds_local_p) (function))
14761 output_asm_insn ("jmp\t%P0", xops);
14762 else
14763 {
14764 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xops[0]), UNSPEC_GOTPCREL);
14765 tmp = gen_rtx_CONST (Pmode, tmp);
14766 tmp = gen_rtx_MEM (QImode, tmp);
14767 xops[0] = tmp;
14768 output_asm_insn ("jmp\t%A0", xops);
14769 }
14770 }
14771 else
14772 {
14773 if (!flag_pic || (*targetm.binds_local_p) (function))
14774 output_asm_insn ("jmp\t%P0", xops);
14775 else
14776 {
14777 tmp = gen_rtx_REG (SImode, 2 );
14778 output_set_got (tmp);
14779
14780 xops[1] = tmp;
14781 output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops);
14782 output_asm_insn ("jmp\t{*}%1", xops);
14783 }
14784 }
14785 }
14786
14787 int
14788 x86_field_alignment (field, computed)
14789 tree field;
14790 int computed;
14791 {
14792 enum machine_mode mode;
14793 tree type = TREE_TYPE (field);
14794
14795 if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
14796 return computed;
14797 mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE
14798 ? get_inner_array_type (type) : type);
14799 if (mode == DFmode || mode == DCmode
14800 || GET_MODE_CLASS (mode) == MODE_INT
14801 || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
14802 return MIN (32, computed);
14803 return computed;
14804 }
14805
14806
14807
14808 void
14809 x86_function_profiler (file, labelno)
14810 FILE *file;
14811 int labelno ATTRIBUTE_UNUSED;
14812 {
14813 if (TARGET_64BIT)
14814 if (flag_pic)
14815 {
14816 #ifndef NO_PROFILE_COUNTERS
14817 fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
14818 #endif
14819 fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME);
14820 }
14821 else
14822 {
14823 #ifndef NO_PROFILE_COUNTERS
14824 fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno);
14825 #endif
14826 fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
14827 }
14828 else if (flag_pic)
14829 {
14830 #ifndef NO_PROFILE_COUNTERS
14831 fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%%s\n",
14832 LPREFIX, labelno, PROFILE_COUNT_REGISTER);
14833 #endif
14834 fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", MCOUNT_NAME);
14835 }
14836 else
14837 {
14838 #ifndef NO_PROFILE_COUNTERS
14839 fprintf (file, "\tmovl\t$%sP%d,%%%s\n", LPREFIX, labelno,
14840 PROFILE_COUNT_REGISTER);
14841 #endif
14842 fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
14843 }
14844 }
14845
14846
14847
14848
14849
14850
14851 void
14852 x86_machine_dependent_reorg (first)
14853 rtx first ATTRIBUTE_UNUSED;
14854 {
14855 edge e;
14856
14857 if (!TARGET_ATHLON || !optimize || optimize_size)
14858 return;
14859 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
14860 {
14861 basic_block bb = e->src;
14862 rtx ret = bb->end;
14863 rtx prev;
14864 bool insert = false;
14865
14866 if (!returnjump_p (ret) || !maybe_hot_bb_p (bb))
14867 continue;
14868 prev = prev_nonnote_insn (ret);
14869 if (prev && GET_CODE (prev) == CODE_LABEL)
14870 {
14871 edge e;
14872 for (e = bb->pred; e; e = e->pred_next)
14873 if (EDGE_FREQUENCY (e) && e->src->index > 0
14874 && !(e->flags & EDGE_FALLTHRU))
14875 insert = 1;
14876 }
14877 if (!insert)
14878 {
14879 prev = prev_real_insn (ret);
14880 if (prev && GET_CODE (prev) == JUMP_INSN
14881 && any_condjump_p (prev))
14882 insert = 1;
14883 }
14884 if (insert)
14885 emit_insn_before (gen_nop (), ret);
14886 }
14887 }
14888
14889 #include "gt-i386.h"