00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "obstack.h"
00038 #include "tree.h"
00039 #include "expr.h"
00040 #include "optabs.h"
00041 #include "except.h"
00042 #include "function.h"
00043 #include "output.h"
00044 #include "basic-block.h"
00045 #include "integrate.h"
00046 #include "toplev.h"
00047 #include "ggc.h"
00048 #include "hashtab.h"
00049 #include "tm_p.h"
00050 #include "target.h"
00051 #include "target-def.h"
00052 #include "langhooks.h"
00053 #include "reload.h"
00054 #include "cfglayout.h"
00055 #include "sched-int.h"
00056 #include "tree-gimple.h"
00057 #include "intl.h"
00058 #include "params.h"
00059 #include "tm-constrs.h"
00060 #if TARGET_XCOFF
00061 #include "xcoffout.h"
00062 #endif
00063 #if TARGET_MACHO
00064 #include "gstab.h"
00065 #endif
00066
00067 #ifndef TARGET_NO_PROTOTYPE
00068 #define TARGET_NO_PROTOTYPE 0
00069 #endif
00070
00071 #define min(A,B) ((A) < (B) ? (A) : (B))
00072 #define max(A,B) ((A) > (B) ? (A) : (B))
00073
00074
00075 typedef struct rs6000_stack {
00076 int first_gp_reg_save;
00077 int first_fp_reg_save;
00078 int first_altivec_reg_save;
00079 int lr_save_p;
00080 int cr_save_p;
00081 unsigned int vrsave_mask;
00082 int push_p;
00083 int calls_p;
00084 int world_save_p;
00085
00086 enum rs6000_abi abi;
00087 int gp_save_offset;
00088 int fp_save_offset;
00089 int altivec_save_offset;
00090 int lr_save_offset;
00091 int cr_save_offset;
00092 int vrsave_save_offset;
00093 int spe_gp_save_offset;
00094 int varargs_save_offset;
00095 int ehrd_offset;
00096 int reg_size;
00097 HOST_WIDE_INT vars_size;
00098 int parm_size;
00099 int save_size;
00100 int fixed_size;
00101 int gp_size;
00102 int fp_size;
00103 int altivec_size;
00104 int cr_size;
00105 int vrsave_size;
00106 int altivec_padding_size;
00107
00108 int spe_gp_size;
00109 int spe_padding_size;
00110 HOST_WIDE_INT total_size;
00111 int spe_64bit_regs_used;
00112 } rs6000_stack_t;
00113
00114
00115
00116 typedef struct machine_function GTY(())
00117 {
00118
00119 int ra_needs_full_frame;
00120
00121 const char *some_ld_name;
00122
00123 int insn_chain_scanned_p;
00124
00125 int ra_need_lr;
00126
00127
00128 HOST_WIDE_INT varargs_save_offset;
00129 } machine_function;
00130
00131
00132
00133 enum processor_type rs6000_cpu;
00134 struct rs6000_cpu_select rs6000_select[3] =
00135 {
00136
00137 { (const char *)0, "--with-cpu=", 1, 1 },
00138 { (const char *)0, "-mcpu=", 1, 1 },
00139 { (const char *)0, "-mtune=", 1, 0 },
00140 };
00141
00142
00143 static GTY(()) bool rs6000_always_hint;
00144
00145
00146 static GTY(()) bool rs6000_sched_groups;
00147
00148
00149 const char *rs6000_sched_costly_dep_str;
00150 enum rs6000_dependence_cost rs6000_sched_costly_dep;
00151
00152
00153 const char *rs6000_sched_insert_nops_str;
00154 enum rs6000_nop_insertion rs6000_sched_insert_nops;
00155
00156
00157 static GTY(()) tree altivec_builtin_mask_for_load;
00158
00159
00160 int rs6000_long_double_type_size;
00161
00162
00163 int rs6000_ieeequad;
00164
00165
00166 int rs6000_altivec_abi;
00167
00168
00169 int rs6000_spe_abi;
00170
00171
00172 int rs6000_float_gprs = 0;
00173
00174
00175 int rs6000_darwin64_abi;
00176
00177
00178 static GTY(()) int common_mode_defined;
00179
00180
00181
00182 rtx rs6000_compare_op0, rs6000_compare_op1;
00183 int rs6000_compare_fp_p;
00184
00185
00186
00187 int rs6000_pic_labelno;
00188
00189 #ifdef USING_ELFOS_H
00190
00191 const char *rs6000_abi_name;
00192
00193
00194 enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
00195
00196
00197 const char *rs6000_sdata_name = (char *)0;
00198
00199
00200 int fixuplabelno = 0;
00201 #endif
00202
00203
00204 int rs6000_tls_size = 32;
00205 const char *rs6000_tls_size_string;
00206
00207
00208 enum rs6000_abi rs6000_current_abi;
00209
00210
00211 int dot_symbols;
00212
00213
00214 const char *rs6000_debug_name;
00215 int rs6000_debug_stack;
00216 int rs6000_debug_arg;
00217
00218
00219 bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
00220
00221
00222
00223 tree rs6000_builtin_types[RS6000_BTI_MAX];
00224 tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
00225
00226 const char *rs6000_traceback_name;
00227 static enum {
00228 traceback_default = 0,
00229 traceback_none,
00230 traceback_part,
00231 traceback_full
00232 } rs6000_traceback;
00233
00234
00235 int toc_initialized;
00236 char toc_label_name[10];
00237
00238 static GTY(()) section *read_only_data_section;
00239 static GTY(()) section *private_data_section;
00240 static GTY(()) section *read_only_private_data_section;
00241 static GTY(()) section *sdata2_section;
00242 static GTY(()) section *toc_section;
00243
00244
00245
00246 int rs6000_alignment_flags;
00247
00248
00249 struct {
00250 bool aix_struct_ret;
00251 bool alignment;
00252 bool abi;
00253 bool spe;
00254 bool float_gprs;
00255 bool isel;
00256 bool long_double;
00257 bool ieee;
00258 } rs6000_explicit_options;
00259
00260 struct builtin_description
00261 {
00262
00263
00264
00265 unsigned int mask;
00266 const enum insn_code icode;
00267 const char *const name;
00268 const enum rs6000_builtins code;
00269 };
00270
00271
00272
00273 struct processor_costs {
00274 const int mulsi;
00275 const int mulsi_const;
00276 const int mulsi_const9;
00277 const int muldi;
00278 const int divsi;
00279 const int divdi;
00280 const int fp;
00281 const int dmul;
00282 const int sdiv;
00283 const int ddiv;
00284 };
00285
00286 const struct processor_costs *rs6000_cost;
00287
00288
00289
00290
00291 static const
00292 struct processor_costs size32_cost = {
00293 COSTS_N_INSNS (1),
00294 COSTS_N_INSNS (1),
00295 COSTS_N_INSNS (1),
00296 COSTS_N_INSNS (1),
00297 COSTS_N_INSNS (1),
00298 COSTS_N_INSNS (1),
00299 COSTS_N_INSNS (1),
00300 COSTS_N_INSNS (1),
00301 COSTS_N_INSNS (1),
00302 COSTS_N_INSNS (1),
00303 };
00304
00305
00306 static const
00307 struct processor_costs size64_cost = {
00308 COSTS_N_INSNS (1),
00309 COSTS_N_INSNS (1),
00310 COSTS_N_INSNS (1),
00311 COSTS_N_INSNS (1),
00312 COSTS_N_INSNS (1),
00313 COSTS_N_INSNS (1),
00314 COSTS_N_INSNS (1),
00315 COSTS_N_INSNS (1),
00316 COSTS_N_INSNS (1),
00317 COSTS_N_INSNS (1),
00318 };
00319
00320
00321 static const
00322 struct processor_costs rios1_cost = {
00323 COSTS_N_INSNS (5),
00324 COSTS_N_INSNS (4),
00325 COSTS_N_INSNS (3),
00326 COSTS_N_INSNS (5),
00327 COSTS_N_INSNS (19),
00328 COSTS_N_INSNS (19),
00329 COSTS_N_INSNS (2),
00330 COSTS_N_INSNS (2),
00331 COSTS_N_INSNS (19),
00332 COSTS_N_INSNS (19),
00333 };
00334
00335
00336 static const
00337 struct processor_costs rios2_cost = {
00338 COSTS_N_INSNS (2),
00339 COSTS_N_INSNS (2),
00340 COSTS_N_INSNS (2),
00341 COSTS_N_INSNS (2),
00342 COSTS_N_INSNS (13),
00343 COSTS_N_INSNS (13),
00344 COSTS_N_INSNS (2),
00345 COSTS_N_INSNS (2),
00346 COSTS_N_INSNS (17),
00347 COSTS_N_INSNS (17),
00348 };
00349
00350
00351 static const
00352 struct processor_costs rs64a_cost = {
00353 COSTS_N_INSNS (20),
00354 COSTS_N_INSNS (12),
00355 COSTS_N_INSNS (8),
00356 COSTS_N_INSNS (34),
00357 COSTS_N_INSNS (65),
00358 COSTS_N_INSNS (67),
00359 COSTS_N_INSNS (4),
00360 COSTS_N_INSNS (4),
00361 COSTS_N_INSNS (31),
00362 COSTS_N_INSNS (31),
00363 };
00364
00365
00366 static const
00367 struct processor_costs mpccore_cost = {
00368 COSTS_N_INSNS (2),
00369 COSTS_N_INSNS (2),
00370 COSTS_N_INSNS (2),
00371 COSTS_N_INSNS (2),
00372 COSTS_N_INSNS (6),
00373 COSTS_N_INSNS (6),
00374 COSTS_N_INSNS (4),
00375 COSTS_N_INSNS (5),
00376 COSTS_N_INSNS (10),
00377 COSTS_N_INSNS (17),
00378 };
00379
00380
00381 static const
00382 struct processor_costs ppc403_cost = {
00383 COSTS_N_INSNS (4),
00384 COSTS_N_INSNS (4),
00385 COSTS_N_INSNS (4),
00386 COSTS_N_INSNS (4),
00387 COSTS_N_INSNS (33),
00388 COSTS_N_INSNS (33),
00389 COSTS_N_INSNS (11),
00390 COSTS_N_INSNS (11),
00391 COSTS_N_INSNS (11),
00392 COSTS_N_INSNS (11),
00393 };
00394
00395
00396 static const
00397 struct processor_costs ppc405_cost = {
00398 COSTS_N_INSNS (5),
00399 COSTS_N_INSNS (4),
00400 COSTS_N_INSNS (3),
00401 COSTS_N_INSNS (5),
00402 COSTS_N_INSNS (35),
00403 COSTS_N_INSNS (35),
00404 COSTS_N_INSNS (11),
00405 COSTS_N_INSNS (11),
00406 COSTS_N_INSNS (11),
00407 COSTS_N_INSNS (11),
00408 };
00409
00410
00411 static const
00412 struct processor_costs ppc440_cost = {
00413 COSTS_N_INSNS (3),
00414 COSTS_N_INSNS (2),
00415 COSTS_N_INSNS (2),
00416 COSTS_N_INSNS (3),
00417 COSTS_N_INSNS (34),
00418 COSTS_N_INSNS (34),
00419 COSTS_N_INSNS (5),
00420 COSTS_N_INSNS (5),
00421 COSTS_N_INSNS (19),
00422 COSTS_N_INSNS (33),
00423 };
00424
00425
00426 static const
00427 struct processor_costs ppc601_cost = {
00428 COSTS_N_INSNS (5),
00429 COSTS_N_INSNS (5),
00430 COSTS_N_INSNS (5),
00431 COSTS_N_INSNS (5),
00432 COSTS_N_INSNS (36),
00433 COSTS_N_INSNS (36),
00434 COSTS_N_INSNS (4),
00435 COSTS_N_INSNS (5),
00436 COSTS_N_INSNS (17),
00437 COSTS_N_INSNS (31),
00438 };
00439
00440
00441 static const
00442 struct processor_costs ppc603_cost = {
00443 COSTS_N_INSNS (5),
00444 COSTS_N_INSNS (3),
00445 COSTS_N_INSNS (2),
00446 COSTS_N_INSNS (5),
00447 COSTS_N_INSNS (37),
00448 COSTS_N_INSNS (37),
00449 COSTS_N_INSNS (3),
00450 COSTS_N_INSNS (4),
00451 COSTS_N_INSNS (18),
00452 COSTS_N_INSNS (33),
00453 };
00454
00455
00456 static const
00457 struct processor_costs ppc604_cost = {
00458 COSTS_N_INSNS (4),
00459 COSTS_N_INSNS (4),
00460 COSTS_N_INSNS (4),
00461 COSTS_N_INSNS (4),
00462 COSTS_N_INSNS (20),
00463 COSTS_N_INSNS (20),
00464 COSTS_N_INSNS (3),
00465 COSTS_N_INSNS (3),
00466 COSTS_N_INSNS (18),
00467 COSTS_N_INSNS (32),
00468 };
00469
00470
00471 static const
00472 struct processor_costs ppc604e_cost = {
00473 COSTS_N_INSNS (2),
00474 COSTS_N_INSNS (2),
00475 COSTS_N_INSNS (2),
00476 COSTS_N_INSNS (2),
00477 COSTS_N_INSNS (20),
00478 COSTS_N_INSNS (20),
00479 COSTS_N_INSNS (3),
00480 COSTS_N_INSNS (3),
00481 COSTS_N_INSNS (18),
00482 COSTS_N_INSNS (32),
00483 };
00484
00485
00486 static const
00487 struct processor_costs ppc620_cost = {
00488 COSTS_N_INSNS (5),
00489 COSTS_N_INSNS (4),
00490 COSTS_N_INSNS (3),
00491 COSTS_N_INSNS (7),
00492 COSTS_N_INSNS (21),
00493 COSTS_N_INSNS (37),
00494 COSTS_N_INSNS (3),
00495 COSTS_N_INSNS (3),
00496 COSTS_N_INSNS (18),
00497 COSTS_N_INSNS (32),
00498 };
00499
00500
00501 static const
00502 struct processor_costs ppc630_cost = {
00503 COSTS_N_INSNS (5),
00504 COSTS_N_INSNS (4),
00505 COSTS_N_INSNS (3),
00506 COSTS_N_INSNS (7),
00507 COSTS_N_INSNS (21),
00508 COSTS_N_INSNS (37),
00509 COSTS_N_INSNS (3),
00510 COSTS_N_INSNS (3),
00511 COSTS_N_INSNS (17),
00512 COSTS_N_INSNS (21),
00513 };
00514
00515
00516 static const
00517 struct processor_costs ppc750_cost = {
00518 COSTS_N_INSNS (5),
00519 COSTS_N_INSNS (3),
00520 COSTS_N_INSNS (2),
00521 COSTS_N_INSNS (5),
00522 COSTS_N_INSNS (17),
00523 COSTS_N_INSNS (17),
00524 COSTS_N_INSNS (3),
00525 COSTS_N_INSNS (3),
00526 COSTS_N_INSNS (17),
00527 COSTS_N_INSNS (31),
00528 };
00529
00530
00531 static const
00532 struct processor_costs ppc7450_cost = {
00533 COSTS_N_INSNS (4),
00534 COSTS_N_INSNS (3),
00535 COSTS_N_INSNS (3),
00536 COSTS_N_INSNS (4),
00537 COSTS_N_INSNS (23),
00538 COSTS_N_INSNS (23),
00539 COSTS_N_INSNS (5),
00540 COSTS_N_INSNS (5),
00541 COSTS_N_INSNS (21),
00542 COSTS_N_INSNS (35),
00543 };
00544
00545
00546 static const
00547 struct processor_costs ppc8540_cost = {
00548 COSTS_N_INSNS (4),
00549 COSTS_N_INSNS (4),
00550 COSTS_N_INSNS (4),
00551 COSTS_N_INSNS (4),
00552 COSTS_N_INSNS (19),
00553 COSTS_N_INSNS (19),
00554 COSTS_N_INSNS (4),
00555 COSTS_N_INSNS (4),
00556 COSTS_N_INSNS (29),
00557 COSTS_N_INSNS (29),
00558 };
00559
00560
00561 static const
00562 struct processor_costs power4_cost = {
00563 COSTS_N_INSNS (3),
00564 COSTS_N_INSNS (2),
00565 COSTS_N_INSNS (2),
00566 COSTS_N_INSNS (4),
00567 COSTS_N_INSNS (18),
00568 COSTS_N_INSNS (34),
00569 COSTS_N_INSNS (3),
00570 COSTS_N_INSNS (3),
00571 COSTS_N_INSNS (17),
00572 COSTS_N_INSNS (17),
00573 };
00574
00575
00576 static bool rs6000_function_ok_for_sibcall (tree, tree);
00577 static const char *rs6000_invalid_within_doloop (rtx);
00578 static rtx rs6000_generate_compare (enum rtx_code);
00579 static void rs6000_maybe_dead (rtx);
00580 static void rs6000_emit_stack_tie (void);
00581 static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx);
00582 static rtx spe_synthesize_frame_save (rtx);
00583 static bool spe_func_has_64bit_regs_p (void);
00584 static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int,
00585 int, HOST_WIDE_INT);
00586 static rtx gen_frame_mem_offset (enum machine_mode, rtx, int);
00587 static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int);
00588 static unsigned rs6000_hash_constant (rtx);
00589 static unsigned toc_hash_function (const void *);
00590 static int toc_hash_eq (const void *, const void *);
00591 static int constant_pool_expr_1 (rtx, int *, int *);
00592 static bool constant_pool_expr_p (rtx);
00593 static bool legitimate_small_data_p (enum machine_mode, rtx);
00594 static bool legitimate_indexed_address_p (rtx, int);
00595 static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
00596 static struct machine_function * rs6000_init_machine_status (void);
00597 static bool rs6000_assemble_integer (rtx, unsigned int, int);
00598 static bool no_global_regs_above (int);
00599 #ifdef HAVE_GAS_HIDDEN
00600 static void rs6000_assemble_visibility (tree, int);
00601 #endif
00602 static int rs6000_ra_ever_killed (void);
00603 static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
00604 static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
00605 static bool rs6000_ms_bitfield_layout_p (tree);
00606 static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
00607 static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
00608 static const char *rs6000_mangle_fundamental_type (tree);
00609 extern const struct attribute_spec rs6000_attribute_table[];
00610 static void rs6000_set_default_type_attributes (tree);
00611 static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT);
00612 static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT);
00613 static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
00614 tree);
00615 static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
00616 static bool rs6000_return_in_memory (tree, tree);
00617 static void rs6000_file_start (void);
00618 #if TARGET_ELF
00619 static int rs6000_elf_reloc_rw_mask (void);
00620 static void rs6000_elf_asm_out_constructor (rtx, int);
00621 static void rs6000_elf_asm_out_destructor (rtx, int);
00622 static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED;
00623 static void rs6000_elf_asm_init_sections (void);
00624 static section *rs6000_elf_select_rtx_section (enum machine_mode, rtx,
00625 unsigned HOST_WIDE_INT);
00626 static void rs6000_elf_encode_section_info (tree, rtx, int)
00627 ATTRIBUTE_UNUSED;
00628 #endif
00629 static bool rs6000_use_blocks_for_constant_p (enum machine_mode, rtx);
00630 #if TARGET_XCOFF
00631 static void rs6000_xcoff_asm_output_anchor (rtx);
00632 static void rs6000_xcoff_asm_globalize_label (FILE *, const char *);
00633 static void rs6000_xcoff_asm_init_sections (void);
00634 static int rs6000_xcoff_reloc_rw_mask (void);
00635 static void rs6000_xcoff_asm_named_section (const char *, unsigned int, tree);
00636 static section *rs6000_xcoff_select_section (tree, int,
00637 unsigned HOST_WIDE_INT);
00638 static void rs6000_xcoff_unique_section (tree, int);
00639 static section *rs6000_xcoff_select_rtx_section
00640 (enum machine_mode, rtx, unsigned HOST_WIDE_INT);
00641 static const char * rs6000_xcoff_strip_name_encoding (const char *);
00642 static unsigned int rs6000_xcoff_section_type_flags (tree, const char *, int);
00643 static void rs6000_xcoff_file_start (void);
00644 static void rs6000_xcoff_file_end (void);
00645 #endif
00646 static int rs6000_variable_issue (FILE *, int, rtx, int);
00647 static bool rs6000_rtx_costs (rtx, int, int, int *);
00648 static int rs6000_adjust_cost (rtx, rtx, rtx, int);
00649 static bool is_microcoded_insn (rtx);
00650 static int is_dispatch_slot_restricted (rtx);
00651 static bool is_cracked_insn (rtx);
00652 static bool is_branch_slot_insn (rtx);
00653 static int rs6000_adjust_priority (rtx, int);
00654 static int rs6000_issue_rate (void);
00655 static bool rs6000_is_costly_dependence (rtx, rtx, rtx, int, int);
00656 static rtx get_next_active_insn (rtx, rtx);
00657 static bool insn_terminates_group_p (rtx , enum group_termination);
00658 static bool is_costly_group (rtx *, rtx);
00659 static int force_new_group (int, FILE *, rtx *, rtx, bool *, int, int *);
00660 static int redefine_groups (FILE *, int, rtx, rtx);
00661 static int pad_groups (FILE *, int, rtx, rtx);
00662 static void rs6000_sched_finish (FILE *, int);
00663 static int rs6000_use_sched_lookahead (void);
00664 static tree rs6000_builtin_mask_for_load (void);
00665
00666 static void def_builtin (int, const char *, tree, int);
00667 static void rs6000_init_builtins (void);
00668 static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx);
00669 static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx);
00670 static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx);
00671 static rtx rs6000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00672 static void altivec_init_builtins (void);
00673 static void rs6000_common_init_builtins (void);
00674 static void rs6000_init_libfuncs (void);
00675
00676 static void enable_mask_for_builtins (struct builtin_description *, int,
00677 enum rs6000_builtins,
00678 enum rs6000_builtins);
00679 static tree build_opaque_vector_type (tree, int);
00680 static void spe_init_builtins (void);
00681 static rtx spe_expand_builtin (tree, rtx, bool *);
00682 static rtx spe_expand_stv_builtin (enum insn_code, tree);
00683 static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
00684 static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
00685 static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
00686 static rs6000_stack_t *rs6000_stack_info (void);
00687 static void debug_stack_info (rs6000_stack_t *);
00688
00689 static rtx altivec_expand_builtin (tree, rtx, bool *);
00690 static rtx altivec_expand_ld_builtin (tree, rtx, bool *);
00691 static rtx altivec_expand_st_builtin (tree, rtx, bool *);
00692 static rtx altivec_expand_dst_builtin (tree, rtx, bool *);
00693 static rtx altivec_expand_abs_builtin (enum insn_code, tree, rtx);
00694 static rtx altivec_expand_predicate_builtin (enum insn_code,
00695 const char *, tree, rtx);
00696 static rtx altivec_expand_lv_builtin (enum insn_code, tree, rtx);
00697 static rtx altivec_expand_stv_builtin (enum insn_code, tree);
00698 static rtx altivec_expand_vec_init_builtin (tree, tree, rtx);
00699 static rtx altivec_expand_vec_set_builtin (tree);
00700 static rtx altivec_expand_vec_ext_builtin (tree, rtx);
00701 static int get_element_number (tree, tree);
00702 static bool rs6000_handle_option (size_t, const char *, int);
00703 static void rs6000_parse_tls_size_option (void);
00704 static void rs6000_parse_yes_no_option (const char *, const char *, int *);
00705 static int first_altivec_reg_to_save (void);
00706 static unsigned int compute_vrsave_mask (void);
00707 static void compute_save_world_info (rs6000_stack_t *info_ptr);
00708 static void is_altivec_return_reg (rtx, void *);
00709 static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
00710 int easy_vector_constant (rtx, enum machine_mode);
00711 static bool rs6000_is_opaque_type (tree);
00712 static rtx rs6000_dwarf_register_span (rtx);
00713 static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
00714 static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
00715 static rtx rs6000_tls_get_addr (void);
00716 static rtx rs6000_got_sym (void);
00717 static int rs6000_tls_symbol_ref_1 (rtx *, void *);
00718 static const char *rs6000_get_some_local_dynamic_name (void);
00719 static int rs6000_get_some_local_dynamic_name_1 (rtx *, void *);
00720 static rtx rs6000_complex_function_value (enum machine_mode);
00721 static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
00722 enum machine_mode, tree);
00723 static void rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *,
00724 HOST_WIDE_INT);
00725 static void rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *,
00726 tree, HOST_WIDE_INT);
00727 static void rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *,
00728 HOST_WIDE_INT,
00729 rtx[], int *);
00730 static void rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *,
00731 tree, HOST_WIDE_INT,
00732 rtx[], int *);
00733 static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, tree, int, bool);
00734 static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int);
00735 static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
00736 static void setup_incoming_varargs (CUMULATIVE_ARGS *,
00737 enum machine_mode, tree,
00738 int *, int);
00739 static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00740 tree, bool);
00741 static int rs6000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00742 tree, bool);
00743 static const char *invalid_arg_for_unprototyped_fn (tree, tree, tree);
00744 #if TARGET_MACHO
00745 static void macho_branch_islands (void);
00746 static int no_previous_def (tree function_name);
00747 static tree get_prev_label (tree function_name);
00748 static void rs6000_darwin_file_start (void);
00749 #endif
00750
00751 static tree rs6000_build_builtin_va_list (void);
00752 static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *);
00753 static bool rs6000_must_pass_in_stack (enum machine_mode, tree);
00754 static bool rs6000_scalar_mode_supported_p (enum machine_mode);
00755 static bool rs6000_vector_mode_supported_p (enum machine_mode);
00756 static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
00757 enum machine_mode);
00758 static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
00759 enum machine_mode);
00760 static int get_vsel_insn (enum machine_mode);
00761 static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
00762 static tree rs6000_stack_protect_fail (void);
00763
00764 const int INSN_NOT_AVAILABLE = -1;
00765 static enum machine_mode rs6000_eh_return_filter_mode (void);
00766
00767
00768
00769 struct toc_hash_struct GTY(())
00770 {
00771
00772
00773 rtx key;
00774 enum machine_mode key_mode;
00775 int labelno;
00776 };
00777
00778 static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
00779
00780
00781 char rs6000_reg_names[][8] =
00782 {
00783 "0", "1", "2", "3", "4", "5", "6", "7",
00784 "8", "9", "10", "11", "12", "13", "14", "15",
00785 "16", "17", "18", "19", "20", "21", "22", "23",
00786 "24", "25", "26", "27", "28", "29", "30", "31",
00787 "0", "1", "2", "3", "4", "5", "6", "7",
00788 "8", "9", "10", "11", "12", "13", "14", "15",
00789 "16", "17", "18", "19", "20", "21", "22", "23",
00790 "24", "25", "26", "27", "28", "29", "30", "31",
00791 "mq", "lr", "ctr","ap",
00792 "0", "1", "2", "3", "4", "5", "6", "7",
00793 "xer",
00794
00795 "0", "1", "2", "3", "4", "5", "6", "7",
00796 "8", "9", "10", "11", "12", "13", "14", "15",
00797 "16", "17", "18", "19", "20", "21", "22", "23",
00798 "24", "25", "26", "27", "28", "29", "30", "31",
00799 "vrsave", "vscr",
00800
00801 "spe_acc", "spefscr",
00802
00803 "sfp"
00804 };
00805
00806 #ifdef TARGET_REGNAMES
00807 static const char alt_reg_names[][8] =
00808 {
00809 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
00810 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
00811 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
00812 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
00813 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
00814 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
00815 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
00816 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
00817 "mq", "lr", "ctr", "ap",
00818 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
00819 "xer",
00820
00821 "%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
00822 "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
00823 "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
00824 "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
00825 "vrsave", "vscr",
00826
00827 "spe_acc", "spefscr",
00828
00829 "sfp"
00830 };
00831 #endif
00832
00833 #ifndef MASK_STRICT_ALIGN
00834 #define MASK_STRICT_ALIGN 0
00835 #endif
00836 #ifndef TARGET_PROFILE_KERNEL
00837 #define TARGET_PROFILE_KERNEL 0
00838 #endif
00839
00840
00841 #define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
00842
00843
00844 #undef TARGET_ATTRIBUTE_TABLE
00845 #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
00846 #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
00847 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes
00848
00849 #undef TARGET_ASM_ALIGNED_DI_OP
00850 #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP
00851
00852
00853
00854 #ifndef OBJECT_FORMAT_ELF
00855 #if TARGET_XCOFF
00856
00857
00858 #undef TARGET_ASM_UNALIGNED_HI_OP
00859 #define TARGET_ASM_UNALIGNED_HI_OP "\t.vbyte\t2,"
00860 #undef TARGET_ASM_UNALIGNED_SI_OP
00861 #define TARGET_ASM_UNALIGNED_SI_OP "\t.vbyte\t4,"
00862 #undef TARGET_ASM_UNALIGNED_DI_OP
00863 #define TARGET_ASM_UNALIGNED_DI_OP "\t.vbyte\t8,"
00864 #else
00865
00866 #undef TARGET_ASM_UNALIGNED_HI_OP
00867 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
00868 #undef TARGET_ASM_UNALIGNED_SI_OP
00869 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
00870 #undef TARGET_ASM_UNALIGNED_DI_OP
00871 #define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t"
00872 #undef TARGET_ASM_ALIGNED_DI_OP
00873 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00874 #endif
00875 #endif
00876
00877
00878
00879 #undef TARGET_ASM_INTEGER
00880 #define TARGET_ASM_INTEGER rs6000_assemble_integer
00881
00882 #ifdef HAVE_GAS_HIDDEN
00883 #undef TARGET_ASM_ASSEMBLE_VISIBILITY
00884 #define TARGET_ASM_ASSEMBLE_VISIBILITY rs6000_assemble_visibility
00885 #endif
00886
00887 #undef TARGET_HAVE_TLS
00888 #define TARGET_HAVE_TLS HAVE_AS_TLS
00889
00890 #undef TARGET_CANNOT_FORCE_CONST_MEM
00891 #define TARGET_CANNOT_FORCE_CONST_MEM rs6000_tls_referenced_p
00892
00893 #undef TARGET_ASM_FUNCTION_PROLOGUE
00894 #define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
00895 #undef TARGET_ASM_FUNCTION_EPILOGUE
00896 #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
00897
00898 #undef TARGET_SCHED_VARIABLE_ISSUE
00899 #define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
00900
00901 #undef TARGET_SCHED_ISSUE_RATE
00902 #define TARGET_SCHED_ISSUE_RATE rs6000_issue_rate
00903 #undef TARGET_SCHED_ADJUST_COST
00904 #define TARGET_SCHED_ADJUST_COST rs6000_adjust_cost
00905 #undef TARGET_SCHED_ADJUST_PRIORITY
00906 #define TARGET_SCHED_ADJUST_PRIORITY rs6000_adjust_priority
00907 #undef TARGET_SCHED_IS_COSTLY_DEPENDENCE
00908 #define TARGET_SCHED_IS_COSTLY_DEPENDENCE rs6000_is_costly_dependence
00909 #undef TARGET_SCHED_FINISH
00910 #define TARGET_SCHED_FINISH rs6000_sched_finish
00911
00912 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
00913 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD rs6000_use_sched_lookahead
00914
00915 #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
00916 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD rs6000_builtin_mask_for_load
00917
00918 #undef TARGET_INIT_BUILTINS
00919 #define TARGET_INIT_BUILTINS rs6000_init_builtins
00920
00921 #undef TARGET_EXPAND_BUILTIN
00922 #define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
00923
00924 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
00925 #define TARGET_MANGLE_FUNDAMENTAL_TYPE rs6000_mangle_fundamental_type
00926
00927 #undef TARGET_INIT_LIBFUNCS
00928 #define TARGET_INIT_LIBFUNCS rs6000_init_libfuncs
00929
00930 #if TARGET_MACHO
00931 #undef TARGET_BINDS_LOCAL_P
00932 #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
00933 #endif
00934
00935 #undef TARGET_MS_BITFIELD_LAYOUT_P
00936 #define TARGET_MS_BITFIELD_LAYOUT_P rs6000_ms_bitfield_layout_p
00937
00938 #undef TARGET_ASM_OUTPUT_MI_THUNK
00939 #define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
00940
00941 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00942 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00943
00944 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00945 #define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
00946
00947 #undef TARGET_INVALID_WITHIN_DOLOOP
00948 #define TARGET_INVALID_WITHIN_DOLOOP rs6000_invalid_within_doloop
00949
00950 #undef TARGET_RTX_COSTS
00951 #define TARGET_RTX_COSTS rs6000_rtx_costs
00952 #undef TARGET_ADDRESS_COST
00953 #define TARGET_ADDRESS_COST hook_int_rtx_0
00954
00955 #undef TARGET_VECTOR_OPAQUE_P
00956 #define TARGET_VECTOR_OPAQUE_P rs6000_is_opaque_type
00957
00958 #undef TARGET_DWARF_REGISTER_SPAN
00959 #define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
00960
00961
00962
00963 #undef TARGET_PROMOTE_FUNCTION_ARGS
00964 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00965 #undef TARGET_PROMOTE_FUNCTION_RETURN
00966 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00967
00968 #undef TARGET_RETURN_IN_MEMORY
00969 #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
00970
00971 #undef TARGET_SETUP_INCOMING_VARARGS
00972 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
00973
00974
00975 #undef TARGET_STRICT_ARGUMENT_NAMING
00976 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
00977 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
00978 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
00979 #undef TARGET_SPLIT_COMPLEX_ARG
00980 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
00981 #undef TARGET_MUST_PASS_IN_STACK
00982 #define TARGET_MUST_PASS_IN_STACK rs6000_must_pass_in_stack
00983 #undef TARGET_PASS_BY_REFERENCE
00984 #define TARGET_PASS_BY_REFERENCE rs6000_pass_by_reference
00985 #undef TARGET_ARG_PARTIAL_BYTES
00986 #define TARGET_ARG_PARTIAL_BYTES rs6000_arg_partial_bytes
00987
00988 #undef TARGET_BUILD_BUILTIN_VA_LIST
00989 #define TARGET_BUILD_BUILTIN_VA_LIST rs6000_build_builtin_va_list
00990
00991 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00992 #define TARGET_GIMPLIFY_VA_ARG_EXPR rs6000_gimplify_va_arg
00993
00994 #undef TARGET_EH_RETURN_FILTER_MODE
00995 #define TARGET_EH_RETURN_FILTER_MODE rs6000_eh_return_filter_mode
00996
00997 #undef TARGET_SCALAR_MODE_SUPPORTED_P
00998 #define TARGET_SCALAR_MODE_SUPPORTED_P rs6000_scalar_mode_supported_p
00999
01000 #undef TARGET_VECTOR_MODE_SUPPORTED_P
01001 #define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p
01002
01003 #undef TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN
01004 #define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN invalid_arg_for_unprototyped_fn
01005
01006 #undef TARGET_HANDLE_OPTION
01007 #define TARGET_HANDLE_OPTION rs6000_handle_option
01008
01009 #undef TARGET_DEFAULT_TARGET_FLAGS
01010 #define TARGET_DEFAULT_TARGET_FLAGS \
01011 (TARGET_DEFAULT)
01012
01013 #undef TARGET_STACK_PROTECT_FAIL
01014 #define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 #undef TARGET_RELAXED_ORDERING
01025 #define TARGET_RELAXED_ORDERING true
01026
01027 #ifdef HAVE_AS_TLS
01028 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
01029 #define TARGET_ASM_OUTPUT_DWARF_DTPREL rs6000_output_dwarf_dtprel
01030 #endif
01031
01032
01033
01034
01035
01036
01037
01038
01039 #undef TARGET_MIN_ANCHOR_OFFSET
01040 #define TARGET_MIN_ANCHOR_OFFSET -0x7fffffff - 1
01041 #undef TARGET_MAX_ANCHOR_OFFSET
01042 #define TARGET_MAX_ANCHOR_OFFSET 0x7fffffff
01043 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
01044 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
01045
01046 struct gcc_target targetm = TARGET_INITIALIZER;
01047
01048
01049
01050
01051 static int
01052 rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
01053 {
01054
01055
01056 if (INT_REGNO_P (regno))
01057 return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
01058
01059
01060
01061 if (FP_REGNO_P (regno))
01062 return
01063 (SCALAR_FLOAT_MODE_P (mode)
01064 && !DECIMAL_FLOAT_MODE_P (mode)
01065 && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
01066 || (GET_MODE_CLASS (mode) == MODE_INT
01067 && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD);
01068
01069
01070 if (CR_REGNO_P (regno))
01071 return GET_MODE_CLASS (mode) == MODE_CC;
01072
01073 if (XER_REGNO_P (regno))
01074 return mode == PSImode;
01075
01076
01077 if (ALTIVEC_REGNO_P (regno))
01078 return ALTIVEC_VECTOR_MODE (mode);
01079
01080
01081 if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
01082 return 1;
01083
01084
01085
01086
01087 return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
01088 }
01089
01090
01091 static void
01092 rs6000_init_hard_regno_mode_ok (void)
01093 {
01094 int r, m;
01095
01096 for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
01097 for (m = 0; m < NUM_MACHINE_MODES; ++m)
01098 if (rs6000_hard_regno_mode_ok (r, m))
01099 rs6000_hard_regno_mode_ok_p[m][r] = true;
01100 }
01101
01102
01103
01104
01105 #ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE
01106 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
01107 #endif
01108
01109
01110
01111
01112 void
01113 rs6000_override_options (const char *default_cpu)
01114 {
01115 size_t i, j;
01116 struct rs6000_cpu_select *ptr;
01117 int set_masks;
01118
01119
01120
01121 enum {
01122 POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
01123 POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
01124 };
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 static struct ptt
01135 {
01136 const char *const name;
01137 const enum processor_type processor;
01138 const int target_enable;
01139 } const processor_target_table[]
01140 = {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01141 {"403", PROCESSOR_PPC403,
01142 POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
01143 {"405", PROCESSOR_PPC405,
01144 POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
01145 {"405fp", PROCESSOR_PPC405,
01146 POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
01147 {"440", PROCESSOR_PPC440,
01148 POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
01149 {"440fp", PROCESSOR_PPC440,
01150 POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
01151 {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
01152 {"601", PROCESSOR_PPC601,
01153 MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
01154 {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01155 {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01156 {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01157 {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01158 {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01159 {"620", PROCESSOR_PPC620,
01160 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01161 {"630", PROCESSOR_PPC630,
01162 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01163 {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01164 {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
01165 {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
01166 {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01167 {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01168 {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01169 {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01170 {"8540", PROCESSOR_PPC8540,
01171 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_STRICT_ALIGN},
01172
01173 {"8548", PROCESSOR_PPC8540,
01174 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_STRICT_ALIGN},
01175 {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01176 {"970", PROCESSOR_POWER4,
01177 POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
01178 {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
01179 {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01180 {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01181 {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK},
01182 {"G5", PROCESSOR_POWER4,
01183 POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
01184 {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01185 {"power2", PROCESSOR_POWER,
01186 MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
01187 {"power3", PROCESSOR_PPC630,
01188 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01189 {"power4", PROCESSOR_POWER4,
01190 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POWERPC64},
01191 {"power5", PROCESSOR_POWER5,
01192 POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT
01193 | MASK_MFCRF | MASK_POPCNTB},
01194 {"power5+", PROCESSOR_POWER5,
01195 POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT
01196 | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
01197 {"power6", PROCESSOR_POWER5,
01198 POWERPC_7400_MASK | MASK_POWERPC64 | MASK_MFCRF | MASK_POPCNTB
01199 | MASK_FPRND},
01200 {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
01201 {"powerpc64", PROCESSOR_POWERPC64,
01202 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01203 {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01204 {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01205 {"rios2", PROCESSOR_RIOS2,
01206 MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
01207 {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01208 {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01209 {"rs64", PROCESSOR_RS64A,
01210 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
01211 };
01212
01213 const size_t ptt_size = ARRAY_SIZE (processor_target_table);
01214
01215
01216
01217
01218
01219
01220
01221 enum {
01222 POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
01223 POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
01224 | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
01225 | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
01226 | MASK_DLMZB)
01227 };
01228
01229 rs6000_init_hard_regno_mode_ok ();
01230
01231 set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
01232 #ifdef OS_MISSING_POWERPC64
01233 if (OS_MISSING_POWERPC64)
01234 set_masks &= ~MASK_POWERPC64;
01235 #endif
01236 #ifdef OS_MISSING_ALTIVEC
01237 if (OS_MISSING_ALTIVEC)
01238 set_masks &= ~MASK_ALTIVEC;
01239 #endif
01240
01241
01242 set_masks &= ~target_flags_explicit;
01243
01244
01245 rs6000_select[0].string = default_cpu;
01246 rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
01247
01248 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
01249 {
01250 ptr = &rs6000_select[i];
01251 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
01252 {
01253 for (j = 0; j < ptt_size; j++)
01254 if (! strcmp (ptr->string, processor_target_table[j].name))
01255 {
01256 if (ptr->set_tune_p)
01257 rs6000_cpu = processor_target_table[j].processor;
01258
01259 if (ptr->set_arch_p)
01260 {
01261 target_flags &= ~set_masks;
01262 target_flags |= (processor_target_table[j].target_enable
01263 & set_masks);
01264 }
01265 break;
01266 }
01267
01268 if (j == ptt_size)
01269 error ("bad value (%s) for %s switch", ptr->string, ptr->name);
01270 }
01271 }
01272
01273 if (TARGET_E500)
01274 rs6000_isel = 1;
01275
01276
01277
01278 if (BYTES_BIG_ENDIAN && optimize_size)
01279 target_flags |= ~target_flags_explicit & (MASK_MULTIPLE | MASK_STRING);
01280
01281
01282
01283
01284
01285
01286
01287 if (!BYTES_BIG_ENDIAN && rs6000_cpu != PROCESSOR_PPC750)
01288 {
01289 if (TARGET_MULTIPLE)
01290 {
01291 target_flags &= ~MASK_MULTIPLE;
01292 if ((target_flags_explicit & MASK_MULTIPLE) != 0)
01293 warning (0, "-mmultiple is not supported on little endian systems");
01294 }
01295
01296 if (TARGET_STRING)
01297 {
01298 target_flags &= ~MASK_STRING;
01299 if ((target_flags_explicit & MASK_STRING) != 0)
01300 warning (0, "-mstring is not supported on little endian systems");
01301 }
01302 }
01303
01304
01305 if (rs6000_debug_name)
01306 {
01307 if (! strcmp (rs6000_debug_name, "all"))
01308 rs6000_debug_stack = rs6000_debug_arg = 1;
01309 else if (! strcmp (rs6000_debug_name, "stack"))
01310 rs6000_debug_stack = 1;
01311 else if (! strcmp (rs6000_debug_name, "arg"))
01312 rs6000_debug_arg = 1;
01313 else
01314 error ("unknown -mdebug-%s switch", rs6000_debug_name);
01315 }
01316
01317 if (rs6000_traceback_name)
01318 {
01319 if (! strncmp (rs6000_traceback_name, "full", 4))
01320 rs6000_traceback = traceback_full;
01321 else if (! strncmp (rs6000_traceback_name, "part", 4))
01322 rs6000_traceback = traceback_part;
01323 else if (! strncmp (rs6000_traceback_name, "no", 2))
01324 rs6000_traceback = traceback_none;
01325 else
01326 error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
01327 rs6000_traceback_name);
01328 }
01329
01330 if (!rs6000_explicit_options.long_double)
01331 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01332
01333 #ifndef POWERPC_LINUX
01334 if (!rs6000_explicit_options.ieee)
01335 rs6000_ieeequad = 1;
01336 #endif
01337
01338
01339 if (TARGET_ELF && TARGET_64BIT)
01340 {
01341 rs6000_altivec_abi = 1;
01342 TARGET_ALTIVEC_VRSAVE = 1;
01343 }
01344
01345
01346 if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
01347 {
01348 rs6000_darwin64_abi = 1;
01349 #if TARGET_MACHO
01350 darwin_one_byte_bool = 1;
01351 #endif
01352
01353 rs6000_alignment_flags = MASK_ALIGN_NATURAL;
01354 }
01355
01356
01357
01358 if (flag_section_anchors)
01359 TARGET_NO_FP_IN_TOC = 1;
01360
01361
01362 rs6000_parse_tls_size_option ();
01363
01364 #ifdef SUBTARGET_OVERRIDE_OPTIONS
01365 SUBTARGET_OVERRIDE_OPTIONS;
01366 #endif
01367 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
01368 SUBSUBTARGET_OVERRIDE_OPTIONS;
01369 #endif
01370 #ifdef SUB3TARGET_OVERRIDE_OPTIONS
01371 SUB3TARGET_OVERRIDE_OPTIONS;
01372 #endif
01373
01374 if (TARGET_E500)
01375 {
01376 if (TARGET_ALTIVEC)
01377 error ("AltiVec and E500 instructions cannot coexist");
01378
01379
01380
01381 if ((target_flags & MASK_STRING) != 0)
01382 target_flags = target_flags & ~MASK_STRING;
01383 }
01384 else if (rs6000_select[1].string != NULL)
01385 {
01386
01387
01388
01389 if (!rs6000_explicit_options.abi)
01390 rs6000_spe_abi = 0;
01391 if (!rs6000_explicit_options.spe)
01392 rs6000_spe = 0;
01393 if (!rs6000_explicit_options.float_gprs)
01394 rs6000_float_gprs = 0;
01395 if (!rs6000_explicit_options.isel)
01396 rs6000_isel = 0;
01397 if (!rs6000_explicit_options.long_double)
01398 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01399 }
01400
01401 rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
01402 && rs6000_cpu != PROCESSOR_POWER5);
01403 rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
01404 || rs6000_cpu == PROCESSOR_POWER5);
01405
01406 rs6000_sched_restricted_insns_priority
01407 = (rs6000_sched_groups ? 1 : 0);
01408
01409
01410 rs6000_sched_costly_dep
01411 = (rs6000_sched_groups ? store_to_load_dep_costly : no_dep_costly);
01412
01413 if (rs6000_sched_costly_dep_str)
01414 {
01415 if (! strcmp (rs6000_sched_costly_dep_str, "no"))
01416 rs6000_sched_costly_dep = no_dep_costly;
01417 else if (! strcmp (rs6000_sched_costly_dep_str, "all"))
01418 rs6000_sched_costly_dep = all_deps_costly;
01419 else if (! strcmp (rs6000_sched_costly_dep_str, "true_store_to_load"))
01420 rs6000_sched_costly_dep = true_store_to_load_dep_costly;
01421 else if (! strcmp (rs6000_sched_costly_dep_str, "store_to_load"))
01422 rs6000_sched_costly_dep = store_to_load_dep_costly;
01423 else
01424 rs6000_sched_costly_dep = atoi (rs6000_sched_costly_dep_str);
01425 }
01426
01427
01428 rs6000_sched_insert_nops
01429 = (rs6000_sched_groups ? sched_finish_regroup_exact : sched_finish_none);
01430
01431 if (rs6000_sched_insert_nops_str)
01432 {
01433 if (! strcmp (rs6000_sched_insert_nops_str, "no"))
01434 rs6000_sched_insert_nops = sched_finish_none;
01435 else if (! strcmp (rs6000_sched_insert_nops_str, "pad"))
01436 rs6000_sched_insert_nops = sched_finish_pad_groups;
01437 else if (! strcmp (rs6000_sched_insert_nops_str, "regroup_exact"))
01438 rs6000_sched_insert_nops = sched_finish_regroup_exact;
01439 else
01440 rs6000_sched_insert_nops = atoi (rs6000_sched_insert_nops_str);
01441 }
01442
01443 #ifdef TARGET_REGNAMES
01444
01445
01446 if (TARGET_REGNAMES)
01447 memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
01448 #endif
01449
01450
01451
01452
01453 if (!rs6000_explicit_options.aix_struct_ret)
01454 aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
01455
01456 if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
01457 REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
01458
01459 if (TARGET_TOC)
01460 ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
01461
01462
01463
01464 if (!TARGET_64BIT)
01465 {
01466 targetm.asm_out.aligned_op.di = NULL;
01467 targetm.asm_out.unaligned_op.di = NULL;
01468 }
01469
01470
01471 if (!optimize_size)
01472 {
01473 if (rs6000_sched_groups)
01474 {
01475 if (align_functions <= 0)
01476 align_functions = 16;
01477 if (align_jumps <= 0)
01478 align_jumps = 16;
01479 if (align_loops <= 0)
01480 align_loops = 16;
01481 }
01482 if (align_jumps_max_skip <= 0)
01483 align_jumps_max_skip = 15;
01484 if (align_loops_max_skip <= 0)
01485 align_loops_max_skip = 15;
01486 }
01487
01488
01489 init_machine_status = rs6000_init_machine_status;
01490
01491
01492
01493 if (DEFAULT_ABI != ABI_AIX)
01494 targetm.calls.split_complex_arg = NULL;
01495
01496
01497 if (optimize_size)
01498 rs6000_cost = TARGET_POWERPC64 ? &size64_cost : &size32_cost;
01499 else
01500 switch (rs6000_cpu)
01501 {
01502 case PROCESSOR_RIOS1:
01503 rs6000_cost = &rios1_cost;
01504 break;
01505
01506 case PROCESSOR_RIOS2:
01507 rs6000_cost = &rios2_cost;
01508 break;
01509
01510 case PROCESSOR_RS64A:
01511 rs6000_cost = &rs64a_cost;
01512 break;
01513
01514 case PROCESSOR_MPCCORE:
01515 rs6000_cost = &mpccore_cost;
01516 break;
01517
01518 case PROCESSOR_PPC403:
01519 rs6000_cost = &ppc403_cost;
01520 break;
01521
01522 case PROCESSOR_PPC405:
01523 rs6000_cost = &ppc405_cost;
01524 break;
01525
01526 case PROCESSOR_PPC440:
01527 rs6000_cost = &ppc440_cost;
01528 break;
01529
01530 case PROCESSOR_PPC601:
01531 rs6000_cost = &ppc601_cost;
01532 break;
01533
01534 case PROCESSOR_PPC603:
01535 rs6000_cost = &ppc603_cost;
01536 break;
01537
01538 case PROCESSOR_PPC604:
01539 rs6000_cost = &ppc604_cost;
01540 break;
01541
01542 case PROCESSOR_PPC604e:
01543 rs6000_cost = &ppc604e_cost;
01544 break;
01545
01546 case PROCESSOR_PPC620:
01547 rs6000_cost = &ppc620_cost;
01548 break;
01549
01550 case PROCESSOR_PPC630:
01551 rs6000_cost = &ppc630_cost;
01552 break;
01553
01554 case PROCESSOR_PPC750:
01555 case PROCESSOR_PPC7400:
01556 rs6000_cost = &ppc750_cost;
01557 break;
01558
01559 case PROCESSOR_PPC7450:
01560 rs6000_cost = &ppc7450_cost;
01561 break;
01562
01563 case PROCESSOR_PPC8540:
01564 rs6000_cost = &ppc8540_cost;
01565 break;
01566
01567 case PROCESSOR_POWER4:
01568 case PROCESSOR_POWER5:
01569 rs6000_cost = &power4_cost;
01570 break;
01571
01572 default:
01573 gcc_unreachable ();
01574 }
01575 }
01576
01577
01578 static tree
01579 rs6000_builtin_mask_for_load (void)
01580 {
01581 if (TARGET_ALTIVEC)
01582 return altivec_builtin_mask_for_load;
01583 else
01584 return 0;
01585 }
01586
01587
01588
01589
01590
01591
01592 static void
01593 rs6000_parse_yes_no_option (const char *name, const char *value, int *flag)
01594 {
01595 if (value == 0)
01596 return;
01597 else if (!strcmp (value, "yes"))
01598 *flag = 1;
01599 else if (!strcmp (value, "no"))
01600 *flag = 0;
01601 else
01602 error ("unknown -m%s= option specified: '%s'", name, value);
01603 }
01604
01605
01606
01607 static void
01608 rs6000_parse_tls_size_option (void)
01609 {
01610 if (rs6000_tls_size_string == 0)
01611 return;
01612 else if (strcmp (rs6000_tls_size_string, "16") == 0)
01613 rs6000_tls_size = 16;
01614 else if (strcmp (rs6000_tls_size_string, "32") == 0)
01615 rs6000_tls_size = 32;
01616 else if (strcmp (rs6000_tls_size_string, "64") == 0)
01617 rs6000_tls_size = 64;
01618 else
01619 error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
01620 }
01621
01622 void
01623 optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
01624 {
01625 if (DEFAULT_ABI == ABI_DARWIN)
01626
01627
01628 flag_errno_math = 0;
01629
01630
01631 set_param_value ("max-grow-copy-bb-insns", 16);
01632
01633
01634
01635
01636 if (!TARGET_MACHO && lang_hooks.name[4] != 'O')
01637 flag_section_anchors = 1;
01638 }
01639
01640
01641
01642 static bool
01643 rs6000_handle_option (size_t code, const char *arg, int value)
01644 {
01645 switch (code)
01646 {
01647 case OPT_mno_power:
01648 target_flags &= ~(MASK_POWER | MASK_POWER2
01649 | MASK_MULTIPLE | MASK_STRING);
01650 target_flags_explicit |= (MASK_POWER | MASK_POWER2
01651 | MASK_MULTIPLE | MASK_STRING);
01652 break;
01653 case OPT_mno_powerpc:
01654 target_flags &= ~(MASK_POWERPC | MASK_PPC_GPOPT
01655 | MASK_PPC_GFXOPT | MASK_POWERPC64);
01656 target_flags_explicit |= (MASK_POWERPC | MASK_PPC_GPOPT
01657 | MASK_PPC_GFXOPT | MASK_POWERPC64);
01658 break;
01659 case OPT_mfull_toc:
01660 target_flags &= ~MASK_MINIMAL_TOC;
01661 TARGET_NO_FP_IN_TOC = 0;
01662 TARGET_NO_SUM_IN_TOC = 0;
01663 target_flags_explicit |= MASK_MINIMAL_TOC;
01664 #ifdef TARGET_USES_SYSV4_OPT
01665
01666
01667 target_flags |= MASK_MINIMAL_TOC;
01668 target_flags_explicit |= MASK_MINIMAL_TOC;
01669 #endif
01670 break;
01671
01672 #ifdef TARGET_USES_SYSV4_OPT
01673 case OPT_mtoc:
01674
01675 target_flags |= MASK_MINIMAL_TOC;
01676 target_flags_explicit |= MASK_MINIMAL_TOC;
01677 break;
01678 #endif
01679
01680 #ifdef TARGET_USES_AIX64_OPT
01681 case OPT_maix64:
01682 #else
01683 case OPT_m64:
01684 #endif
01685 target_flags |= MASK_POWERPC64 | MASK_POWERPC;
01686 target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
01687 target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
01688 break;
01689
01690 #ifdef TARGET_USES_AIX64_OPT
01691 case OPT_maix32:
01692 #else
01693 case OPT_m32:
01694 #endif
01695 target_flags &= ~MASK_POWERPC64;
01696 target_flags_explicit |= MASK_POWERPC64;
01697 break;
01698
01699 case OPT_minsert_sched_nops_:
01700 rs6000_sched_insert_nops_str = arg;
01701 break;
01702
01703 case OPT_mminimal_toc:
01704 if (value == 1)
01705 {
01706 TARGET_NO_FP_IN_TOC = 0;
01707 TARGET_NO_SUM_IN_TOC = 0;
01708 }
01709 break;
01710
01711 case OPT_mpower:
01712 if (value == 1)
01713 {
01714 target_flags |= (MASK_MULTIPLE | MASK_STRING);
01715 target_flags_explicit |= (MASK_MULTIPLE | MASK_STRING);
01716 }
01717 break;
01718
01719 case OPT_mpower2:
01720 if (value == 1)
01721 {
01722 target_flags |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
01723 target_flags_explicit |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
01724 }
01725 break;
01726
01727 case OPT_mpowerpc_gpopt:
01728 case OPT_mpowerpc_gfxopt:
01729 if (value == 1)
01730 {
01731 target_flags |= MASK_POWERPC;
01732 target_flags_explicit |= MASK_POWERPC;
01733 }
01734 break;
01735
01736 case OPT_maix_struct_return:
01737 case OPT_msvr4_struct_return:
01738 rs6000_explicit_options.aix_struct_ret = true;
01739 break;
01740
01741 case OPT_mvrsave_:
01742 rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
01743 break;
01744
01745 case OPT_misel_:
01746 rs6000_explicit_options.isel = true;
01747 rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel));
01748 break;
01749
01750 case OPT_mspe_:
01751 rs6000_explicit_options.spe = true;
01752 rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe));
01753
01754 if (!rs6000_spe)
01755 rs6000_long_double_type_size = 64;
01756 break;
01757
01758 case OPT_mdebug_:
01759 rs6000_debug_name = arg;
01760 break;
01761
01762 #ifdef TARGET_USES_SYSV4_OPT
01763 case OPT_mcall_:
01764 rs6000_abi_name = arg;
01765 break;
01766
01767 case OPT_msdata_:
01768 rs6000_sdata_name = arg;
01769 break;
01770
01771 case OPT_mtls_size_:
01772 rs6000_tls_size_string = arg;
01773 break;
01774
01775 case OPT_mrelocatable:
01776 if (value == 1)
01777 {
01778 target_flags |= MASK_MINIMAL_TOC;
01779 target_flags_explicit |= MASK_MINIMAL_TOC;
01780 TARGET_NO_FP_IN_TOC = 1;
01781 }
01782 break;
01783
01784 case OPT_mrelocatable_lib:
01785 if (value == 1)
01786 {
01787 target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
01788 target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
01789 TARGET_NO_FP_IN_TOC = 1;
01790 }
01791 else
01792 {
01793 target_flags &= ~MASK_RELOCATABLE;
01794 target_flags_explicit |= MASK_RELOCATABLE;
01795 }
01796 break;
01797 #endif
01798
01799 case OPT_mabi_:
01800 if (!strcmp (arg, "altivec"))
01801 {
01802 rs6000_explicit_options.abi = true;
01803 rs6000_altivec_abi = 1;
01804 rs6000_spe_abi = 0;
01805 }
01806 else if (! strcmp (arg, "no-altivec"))
01807 {
01808
01809
01810 rs6000_altivec_abi = 0;
01811 }
01812 else if (! strcmp (arg, "spe"))
01813 {
01814 rs6000_explicit_options.abi = true;
01815 rs6000_spe_abi = 1;
01816 rs6000_altivec_abi = 0;
01817 if (!TARGET_SPE_ABI)
01818 error ("not configured for ABI: '%s'", arg);
01819 }
01820 else if (! strcmp (arg, "no-spe"))
01821 {
01822 rs6000_explicit_options.abi = true;
01823 rs6000_spe_abi = 0;
01824 }
01825
01826
01827
01828 else if (! strcmp (arg, "d64"))
01829 {
01830 rs6000_darwin64_abi = 1;
01831 warning (0, "Using darwin64 ABI");
01832 }
01833 else if (! strcmp (arg, "d32"))
01834 {
01835 rs6000_darwin64_abi = 0;
01836 warning (0, "Using old darwin ABI");
01837 }
01838
01839 else if (! strcmp (arg, "ibmlongdouble"))
01840 {
01841 rs6000_explicit_options.ieee = true;
01842 rs6000_ieeequad = 0;
01843 warning (0, "Using IBM extended precision long double");
01844 }
01845 else if (! strcmp (arg, "ieeelongdouble"))
01846 {
01847 rs6000_explicit_options.ieee = true;
01848 rs6000_ieeequad = 1;
01849 warning (0, "Using IEEE extended precision long double");
01850 }
01851
01852 else
01853 {
01854 error ("unknown ABI specified: '%s'", arg);
01855 return false;
01856 }
01857 break;
01858
01859 case OPT_mcpu_:
01860 rs6000_select[1].string = arg;
01861 break;
01862
01863 case OPT_mtune_:
01864 rs6000_select[2].string = arg;
01865 break;
01866
01867 case OPT_mtraceback_:
01868 rs6000_traceback_name = arg;
01869 break;
01870
01871 case OPT_mfloat_gprs_:
01872 rs6000_explicit_options.float_gprs = true;
01873 if (! strcmp (arg, "yes") || ! strcmp (arg, "single"))
01874 rs6000_float_gprs = 1;
01875 else if (! strcmp (arg, "double"))
01876 rs6000_float_gprs = 2;
01877 else if (! strcmp (arg, "no"))
01878 rs6000_float_gprs = 0;
01879 else
01880 {
01881 error ("invalid option for -mfloat-gprs: '%s'", arg);
01882 return false;
01883 }
01884 break;
01885
01886 case OPT_mlong_double_:
01887 rs6000_explicit_options.long_double = true;
01888 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01889 if (value != 64 && value != 128)
01890 {
01891 error ("Unknown switch -mlong-double-%s", arg);
01892 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01893 return false;
01894 }
01895 else
01896 rs6000_long_double_type_size = value;
01897 break;
01898
01899 case OPT_msched_costly_dep_:
01900 rs6000_sched_costly_dep_str = arg;
01901 break;
01902
01903 case OPT_malign_:
01904 rs6000_explicit_options.alignment = true;
01905 if (! strcmp (arg, "power"))
01906 {
01907
01908
01909
01910
01911 if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
01912 warning (0, "-malign-power is not supported for 64-bit Darwin;"
01913 " it is incompatible with the installed C and C++ libraries");
01914 rs6000_alignment_flags = MASK_ALIGN_POWER;
01915 }
01916 else if (! strcmp (arg, "natural"))
01917 rs6000_alignment_flags = MASK_ALIGN_NATURAL;
01918 else
01919 {
01920 error ("unknown -malign-XXXXX option specified: '%s'", arg);
01921 return false;
01922 }
01923 break;
01924 }
01925 return true;
01926 }
01927
01928
01929
01930 static void
01931 rs6000_file_start (void)
01932 {
01933 size_t i;
01934 char buffer[80];
01935 const char *start = buffer;
01936 struct rs6000_cpu_select *ptr;
01937 const char *default_cpu = TARGET_CPU_DEFAULT;
01938 FILE *file = asm_out_file;
01939
01940 default_file_start ();
01941
01942 #ifdef TARGET_BI_ARCH
01943 if ((TARGET_DEFAULT ^ target_flags) & MASK_64BIT)
01944 default_cpu = 0;
01945 #endif
01946
01947 if (flag_verbose_asm)
01948 {
01949 sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);
01950 rs6000_select[0].string = default_cpu;
01951
01952 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
01953 {
01954 ptr = &rs6000_select[i];
01955 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
01956 {
01957 fprintf (file, "%s %s%s", start, ptr->name, ptr->string);
01958 start = "";
01959 }
01960 }
01961
01962 if (PPC405_ERRATUM77)
01963 {
01964 fprintf (file, "%s PPC405CR_ERRATUM77", start);
01965 start = "";
01966 }
01967
01968 #ifdef USING_ELFOS_H
01969 switch (rs6000_sdata)
01970 {
01971 case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
01972 case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
01973 case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;
01974 case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
01975 }
01976
01977 if (rs6000_sdata && g_switch_value)
01978 {
01979 fprintf (file, "%s -G " HOST_WIDE_INT_PRINT_UNSIGNED, start,
01980 g_switch_value);
01981 start = "";
01982 }
01983 #endif
01984
01985 if (*start == '\0')
01986 putc ('\n', file);
01987 }
01988
01989 if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
01990 {
01991 switch_to_section (toc_section);
01992 switch_to_section (text_section);
01993 }
01994 }
01995
01996
01997
01998
01999 int
02000 direct_return (void)
02001 {
02002 if (reload_completed)
02003 {
02004 rs6000_stack_t *info = rs6000_stack_info ();
02005
02006 if (info->first_gp_reg_save == 32
02007 && info->first_fp_reg_save == 64
02008 && info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
02009 && ! info->lr_save_p
02010 && ! info->cr_save_p
02011 && info->vrsave_mask == 0
02012 && ! info->push_p)
02013 return 1;
02014 }
02015
02016 return 0;
02017 }
02018
02019
02020
02021
02022 int
02023 num_insns_constant_wide (HOST_WIDE_INT value)
02024 {
02025
02026 if ((unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000)
02027 return 1;
02028
02029
02030 else if ((value & 0xffff) == 0
02031 && (value >> 31 == -1 || value >> 31 == 0))
02032 return 1;
02033
02034 #if HOST_BITS_PER_WIDE_INT == 64
02035 else if (TARGET_POWERPC64)
02036 {
02037 HOST_WIDE_INT low = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
02038 HOST_WIDE_INT high = value >> 31;
02039
02040 if (high == 0 || high == -1)
02041 return 2;
02042
02043 high >>= 1;
02044
02045 if (low == 0)
02046 return num_insns_constant_wide (high) + 1;
02047 else
02048 return (num_insns_constant_wide (high)
02049 + num_insns_constant_wide (low) + 1);
02050 }
02051 #endif
02052
02053 else
02054 return 2;
02055 }
02056
02057 int
02058 num_insns_constant (rtx op, enum machine_mode mode)
02059 {
02060 HOST_WIDE_INT low, high;
02061
02062 switch (GET_CODE (op))
02063 {
02064 case CONST_INT:
02065 #if HOST_BITS_PER_WIDE_INT == 64
02066 if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
02067 && mask64_operand (op, mode))
02068 return 2;
02069 else
02070 #endif
02071 return num_insns_constant_wide (INTVAL (op));
02072
02073 case CONST_DOUBLE:
02074 if (mode == SFmode)
02075 {
02076 long l;
02077 REAL_VALUE_TYPE rv;
02078
02079 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02080 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
02081 return num_insns_constant_wide ((HOST_WIDE_INT) l);
02082 }
02083
02084 if (mode == VOIDmode || mode == DImode)
02085 {
02086 high = CONST_DOUBLE_HIGH (op);
02087 low = CONST_DOUBLE_LOW (op);
02088 }
02089 else
02090 {
02091 long l[2];
02092 REAL_VALUE_TYPE rv;
02093
02094 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02095 REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
02096 high = l[WORDS_BIG_ENDIAN == 0];
02097 low = l[WORDS_BIG_ENDIAN != 0];
02098 }
02099
02100 if (TARGET_32BIT)
02101 return (num_insns_constant_wide (low)
02102 + num_insns_constant_wide (high));
02103 else
02104 {
02105 if ((high == 0 && low >= 0)
02106 || (high == -1 && low < 0))
02107 return num_insns_constant_wide (low);
02108
02109 else if (mask64_operand (op, mode))
02110 return 2;
02111
02112 else if (low == 0)
02113 return num_insns_constant_wide (high) + 1;
02114
02115 else
02116 return (num_insns_constant_wide (high)
02117 + num_insns_constant_wide (low) + 1);
02118 }
02119
02120 default:
02121 gcc_unreachable ();
02122 }
02123 }
02124
02125
02126
02127
02128
02129
02130 static HOST_WIDE_INT
02131 const_vector_elt_as_int (rtx op, unsigned int elt)
02132 {
02133 rtx tmp = CONST_VECTOR_ELT (op, elt);
02134 if (GET_MODE (op) == V4SFmode
02135 || GET_MODE (op) == V2SFmode)
02136 tmp = gen_lowpart (SImode, tmp);
02137 return INTVAL (tmp);
02138 }
02139
02140
02141
02142
02143
02144
02145
02146
02147 static bool
02148 vspltis_constant (rtx op, unsigned step, unsigned copies)
02149 {
02150 enum machine_mode mode = GET_MODE (op);
02151 enum machine_mode inner = GET_MODE_INNER (mode);
02152
02153 unsigned i;
02154 unsigned nunits = GET_MODE_NUNITS (mode);
02155 unsigned bitsize = GET_MODE_BITSIZE (inner);
02156 unsigned mask = GET_MODE_MASK (inner);
02157
02158 HOST_WIDE_INT val = const_vector_elt_as_int (op, nunits - 1);
02159 HOST_WIDE_INT splat_val = val;
02160 HOST_WIDE_INT msb_val = val > 0 ? 0 : -1;
02161
02162
02163 for (i = 2; i <= copies; i *= 2)
02164 {
02165 HOST_WIDE_INT small_val;
02166 bitsize /= 2;
02167 small_val = splat_val >> bitsize;
02168 mask >>= bitsize;
02169 if (splat_val != ((small_val << bitsize) | (small_val & mask)))
02170 return false;
02171 splat_val = small_val;
02172 }
02173
02174
02175 if (EASY_VECTOR_15 (splat_val))
02176 ;
02177
02178
02179
02180
02181 else if (EASY_VECTOR_15_ADD_SELF (splat_val)
02182 && (splat_val >= 0 || (step == 1 && copies == 1)))
02183 ;
02184
02185 else
02186 return false;
02187
02188
02189
02190 for (i = 0; i < nunits - 1; ++i)
02191 {
02192 HOST_WIDE_INT desired_val;
02193 if (((i + 1) & (step - 1)) == 0)
02194 desired_val = val;
02195 else
02196 desired_val = msb_val;
02197
02198 if (desired_val != const_vector_elt_as_int (op, i))
02199 return false;
02200 }
02201
02202 return true;
02203 }
02204
02205
02206
02207
02208
02209 bool
02210 easy_altivec_constant (rtx op, enum machine_mode mode)
02211 {
02212 unsigned step, copies;
02213
02214 if (mode == VOIDmode)
02215 mode = GET_MODE (op);
02216 else if (mode != GET_MODE (op))
02217 return false;
02218
02219
02220 step = GET_MODE_NUNITS (mode) / 4;
02221 copies = 1;
02222
02223 if (vspltis_constant (op, step, copies))
02224 return true;
02225
02226
02227 if (step == 1)
02228 copies <<= 1;
02229 else
02230 step >>= 1;
02231
02232 if (vspltis_constant (op, step, copies))
02233 return true;
02234
02235
02236 if (step == 1)
02237 copies <<= 1;
02238 else
02239 step >>= 1;
02240
02241 if (vspltis_constant (op, step, copies))
02242 return true;
02243
02244 return false;
02245 }
02246
02247
02248
02249
02250 rtx
02251 gen_easy_altivec_constant (rtx op)
02252 {
02253 enum machine_mode mode = GET_MODE (op);
02254 int nunits = GET_MODE_NUNITS (mode);
02255 rtx last = CONST_VECTOR_ELT (op, nunits - 1);
02256 unsigned step = nunits / 4;
02257 unsigned copies = 1;
02258
02259
02260 if (vspltis_constant (op, step, copies))
02261 return gen_rtx_VEC_DUPLICATE (V4SImode, gen_lowpart (SImode, last));
02262
02263
02264 if (step == 1)
02265 copies <<= 1;
02266 else
02267 step >>= 1;
02268
02269 if (vspltis_constant (op, step, copies))
02270 return gen_rtx_VEC_DUPLICATE (V8HImode, gen_lowpart (HImode, last));
02271
02272
02273 if (step == 1)
02274 copies <<= 1;
02275 else
02276 step >>= 1;
02277
02278 if (vspltis_constant (op, step, copies))
02279 return gen_rtx_VEC_DUPLICATE (V16QImode, gen_lowpart (QImode, last));
02280
02281 gcc_unreachable ();
02282 }
02283
02284 const char *
02285 output_vec_const_move (rtx *operands)
02286 {
02287 int cst, cst2;
02288 enum machine_mode mode;
02289 rtx dest, vec;
02290
02291 dest = operands[0];
02292 vec = operands[1];
02293 mode = GET_MODE (dest);
02294
02295 if (TARGET_ALTIVEC)
02296 {
02297 rtx splat_vec;
02298 if (zero_constant (vec, mode))
02299 return "vxor %0,%0,%0";
02300
02301 splat_vec = gen_easy_altivec_constant (vec);
02302 gcc_assert (GET_CODE (splat_vec) == VEC_DUPLICATE);
02303 operands[1] = XEXP (splat_vec, 0);
02304 if (!EASY_VECTOR_15 (INTVAL (operands[1])))
02305 return "#";
02306
02307 switch (GET_MODE (splat_vec))
02308 {
02309 case V4SImode:
02310 return "vspltisw %0,%1";
02311
02312 case V8HImode:
02313 return "vspltish %0,%1";
02314
02315 case V16QImode:
02316 return "vspltisb %0,%1";
02317
02318 default:
02319 gcc_unreachable ();
02320 }
02321 }
02322
02323 gcc_assert (TARGET_SPE);
02324
02325
02326
02327
02328
02329
02330 cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
02331 cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
02332 operands[1] = CONST_VECTOR_ELT (vec, 0);
02333 operands[2] = CONST_VECTOR_ELT (vec, 1);
02334 if (cst == cst2)
02335 return "li %0,%1\n\tevmergelo %0,%0,%0";
02336 else
02337 return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
02338 }
02339
02340
02341
02342 void
02343 rs6000_expand_vector_init (rtx target, rtx vals)
02344 {
02345 enum machine_mode mode = GET_MODE (target);
02346 enum machine_mode inner_mode = GET_MODE_INNER (mode);
02347 int n_elts = GET_MODE_NUNITS (mode);
02348 int n_var = 0, one_var = -1;
02349 bool all_same = true, all_const_zero = true;
02350 rtx x, mem;
02351 int i;
02352
02353 for (i = 0; i < n_elts; ++i)
02354 {
02355 x = XVECEXP (vals, 0, i);
02356 if (!CONSTANT_P (x))
02357 ++n_var, one_var = i;
02358 else if (x != CONST0_RTX (inner_mode))
02359 all_const_zero = false;
02360
02361 if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
02362 all_same = false;
02363 }
02364
02365 if (n_var == 0)
02366 {
02367 if (mode != V4SFmode && all_const_zero)
02368 {
02369
02370 emit_insn (gen_rtx_SET (VOIDmode, target,
02371 gen_rtx_XOR (mode, target, target)));
02372 return;
02373 }
02374 else if (mode != V4SFmode && easy_vector_constant (vals, mode))
02375 {
02376
02377 emit_insn (gen_rtx_SET (VOIDmode, target, vals));
02378 return;
02379 }
02380 else if (all_same)
02381 ;
02382 else
02383 {
02384
02385 emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
02386 return;
02387 }
02388 }
02389
02390
02391 if (all_same)
02392 {
02393 mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
02394 emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
02395 XVECEXP (vals, 0, 0));
02396 x = gen_rtx_UNSPEC (VOIDmode,
02397 gen_rtvec (1, const0_rtx), UNSPEC_LVE);
02398 emit_insn (gen_rtx_PARALLEL (VOIDmode,
02399 gen_rtvec (2,
02400 gen_rtx_SET (VOIDmode,
02401 target, mem),
02402 x)));
02403 x = gen_rtx_VEC_SELECT (inner_mode, target,
02404 gen_rtx_PARALLEL (VOIDmode,
02405 gen_rtvec (1, const0_rtx)));
02406 emit_insn (gen_rtx_SET (VOIDmode, target,
02407 gen_rtx_VEC_DUPLICATE (mode, x)));
02408 return;
02409 }
02410
02411
02412
02413 if (n_var == 1)
02414 {
02415 rtx copy = copy_rtx (vals);
02416
02417
02418
02419 XVECEXP (copy, 0, one_var) = XVECEXP (vals, 0, (one_var + 1) % n_elts);
02420 rs6000_expand_vector_init (target, copy);
02421
02422
02423 rs6000_expand_vector_set (target, XVECEXP (vals, 0, one_var), one_var);
02424 return;
02425 }
02426
02427
02428
02429 mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
02430 for (i = 0; i < n_elts; i++)
02431 emit_move_insn (adjust_address_nv (mem, inner_mode,
02432 i * GET_MODE_SIZE (inner_mode)),
02433 XVECEXP (vals, 0, i));
02434 emit_move_insn (target, mem);
02435 }
02436
02437
02438
02439 void
02440 rs6000_expand_vector_set (rtx target, rtx val, int elt)
02441 {
02442 enum machine_mode mode = GET_MODE (target);
02443 enum machine_mode inner_mode = GET_MODE_INNER (mode);
02444 rtx reg = gen_reg_rtx (mode);
02445 rtx mask, mem, x;
02446 int width = GET_MODE_SIZE (inner_mode);
02447 int i;
02448
02449
02450 mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
02451 emit_move_insn (adjust_address_nv (mem, inner_mode, 0), val);
02452 x = gen_rtx_UNSPEC (VOIDmode,
02453 gen_rtvec (1, const0_rtx), UNSPEC_LVE);
02454 emit_insn (gen_rtx_PARALLEL (VOIDmode,
02455 gen_rtvec (2,
02456 gen_rtx_SET (VOIDmode,
02457 reg, mem),
02458 x)));
02459
02460
02461 mask = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
02462 for (i = 0; i < 16; ++i)
02463 XVECEXP (mask, 0, i) = GEN_INT (i);
02464
02465
02466 for (i = 0; i < width; ++i)
02467 XVECEXP (mask, 0, elt*width + i)
02468 = GEN_INT (i + 0x10);
02469 x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
02470 x = gen_rtx_UNSPEC (mode,
02471 gen_rtvec (3, target, reg,
02472 force_reg (V16QImode, x)),
02473 UNSPEC_VPERM);
02474 emit_insn (gen_rtx_SET (VOIDmode, target, x));
02475 }
02476
02477
02478
02479 void
02480 rs6000_expand_vector_extract (rtx target, rtx vec, int elt)
02481 {
02482 enum machine_mode mode = GET_MODE (vec);
02483 enum machine_mode inner_mode = GET_MODE_INNER (mode);
02484 rtx mem, x;
02485
02486
02487 mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
02488
02489
02490 mem = adjust_address_nv (mem, mode, elt * GET_MODE_SIZE (inner_mode));
02491
02492
02493 x = gen_rtx_UNSPEC (VOIDmode,
02494 gen_rtvec (1, const0_rtx), UNSPEC_STVE);
02495 emit_insn (gen_rtx_PARALLEL (VOIDmode,
02496 gen_rtvec (2,
02497 gen_rtx_SET (VOIDmode,
02498 mem, vec),
02499 x)));
02500 emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
02501 }
02502
02503
02504
02505 void
02506 build_mask64_2_operands (rtx in, rtx *out)
02507 {
02508 #if HOST_BITS_PER_WIDE_INT >= 64
02509 unsigned HOST_WIDE_INT c, lsb, m1, m2;
02510 int shift;
02511
02512 gcc_assert (GET_CODE (in) == CONST_INT);
02513
02514 c = INTVAL (in);
02515 if (c & 1)
02516 {
02517
02518
02519
02520
02521
02522 c = ~c;
02523 lsb = c & -c;
02524 m1 = -lsb;
02525 c = ~c;
02526 c &= -lsb;
02527 lsb = c & -c;
02528 c = ~c;
02529 c &= -lsb;
02530 shift = 0;
02531 while ((lsb >>= 1) != 0)
02532 shift++;
02533 m1 <<= 64 - shift;
02534 m1 = ~m1;
02535 m2 = ~c;
02536 }
02537 else
02538 {
02539
02540
02541
02542
02543
02544 lsb = c & -c;
02545 m2 = -lsb;
02546 c = ~c;
02547 c &= -lsb;
02548 lsb = c & -c;
02549 c = ~c;
02550 c &= -lsb;
02551 shift = 0;
02552 while ((lsb >>= 1) != 0)
02553 shift++;
02554 m1 = ~c;
02555 m1 >>= shift;
02556 m1 = ~m1;
02557 }
02558
02559
02560
02561 out[0] = GEN_INT (64 - shift);
02562 out[1] = GEN_INT (m1);
02563 out[2] = GEN_INT (shift);
02564 out[3] = GEN_INT (m2);
02565 #else
02566 (void)in;
02567 (void)out;
02568 gcc_unreachable ();
02569 #endif
02570 }
02571
02572
02573
02574 bool
02575 invalid_e500_subreg (rtx op, enum machine_mode mode)
02576 {
02577 if (TARGET_E500_DOUBLE)
02578 {
02579
02580 if (GET_CODE (op) == SUBREG
02581 && mode == SImode
02582 && REG_P (SUBREG_REG (op))
02583 && GET_MODE (SUBREG_REG (op)) == DFmode)
02584 return true;
02585
02586
02587 if (GET_CODE (op) == SUBREG
02588 && mode == DFmode
02589 && REG_P (SUBREG_REG (op))
02590 && GET_MODE (SUBREG_REG (op)) == DImode)
02591 return true;
02592 }
02593
02594 if (TARGET_SPE
02595 && GET_CODE (op) == SUBREG
02596 && mode == SImode
02597 && REG_P (SUBREG_REG (op))
02598 && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op))))
02599 return true;
02600
02601 return false;
02602 }
02603
02604
02605
02606
02607 unsigned int
02608 rs6000_special_round_type_align (tree type, unsigned int computed,
02609 unsigned int specified)
02610 {
02611 unsigned int align = MAX (computed, specified);
02612 tree field = TYPE_FIELDS (type);
02613
02614
02615 while (field != NULL && TREE_CODE (field) != FIELD_DECL)
02616 field = TREE_CHAIN (field);
02617
02618 if (field != NULL && field != type)
02619 {
02620 type = TREE_TYPE (field);
02621 while (TREE_CODE (type) == ARRAY_TYPE)
02622 type = TREE_TYPE (type);
02623
02624 if (type != error_mark_node && TYPE_MODE (type) == DFmode)
02625 align = MAX (align, 64);
02626 }
02627
02628 return align;
02629 }
02630
02631
02632
02633 int
02634 small_data_operand (rtx op ATTRIBUTE_UNUSED,
02635 enum machine_mode mode ATTRIBUTE_UNUSED)
02636 {
02637 #if TARGET_ELF
02638 rtx sym_ref;
02639
02640 if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
02641 return 0;
02642
02643 if (DEFAULT_ABI != ABI_V4)
02644 return 0;
02645
02646 if (GET_CODE (op) == SYMBOL_REF)
02647 sym_ref = op;
02648
02649 else if (GET_CODE (op) != CONST
02650 || GET_CODE (XEXP (op, 0)) != PLUS
02651 || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF
02652 || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT)
02653 return 0;
02654
02655 else
02656 {
02657 rtx sum = XEXP (op, 0);
02658 HOST_WIDE_INT summand;
02659
02660
02661
02662 summand = INTVAL (XEXP (sum, 1));
02663 if (summand < 0 || (unsigned HOST_WIDE_INT) summand > g_switch_value)
02664 return 0;
02665
02666 sym_ref = XEXP (sum, 0);
02667 }
02668
02669 return SYMBOL_REF_SMALL_P (sym_ref);
02670 #else
02671 return 0;
02672 #endif
02673 }
02674
02675
02676
02677 bool
02678 gpr_or_gpr_p (rtx op0, rtx op1)
02679 {
02680 return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
02681 || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
02682 }
02683
02684
02685
02686
02687 static int
02688 constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc)
02689 {
02690 switch (GET_CODE (op))
02691 {
02692 case SYMBOL_REF:
02693 if (RS6000_SYMBOL_REF_TLS_P (op))
02694 return 0;
02695 else if (CONSTANT_POOL_ADDRESS_P (op))
02696 {
02697 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
02698 {
02699 *have_sym = 1;
02700 return 1;
02701 }
02702 else
02703 return 0;
02704 }
02705 else if (! strcmp (XSTR (op, 0), toc_label_name))
02706 {
02707 *have_toc = 1;
02708 return 1;
02709 }
02710 else
02711 return 0;
02712 case PLUS:
02713 case MINUS:
02714 return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc)
02715 && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc));
02716 case CONST:
02717 return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc);
02718 case CONST_INT:
02719 return 1;
02720 default:
02721 return 0;
02722 }
02723 }
02724
02725 static bool
02726 constant_pool_expr_p (rtx op)
02727 {
02728 int have_sym = 0;
02729 int have_toc = 0;
02730 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
02731 }
02732
02733 bool
02734 toc_relative_expr_p (rtx op)
02735 {
02736 int have_sym = 0;
02737 int have_toc = 0;
02738 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
02739 }
02740
02741 bool
02742 legitimate_constant_pool_address_p (rtx x)
02743 {
02744 return (TARGET_TOC
02745 && GET_CODE (x) == PLUS
02746 && GET_CODE (XEXP (x, 0)) == REG
02747 && (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER)
02748 && constant_pool_expr_p (XEXP (x, 1)));
02749 }
02750
02751 static bool
02752 legitimate_small_data_p (enum machine_mode mode, rtx x)
02753 {
02754 return (DEFAULT_ABI == ABI_V4
02755 && !flag_pic && !TARGET_TOC
02756 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)
02757 && small_data_operand (x, mode));
02758 }
02759
02760
02761 #define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
02762
02763 bool
02764 rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
02765 {
02766 unsigned HOST_WIDE_INT offset, extra;
02767
02768 if (GET_CODE (x) != PLUS)
02769 return false;
02770 if (GET_CODE (XEXP (x, 0)) != REG)
02771 return false;
02772 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
02773 return false;
02774 if (legitimate_constant_pool_address_p (x))
02775 return true;
02776 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
02777 return false;
02778
02779 offset = INTVAL (XEXP (x, 1));
02780 extra = 0;
02781 switch (mode)
02782 {
02783 case V16QImode:
02784 case V8HImode:
02785 case V4SFmode:
02786 case V4SImode:
02787
02788
02789
02790 return !strict;
02791
02792 case V4HImode:
02793 case V2SImode:
02794 case V1DImode:
02795 case V2SFmode:
02796
02797 return SPE_CONST_OFFSET_OK (offset);
02798
02799 case DFmode:
02800 if (TARGET_E500_DOUBLE)
02801 return SPE_CONST_OFFSET_OK (offset);
02802
02803 case DImode:
02804
02805
02806
02807
02808
02809 if (TARGET_E500_DOUBLE)
02810 return SPE_CONST_OFFSET_OK (offset);
02811
02812 if (mode == DFmode || !TARGET_POWERPC64)
02813 extra = 4;
02814 else if (offset & 3)
02815 return false;
02816 break;
02817
02818 case TFmode:
02819 case TImode:
02820 if (mode == TFmode || !TARGET_POWERPC64)
02821 extra = 12;
02822 else if (offset & 3)
02823 return false;
02824 else
02825 extra = 8;
02826 break;
02827
02828 default:
02829 break;
02830 }
02831
02832 offset += 0x8000;
02833 return (offset < 0x10000) && (offset + extra < 0x10000);
02834 }
02835
02836 static bool
02837 legitimate_indexed_address_p (rtx x, int strict)
02838 {
02839 rtx op0, op1;
02840
02841 if (GET_CODE (x) != PLUS)
02842 return false;
02843
02844 op0 = XEXP (x, 0);
02845 op1 = XEXP (x, 1);
02846
02847
02848
02849 if (!strict
02850 && reload_in_progress
02851 && (REG_P (op0) || GET_CODE (op0) == PLUS)
02852 && REG_P (op1))
02853 return true;
02854
02855 return (REG_P (op0) && REG_P (op1)
02856 && ((INT_REG_OK_FOR_BASE_P (op0, strict)
02857 && INT_REG_OK_FOR_INDEX_P (op1, strict))
02858 || (INT_REG_OK_FOR_BASE_P (op1, strict)
02859 && INT_REG_OK_FOR_INDEX_P (op0, strict))));
02860 }
02861
02862 inline bool
02863 legitimate_indirect_address_p (rtx x, int strict)
02864 {
02865 return GET_CODE (x) == REG && INT_REG_OK_FOR_BASE_P (x, strict);
02866 }
02867
02868 bool
02869 macho_lo_sum_memory_operand (rtx x, enum machine_mode mode)
02870 {
02871 if (!TARGET_MACHO || !flag_pic
02872 || mode != SImode || GET_CODE (x) != MEM)
02873 return false;
02874 x = XEXP (x, 0);
02875
02876 if (GET_CODE (x) != LO_SUM)
02877 return false;
02878 if (GET_CODE (XEXP (x, 0)) != REG)
02879 return false;
02880 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 0))
02881 return false;
02882 x = XEXP (x, 1);
02883
02884 return CONSTANT_P (x);
02885 }
02886
02887 static bool
02888 legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
02889 {
02890 if (GET_CODE (x) != LO_SUM)
02891 return false;
02892 if (GET_CODE (XEXP (x, 0)) != REG)
02893 return false;
02894 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
02895 return false;
02896
02897 if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
02898 return false;
02899 x = XEXP (x, 1);
02900
02901 if (TARGET_ELF || TARGET_MACHO)
02902 {
02903 if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
02904 return false;
02905 if (TARGET_TOC)
02906 return false;
02907 if (GET_MODE_NUNITS (mode) != 1)
02908 return false;
02909 if (GET_MODE_BITSIZE (mode) > 64
02910 || (GET_MODE_BITSIZE (mode) > 32 && !TARGET_POWERPC64
02911 && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode)))
02912 return false;
02913
02914 return CONSTANT_P (x);
02915 }
02916
02917 return false;
02918 }
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944 rtx
02945 rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
02946 enum machine_mode mode)
02947 {
02948 if (GET_CODE (x) == SYMBOL_REF)
02949 {
02950 enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
02951 if (model != 0)
02952 return rs6000_legitimize_tls_address (x, model);
02953 }
02954
02955 if (GET_CODE (x) == PLUS
02956 && GET_CODE (XEXP (x, 0)) == REG
02957 && GET_CODE (XEXP (x, 1)) == CONST_INT
02958 && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000)
02959 {
02960 HOST_WIDE_INT high_int, low_int;
02961 rtx sum;
02962 low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;
02963 high_int = INTVAL (XEXP (x, 1)) - low_int;
02964 sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
02965 GEN_INT (high_int)), 0);
02966 return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
02967 }
02968 else if (GET_CODE (x) == PLUS
02969 && GET_CODE (XEXP (x, 0)) == REG
02970 && GET_CODE (XEXP (x, 1)) != CONST_INT
02971 && GET_MODE_NUNITS (mode) == 1
02972 && ((TARGET_HARD_FLOAT && TARGET_FPRS)
02973 || TARGET_POWERPC64
02974 || (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE)
02975 && mode != TFmode))
02976 && (TARGET_POWERPC64 || mode != DImode)
02977 && mode != TImode)
02978 {
02979 return gen_rtx_PLUS (Pmode, XEXP (x, 0),
02980 force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
02981 }
02982 else if (ALTIVEC_VECTOR_MODE (mode))
02983 {
02984 rtx reg;
02985
02986
02987 if (GET_CODE (x) == PLUS)
02988 return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
02989 force_reg (Pmode, XEXP (x, 1)));
02990
02991 reg = force_reg (Pmode, x);
02992 return reg;
02993 }
02994 else if (SPE_VECTOR_MODE (mode)
02995 || (TARGET_E500_DOUBLE && (mode == DFmode
02996 || mode == DImode)))
02997 {
02998 if (mode == DImode)
02999 return NULL_RTX;
03000
03001
03002 if (GET_CODE (x) == PLUS)
03003 {
03004 rtx op1 = XEXP (x, 0);
03005 rtx op2 = XEXP (x, 1);
03006
03007 op1 = force_reg (Pmode, op1);
03008
03009 if (GET_CODE (op2) != REG
03010 && (GET_CODE (op2) != CONST_INT
03011 || !SPE_CONST_OFFSET_OK (INTVAL (op2))))
03012 op2 = force_reg (Pmode, op2);
03013
03014 return gen_rtx_PLUS (Pmode, op1, op2);
03015 }
03016
03017 return force_reg (Pmode, x);
03018 }
03019 else if (TARGET_ELF
03020 && TARGET_32BIT
03021 && TARGET_NO_TOC
03022 && ! flag_pic
03023 && GET_CODE (x) != CONST_INT
03024 && GET_CODE (x) != CONST_DOUBLE
03025 && CONSTANT_P (x)
03026 && GET_MODE_NUNITS (mode) == 1
03027 && (GET_MODE_BITSIZE (mode) <= 32
03028 || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode)))
03029 {
03030 rtx reg = gen_reg_rtx (Pmode);
03031 emit_insn (gen_elf_high (reg, x));
03032 return gen_rtx_LO_SUM (Pmode, reg, x);
03033 }
03034 else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
03035 && ! flag_pic
03036 #if TARGET_MACHO
03037 && ! MACHO_DYNAMIC_NO_PIC_P
03038 #endif
03039 && GET_CODE (x) != CONST_INT
03040 && GET_CODE (x) != CONST_DOUBLE
03041 && CONSTANT_P (x)
03042 && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
03043 && mode != DImode
03044 && mode != TImode)
03045 {
03046 rtx reg = gen_reg_rtx (Pmode);
03047 emit_insn (gen_macho_high (reg, x));
03048 return gen_rtx_LO_SUM (Pmode, reg, x);
03049 }
03050 else if (TARGET_TOC
03051 && constant_pool_expr_p (x)
03052 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
03053 {
03054 return create_TOC_reference (x);
03055 }
03056 else
03057 return NULL_RTX;
03058 }
03059
03060
03061
03062
03063 static void
03064 rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
03065 {
03066 switch (size)
03067 {
03068 case 4:
03069 fputs ("\t.long\t", file);
03070 break;
03071 case 8:
03072 fputs (DOUBLE_INT_ASM_OP, file);
03073 break;
03074 default:
03075 gcc_unreachable ();
03076 }
03077 output_addr_const (file, x);
03078 fputs ("@dtprel+0x8000", file);
03079 }
03080
03081
03082
03083 static GTY(()) rtx rs6000_tls_symbol;
03084 static rtx
03085 rs6000_tls_get_addr (void)
03086 {
03087 if (!rs6000_tls_symbol)
03088 rs6000_tls_symbol = init_one_libfunc ("__tls_get_addr");
03089
03090 return rs6000_tls_symbol;
03091 }
03092
03093
03094
03095 static GTY(()) rtx rs6000_got_symbol;
03096 static rtx
03097 rs6000_got_sym (void)
03098 {
03099 if (!rs6000_got_symbol)
03100 {
03101 rs6000_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
03102 SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_LOCAL;
03103 SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_EXTERNAL;
03104 }
03105
03106 return rs6000_got_symbol;
03107 }
03108
03109
03110
03111
03112 static rtx
03113 rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
03114 {
03115 rtx dest, insn;
03116
03117 dest = gen_reg_rtx (Pmode);
03118 if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
03119 {
03120 rtx tlsreg;
03121
03122 if (TARGET_64BIT)
03123 {
03124 tlsreg = gen_rtx_REG (Pmode, 13);
03125 insn = gen_tls_tprel_64 (dest, tlsreg, addr);
03126 }
03127 else
03128 {
03129 tlsreg = gen_rtx_REG (Pmode, 2);
03130 insn = gen_tls_tprel_32 (dest, tlsreg, addr);
03131 }
03132 emit_insn (insn);
03133 }
03134 else if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 32)
03135 {
03136 rtx tlsreg, tmp;
03137
03138 tmp = gen_reg_rtx (Pmode);
03139 if (TARGET_64BIT)
03140 {
03141 tlsreg = gen_rtx_REG (Pmode, 13);
03142 insn = gen_tls_tprel_ha_64 (tmp, tlsreg, addr);
03143 }
03144 else
03145 {
03146 tlsreg = gen_rtx_REG (Pmode, 2);
03147 insn = gen_tls_tprel_ha_32 (tmp, tlsreg, addr);
03148 }
03149 emit_insn (insn);
03150 if (TARGET_64BIT)
03151 insn = gen_tls_tprel_lo_64 (dest, tmp, addr);
03152 else
03153 insn = gen_tls_tprel_lo_32 (dest, tmp, addr);
03154 emit_insn (insn);
03155 }
03156 else
03157 {
03158 rtx r3, got, tga, tmp1, tmp2, eqv;
03159
03160
03161
03162
03163
03164
03165 if (TARGET_64BIT)
03166 got = gen_rtx_REG (Pmode, 2);
03167 else
03168 {
03169 if (flag_pic == 1)
03170 got = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
03171 else
03172 {
03173 rtx gsym = rs6000_got_sym ();
03174 got = gen_reg_rtx (Pmode);
03175 if (flag_pic == 0)
03176 rs6000_emit_move (got, gsym, Pmode);
03177 else
03178 {
03179 rtx tempLR, tmp3, mem;
03180 rtx first, last;
03181
03182 tempLR = gen_reg_rtx (Pmode);
03183 tmp1 = gen_reg_rtx (Pmode);
03184 tmp2 = gen_reg_rtx (Pmode);
03185 tmp3 = gen_reg_rtx (Pmode);
03186 mem = gen_const_mem (Pmode, tmp1);
03187
03188 first = emit_insn (gen_load_toc_v4_PIC_1b (tempLR, gsym));
03189 emit_move_insn (tmp1, tempLR);
03190 emit_move_insn (tmp2, mem);
03191 emit_insn (gen_addsi3 (tmp3, tmp1, tmp2));
03192 last = emit_move_insn (got, tmp3);
03193 REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, gsym,
03194 REG_NOTES (last));
03195 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
03196 REG_NOTES (first));
03197 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
03198 REG_NOTES (last));
03199 }
03200 }
03201 }
03202
03203 if (model == TLS_MODEL_GLOBAL_DYNAMIC)
03204 {
03205 r3 = gen_rtx_REG (Pmode, 3);
03206 if (TARGET_64BIT)
03207 insn = gen_tls_gd_64 (r3, got, addr);
03208 else
03209 insn = gen_tls_gd_32 (r3, got, addr);
03210 start_sequence ();
03211 emit_insn (insn);
03212 tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
03213 insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
03214 insn = emit_call_insn (insn);
03215 CONST_OR_PURE_CALL_P (insn) = 1;
03216 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
03217 insn = get_insns ();
03218 end_sequence ();
03219 emit_libcall_block (insn, dest, r3, addr);
03220 }
03221 else if (model == TLS_MODEL_LOCAL_DYNAMIC)
03222 {
03223 r3 = gen_rtx_REG (Pmode, 3);
03224 if (TARGET_64BIT)
03225 insn = gen_tls_ld_64 (r3, got);
03226 else
03227 insn = gen_tls_ld_32 (r3, got);
03228 start_sequence ();
03229 emit_insn (insn);
03230 tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
03231 insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
03232 insn = emit_call_insn (insn);
03233 CONST_OR_PURE_CALL_P (insn) = 1;
03234 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
03235 insn = get_insns ();
03236 end_sequence ();
03237 tmp1 = gen_reg_rtx (Pmode);
03238 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
03239 UNSPEC_TLSLD);
03240 emit_libcall_block (insn, tmp1, r3, eqv);
03241 if (rs6000_tls_size == 16)
03242 {
03243 if (TARGET_64BIT)
03244 insn = gen_tls_dtprel_64 (dest, tmp1, addr);
03245 else
03246 insn = gen_tls_dtprel_32 (dest, tmp1, addr);
03247 }
03248 else if (rs6000_tls_size == 32)
03249 {
03250 tmp2 = gen_reg_rtx (Pmode);
03251 if (TARGET_64BIT)
03252 insn = gen_tls_dtprel_ha_64 (tmp2, tmp1, addr);
03253 else
03254 insn = gen_tls_dtprel_ha_32 (tmp2, tmp1, addr);
03255 emit_insn (insn);
03256 if (TARGET_64BIT)
03257 insn = gen_tls_dtprel_lo_64 (dest, tmp2, addr);
03258 else
03259 insn = gen_tls_dtprel_lo_32 (dest, tmp2, addr);
03260 }
03261 else
03262 {
03263 tmp2 = gen_reg_rtx (Pmode);
03264 if (TARGET_64BIT)
03265 insn = gen_tls_got_dtprel_64 (tmp2, got, addr);
03266 else
03267 insn = gen_tls_got_dtprel_32 (tmp2, got, addr);
03268 emit_insn (insn);
03269 insn = gen_rtx_SET (Pmode, dest,
03270 gen_rtx_PLUS (Pmode, tmp2, tmp1));
03271 }
03272 emit_insn (insn);
03273 }
03274 else
03275 {
03276
03277 tmp2 = gen_reg_rtx (Pmode);
03278 if (TARGET_64BIT)
03279 insn = gen_tls_got_tprel_64 (tmp2, got, addr);
03280 else
03281 insn = gen_tls_got_tprel_32 (tmp2, got, addr);
03282 emit_insn (insn);
03283 if (TARGET_64BIT)
03284 insn = gen_tls_tls_64 (dest, tmp2, addr);
03285 else
03286 insn = gen_tls_tls_32 (dest, tmp2, addr);
03287 emit_insn (insn);
03288 }
03289 }
03290
03291 return dest;
03292 }
03293
03294
03295
03296 bool
03297 rs6000_tls_referenced_p (rtx x)
03298 {
03299 if (! TARGET_HAVE_TLS)
03300 return false;
03301
03302 return for_each_rtx (&x, &rs6000_tls_symbol_ref_1, 0);
03303 }
03304
03305
03306
03307
03308 static int
03309 rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
03310 {
03311 return RS6000_SYMBOL_REF_TLS_P (*x);
03312 }
03313
03314
03315
03316
03317 #ifndef REG_MODE_OK_FOR_BASE_P
03318 #define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
03319 #endif
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334 rtx
03335 rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
03336 int opnum, int type,
03337 int ind_levels ATTRIBUTE_UNUSED, int *win)
03338 {
03339
03340 if (GET_CODE (x) == PLUS
03341 && GET_CODE (XEXP (x, 0)) == PLUS
03342 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
03343 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03344 && GET_CODE (XEXP (x, 1)) == CONST_INT)
03345 {
03346 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03347 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03348 opnum, (enum reload_type)type);
03349 *win = 1;
03350 return x;
03351 }
03352
03353 #if TARGET_MACHO
03354 if (DEFAULT_ABI == ABI_DARWIN && flag_pic
03355 && GET_CODE (x) == LO_SUM
03356 && GET_CODE (XEXP (x, 0)) == PLUS
03357 && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
03358 && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
03359 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST
03360 && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
03361 && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS
03362 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF
03363 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF)
03364 {
03365
03366
03367 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03368 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
03369 opnum, (enum reload_type)type);
03370 *win = 1;
03371 return x;
03372 }
03373 #endif
03374
03375
03376
03377 if (GET_CODE (x) == PLUS
03378 && GET_CODE (XEXP (x, 0)) == REG
03379 && REGNO (XEXP (x, 0)) < 32
03380 && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
03381 && GET_CODE (XEXP (x, 1)) == CONST_INT
03382 && (INTVAL (XEXP (x, 1)) & 3) != 0
03383 && !ALTIVEC_VECTOR_MODE (mode)
03384 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
03385 && TARGET_POWERPC64)
03386 {
03387 x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
03388 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03389 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03390 opnum, (enum reload_type) type);
03391 *win = 1;
03392 return x;
03393 }
03394
03395 if (GET_CODE (x) == PLUS
03396 && GET_CODE (XEXP (x, 0)) == REG
03397 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
03398 && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
03399 && GET_CODE (XEXP (x, 1)) == CONST_INT
03400 && !SPE_VECTOR_MODE (mode)
03401 && !(TARGET_E500_DOUBLE && (mode == DFmode
03402 || mode == DImode))
03403 && !ALTIVEC_VECTOR_MODE (mode))
03404 {
03405 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
03406 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
03407 HOST_WIDE_INT high
03408 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
03409
03410
03411 if (high + low != val)
03412 {
03413 *win = 0;
03414 return x;
03415 }
03416
03417
03418
03419
03420 x = gen_rtx_PLUS (GET_MODE (x),
03421 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
03422 GEN_INT (high)),
03423 GEN_INT (low));
03424
03425 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03426 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03427 opnum, (enum reload_type)type);
03428 *win = 1;
03429 return x;
03430 }
03431
03432 if (GET_CODE (x) == SYMBOL_REF
03433 && !ALTIVEC_VECTOR_MODE (mode)
03434 && !SPE_VECTOR_MODE (mode)
03435 #if TARGET_MACHO
03436 && DEFAULT_ABI == ABI_DARWIN
03437 && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
03438 #else
03439 && DEFAULT_ABI == ABI_V4
03440 && !flag_pic
03441 #endif
03442
03443
03444
03445 && mode != TFmode
03446 && (mode != DImode || TARGET_POWERPC64)
03447 && (mode != DFmode || TARGET_POWERPC64
03448 || (TARGET_FPRS && TARGET_HARD_FLOAT)))
03449 {
03450 #if TARGET_MACHO
03451 if (flag_pic)
03452 {
03453 rtx offset = gen_rtx_CONST (Pmode,
03454 gen_rtx_MINUS (Pmode, x,
03455 machopic_function_base_sym ()));
03456 x = gen_rtx_LO_SUM (GET_MODE (x),
03457 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
03458 gen_rtx_HIGH (Pmode, offset)), offset);
03459 }
03460 else
03461 #endif
03462 x = gen_rtx_LO_SUM (GET_MODE (x),
03463 gen_rtx_HIGH (Pmode, x), x);
03464
03465 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03466 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
03467 opnum, (enum reload_type)type);
03468 *win = 1;
03469 return x;
03470 }
03471
03472
03473
03474
03475 if (TARGET_ALTIVEC
03476 && ALTIVEC_VECTOR_MODE (mode)
03477 && GET_CODE (x) == AND
03478 && GET_CODE (XEXP (x, 0)) == PLUS
03479 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
03480 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03481 && GET_CODE (XEXP (x, 1)) == CONST_INT
03482 && INTVAL (XEXP (x, 1)) == -16)
03483 {
03484 x = XEXP (x, 0);
03485 *win = 1;
03486 return x;
03487 }
03488
03489 if (TARGET_TOC
03490 && constant_pool_expr_p (x)
03491 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
03492 {
03493 x = create_TOC_reference (x);
03494 *win = 1;
03495 return x;
03496 }
03497 *win = 0;
03498 return x;
03499 }
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518 int
03519 rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
03520 {
03521
03522 if (TARGET_ALTIVEC
03523 && ALTIVEC_VECTOR_MODE (mode)
03524 && GET_CODE (x) == AND
03525 && GET_CODE (XEXP (x, 1)) == CONST_INT
03526 && INTVAL (XEXP (x, 1)) == -16)
03527 x = XEXP (x, 0);
03528
03529 if (RS6000_SYMBOL_REF_TLS_P (x))
03530 return 0;
03531 if (legitimate_indirect_address_p (x, reg_ok_strict))
03532 return 1;
03533 if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
03534 && !ALTIVEC_VECTOR_MODE (mode)
03535 && !SPE_VECTOR_MODE (mode)
03536 && mode != TFmode
03537
03538 && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
03539 && TARGET_UPDATE
03540 && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
03541 return 1;
03542 if (legitimate_small_data_p (mode, x))
03543 return 1;
03544 if (legitimate_constant_pool_address_p (x))
03545 return 1;
03546
03547 if (! reg_ok_strict
03548 && GET_CODE (x) == PLUS
03549 && GET_CODE (XEXP (x, 0)) == REG
03550 && (XEXP (x, 0) == virtual_stack_vars_rtx
03551 || XEXP (x, 0) == arg_pointer_rtx)
03552 && GET_CODE (XEXP (x, 1)) == CONST_INT)
03553 return 1;
03554 if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
03555 return 1;
03556 if (mode != TImode
03557 && mode != TFmode
03558 && ((TARGET_HARD_FLOAT && TARGET_FPRS)
03559 || TARGET_POWERPC64
03560 || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
03561 && (TARGET_POWERPC64 || mode != DImode)
03562 && legitimate_indexed_address_p (x, reg_ok_strict))
03563 return 1;
03564 if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
03565 return 1;
03566 return 0;
03567 }
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580 bool
03581 rs6000_mode_dependent_address (rtx addr)
03582 {
03583 switch (GET_CODE (addr))
03584 {
03585 case PLUS:
03586 if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
03587 {
03588 unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
03589 return val + 12 + 0x8000 >= 0x10000;
03590 }
03591 break;
03592
03593 case LO_SUM:
03594 return true;
03595
03596 case PRE_INC:
03597 case PRE_DEC:
03598 return TARGET_UPDATE;
03599
03600 default:
03601 break;
03602 }
03603
03604 return false;
03605 }
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615 bool
03616 rs6000_offsettable_memref_p (rtx op)
03617 {
03618 if (!MEM_P (op))
03619 return false;
03620
03621
03622 if (offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)))
03623 return true;
03624
03625
03626
03627
03628
03629
03630
03631 return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
03632 }
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646 int
03647 rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
03648 {
03649 if (FP_REGNO_P (regno))
03650 return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
03651
03652 if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
03653 return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
03654
03655 if (ALTIVEC_REGNO_P (regno))
03656 return
03657 (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
03658
03659
03660
03661
03662
03663
03664 if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode)
03665 return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
03666
03667 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03668 }
03669
03670
03671 void
03672 rs6000_conditional_register_usage (void)
03673 {
03674 int i;
03675
03676
03677
03678
03679 if (! TARGET_POWER)
03680 fixed_regs[64] = 1;
03681
03682
03683 if (TARGET_64BIT)
03684 fixed_regs[13] = call_used_regs[13]
03685 = call_really_used_regs[13] = 1;
03686
03687
03688 if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
03689 for (i = 32; i < 64; i++)
03690 fixed_regs[i] = call_used_regs[i]
03691 = call_really_used_regs[i] = 1;
03692
03693
03694
03695 if (DEFAULT_ABI == ABI_AIX)
03696 call_really_used_regs[2] = 0;
03697
03698 if (DEFAULT_ABI == ABI_V4
03699 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
03700 && flag_pic == 2)
03701 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
03702
03703 if (DEFAULT_ABI == ABI_V4
03704 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
03705 && flag_pic == 1)
03706 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
03707 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
03708 = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
03709
03710 if (DEFAULT_ABI == ABI_DARWIN
03711 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
03712 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
03713 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
03714 = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
03715
03716 if (TARGET_TOC && TARGET_MINIMAL_TOC)
03717 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
03718 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
03719
03720 if (TARGET_ALTIVEC)
03721 global_regs[VSCR_REGNO] = 1;
03722
03723 if (TARGET_SPE)
03724 {
03725 global_regs[SPEFSCR_REGNO] = 1;
03726 fixed_regs[FIXED_SCRATCH]
03727 = call_used_regs[FIXED_SCRATCH]
03728 = call_really_used_regs[FIXED_SCRATCH] = 1;
03729 }
03730
03731 if (! TARGET_ALTIVEC)
03732 {
03733 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
03734 fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
03735 call_really_used_regs[VRSAVE_REGNO] = 1;
03736 }
03737
03738 if (TARGET_ALTIVEC_ABI)
03739 for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i)
03740 call_used_regs[i] = call_really_used_regs[i] = 1;
03741 }
03742
03743
03744
03745
03746
03747
03748
03749 rtx
03750 rs6000_emit_set_const (rtx dest, enum machine_mode mode,
03751 rtx source, int n ATTRIBUTE_UNUSED)
03752 {
03753 rtx result, insn, set;
03754 HOST_WIDE_INT c0, c1;
03755
03756 switch (mode)
03757 {
03758 case QImode:
03759 case HImode:
03760 if (dest == NULL)
03761 dest = gen_reg_rtx (mode);
03762 emit_insn (gen_rtx_SET (VOIDmode, dest, source));
03763 return dest;
03764
03765 case SImode:
03766 result = no_new_pseudos ? dest : gen_reg_rtx (SImode);
03767
03768 emit_insn (gen_rtx_SET (VOIDmode, result,
03769 GEN_INT (INTVAL (source)
03770 & (~ (HOST_WIDE_INT) 0xffff))));
03771 emit_insn (gen_rtx_SET (VOIDmode, dest,
03772 gen_rtx_IOR (SImode, result,
03773 GEN_INT (INTVAL (source) & 0xffff))));
03774 result = dest;
03775 break;
03776
03777 case DImode:
03778 switch (GET_CODE (source))
03779 {
03780 case CONST_INT:
03781 c0 = INTVAL (source);
03782 c1 = -(c0 < 0);
03783 break;
03784
03785 case CONST_DOUBLE:
03786 #if HOST_BITS_PER_WIDE_INT >= 64
03787 c0 = CONST_DOUBLE_LOW (source);
03788 c1 = -(c0 < 0);
03789 #else
03790 c0 = CONST_DOUBLE_LOW (source);
03791 c1 = CONST_DOUBLE_HIGH (source);
03792 #endif
03793 break;
03794
03795 default:
03796 gcc_unreachable ();
03797 }
03798
03799 result = rs6000_emit_set_long_const (dest, c0, c1);
03800 break;
03801
03802 default:
03803 gcc_unreachable ();
03804 }
03805
03806 insn = get_last_insn ();
03807 set = single_set (insn);
03808 if (! CONSTANT_P (SET_SRC (set)))
03809 set_unique_reg_note (insn, REG_EQUAL, source);
03810
03811 return result;
03812 }
03813
03814
03815
03816
03817
03818 static rtx
03819 rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
03820 {
03821 if (!TARGET_POWERPC64)
03822 {
03823 rtx operand1, operand2;
03824
03825 operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
03826 DImode);
03827 operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
03828 DImode);
03829 emit_move_insn (operand1, GEN_INT (c1));
03830 emit_move_insn (operand2, GEN_INT (c2));
03831 }
03832 else
03833 {
03834 HOST_WIDE_INT ud1, ud2, ud3, ud4;
03835
03836 ud1 = c1 & 0xffff;
03837 ud2 = (c1 & 0xffff0000) >> 16;
03838 #if HOST_BITS_PER_WIDE_INT >= 64
03839 c2 = c1 >> 32;
03840 #endif
03841 ud3 = c2 & 0xffff;
03842 ud4 = (c2 & 0xffff0000) >> 16;
03843
03844 if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
03845 || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
03846 {
03847 if (ud1 & 0x8000)
03848 emit_move_insn (dest, GEN_INT (((ud1 ^ 0x8000) - 0x8000)));
03849 else
03850 emit_move_insn (dest, GEN_INT (ud1));
03851 }
03852
03853 else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
03854 || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
03855 {
03856 if (ud2 & 0x8000)
03857 emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
03858 - 0x80000000));
03859 else
03860 emit_move_insn (dest, GEN_INT (ud2 << 16));
03861 if (ud1 != 0)
03862 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
03863 }
03864 else if ((ud4 == 0xffff && (ud3 & 0x8000))
03865 || (ud4 == 0 && ! (ud3 & 0x8000)))
03866 {
03867 if (ud3 & 0x8000)
03868 emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
03869 - 0x80000000));
03870 else
03871 emit_move_insn (dest, GEN_INT (ud3 << 16));
03872
03873 if (ud2 != 0)
03874 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud2)));
03875 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (16)));
03876 if (ud1 != 0)
03877 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
03878 }
03879 else
03880 {
03881 if (ud4 & 0x8000)
03882 emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
03883 - 0x80000000));
03884 else
03885 emit_move_insn (dest, GEN_INT (ud4 << 16));
03886
03887 if (ud3 != 0)
03888 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud3)));
03889
03890 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
03891 if (ud2 != 0)
03892 emit_move_insn (dest, gen_rtx_IOR (DImode, dest,
03893 GEN_INT (ud2 << 16)));
03894 if (ud1 != 0)
03895 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
03896 }
03897 }
03898 return dest;
03899 }
03900
03901
03902
03903
03904 static void
03905 rs6000_eliminate_indexed_memrefs (rtx operands[2])
03906 {
03907 if (GET_CODE (operands[0]) == MEM
03908 && GET_CODE (XEXP (operands[0], 0)) != REG
03909 && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0))
03910 && ! reload_in_progress)
03911 operands[0]
03912 = replace_equiv_address (operands[0],
03913 copy_addr_to_reg (XEXP (operands[0], 0)));
03914
03915 if (GET_CODE (operands[1]) == MEM
03916 && GET_CODE (XEXP (operands[1], 0)) != REG
03917 && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0))
03918 && ! reload_in_progress)
03919 operands[1]
03920 = replace_equiv_address (operands[1],
03921 copy_addr_to_reg (XEXP (operands[1], 0)));
03922 }
03923
03924
03925 void
03926 rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
03927 {
03928 rtx operands[2];
03929 operands[0] = dest;
03930 operands[1] = source;
03931
03932
03933 if (GET_CODE (operands[1]) == CONST_DOUBLE
03934 && ! FLOAT_MODE_P (mode)
03935 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
03936 {
03937
03938
03939
03940 operands[1] = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), mode);
03941 }
03942 gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE
03943 || FLOAT_MODE_P (mode)
03944 || ((CONST_DOUBLE_HIGH (operands[1]) != 0
03945 || CONST_DOUBLE_LOW (operands[1]) < 0)
03946 && (CONST_DOUBLE_HIGH (operands[1]) != -1
03947 || CONST_DOUBLE_LOW (operands[1]) >= 0)));
03948
03949
03950
03951 if (GET_CODE (operands[0]) == MEM
03952 && GET_CODE (operands[1]) == MEM
03953 && mode == DImode
03954 && (SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[0]))
03955 || SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[1])))
03956 && ! (SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[0]) > 32
03957 ? 32 : MEM_ALIGN (operands[0])))
03958 || SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[1]) > 32
03959 ? 32
03960 : MEM_ALIGN (operands[1]))))
03961 && ! MEM_VOLATILE_P (operands [0])
03962 && ! MEM_VOLATILE_P (operands [1]))
03963 {
03964 emit_move_insn (adjust_address (operands[0], SImode, 0),
03965 adjust_address (operands[1], SImode, 0));
03966 emit_move_insn (adjust_address (operands[0], SImode, 4),
03967 adjust_address (operands[1], SImode, 4));
03968 return;
03969 }
03970
03971 if (!no_new_pseudos && GET_CODE (operands[0]) == MEM
03972 && !gpc_reg_operand (operands[1], mode))
03973 operands[1] = force_reg (mode, operands[1]);
03974
03975 if (mode == SFmode && ! TARGET_POWERPC
03976 && TARGET_HARD_FLOAT && TARGET_FPRS
03977 && GET_CODE (operands[0]) == MEM)
03978 {
03979 int regnum;
03980
03981 if (reload_in_progress || reload_completed)
03982 regnum = true_regnum (operands[1]);
03983 else if (GET_CODE (operands[1]) == REG)
03984 regnum = REGNO (operands[1]);
03985 else
03986 regnum = -1;
03987
03988
03989
03990
03991 if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
03992 {
03993 rtx newreg;
03994 newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
03995 emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
03996 operands[1] = newreg;
03997 }
03998 }
03999
04000
04001
04002 if (rs6000_tls_referenced_p (operands[1]))
04003 {
04004 enum tls_model model;
04005 rtx tmp = operands[1];
04006 rtx addend = NULL;
04007
04008 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
04009 {
04010 addend = XEXP (XEXP (tmp, 0), 1);
04011 tmp = XEXP (XEXP (tmp, 0), 0);
04012 }
04013
04014 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
04015 model = SYMBOL_REF_TLS_MODEL (tmp);
04016 gcc_assert (model != 0);
04017
04018 tmp = rs6000_legitimize_tls_address (tmp, model);
04019 if (addend)
04020 {
04021 tmp = gen_rtx_PLUS (mode, tmp, addend);
04022 tmp = force_operand (tmp, operands[0]);
04023 }
04024 operands[1] = tmp;
04025 }
04026
04027
04028 if (reload_in_progress && mode == Pmode
04029 && (! general_operand (operands[1], mode)
04030 || ! nonimmediate_operand (operands[0], mode)))
04031 goto emit_set;
04032
04033
04034
04035 if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
04036 && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
04037 {
04038
04039
04040 rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode, 0),
04041 simplify_gen_subreg (DImode, operands[1], mode, 0),
04042 DImode);
04043 rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode,
04044 GET_MODE_SIZE (DImode)),
04045 simplify_gen_subreg (DImode, operands[1], mode,
04046 GET_MODE_SIZE (DImode)),
04047 DImode);
04048 return;
04049 }
04050
04051
04052
04053
04054 switch (mode)
04055 {
04056 case HImode:
04057 case QImode:
04058 if (CONSTANT_P (operands[1])
04059 && GET_CODE (operands[1]) != CONST_INT)
04060 operands[1] = force_const_mem (mode, operands[1]);
04061 break;
04062
04063 case TFmode:
04064 rs6000_eliminate_indexed_memrefs (operands);
04065
04066
04067 case DFmode:
04068 case SFmode:
04069 if (CONSTANT_P (operands[1])
04070 && ! easy_fp_constant (operands[1], mode))
04071 operands[1] = force_const_mem (mode, operands[1]);
04072 break;
04073
04074 case V16QImode:
04075 case V8HImode:
04076 case V4SFmode:
04077 case V4SImode:
04078 case V4HImode:
04079 case V2SFmode:
04080 case V2SImode:
04081 case V1DImode:
04082 if (CONSTANT_P (operands[1])
04083 && !easy_vector_constant (operands[1], mode))
04084 operands[1] = force_const_mem (mode, operands[1]);
04085 break;
04086
04087 case SImode:
04088 case DImode:
04089
04090 if (TARGET_ELF
04091 && mode == Pmode
04092 && DEFAULT_ABI == ABI_V4
04093 && (GET_CODE (operands[1]) == SYMBOL_REF
04094 || GET_CODE (operands[1]) == CONST)
04095 && small_data_operand (operands[1], mode))
04096 {
04097 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04098 return;
04099 }
04100
04101 if (DEFAULT_ABI == ABI_V4
04102 && mode == Pmode && mode == SImode
04103 && flag_pic == 1 && got_operand (operands[1], mode))
04104 {
04105 emit_insn (gen_movsi_got (operands[0], operands[1]));
04106 return;
04107 }
04108
04109 if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
04110 && TARGET_NO_TOC
04111 && ! flag_pic
04112 && mode == Pmode
04113 && CONSTANT_P (operands[1])
04114 && GET_CODE (operands[1]) != HIGH
04115 && GET_CODE (operands[1]) != CONST_INT)
04116 {
04117 rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode));
04118
04119
04120
04121 if (DEFAULT_ABI == ABI_AIX
04122 && GET_CODE (operands[1]) == SYMBOL_REF
04123 && XSTR (operands[1], 0)[0] == '.')
04124 {
04125 const char *name = XSTR (operands[1], 0);
04126 rtx new_ref;
04127 while (*name == '.')
04128 name++;
04129 new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
04130 CONSTANT_POOL_ADDRESS_P (new_ref)
04131 = CONSTANT_POOL_ADDRESS_P (operands[1]);
04132 SYMBOL_REF_FLAGS (new_ref) = SYMBOL_REF_FLAGS (operands[1]);
04133 SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
04134 SYMBOL_REF_DATA (new_ref) = SYMBOL_REF_DATA (operands[1]);
04135 operands[1] = new_ref;
04136 }
04137
04138 if (DEFAULT_ABI == ABI_DARWIN)
04139 {
04140 #if TARGET_MACHO
04141 if (MACHO_DYNAMIC_NO_PIC_P)
04142 {
04143
04144 operands[1] = rs6000_machopic_legitimize_pic_address (
04145 operands[1], mode, operands[0]);
04146 if (operands[0] != operands[1])
04147 emit_insn (gen_rtx_SET (VOIDmode,
04148 operands[0], operands[1]));
04149 return;
04150 }
04151 #endif
04152 emit_insn (gen_macho_high (target, operands[1]));
04153 emit_insn (gen_macho_low (operands[0], target, operands[1]));
04154 return;
04155 }
04156
04157 emit_insn (gen_elf_high (target, operands[1]));
04158 emit_insn (gen_elf_low (operands[0], target, operands[1]));
04159 return;
04160 }
04161
04162
04163
04164
04165 if (TARGET_TOC
04166 && GET_CODE (operands[1]) == SYMBOL_REF
04167 && constant_pool_expr_p (operands[1])
04168 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
04169 get_pool_mode (operands[1])))
04170 {
04171 operands[1] = create_TOC_reference (operands[1]);
04172 }
04173 else if (mode == Pmode
04174 && CONSTANT_P (operands[1])
04175 && ((GET_CODE (operands[1]) != CONST_INT
04176 && ! easy_fp_constant (operands[1], mode))
04177 || (GET_CODE (operands[1]) == CONST_INT
04178 && num_insns_constant (operands[1], mode) > 2)
04179 || (GET_CODE (operands[0]) == REG
04180 && FP_REGNO_P (REGNO (operands[0]))))
04181 && GET_CODE (operands[1]) != HIGH
04182 && ! legitimate_constant_pool_address_p (operands[1])
04183 && ! toc_relative_expr_p (operands[1]))
04184 {
04185
04186
04187
04188
04189
04190
04191 if (GET_CODE (operands[1]) != LABEL_REF)
04192 emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
04193
04194 #if TARGET_MACHO
04195
04196 if (DEFAULT_ABI == ABI_DARWIN && MACHOPIC_INDIRECT)
04197 {
04198 operands[1] =
04199 rs6000_machopic_legitimize_pic_address (operands[1], mode,
04200 operands[0]);
04201 if (operands[0] != operands[1])
04202 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04203 return;
04204 }
04205 #endif
04206
04207
04208
04209
04210
04211 if (GET_CODE (operands[1]) == CONST
04212 && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
04213 && GET_CODE (XEXP (operands[1], 0)) == PLUS
04214 && add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
04215 && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
04216 || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
04217 && ! side_effects_p (operands[0]))
04218 {
04219 rtx sym =
04220 force_const_mem (mode, XEXP (XEXP (operands[1], 0), 0));
04221 rtx other = XEXP (XEXP (operands[1], 0), 1);
04222
04223 sym = force_reg (mode, sym);
04224 if (mode == SImode)
04225 emit_insn (gen_addsi3 (operands[0], sym, other));
04226 else
04227 emit_insn (gen_adddi3 (operands[0], sym, other));
04228 return;
04229 }
04230
04231 operands[1] = force_const_mem (mode, operands[1]);
04232
04233 if (TARGET_TOC
04234 && constant_pool_expr_p (XEXP (operands[1], 0))
04235 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (
04236 get_pool_constant (XEXP (operands[1], 0)),
04237 get_pool_mode (XEXP (operands[1], 0))))
04238 {
04239 operands[1]
04240 = gen_const_mem (mode,
04241 create_TOC_reference (XEXP (operands[1], 0)));
04242 set_mem_alias_set (operands[1], get_TOC_alias_set ());
04243 }
04244 }
04245 break;
04246
04247 case TImode:
04248 rs6000_eliminate_indexed_memrefs (operands);
04249
04250 if (TARGET_POWER)
04251 {
04252 emit_insn (gen_rtx_PARALLEL (VOIDmode,
04253 gen_rtvec (2,
04254 gen_rtx_SET (VOIDmode,
04255 operands[0], operands[1]),
04256 gen_rtx_CLOBBER (VOIDmode,
04257 gen_rtx_SCRATCH (SImode)))));
04258 return;
04259 }
04260 break;
04261
04262 default:
04263 gcc_unreachable ();
04264 }
04265
04266
04267
04268
04269 if (GET_CODE (operands[1]) == MEM && ! reload_in_progress)
04270 operands[1] = validize_mem (operands[1]);
04271
04272 emit_set:
04273 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04274 }
04275
04276
04277 #define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
04278 (SCALAR_FLOAT_MODE_P (MODE) \
04279 && !DECIMAL_FLOAT_MODE_P (MODE) \
04280 && (CUM)->fregno <= FP_ARG_MAX_REG \
04281 && TARGET_HARD_FLOAT && TARGET_FPRS)
04282
04283
04284 #define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
04285 (ALTIVEC_VECTOR_MODE (MODE) \
04286 && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
04287 && TARGET_ALTIVEC_ABI \
04288 && (NAMED))
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311 static bool
04312 rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
04313 {
04314
04315
04316 if (rs6000_darwin64_abi
04317 && TREE_CODE (type) == RECORD_TYPE
04318 && int_size_in_bytes (type) > 0)
04319 {
04320 CUMULATIVE_ARGS valcum;
04321 rtx valret;
04322
04323 valcum.words = 0;
04324 valcum.fregno = FP_ARG_MIN_REG;
04325 valcum.vregno = ALTIVEC_ARG_MIN_REG;
04326
04327
04328 valret = rs6000_darwin64_record_arg (&valcum, type, 1, true);
04329 if (valret)
04330 return false;
04331
04332 }
04333
04334 if (AGGREGATE_TYPE_P (type)
04335 && (aix_struct_return
04336 || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
04337 return true;
04338
04339
04340
04341 if (TARGET_32BIT && !TARGET_ALTIVEC_ABI
04342 && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
04343 return false;
04344
04345
04346 if (TREE_CODE (type) == VECTOR_TYPE
04347 && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
04348 {
04349 static bool warned_for_return_big_vectors = false;
04350 if (!warned_for_return_big_vectors)
04351 {
04352 warning (0, "GCC vector returned by reference: "
04353 "non-standard ABI extension with no compatibility guarantee");
04354 warned_for_return_big_vectors = true;
04355 }
04356 return true;
04357 }
04358
04359 if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode)
04360 return true;
04361
04362 return false;
04363 }
04364
04365
04366
04367
04368
04369
04370
04371
04372 void
04373 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
04374 rtx libname ATTRIBUTE_UNUSED, int incoming,
04375 int libcall, int n_named_args)
04376 {
04377 static CUMULATIVE_ARGS zero_cumulative;
04378
04379 *cum = zero_cumulative;
04380 cum->words = 0;
04381 cum->fregno = FP_ARG_MIN_REG;
04382 cum->vregno = ALTIVEC_ARG_MIN_REG;
04383 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
04384 cum->call_cookie = ((DEFAULT_ABI == ABI_V4 && libcall)
04385 ? CALL_LIBCALL : CALL_NORMAL);
04386 cum->sysv_gregno = GP_ARG_MIN_REG;
04387 cum->stdarg = fntype
04388 && (TYPE_ARG_TYPES (fntype) != 0
04389 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04390 != void_type_node));
04391
04392 cum->nargs_prototype = 0;
04393 if (incoming || cum->prototype)
04394 cum->nargs_prototype = n_named_args;
04395
04396
04397 if ((!fntype && rs6000_default_long_calls)
04398 || (fntype
04399 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
04400 && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))))
04401 cum->call_cookie |= CALL_LONG;
04402
04403 if (TARGET_DEBUG_ARG)
04404 {
04405 fprintf (stderr, "\ninit_cumulative_args:");
04406 if (fntype)
04407 {
04408 tree ret_type = TREE_TYPE (fntype);
04409 fprintf (stderr, " ret code = %s,",
04410 tree_code_name[ (int)TREE_CODE (ret_type) ]);
04411 }
04412
04413 if (cum->call_cookie & CALL_LONG)
04414 fprintf (stderr, " longcall,");
04415
04416 fprintf (stderr, " proto = %d, nargs = %d\n",
04417 cum->prototype, cum->nargs_prototype);
04418 }
04419
04420 if (fntype
04421 && !TARGET_ALTIVEC
04422 && TARGET_ALTIVEC_ABI
04423 && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
04424 {
04425 error ("cannot return value in vector register because"
04426 " altivec instructions are disabled, use -maltivec"
04427 " to enable them");
04428 }
04429 }
04430
04431
04432
04433 static bool
04434 rs6000_must_pass_in_stack (enum machine_mode mode, tree type)
04435 {
04436 if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT)
04437 return must_pass_in_stack_var_size (mode, type);
04438 else
04439 return must_pass_in_stack_var_size_or_pad (mode, type);
04440 }
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451 enum direction
04452 function_arg_padding (enum machine_mode mode, tree type)
04453 {
04454 #ifndef AGGREGATE_PADDING_FIXED
04455 #define AGGREGATE_PADDING_FIXED 0
04456 #endif
04457 #ifndef AGGREGATES_PAD_UPWARD_ALWAYS
04458 #define AGGREGATES_PAD_UPWARD_ALWAYS 0
04459 #endif
04460
04461 if (!AGGREGATE_PADDING_FIXED)
04462 {
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472 if (BYTES_BIG_ENDIAN)
04473 {
04474 HOST_WIDE_INT size = 0;
04475
04476 if (mode == BLKmode)
04477 {
04478 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
04479 size = int_size_in_bytes (type);
04480 }
04481 else
04482 size = GET_MODE_SIZE (mode);
04483
04484 if (size == 1 || size == 2 || size == 4)
04485 return downward;
04486 }
04487 return upward;
04488 }
04489
04490 if (AGGREGATES_PAD_UPWARD_ALWAYS)
04491 {
04492 if (type != 0 && AGGREGATE_TYPE_P (type))
04493 return upward;
04494 }
04495
04496
04497 return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
04498 }
04499
04500
04501
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514 int
04515 function_arg_boundary (enum machine_mode mode, tree type)
04516 {
04517 if (DEFAULT_ABI == ABI_V4
04518 && (GET_MODE_SIZE (mode) == 8
04519 || (TARGET_HARD_FLOAT
04520 && TARGET_FPRS
04521 && mode == TFmode)))
04522 return 64;
04523 else if (SPE_VECTOR_MODE (mode)
04524 || (type && TREE_CODE (type) == VECTOR_TYPE
04525 && int_size_in_bytes (type) >= 8
04526 && int_size_in_bytes (type) < 16))
04527 return 64;
04528 else if (ALTIVEC_VECTOR_MODE (mode)
04529 || (type && TREE_CODE (type) == VECTOR_TYPE
04530 && int_size_in_bytes (type) >= 16))
04531 return 128;
04532 else if (rs6000_darwin64_abi && mode == BLKmode
04533 && type && TYPE_ALIGN (type) > 64)
04534 return 128;
04535 else
04536 return PARM_BOUNDARY;
04537 }
04538
04539
04540
04541
04542 static unsigned int
04543 rs6000_parm_start (enum machine_mode mode, tree type, unsigned int nwords)
04544 {
04545 unsigned int align;
04546 unsigned int parm_offset;
04547
04548 align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
04549 parm_offset = DEFAULT_ABI == ABI_V4 ? 2 : 6;
04550 return nwords + (-(parm_offset + nwords) & align);
04551 }
04552
04553
04554
04555 static unsigned long
04556 rs6000_arg_size (enum machine_mode mode, tree type)
04557 {
04558 unsigned long size;
04559
04560 if (mode != BLKmode)
04561 size = GET_MODE_SIZE (mode);
04562 else
04563 size = int_size_in_bytes (type);
04564
04565 if (TARGET_32BIT)
04566 return (size + 3) >> 2;
04567 else
04568 return (size + 7) >> 3;
04569 }
04570
04571
04572
04573 static void
04574 rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum,
04575 HOST_WIDE_INT bitpos)
04576 {
04577 unsigned int startbit, endbit;
04578 int intregs, intoffset;
04579 enum machine_mode mode;
04580
04581 if (cum->intoffset == -1)
04582 return;
04583
04584 intoffset = cum->intoffset;
04585 cum->intoffset = -1;
04586
04587 if (intoffset % BITS_PER_WORD != 0)
04588 {
04589 mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
04590 MODE_INT, 0);
04591 if (mode == BLKmode)
04592 {
04593
04594
04595
04596
04597 intoffset = intoffset & -BITS_PER_WORD;
04598 }
04599 }
04600
04601 startbit = intoffset & -BITS_PER_WORD;
04602 endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
04603 intregs = (endbit - startbit) / BITS_PER_WORD;
04604 cum->words += intregs;
04605 }
04606
04607
04608
04609
04610
04611
04612 static void
04613 rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum,
04614 tree type,
04615 HOST_WIDE_INT startbitpos)
04616 {
04617 tree f;
04618
04619 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
04620 if (TREE_CODE (f) == FIELD_DECL)
04621 {
04622 HOST_WIDE_INT bitpos = startbitpos;
04623 tree ftype = TREE_TYPE (f);
04624 enum machine_mode mode;
04625 if (ftype == error_mark_node)
04626 continue;
04627 mode = TYPE_MODE (ftype);
04628
04629 if (DECL_SIZE (f) != 0
04630 && host_integerp (bit_position (f), 1))
04631 bitpos += int_bit_position (f);
04632
04633
04634
04635 if (TREE_CODE (ftype) == RECORD_TYPE)
04636 rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos);
04637 else if (USE_FP_FOR_ARG_P (cum, mode, ftype))
04638 {
04639 rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
04640 cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
04641 cum->words += (GET_MODE_SIZE (mode) + 7) >> 3;
04642 }
04643 else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, 1))
04644 {
04645 rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
04646 cum->vregno++;
04647 cum->words += 2;
04648 }
04649 else if (cum->intoffset == -1)
04650 cum->intoffset = bitpos;
04651 }
04652 }
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662 void
04663 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04664 tree type, int named, int depth)
04665 {
04666 int size;
04667
04668
04669 if (depth == 0)
04670 cum->nargs_prototype--;
04671
04672 if (TARGET_ALTIVEC_ABI
04673 && (ALTIVEC_VECTOR_MODE (mode)
04674 || (type && TREE_CODE (type) == VECTOR_TYPE
04675 && int_size_in_bytes (type) == 16)))
04676 {
04677 bool stack = false;
04678
04679 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
04680 {
04681 cum->vregno++;
04682 if (!TARGET_ALTIVEC)
04683 error ("cannot pass argument in vector register because"
04684 " altivec instructions are disabled, use -maltivec"
04685 " to enable them");
04686
04687
04688
04689
04690 if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
04691 || (cum->stdarg && DEFAULT_ABI != ABI_V4))
04692 stack = true;
04693 }
04694 else
04695 stack = true;
04696
04697 if (stack)
04698 {
04699 int align;
04700
04701
04702
04703
04704
04705
04706
04707
04708 if (TARGET_32BIT)
04709 align = (2 - cum->words) & 3;
04710 else
04711 align = cum->words & 1;
04712 cum->words += align + rs6000_arg_size (mode, type);
04713
04714 if (TARGET_DEBUG_ARG)
04715 {
04716 fprintf (stderr, "function_adv: words = %2d, align=%d, ",
04717 cum->words, align);
04718 fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
04719 cum->nargs_prototype, cum->prototype,
04720 GET_MODE_NAME (mode));
04721 }
04722 }
04723 }
04724 else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode)
04725 && !cum->stdarg
04726 && cum->sysv_gregno <= GP_ARG_MAX_REG)
04727 cum->sysv_gregno++;
04728
04729 else if (rs6000_darwin64_abi
04730 && mode == BLKmode
04731 && TREE_CODE (type) == RECORD_TYPE
04732 && (size = int_size_in_bytes (type)) > 0)
04733 {
04734
04735
04736
04737 if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
04738 && (cum->words % 2) != 0)
04739 cum->words++;
04740
04741 if (!named)
04742 cum->words += (size + 7) / 8;
04743 else
04744 {
04745
04746
04747
04748
04749 cum->intoffset = 0;
04750 rs6000_darwin64_record_arg_advance_recurse (cum, type, 0);
04751 rs6000_darwin64_record_arg_advance_flush (cum,
04752 size * BITS_PER_UNIT);
04753 }
04754 }
04755 else if (DEFAULT_ABI == ABI_V4)
04756 {
04757 if (TARGET_HARD_FLOAT && TARGET_FPRS
04758 && (mode == SFmode || mode == DFmode
04759 || (mode == TFmode && !TARGET_IEEEQUAD)))
04760 {
04761 if (cum->fregno + (mode == TFmode ? 1 : 0) <= FP_ARG_V4_MAX_REG)
04762 cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
04763 else
04764 {
04765 cum->fregno = FP_ARG_V4_MAX_REG + 1;
04766 if (mode == DFmode || mode == TFmode)
04767 cum->words += cum->words & 1;
04768 cum->words += rs6000_arg_size (mode, type);
04769 }
04770 }
04771 else
04772 {
04773 int n_words = rs6000_arg_size (mode, type);
04774 int gregno = cum->sysv_gregno;
04775
04776
04777
04778
04779 if (n_words == 2)
04780 gregno += (1 - gregno) & 1;
04781
04782
04783 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
04784 {
04785
04786
04787
04788 if (n_words == 2)
04789 cum->words += cum->words & 1;
04790 cum->words += n_words;
04791 }
04792
04793
04794
04795
04796 cum->sysv_gregno = gregno + n_words;
04797 }
04798
04799 if (TARGET_DEBUG_ARG)
04800 {
04801 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
04802 cum->words, cum->fregno);
04803 fprintf (stderr, "gregno = %2d, nargs = %4d, proto = %d, ",
04804 cum->sysv_gregno, cum->nargs_prototype, cum->prototype);
04805 fprintf (stderr, "mode = %4s, named = %d\n",
04806 GET_MODE_NAME (mode), named);
04807 }
04808 }
04809 else
04810 {
04811 int n_words = rs6000_arg_size (mode, type);
04812 int start_words = cum->words;
04813 int align_words = rs6000_parm_start (mode, type, start_words);
04814
04815 cum->words = align_words + n_words;
04816
04817 if (SCALAR_FLOAT_MODE_P (mode)
04818 && !DECIMAL_FLOAT_MODE_P (mode)
04819 && TARGET_HARD_FLOAT && TARGET_FPRS)
04820 cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
04821
04822 if (TARGET_DEBUG_ARG)
04823 {
04824 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
04825 cum->words, cum->fregno);
04826 fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ",
04827 cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
04828 fprintf (stderr, "named = %d, align = %d, depth = %d\n",
04829 named, align_words - start_words, depth);
04830 }
04831 }
04832 }
04833
04834 static rtx
04835 spe_build_register_parallel (enum machine_mode mode, int gregno)
04836 {
04837 rtx r1, r3;
04838
04839 switch (mode)
04840 {
04841 case DFmode:
04842 r1 = gen_rtx_REG (DImode, gregno);
04843 r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
04844 return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
04845
04846 case DCmode:
04847 r1 = gen_rtx_REG (DImode, gregno);
04848 r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
04849 r3 = gen_rtx_REG (DImode, gregno + 2);
04850 r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
04851 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
04852
04853 default:
04854 gcc_unreachable ();
04855 }
04856 }
04857
04858
04859 static rtx
04860 rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04861 tree type)
04862 {
04863 int gregno = cum->sysv_gregno;
04864
04865
04866
04867 if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode))
04868 {
04869 int n_words = rs6000_arg_size (mode, type);
04870
04871
04872 if (mode == DFmode)
04873 gregno += (1 - gregno) & 1;
04874
04875
04876 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
04877 return NULL_RTX;
04878
04879 return spe_build_register_parallel (mode, gregno);
04880 }
04881 if (cum->stdarg)
04882 {
04883 int n_words = rs6000_arg_size (mode, type);
04884
04885
04886 if (n_words == 2 && (gregno & 1) == 0)
04887 gregno += 1;
04888
04889 if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
04890 {
04891 rtx r1, r2;
04892 enum machine_mode m = SImode;
04893
04894 r1 = gen_rtx_REG (m, gregno);
04895 r1 = gen_rtx_EXPR_LIST (m, r1, const0_rtx);
04896 r2 = gen_rtx_REG (m, gregno + 1);
04897 r2 = gen_rtx_EXPR_LIST (m, r2, GEN_INT (4));
04898 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
04899 }
04900 else
04901 return NULL_RTX;
04902 }
04903 else
04904 {
04905 if (gregno <= GP_ARG_MAX_REG)
04906 return gen_rtx_REG (mode, gregno);
04907 else
04908 return NULL_RTX;
04909 }
04910 }
04911
04912
04913
04914
04915 static void
04916 rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum,
04917 HOST_WIDE_INT bitpos, rtx rvec[], int *k)
04918 {
04919 enum machine_mode mode;
04920 unsigned int regno;
04921 unsigned int startbit, endbit;
04922 int this_regno, intregs, intoffset;
04923 rtx reg;
04924
04925 if (cum->intoffset == -1)
04926 return;
04927
04928 intoffset = cum->intoffset;
04929 cum->intoffset = -1;
04930
04931
04932
04933
04934
04935
04936 if (intoffset % BITS_PER_WORD != 0)
04937 {
04938 mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
04939 MODE_INT, 0);
04940 if (mode == BLKmode)
04941 {
04942
04943
04944
04945
04946 intoffset = intoffset & -BITS_PER_WORD;
04947 mode = word_mode;
04948 }
04949 }
04950 else
04951 mode = word_mode;
04952
04953 startbit = intoffset & -BITS_PER_WORD;
04954 endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
04955 intregs = (endbit - startbit) / BITS_PER_WORD;
04956 this_regno = cum->words + intoffset / BITS_PER_WORD;
04957
04958 if (intregs > 0 && intregs > GP_ARG_NUM_REG - this_regno)
04959 cum->use_stack = 1;
04960
04961 intregs = MIN (intregs, GP_ARG_NUM_REG - this_regno);
04962 if (intregs <= 0)
04963 return;
04964
04965 intoffset /= BITS_PER_UNIT;
04966 do
04967 {
04968 regno = GP_ARG_MIN_REG + this_regno;
04969 reg = gen_rtx_REG (mode, regno);
04970 rvec[(*k)++] =
04971 gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
04972
04973 this_regno += 1;
04974 intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
04975 mode = word_mode;
04976 intregs -= 1;
04977 }
04978 while (intregs > 0);
04979 }
04980
04981
04982
04983 static void
04984 rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, tree type,
04985 HOST_WIDE_INT startbitpos, rtx rvec[],
04986 int *k)
04987 {
04988 tree f;
04989
04990 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
04991 if (TREE_CODE (f) == FIELD_DECL)
04992 {
04993 HOST_WIDE_INT bitpos = startbitpos;
04994 tree ftype = TREE_TYPE (f);
04995 enum machine_mode mode;
04996 if (ftype == error_mark_node)
04997 continue;
04998 mode = TYPE_MODE (ftype);
04999
05000 if (DECL_SIZE (f) != 0
05001 && host_integerp (bit_position (f), 1))
05002 bitpos += int_bit_position (f);
05003
05004
05005
05006 if (TREE_CODE (ftype) == RECORD_TYPE)
05007 rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k);
05008 else if (cum->named && USE_FP_FOR_ARG_P (cum, mode, ftype))
05009 {
05010 #if 0
05011 switch (mode)
05012 {
05013 case SCmode: mode = SFmode; break;
05014 case DCmode: mode = DFmode; break;
05015 case TCmode: mode = TFmode; break;
05016 default: break;
05017 }
05018 #endif
05019 rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
05020 rvec[(*k)++]
05021 = gen_rtx_EXPR_LIST (VOIDmode,
05022 gen_rtx_REG (mode, cum->fregno++),
05023 GEN_INT (bitpos / BITS_PER_UNIT));
05024 if (mode == TFmode)
05025 cum->fregno++;
05026 }
05027 else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, ftype, 1))
05028 {
05029 rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
05030 rvec[(*k)++]
05031 = gen_rtx_EXPR_LIST (VOIDmode,
05032 gen_rtx_REG (mode, cum->vregno++),
05033 GEN_INT (bitpos / BITS_PER_UNIT));
05034 }
05035 else if (cum->intoffset == -1)
05036 cum->intoffset = bitpos;
05037 }
05038 }
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053 static rtx
05054 rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, tree type,
05055 int named, bool retval)
05056 {
05057 rtx rvec[FIRST_PSEUDO_REGISTER];
05058 int k = 1, kbase = 1;
05059 HOST_WIDE_INT typesize = int_size_in_bytes (type);
05060
05061 CUMULATIVE_ARGS copy_cum = *orig_cum;
05062 CUMULATIVE_ARGS *cum = ©_cum;
05063
05064
05065 if (!retval && TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
05066 && (cum->words % 2) != 0)
05067 cum->words++;
05068
05069 cum->intoffset = 0;
05070 cum->use_stack = 0;
05071 cum->named = named;
05072
05073
05074
05075
05076
05077 rs6000_darwin64_record_arg_recurse (cum, type, 0, rvec, &k);
05078 rs6000_darwin64_record_arg_flush (cum, typesize * BITS_PER_UNIT, rvec, &k);
05079
05080
05081
05082
05083
05084 if (cum->use_stack)
05085 {
05086 if (retval)
05087 return NULL_RTX;
05088 kbase = 0;
05089 rvec[0] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05090 }
05091 if (k > 1 || cum->use_stack)
05092 return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (k - kbase, &rvec[kbase]));
05093 else
05094 return NULL_RTX;
05095 }
05096
05097
05098
05099 static rtx
05100 rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
05101 {
05102 int n_units;
05103 int i, k;
05104 rtx rvec[GP_ARG_NUM_REG + 1];
05105
05106 if (align_words >= GP_ARG_NUM_REG)
05107 return NULL_RTX;
05108
05109 n_units = rs6000_arg_size (mode, type);
05110
05111
05112
05113
05114 if (n_units == 0
05115 || (n_units == 1 && mode != BLKmode))
05116 return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05117
05118 k = 0;
05119 if (align_words + n_units > GP_ARG_NUM_REG)
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05130
05131 i = 0;
05132 do
05133 {
05134 rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words);
05135 rtx off = GEN_INT (i++ * 4);
05136 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
05137 }
05138 while (++align_words < GP_ARG_NUM_REG && --n_units != 0);
05139
05140 return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
05141 }
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171 rtx
05172 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05173 tree type, int named)
05174 {
05175 enum rs6000_abi abi = DEFAULT_ABI;
05176
05177
05178
05179
05180
05181 if (mode == VOIDmode)
05182 {
05183 if (abi == ABI_V4
05184 && (cum->call_cookie & CALL_LIBCALL) == 0
05185 && (cum->stdarg
05186 || (cum->nargs_prototype < 0
05187 && (cum->prototype || TARGET_NO_PROTOTYPE))))
05188 {
05189
05190 if (TARGET_SPE_ABI)
05191 return GEN_INT (cum->call_cookie | CALL_V4_SET_FP_ARGS);
05192 else if (TARGET_HARD_FLOAT && TARGET_FPRS)
05193 return GEN_INT (cum->call_cookie
05194 | ((cum->fregno == FP_ARG_MIN_REG)
05195 ? CALL_V4_SET_FP_ARGS
05196 : CALL_V4_CLEAR_FP_ARGS));
05197 }
05198
05199 return GEN_INT (cum->call_cookie);
05200 }
05201
05202 if (rs6000_darwin64_abi && mode == BLKmode
05203 && TREE_CODE (type) == RECORD_TYPE)
05204 {
05205 rtx rslt = rs6000_darwin64_record_arg (cum, type, named, false);
05206 if (rslt != NULL_RTX)
05207 return rslt;
05208
05209 }
05210
05211 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
05212 if (TARGET_64BIT && ! cum->prototype)
05213 {
05214
05215
05216 int align_words;
05217 rtx slot;
05218 align_words = (cum->words + 1) & ~1;
05219
05220 if (align_words >= GP_ARG_NUM_REG)
05221 {
05222 slot = NULL_RTX;
05223 }
05224 else
05225 {
05226 slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05227 }
05228 return gen_rtx_PARALLEL (mode,
05229 gen_rtvec (2,
05230 gen_rtx_EXPR_LIST (VOIDmode,
05231 slot, const0_rtx),
05232 gen_rtx_EXPR_LIST (VOIDmode,
05233 gen_rtx_REG (mode, cum->vregno),
05234 const0_rtx)));
05235 }
05236 else
05237 return gen_rtx_REG (mode, cum->vregno);
05238 else if (TARGET_ALTIVEC_ABI
05239 && (ALTIVEC_VECTOR_MODE (mode)
05240 || (type && TREE_CODE (type) == VECTOR_TYPE
05241 && int_size_in_bytes (type) == 16)))
05242 {
05243 if (named || abi == ABI_V4)
05244 return NULL_RTX;
05245 else
05246 {
05247
05248
05249 int align, align_words, n_words;
05250 enum machine_mode part_mode;
05251
05252
05253
05254
05255
05256
05257 if (TARGET_32BIT)
05258 align = (2 - cum->words) & 3;
05259 else
05260 align = cum->words & 1;
05261 align_words = cum->words + align;
05262
05263
05264 if (align_words >= GP_ARG_NUM_REG)
05265 return NULL_RTX;
05266
05267 if (TARGET_32BIT && TARGET_POWERPC64)
05268 return rs6000_mixed_function_arg (mode, type, align_words);
05269
05270
05271
05272 part_mode = mode;
05273 n_words = rs6000_arg_size (mode, type);
05274 if (align_words + n_words > GP_ARG_NUM_REG)
05275
05276
05277 part_mode = DImode;
05278
05279 return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
05280 }
05281 }
05282 else if (TARGET_SPE_ABI && TARGET_SPE
05283 && (SPE_VECTOR_MODE (mode)
05284 || (TARGET_E500_DOUBLE && (mode == DFmode
05285 || mode == DCmode))))
05286 return rs6000_spe_function_arg (cum, mode, type);
05287
05288 else if (abi == ABI_V4)
05289 {
05290 if (TARGET_HARD_FLOAT && TARGET_FPRS
05291 && (mode == SFmode || mode == DFmode
05292 || (mode == TFmode && !TARGET_IEEEQUAD)))
05293 {
05294 if (cum->fregno + (mode == TFmode ? 1 : 0) <= FP_ARG_V4_MAX_REG)
05295 return gen_rtx_REG (mode, cum->fregno);
05296 else
05297 return NULL_RTX;
05298 }
05299 else
05300 {
05301 int n_words = rs6000_arg_size (mode, type);
05302 int gregno = cum->sysv_gregno;
05303
05304
05305
05306
05307 if (n_words == 2)
05308 gregno += (1 - gregno) & 1;
05309
05310
05311 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
05312 return NULL_RTX;
05313
05314 if (TARGET_32BIT && TARGET_POWERPC64)
05315 return rs6000_mixed_function_arg (mode, type,
05316 gregno - GP_ARG_MIN_REG);
05317 return gen_rtx_REG (mode, gregno);
05318 }
05319 }
05320 else
05321 {
05322 int align_words = rs6000_parm_start (mode, type, cum->words);
05323
05324 if (USE_FP_FOR_ARG_P (cum, mode, type))
05325 {
05326 rtx rvec[GP_ARG_NUM_REG + 1];
05327 rtx r;
05328 int k;
05329 bool needs_psave;
05330 enum machine_mode fmode = mode;
05331 unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
05332
05333 if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
05334 {
05335
05336
05337 gcc_assert (cum->fregno == FP_ARG_MAX_REG && fmode == TFmode);
05338
05339
05340 fmode = DFmode;
05341 }
05342
05343
05344
05345 needs_psave = (type
05346 && (cum->nargs_prototype <= 0
05347 || (DEFAULT_ABI == ABI_AIX
05348 && TARGET_XL_COMPAT
05349 && align_words >= GP_ARG_NUM_REG)));
05350
05351 if (!needs_psave && mode == fmode)
05352 return gen_rtx_REG (fmode, cum->fregno);
05353
05354 k = 0;
05355 if (needs_psave)
05356 {
05357
05358
05359 if (align_words < GP_ARG_NUM_REG)
05360 {
05361 unsigned long n_words = rs6000_arg_size (mode, type);
05362
05363 if (align_words + n_words > GP_ARG_NUM_REG
05364 || (TARGET_32BIT && TARGET_POWERPC64))
05365 {
05366
05367
05368 enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
05369 rtx off;
05370 int i = 0;
05371 if (align_words + n_words > GP_ARG_NUM_REG)
05372
05373
05374
05375
05376
05377
05378 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX,
05379 const0_rtx);
05380 do
05381 {
05382 r = gen_rtx_REG (rmode,
05383 GP_ARG_MIN_REG + align_words);
05384 off = GEN_INT (i++ * GET_MODE_SIZE (rmode));
05385 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
05386 }
05387 while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
05388 }
05389 else
05390 {
05391
05392 r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05393 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
05394 }
05395 }
05396 else
05397
05398 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05399 }
05400
05401
05402 r = gen_rtx_REG (fmode, cum->fregno);
05403 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
05404
05405 return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
05406 }
05407 else if (align_words < GP_ARG_NUM_REG)
05408 {
05409 if (TARGET_32BIT && TARGET_POWERPC64)
05410 return rs6000_mixed_function_arg (mode, type, align_words);
05411
05412 if (mode == BLKmode)
05413 mode = Pmode;
05414
05415 return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05416 }
05417 else
05418 return NULL_RTX;
05419 }
05420 }
05421
05422
05423
05424
05425
05426
05427
05428 static int
05429 rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05430 tree type, bool named)
05431 {
05432 int ret = 0;
05433 int align_words;
05434
05435 if (DEFAULT_ABI == ABI_V4)
05436 return 0;
05437
05438 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named)
05439 && cum->nargs_prototype >= 0)
05440 return 0;
05441
05442
05443 if (rs6000_darwin64_abi && mode == BLKmode
05444 && TREE_CODE (type) == RECORD_TYPE
05445 && int_size_in_bytes (type) > 0)
05446 return 0;
05447
05448 align_words = rs6000_parm_start (mode, type, cum->words);
05449
05450 if (USE_FP_FOR_ARG_P (cum, mode, type))
05451 {
05452
05453
05454
05455
05456 if (type
05457 && (cum->nargs_prototype <= 0
05458 || (DEFAULT_ABI == ABI_AIX
05459 && TARGET_XL_COMPAT
05460 && align_words >= GP_ARG_NUM_REG)))
05461 return 0;
05462 else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3)
05463 > FP_ARG_MAX_REG + 1)
05464 ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8;
05465 else if (cum->nargs_prototype >= 0)
05466 return 0;
05467 }
05468
05469 if (align_words < GP_ARG_NUM_REG
05470 && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
05471 ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8);
05472
05473 if (ret != 0 && TARGET_DEBUG_ARG)
05474 fprintf (stderr, "rs6000_arg_partial_bytes: %d\n", ret);
05475
05476 return ret;
05477 }
05478
05479
05480
05481
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493 static bool
05494 rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
05495 enum machine_mode mode, tree type,
05496 bool named ATTRIBUTE_UNUSED)
05497 {
05498 if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode)
05499 {
05500 if (TARGET_DEBUG_ARG)
05501 fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
05502 return 1;
05503 }
05504
05505 if (!type)
05506 return 0;
05507
05508 if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type))
05509 {
05510 if (TARGET_DEBUG_ARG)
05511 fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n");
05512 return 1;
05513 }
05514
05515 if (int_size_in_bytes (type) < 0)
05516 {
05517 if (TARGET_DEBUG_ARG)
05518 fprintf (stderr, "function_arg_pass_by_reference: variable size\n");
05519 return 1;
05520 }
05521
05522
05523
05524 if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
05525 {
05526 if (TARGET_DEBUG_ARG)
05527 fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n");
05528 return 1;
05529 }
05530
05531
05532 if (TREE_CODE (type) == VECTOR_TYPE
05533 && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
05534 {
05535 static bool warned_for_pass_big_vectors = false;
05536 if (TARGET_DEBUG_ARG)
05537 fprintf (stderr, "function_arg_pass_by_reference: synthetic vector\n");
05538 if (!warned_for_pass_big_vectors)
05539 {
05540 warning (0, "GCC vector passed by reference: "
05541 "non-standard ABI extension with no compatibility guarantee");
05542 warned_for_pass_big_vectors = true;
05543 }
05544 return 1;
05545 }
05546
05547 return 0;
05548 }
05549
05550 static void
05551 rs6000_move_block_from_reg (int regno, rtx x, int nregs)
05552 {
05553 int i;
05554 enum machine_mode reg_mode = TARGET_32BIT ? SImode : DImode;
05555
05556 if (nregs == 0)
05557 return;
05558
05559 for (i = 0; i < nregs; i++)
05560 {
05561 rtx tem = adjust_address_nv (x, reg_mode, i * GET_MODE_SIZE (reg_mode));
05562 if (reload_completed)
05563 {
05564 if (! strict_memory_address_p (reg_mode, XEXP (tem, 0)))
05565 tem = NULL_RTX;
05566 else
05567 tem = simplify_gen_subreg (reg_mode, x, BLKmode,
05568 i * GET_MODE_SIZE (reg_mode));
05569 }
05570 else
05571 tem = replace_equiv_address (tem, XEXP (tem, 0));
05572
05573 gcc_assert (tem);
05574
05575 emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i));
05576 }
05577 }
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593 static void
05594 setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05595 tree type, int *pretend_size ATTRIBUTE_UNUSED,
05596 int no_rtl)
05597 {
05598 CUMULATIVE_ARGS next_cum;
05599 int reg_size = TARGET_32BIT ? 4 : 8;
05600 rtx save_area = NULL_RTX, mem;
05601 int first_reg_offset, set;
05602
05603
05604 next_cum = *cum;
05605 function_arg_advance (&next_cum, mode, type, 1, 0);
05606
05607 if (DEFAULT_ABI == ABI_V4)
05608 {
05609 first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
05610
05611 if (! no_rtl)
05612 {
05613 int gpr_reg_num = 0, gpr_size = 0, fpr_size = 0;
05614 HOST_WIDE_INT offset = 0;
05615
05616
05617
05618
05619
05620
05621 if (cfun->va_list_gpr_size && first_reg_offset < GP_ARG_NUM_REG)
05622 gpr_reg_num = GP_ARG_NUM_REG - first_reg_offset;
05623 if (TARGET_HARD_FLOAT && TARGET_FPRS
05624 && next_cum.fregno <= FP_ARG_V4_MAX_REG
05625 && cfun->va_list_fpr_size)
05626 {
05627 if (gpr_reg_num)
05628 fpr_size = (next_cum.fregno - FP_ARG_MIN_REG)
05629 * UNITS_PER_FP_WORD;
05630 if (cfun->va_list_fpr_size
05631 < FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
05632 fpr_size += cfun->va_list_fpr_size * UNITS_PER_FP_WORD;
05633 else
05634 fpr_size += (FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
05635 * UNITS_PER_FP_WORD;
05636 }
05637 if (gpr_reg_num)
05638 {
05639 offset = -((first_reg_offset * reg_size) & ~7);
05640 if (!fpr_size && gpr_reg_num > cfun->va_list_gpr_size)
05641 {
05642 gpr_reg_num = cfun->va_list_gpr_size;
05643 if (reg_size == 4 && (first_reg_offset & 1))
05644 gpr_reg_num++;
05645 }
05646 gpr_size = (gpr_reg_num * reg_size + 7) & ~7;
05647 }
05648 else if (fpr_size)
05649 offset = - (int) (next_cum.fregno - FP_ARG_MIN_REG)
05650 * UNITS_PER_FP_WORD
05651 - (int) (GP_ARG_NUM_REG * reg_size);
05652
05653 if (gpr_size + fpr_size)
05654 {
05655 rtx reg_save_area
05656 = assign_stack_local (BLKmode, gpr_size + fpr_size, 64);
05657 gcc_assert (GET_CODE (reg_save_area) == MEM);
05658 reg_save_area = XEXP (reg_save_area, 0);
05659 if (GET_CODE (reg_save_area) == PLUS)
05660 {
05661 gcc_assert (XEXP (reg_save_area, 0)
05662 == virtual_stack_vars_rtx);
05663 gcc_assert (GET_CODE (XEXP (reg_save_area, 1)) == CONST_INT);
05664 offset += INTVAL (XEXP (reg_save_area, 1));
05665 }
05666 else
05667 gcc_assert (reg_save_area == virtual_stack_vars_rtx);
05668 }
05669
05670 cfun->machine->varargs_save_offset = offset;
05671 save_area = plus_constant (virtual_stack_vars_rtx, offset);
05672 }
05673 }
05674 else
05675 {
05676 first_reg_offset = next_cum.words;
05677 save_area = virtual_incoming_args_rtx;
05678
05679 if (targetm.calls.must_pass_in_stack (mode, type))
05680 first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type);
05681 }
05682
05683 set = get_varargs_alias_set ();
05684 if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG
05685 && cfun->va_list_gpr_size)
05686 {
05687 int nregs = GP_ARG_NUM_REG - first_reg_offset;
05688
05689 if (va_list_gpr_counter_field)
05690 {
05691
05692 if (nregs > cfun->va_list_gpr_size)
05693 nregs = cfun->va_list_gpr_size;
05694 }
05695 else
05696 {
05697
05698 if (nregs > cfun->va_list_gpr_size / reg_size)
05699 nregs = cfun->va_list_gpr_size / reg_size;
05700 }
05701
05702 mem = gen_rtx_MEM (BLKmode,
05703 plus_constant (save_area,
05704 first_reg_offset * reg_size));
05705 MEM_NOTRAP_P (mem) = 1;
05706 set_mem_alias_set (mem, set);
05707 set_mem_align (mem, BITS_PER_WORD);
05708
05709 rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
05710 nregs);
05711 }
05712
05713
05714 if (DEFAULT_ABI == ABI_V4
05715 && TARGET_HARD_FLOAT && TARGET_FPRS
05716 && ! no_rtl
05717 && next_cum.fregno <= FP_ARG_V4_MAX_REG
05718 && cfun->va_list_fpr_size)
05719 {
05720 int fregno = next_cum.fregno, nregs;
05721 rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO);
05722 rtx lab = gen_label_rtx ();
05723 int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG)
05724 * UNITS_PER_FP_WORD);
05725
05726 emit_jump_insn
05727 (gen_rtx_SET (VOIDmode,
05728 pc_rtx,
05729 gen_rtx_IF_THEN_ELSE (VOIDmode,
05730 gen_rtx_NE (VOIDmode, cr1,
05731 const0_rtx),
05732 gen_rtx_LABEL_REF (VOIDmode, lab),
05733 pc_rtx)));
05734
05735 for (nregs = 0;
05736 fregno <= FP_ARG_V4_MAX_REG && nregs < cfun->va_list_fpr_size;
05737 fregno++, off += UNITS_PER_FP_WORD, nregs++)
05738 {
05739 mem = gen_rtx_MEM (DFmode, plus_constant (save_area, off));
05740 MEM_NOTRAP_P (mem) = 1;
05741 set_mem_alias_set (mem, set);
05742 set_mem_align (mem, GET_MODE_ALIGNMENT (DFmode));
05743 emit_move_insn (mem, gen_rtx_REG (DFmode, fregno));
05744 }
05745
05746 emit_label (lab);
05747 }
05748 }
05749
05750
05751
05752 static tree
05753 rs6000_build_builtin_va_list (void)
05754 {
05755 tree f_gpr, f_fpr, f_res, f_ovf, f_sav, record, type_decl;
05756
05757
05758
05759 if (DEFAULT_ABI != ABI_V4)
05760 return build_pointer_type (char_type_node);
05761
05762 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
05763 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
05764
05765 f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
05766 unsigned_char_type_node);
05767 f_fpr = build_decl (FIELD_DECL, get_identifier ("fpr"),
05768 unsigned_char_type_node);
05769
05770
05771 f_res = build_decl (FIELD_DECL, get_identifier ("reserved"),
05772 short_unsigned_type_node);
05773 f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
05774 ptr_type_node);
05775 f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
05776 ptr_type_node);
05777
05778 va_list_gpr_counter_field = f_gpr;
05779 va_list_fpr_counter_field = f_fpr;
05780
05781 DECL_FIELD_CONTEXT (f_gpr) = record;
05782 DECL_FIELD_CONTEXT (f_fpr) = record;
05783 DECL_FIELD_CONTEXT (f_res) = record;
05784 DECL_FIELD_CONTEXT (f_ovf) = record;
05785 DECL_FIELD_CONTEXT (f_sav) = record;
05786
05787 TREE_CHAIN (record) = type_decl;
05788 TYPE_NAME (record) = type_decl;
05789 TYPE_FIELDS (record) = f_gpr;
05790 TREE_CHAIN (f_gpr) = f_fpr;
05791 TREE_CHAIN (f_fpr) = f_res;
05792 TREE_CHAIN (f_res) = f_ovf;
05793 TREE_CHAIN (f_ovf) = f_sav;
05794
05795 layout_type (record);
05796
05797
05798 return build_array_type (record, build_index_type (size_zero_node));
05799 }
05800
05801
05802
05803 void
05804 rs6000_va_start (tree valist, rtx nextarg)
05805 {
05806 HOST_WIDE_INT words, n_gpr, n_fpr;
05807 tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
05808 tree gpr, fpr, ovf, sav, t;
05809
05810
05811 if (DEFAULT_ABI != ABI_V4)
05812 {
05813 std_expand_builtin_va_start (valist, nextarg);
05814 return;
05815 }
05816
05817 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
05818 f_fpr = TREE_CHAIN (f_gpr);
05819 f_res = TREE_CHAIN (f_fpr);
05820 f_ovf = TREE_CHAIN (f_res);
05821 f_sav = TREE_CHAIN (f_ovf);
05822
05823 valist = build_va_arg_indirect_ref (valist);
05824 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
05825 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
05826 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
05827 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
05828
05829
05830 words = current_function_args_info.words;
05831 n_gpr = MIN (current_function_args_info.sysv_gregno - GP_ARG_MIN_REG,
05832 GP_ARG_NUM_REG);
05833 n_fpr = MIN (current_function_args_info.fregno - FP_ARG_MIN_REG,
05834 FP_ARG_NUM_REG);
05835
05836 if (TARGET_DEBUG_ARG)
05837 fprintf (stderr, "va_start: words = "HOST_WIDE_INT_PRINT_DEC", n_gpr = "
05838 HOST_WIDE_INT_PRINT_DEC", n_fpr = "HOST_WIDE_INT_PRINT_DEC"\n",
05839 words, n_gpr, n_fpr);
05840
05841 if (cfun->va_list_gpr_size)
05842 {
05843 t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
05844 build_int_cst (NULL_TREE, n_gpr));
05845 TREE_SIDE_EFFECTS (t) = 1;
05846 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05847 }
05848
05849 if (cfun->va_list_fpr_size)
05850 {
05851 t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
05852 build_int_cst (NULL_TREE, n_fpr));
05853 TREE_SIDE_EFFECTS (t) = 1;
05854 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05855 }
05856
05857
05858 t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
05859 if (words != 0)
05860 t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t,
05861 build_int_cst (NULL_TREE, words * UNITS_PER_WORD));
05862 t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
05863 TREE_SIDE_EFFECTS (t) = 1;
05864 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05865
05866
05867
05868 if (!cfun->va_list_gpr_size
05869 && !cfun->va_list_fpr_size
05870 && n_gpr < GP_ARG_NUM_REG
05871 && n_fpr < FP_ARG_V4_MAX_REG)
05872 return;
05873
05874
05875 t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
05876 if (cfun->machine->varargs_save_offset)
05877 t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
05878 build_int_cst (NULL_TREE, cfun->machine->varargs_save_offset));
05879 t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
05880 TREE_SIDE_EFFECTS (t) = 1;
05881 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05882 }
05883
05884
05885
05886 tree
05887 rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
05888 {
05889 tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
05890 tree gpr, fpr, ovf, sav, reg, t, u;
05891 int size, rsize, n_reg, sav_ofs, sav_scale;
05892 tree lab_false, lab_over, addr;
05893 int align;
05894 tree ptrtype = build_pointer_type (type);
05895
05896 if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
05897 {
05898 t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
05899 return build_va_arg_indirect_ref (t);
05900 }
05901
05902 if (DEFAULT_ABI != ABI_V4)
05903 {
05904 if (targetm.calls.split_complex_arg && TREE_CODE (type) == COMPLEX_TYPE)
05905 {
05906 tree elem_type = TREE_TYPE (type);
05907 enum machine_mode elem_mode = TYPE_MODE (elem_type);
05908 int elem_size = GET_MODE_SIZE (elem_mode);
05909
05910 if (elem_size < UNITS_PER_WORD)
05911 {
05912 tree real_part, imag_part;
05913 tree post = NULL_TREE;
05914
05915 real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
05916 &post);
05917
05918
05919 real_part = get_initialized_tmp_var (real_part, pre_p, &post);
05920 append_to_statement_list (post, pre_p);
05921
05922 imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
05923 post_p);
05924
05925 return build2 (COMPLEX_EXPR, type, real_part, imag_part);
05926 }
05927 }
05928
05929 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
05930 }
05931
05932 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
05933 f_fpr = TREE_CHAIN (f_gpr);
05934 f_res = TREE_CHAIN (f_fpr);
05935 f_ovf = TREE_CHAIN (f_res);
05936 f_sav = TREE_CHAIN (f_ovf);
05937
05938 valist = build_va_arg_indirect_ref (valist);
05939 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
05940 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
05941 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
05942 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
05943
05944 size = int_size_in_bytes (type);
05945 rsize = (size + 3) / 4;
05946 align = 1;
05947
05948 if (TARGET_HARD_FLOAT && TARGET_FPRS
05949 && (TYPE_MODE (type) == SFmode
05950 || TYPE_MODE (type) == DFmode
05951 || TYPE_MODE (type) == TFmode))
05952 {
05953
05954 reg = fpr;
05955 n_reg = (size + 7) / 8;
05956 sav_ofs = 8*4;
05957 sav_scale = 8;
05958 if (TYPE_MODE (type) != SFmode)
05959 align = 8;
05960 }
05961 else
05962 {
05963
05964 reg = gpr;
05965 n_reg = rsize;
05966 sav_ofs = 0;
05967 sav_scale = 4;
05968 if (n_reg == 2)
05969 align = 8;
05970 }
05971
05972
05973
05974 lab_over = NULL;
05975 addr = create_tmp_var (ptr_type_node, "addr");
05976 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
05977
05978
05979 if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
05980 align = 16;
05981 else
05982 {
05983 lab_false = create_artificial_label ();
05984 lab_over = create_artificial_label ();
05985
05986
05987
05988
05989 u = reg;
05990 if (n_reg == 2 && reg == gpr)
05991 {
05992 u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), reg,
05993 size_int (n_reg - 1));
05994 u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u);
05995 }
05996
05997 t = fold_convert (TREE_TYPE (reg), size_int (8 - n_reg + 1));
05998 t = build2 (GE_EXPR, boolean_type_node, u, t);
05999 u = build1 (GOTO_EXPR, void_type_node, lab_false);
06000 t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
06001 gimplify_and_add (t, pre_p);
06002
06003 t = sav;
06004 if (sav_ofs)
06005 t = build2 (PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
06006
06007 u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg));
06008 u = build1 (CONVERT_EXPR, integer_type_node, u);
06009 u = build2 (MULT_EXPR, integer_type_node, u, size_int (sav_scale));
06010 t = build2 (PLUS_EXPR, ptr_type_node, t, u);
06011
06012 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
06013 gimplify_and_add (t, pre_p);
06014
06015 t = build1 (GOTO_EXPR, void_type_node, lab_over);
06016 gimplify_and_add (t, pre_p);
06017
06018 t = build1 (LABEL_EXPR, void_type_node, lab_false);
06019 append_to_statement_list (t, pre_p);
06020
06021 if ((n_reg == 2 && reg != gpr) || n_reg > 2)
06022 {
06023
06024
06025 t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, size_int (8));
06026 gimplify_and_add (t, pre_p);
06027 }
06028 }
06029
06030
06031
06032
06033 t = ovf;
06034 if (align != 1)
06035 {
06036 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
06037 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
06038 build_int_cst (NULL_TREE, -align));
06039 }
06040 gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
06041
06042 u = build2 (MODIFY_EXPR, void_type_node, addr, t);
06043 gimplify_and_add (u, pre_p);
06044
06045 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
06046 t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
06047 gimplify_and_add (t, pre_p);
06048
06049 if (lab_over)
06050 {
06051 t = build1 (LABEL_EXPR, void_type_node, lab_over);
06052 append_to_statement_list (t, pre_p);
06053 }
06054
06055 if (STRICT_ALIGNMENT
06056 && (TYPE_ALIGN (type)
06057 > (unsigned) BITS_PER_UNIT * (align < 4 ? 4 : align)))
06058 {
06059
06060
06061
06062 tree tmp = create_tmp_var (type, "va_arg_tmp");
06063 tree dest_addr = build_fold_addr_expr (tmp);
06064
06065 tree copy = build_function_call_expr
06066 (implicit_built_in_decls[BUILT_IN_MEMCPY],
06067 tree_cons (NULL_TREE, dest_addr,
06068 tree_cons (NULL_TREE, addr,
06069 tree_cons (NULL_TREE, size_int (rsize * 4),
06070 NULL_TREE))));
06071
06072 gimplify_and_add (copy, pre_p);
06073 addr = dest_addr;
06074 }
06075
06076 addr = fold_convert (ptrtype, addr);
06077 return build_va_arg_indirect_ref (addr);
06078 }
06079
06080
06081
06082 static void
06083 def_builtin (int mask, const char *name, tree type, int code)
06084 {
06085 if (mask & target_flags)
06086 {
06087 if (rs6000_builtin_decls[code])
06088 abort ();
06089
06090 rs6000_builtin_decls[code] =
06091 lang_hooks.builtin_function (name, type, code, BUILT_IN_MD,
06092 NULL, NULL_TREE);
06093 }
06094 }
06095
06096
06097
06098 static const struct builtin_description bdesc_3arg[] =
06099 {
06100 { MASK_ALTIVEC, CODE_FOR_altivec_vmaddfp, "__builtin_altivec_vmaddfp", ALTIVEC_BUILTIN_VMADDFP },
06101 { MASK_ALTIVEC, CODE_FOR_altivec_vmhaddshs, "__builtin_altivec_vmhaddshs", ALTIVEC_BUILTIN_VMHADDSHS },
06102 { MASK_ALTIVEC, CODE_FOR_altivec_vmhraddshs, "__builtin_altivec_vmhraddshs", ALTIVEC_BUILTIN_VMHRADDSHS },
06103 { MASK_ALTIVEC, CODE_FOR_altivec_vmladduhm, "__builtin_altivec_vmladduhm", ALTIVEC_BUILTIN_VMLADDUHM},
06104 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumubm, "__builtin_altivec_vmsumubm", ALTIVEC_BUILTIN_VMSUMUBM },
06105 { MASK_ALTIVEC, CODE_FOR_altivec_vmsummbm, "__builtin_altivec_vmsummbm", ALTIVEC_BUILTIN_VMSUMMBM },
06106 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhm, "__builtin_altivec_vmsumuhm", ALTIVEC_BUILTIN_VMSUMUHM },
06107 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshm, "__builtin_altivec_vmsumshm", ALTIVEC_BUILTIN_VMSUMSHM },
06108 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
06109 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
06110 { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
06111 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
06112 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
06113 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
06114 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
06115 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
06116 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
06117 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
06118 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
06119 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
06120 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
06121 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
06122 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
06123
06124 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madd", ALTIVEC_BUILTIN_VEC_MADD },
06125 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madds", ALTIVEC_BUILTIN_VEC_MADDS },
06126 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mladd", ALTIVEC_BUILTIN_VEC_MLADD },
06127 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mradds", ALTIVEC_BUILTIN_VEC_MRADDS },
06128 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msum", ALTIVEC_BUILTIN_VEC_MSUM },
06129 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshm", ALTIVEC_BUILTIN_VEC_VMSUMSHM },
06130 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhm", ALTIVEC_BUILTIN_VEC_VMSUMUHM },
06131 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsummbm", ALTIVEC_BUILTIN_VEC_VMSUMMBM },
06132 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumubm", ALTIVEC_BUILTIN_VEC_VMSUMUBM },
06133 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msums", ALTIVEC_BUILTIN_VEC_MSUMS },
06134 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshs", ALTIVEC_BUILTIN_VEC_VMSUMSHS },
06135 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhs", ALTIVEC_BUILTIN_VEC_VMSUMUHS },
06136 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB },
06137 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
06138 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
06139 };
06140
06141
06142
06143 static const struct builtin_description bdesc_dst[] =
06144 {
06145 { MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
06146 { MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
06147 { MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
06148 { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT },
06149
06150 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dst", ALTIVEC_BUILTIN_VEC_DST },
06151 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstt", ALTIVEC_BUILTIN_VEC_DSTT },
06152 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstst", ALTIVEC_BUILTIN_VEC_DSTST },
06153 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dststt", ALTIVEC_BUILTIN_VEC_DSTSTT }
06154 };
06155
06156
06157
06158 static struct builtin_description bdesc_2arg[] =
06159 {
06160 { MASK_ALTIVEC, CODE_FOR_addv16qi3, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
06161 { MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
06162 { MASK_ALTIVEC, CODE_FOR_addv4si3, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
06163 { MASK_ALTIVEC, CODE_FOR_addv4sf3, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
06164 { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
06165 { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
06166 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
06167 { MASK_ALTIVEC, CODE_FOR_altivec_vadduhs, "__builtin_altivec_vadduhs", ALTIVEC_BUILTIN_VADDUHS },
06168 { MASK_ALTIVEC, CODE_FOR_altivec_vaddshs, "__builtin_altivec_vaddshs", ALTIVEC_BUILTIN_VADDSHS },
06169 { MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
06170 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
06171 { MASK_ALTIVEC, CODE_FOR_andv4si3, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
06172 { MASK_ALTIVEC, CODE_FOR_andcv4si3, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
06173 { MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
06174 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
06175 { MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
06176 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsh, "__builtin_altivec_vavgsh", ALTIVEC_BUILTIN_VAVGSH },
06177 { MASK_ALTIVEC, CODE_FOR_altivec_vavguw, "__builtin_altivec_vavguw", ALTIVEC_BUILTIN_VAVGUW },
06178 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsw, "__builtin_altivec_vavgsw", ALTIVEC_BUILTIN_VAVGSW },
06179 { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
06180 { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
06181 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
06182 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
06183 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
06184 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
06185 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
06186 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
06187 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
06188 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
06189 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
06190 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
06191 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
06192 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
06193 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
06194 { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
06195 { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
06196 { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
06197 { MASK_ALTIVEC, CODE_FOR_smaxv16qi3, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
06198 { MASK_ALTIVEC, CODE_FOR_umaxv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
06199 { MASK_ALTIVEC, CODE_FOR_smaxv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
06200 { MASK_ALTIVEC, CODE_FOR_umaxv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
06201 { MASK_ALTIVEC, CODE_FOR_smaxv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
06202 { MASK_ALTIVEC, CODE_FOR_smaxv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
06203 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
06204 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
06205 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
06206 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, "__builtin_altivec_vmrglb", ALTIVEC_BUILTIN_VMRGLB },
06207 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, "__builtin_altivec_vmrglh", ALTIVEC_BUILTIN_VMRGLH },
06208 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, "__builtin_altivec_vmrglw", ALTIVEC_BUILTIN_VMRGLW },
06209 { MASK_ALTIVEC, CODE_FOR_uminv16qi3, "__builtin_altivec_vminub", ALTIVEC_BUILTIN_VMINUB },
06210 { MASK_ALTIVEC, CODE_FOR_sminv16qi3, "__builtin_altivec_vminsb", ALTIVEC_BUILTIN_VMINSB },
06211 { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vminuh", ALTIVEC_BUILTIN_VMINUH },
06212 { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vminsh", ALTIVEC_BUILTIN_VMINSH },
06213 { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vminuw", ALTIVEC_BUILTIN_VMINUW },
06214 { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
06215 { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
06216 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
06217 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
06218 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
06219 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
06220 { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
06221 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
06222 { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
06223 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
06224 { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
06225 { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
06226 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
06227 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
06228 { MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
06229 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
06230 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
06231 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
06232 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
06233 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
06234 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
06235 { MASK_ALTIVEC, CODE_FOR_altivec_vrlb, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
06236 { MASK_ALTIVEC, CODE_FOR_altivec_vrlh, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
06237 { MASK_ALTIVEC, CODE_FOR_altivec_vrlw, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
06238 { MASK_ALTIVEC, CODE_FOR_altivec_vslb, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
06239 { MASK_ALTIVEC, CODE_FOR_altivec_vslh, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
06240 { MASK_ALTIVEC, CODE_FOR_altivec_vslw, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
06241 { MASK_ALTIVEC, CODE_FOR_altivec_vsl, "__builtin_altivec_vsl", ALTIVEC_BUILTIN_VSL },
06242 { MASK_ALTIVEC, CODE_FOR_altivec_vslo, "__builtin_altivec_vslo", ALTIVEC_BUILTIN_VSLO },
06243 { MASK_ALTIVEC, CODE_FOR_altivec_vspltb, "__builtin_altivec_vspltb", ALTIVEC_BUILTIN_VSPLTB },
06244 { MASK_ALTIVEC, CODE_FOR_altivec_vsplth, "__builtin_altivec_vsplth", ALTIVEC_BUILTIN_VSPLTH },
06245 { MASK_ALTIVEC, CODE_FOR_altivec_vspltw, "__builtin_altivec_vspltw", ALTIVEC_BUILTIN_VSPLTW },
06246 { MASK_ALTIVEC, CODE_FOR_lshrv16qi3, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
06247 { MASK_ALTIVEC, CODE_FOR_lshrv8hi3, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
06248 { MASK_ALTIVEC, CODE_FOR_lshrv4si3, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
06249 { MASK_ALTIVEC, CODE_FOR_ashrv16qi3, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
06250 { MASK_ALTIVEC, CODE_FOR_ashrv8hi3, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
06251 { MASK_ALTIVEC, CODE_FOR_ashrv4si3, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
06252 { MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
06253 { MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
06254 { MASK_ALTIVEC, CODE_FOR_subv16qi3, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
06255 { MASK_ALTIVEC, CODE_FOR_subv8hi3, "__builtin_altivec_vsubuhm", ALTIVEC_BUILTIN_VSUBUHM },
06256 { MASK_ALTIVEC, CODE_FOR_subv4si3, "__builtin_altivec_vsubuwm", ALTIVEC_BUILTIN_VSUBUWM },
06257 { MASK_ALTIVEC, CODE_FOR_subv4sf3, "__builtin_altivec_vsubfp", ALTIVEC_BUILTIN_VSUBFP },
06258 { MASK_ALTIVEC, CODE_FOR_altivec_vsubcuw, "__builtin_altivec_vsubcuw", ALTIVEC_BUILTIN_VSUBCUW },
06259 { MASK_ALTIVEC, CODE_FOR_altivec_vsububs, "__builtin_altivec_vsububs", ALTIVEC_BUILTIN_VSUBUBS },
06260 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsbs, "__builtin_altivec_vsubsbs", ALTIVEC_BUILTIN_VSUBSBS },
06261 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhs, "__builtin_altivec_vsubuhs", ALTIVEC_BUILTIN_VSUBUHS },
06262 { MASK_ALTIVEC, CODE_FOR_altivec_vsubshs, "__builtin_altivec_vsubshs", ALTIVEC_BUILTIN_VSUBSHS },
06263 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuws, "__builtin_altivec_vsubuws", ALTIVEC_BUILTIN_VSUBUWS },
06264 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsws, "__builtin_altivec_vsubsws", ALTIVEC_BUILTIN_VSUBSWS },
06265 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4ubs, "__builtin_altivec_vsum4ubs", ALTIVEC_BUILTIN_VSUM4UBS },
06266 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4sbs, "__builtin_altivec_vsum4sbs", ALTIVEC_BUILTIN_VSUM4SBS },
06267 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4shs, "__builtin_altivec_vsum4shs", ALTIVEC_BUILTIN_VSUM4SHS },
06268 { MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
06269 { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
06270 { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
06271
06272 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
06273 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
06274 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
06275 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM },
06276 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM },
06277 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_addc", ALTIVEC_BUILTIN_VEC_ADDC },
06278 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_adds", ALTIVEC_BUILTIN_VEC_ADDS },
06279 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsws", ALTIVEC_BUILTIN_VEC_VADDSWS },
06280 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduws", ALTIVEC_BUILTIN_VEC_VADDUWS },
06281 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddshs", ALTIVEC_BUILTIN_VEC_VADDSHS },
06282 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS },
06283 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS },
06284 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS },
06285 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
06286 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
06287 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG },
06288 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW },
06289 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW },
06290 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsh", ALTIVEC_BUILTIN_VEC_VAVGSH },
06291 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguh", ALTIVEC_BUILTIN_VEC_VAVGUH },
06292 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsb", ALTIVEC_BUILTIN_VEC_VAVGSB },
06293 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgub", ALTIVEC_BUILTIN_VEC_VAVGUB },
06294 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpb", ALTIVEC_BUILTIN_VEC_CMPB },
06295 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpeq", ALTIVEC_BUILTIN_VEC_CMPEQ },
06296 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpeqfp", ALTIVEC_BUILTIN_VEC_VCMPEQFP },
06297 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequw", ALTIVEC_BUILTIN_VEC_VCMPEQUW },
06298 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequh", ALTIVEC_BUILTIN_VEC_VCMPEQUH },
06299 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequb", ALTIVEC_BUILTIN_VEC_VCMPEQUB },
06300 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpge", ALTIVEC_BUILTIN_VEC_CMPGE },
06301 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpgt", ALTIVEC_BUILTIN_VEC_CMPGT },
06302 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtfp", ALTIVEC_BUILTIN_VEC_VCMPGTFP },
06303 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsw", ALTIVEC_BUILTIN_VEC_VCMPGTSW },
06304 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuw", ALTIVEC_BUILTIN_VEC_VCMPGTUW },
06305 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsh", ALTIVEC_BUILTIN_VEC_VCMPGTSH },
06306 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuh", ALTIVEC_BUILTIN_VEC_VCMPGTUH },
06307 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsb", ALTIVEC_BUILTIN_VEC_VCMPGTSB },
06308 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
06309 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
06310 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
06311 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
06312 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
06313 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
06314 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW },
06315 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH },
06316 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuh", ALTIVEC_BUILTIN_VEC_VMAXUH },
06317 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsb", ALTIVEC_BUILTIN_VEC_VMAXSB },
06318 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxub", ALTIVEC_BUILTIN_VEC_VMAXUB },
06319 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergeh", ALTIVEC_BUILTIN_VEC_MERGEH },
06320 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghw", ALTIVEC_BUILTIN_VEC_VMRGHW },
06321 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghh", ALTIVEC_BUILTIN_VEC_VMRGHH },
06322 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghb", ALTIVEC_BUILTIN_VEC_VMRGHB },
06323 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergel", ALTIVEC_BUILTIN_VEC_MERGEL },
06324 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW },
06325 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH },
06326 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB },
06327 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
06328 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
06329 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW },
06330 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW },
06331 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH },
06332 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuh", ALTIVEC_BUILTIN_VEC_VMINUH },
06333 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsb", ALTIVEC_BUILTIN_VEC_VMINSB },
06334 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminub", ALTIVEC_BUILTIN_VEC_VMINUB },
06335 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mule", ALTIVEC_BUILTIN_VEC_MULE },
06336 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleub", ALTIVEC_BUILTIN_VEC_VMULEUB },
06337 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesb", ALTIVEC_BUILTIN_VEC_VMULESB },
06338 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleuh", ALTIVEC_BUILTIN_VEC_VMULEUH },
06339 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesh", ALTIVEC_BUILTIN_VEC_VMULESH },
06340 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mulo", ALTIVEC_BUILTIN_VEC_MULO },
06341 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosh", ALTIVEC_BUILTIN_VEC_VMULOSH },
06342 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH },
06343 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB },
06344 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB },
06345 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
06346 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
06347 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK },
06348 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM },
06349 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM },
06350 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packpx", ALTIVEC_BUILTIN_VEC_PACKPX },
06351 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packs", ALTIVEC_BUILTIN_VEC_PACKS },
06352 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswss", ALTIVEC_BUILTIN_VEC_VPKSWSS },
06353 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwus", ALTIVEC_BUILTIN_VEC_VPKUWUS },
06354 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshss", ALTIVEC_BUILTIN_VEC_VPKSHSS },
06355 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhus", ALTIVEC_BUILTIN_VEC_VPKUHUS },
06356 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packsu", ALTIVEC_BUILTIN_VEC_PACKSU },
06357 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswus", ALTIVEC_BUILTIN_VEC_VPKSWUS },
06358 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshus", ALTIVEC_BUILTIN_VEC_VPKSHUS },
06359 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rl", ALTIVEC_BUILTIN_VEC_RL },
06360 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlw", ALTIVEC_BUILTIN_VEC_VRLW },
06361 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlh", ALTIVEC_BUILTIN_VEC_VRLH },
06362 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlb", ALTIVEC_BUILTIN_VEC_VRLB },
06363 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sl", ALTIVEC_BUILTIN_VEC_SL },
06364 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslw", ALTIVEC_BUILTIN_VEC_VSLW },
06365 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslh", ALTIVEC_BUILTIN_VEC_VSLH },
06366 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslb", ALTIVEC_BUILTIN_VEC_VSLB },
06367 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sll", ALTIVEC_BUILTIN_VEC_SLL },
06368 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_slo", ALTIVEC_BUILTIN_VEC_SLO },
06369 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sr", ALTIVEC_BUILTIN_VEC_SR },
06370 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrw", ALTIVEC_BUILTIN_VEC_VSRW },
06371 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrh", ALTIVEC_BUILTIN_VEC_VSRH },
06372 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrb", ALTIVEC_BUILTIN_VEC_VSRB },
06373 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sra", ALTIVEC_BUILTIN_VEC_SRA },
06374 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsraw", ALTIVEC_BUILTIN_VEC_VSRAW },
06375 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrah", ALTIVEC_BUILTIN_VEC_VSRAH },
06376 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB },
06377 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL },
06378 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro",