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", ALTIVEC_BUILTIN_VEC_SRO },
06379 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
06380 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
06381 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM },
06382 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM },
06383 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM },
06384 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subc", ALTIVEC_BUILTIN_VEC_SUBC },
06385 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subs", ALTIVEC_BUILTIN_VEC_SUBS },
06386 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsws", ALTIVEC_BUILTIN_VEC_VSUBSWS },
06387 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuws", ALTIVEC_BUILTIN_VEC_VSUBUWS },
06388 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubshs", ALTIVEC_BUILTIN_VEC_VSUBSHS },
06389 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhs", ALTIVEC_BUILTIN_VEC_VSUBUHS },
06390 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsbs", ALTIVEC_BUILTIN_VEC_VSUBSBS },
06391 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububs", ALTIVEC_BUILTIN_VEC_VSUBUBS },
06392 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum4s", ALTIVEC_BUILTIN_VEC_SUM4S },
06393 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4shs", ALTIVEC_BUILTIN_VEC_VSUM4SHS },
06394 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4sbs", ALTIVEC_BUILTIN_VEC_VSUM4SBS },
06395 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS },
06396 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S },
06397 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
06398 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
06399
06400
06401 { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
06402 { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
06403 { 0, CODE_FOR_spe_evandc, "__builtin_spe_evandc", SPE_BUILTIN_EVANDC },
06404 { 0, CODE_FOR_spe_evdivws, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
06405 { 0, CODE_FOR_spe_evdivwu, "__builtin_spe_evdivwu", SPE_BUILTIN_EVDIVWU },
06406 { 0, CODE_FOR_spe_eveqv, "__builtin_spe_eveqv", SPE_BUILTIN_EVEQV },
06407 { 0, CODE_FOR_spe_evfsadd, "__builtin_spe_evfsadd", SPE_BUILTIN_EVFSADD },
06408 { 0, CODE_FOR_spe_evfsdiv, "__builtin_spe_evfsdiv", SPE_BUILTIN_EVFSDIV },
06409 { 0, CODE_FOR_spe_evfsmul, "__builtin_spe_evfsmul", SPE_BUILTIN_EVFSMUL },
06410 { 0, CODE_FOR_spe_evfssub, "__builtin_spe_evfssub", SPE_BUILTIN_EVFSSUB },
06411 { 0, CODE_FOR_spe_evmergehi, "__builtin_spe_evmergehi", SPE_BUILTIN_EVMERGEHI },
06412 { 0, CODE_FOR_spe_evmergehilo, "__builtin_spe_evmergehilo", SPE_BUILTIN_EVMERGEHILO },
06413 { 0, CODE_FOR_spe_evmergelo, "__builtin_spe_evmergelo", SPE_BUILTIN_EVMERGELO },
06414 { 0, CODE_FOR_spe_evmergelohi, "__builtin_spe_evmergelohi", SPE_BUILTIN_EVMERGELOHI },
06415 { 0, CODE_FOR_spe_evmhegsmfaa, "__builtin_spe_evmhegsmfaa", SPE_BUILTIN_EVMHEGSMFAA },
06416 { 0, CODE_FOR_spe_evmhegsmfan, "__builtin_spe_evmhegsmfan", SPE_BUILTIN_EVMHEGSMFAN },
06417 { 0, CODE_FOR_spe_evmhegsmiaa, "__builtin_spe_evmhegsmiaa", SPE_BUILTIN_EVMHEGSMIAA },
06418 { 0, CODE_FOR_spe_evmhegsmian, "__builtin_spe_evmhegsmian", SPE_BUILTIN_EVMHEGSMIAN },
06419 { 0, CODE_FOR_spe_evmhegumiaa, "__builtin_spe_evmhegumiaa", SPE_BUILTIN_EVMHEGUMIAA },
06420 { 0, CODE_FOR_spe_evmhegumian, "__builtin_spe_evmhegumian", SPE_BUILTIN_EVMHEGUMIAN },
06421 { 0, CODE_FOR_spe_evmhesmf, "__builtin_spe_evmhesmf", SPE_BUILTIN_EVMHESMF },
06422 { 0, CODE_FOR_spe_evmhesmfa, "__builtin_spe_evmhesmfa", SPE_BUILTIN_EVMHESMFA },
06423 { 0, CODE_FOR_spe_evmhesmfaaw, "__builtin_spe_evmhesmfaaw", SPE_BUILTIN_EVMHESMFAAW },
06424 { 0, CODE_FOR_spe_evmhesmfanw, "__builtin_spe_evmhesmfanw", SPE_BUILTIN_EVMHESMFANW },
06425 { 0, CODE_FOR_spe_evmhesmi, "__builtin_spe_evmhesmi", SPE_BUILTIN_EVMHESMI },
06426 { 0, CODE_FOR_spe_evmhesmia, "__builtin_spe_evmhesmia", SPE_BUILTIN_EVMHESMIA },
06427 { 0, CODE_FOR_spe_evmhesmiaaw, "__builtin_spe_evmhesmiaaw", SPE_BUILTIN_EVMHESMIAAW },
06428 { 0, CODE_FOR_spe_evmhesmianw, "__builtin_spe_evmhesmianw", SPE_BUILTIN_EVMHESMIANW },
06429 { 0, CODE_FOR_spe_evmhessf, "__builtin_spe_evmhessf", SPE_BUILTIN_EVMHESSF },
06430 { 0, CODE_FOR_spe_evmhessfa, "__builtin_spe_evmhessfa", SPE_BUILTIN_EVMHESSFA },
06431 { 0, CODE_FOR_spe_evmhessfaaw, "__builtin_spe_evmhessfaaw", SPE_BUILTIN_EVMHESSFAAW },
06432 { 0, CODE_FOR_spe_evmhessfanw, "__builtin_spe_evmhessfanw", SPE_BUILTIN_EVMHESSFANW },
06433 { 0, CODE_FOR_spe_evmhessiaaw, "__builtin_spe_evmhessiaaw", SPE_BUILTIN_EVMHESSIAAW },
06434 { 0, CODE_FOR_spe_evmhessianw, "__builtin_spe_evmhessianw", SPE_BUILTIN_EVMHESSIANW },
06435 { 0, CODE_FOR_spe_evmheumi, "__builtin_spe_evmheumi", SPE_BUILTIN_EVMHEUMI },
06436 { 0, CODE_FOR_spe_evmheumia, "__builtin_spe_evmheumia", SPE_BUILTIN_EVMHEUMIA },
06437 { 0, CODE_FOR_spe_evmheumiaaw, "__builtin_spe_evmheumiaaw", SPE_BUILTIN_EVMHEUMIAAW },
06438 { 0, CODE_FOR_spe_evmheumianw, "__builtin_spe_evmheumianw", SPE_BUILTIN_EVMHEUMIANW },
06439 { 0, CODE_FOR_spe_evmheusiaaw, "__builtin_spe_evmheusiaaw", SPE_BUILTIN_EVMHEUSIAAW },
06440 { 0, CODE_FOR_spe_evmheusianw, "__builtin_spe_evmheusianw", SPE_BUILTIN_EVMHEUSIANW },
06441 { 0, CODE_FOR_spe_evmhogsmfaa, "__builtin_spe_evmhogsmfaa", SPE_BUILTIN_EVMHOGSMFAA },
06442 { 0, CODE_FOR_spe_evmhogsmfan, "__builtin_spe_evmhogsmfan", SPE_BUILTIN_EVMHOGSMFAN },
06443 { 0, CODE_FOR_spe_evmhogsmiaa, "__builtin_spe_evmhogsmiaa", SPE_BUILTIN_EVMHOGSMIAA },
06444 { 0, CODE_FOR_spe_evmhogsmian, "__builtin_spe_evmhogsmian", SPE_BUILTIN_EVMHOGSMIAN },
06445 { 0, CODE_FOR_spe_evmhogumiaa, "__builtin_spe_evmhogumiaa", SPE_BUILTIN_EVMHOGUMIAA },
06446 { 0, CODE_FOR_spe_evmhogumian, "__builtin_spe_evmhogumian", SPE_BUILTIN_EVMHOGUMIAN },
06447 { 0, CODE_FOR_spe_evmhosmf, "__builtin_spe_evmhosmf", SPE_BUILTIN_EVMHOSMF },
06448 { 0, CODE_FOR_spe_evmhosmfa, "__builtin_spe_evmhosmfa", SPE_BUILTIN_EVMHOSMFA },
06449 { 0, CODE_FOR_spe_evmhosmfaaw, "__builtin_spe_evmhosmfaaw", SPE_BUILTIN_EVMHOSMFAAW },
06450 { 0, CODE_FOR_spe_evmhosmfanw, "__builtin_spe_evmhosmfanw", SPE_BUILTIN_EVMHOSMFANW },
06451 { 0, CODE_FOR_spe_evmhosmi, "__builtin_spe_evmhosmi", SPE_BUILTIN_EVMHOSMI },
06452 { 0, CODE_FOR_spe_evmhosmia, "__builtin_spe_evmhosmia", SPE_BUILTIN_EVMHOSMIA },
06453 { 0, CODE_FOR_spe_evmhosmiaaw, "__builtin_spe_evmhosmiaaw", SPE_BUILTIN_EVMHOSMIAAW },
06454 { 0, CODE_FOR_spe_evmhosmianw, "__builtin_spe_evmhosmianw", SPE_BUILTIN_EVMHOSMIANW },
06455 { 0, CODE_FOR_spe_evmhossf, "__builtin_spe_evmhossf", SPE_BUILTIN_EVMHOSSF },
06456 { 0, CODE_FOR_spe_evmhossfa, "__builtin_spe_evmhossfa", SPE_BUILTIN_EVMHOSSFA },
06457 { 0, CODE_FOR_spe_evmhossfaaw, "__builtin_spe_evmhossfaaw", SPE_BUILTIN_EVMHOSSFAAW },
06458 { 0, CODE_FOR_spe_evmhossfanw, "__builtin_spe_evmhossfanw", SPE_BUILTIN_EVMHOSSFANW },
06459 { 0, CODE_FOR_spe_evmhossiaaw, "__builtin_spe_evmhossiaaw", SPE_BUILTIN_EVMHOSSIAAW },
06460 { 0, CODE_FOR_spe_evmhossianw, "__builtin_spe_evmhossianw", SPE_BUILTIN_EVMHOSSIANW },
06461 { 0, CODE_FOR_spe_evmhoumi, "__builtin_spe_evmhoumi", SPE_BUILTIN_EVMHOUMI },
06462 { 0, CODE_FOR_spe_evmhoumia, "__builtin_spe_evmhoumia", SPE_BUILTIN_EVMHOUMIA },
06463 { 0, CODE_FOR_spe_evmhoumiaaw, "__builtin_spe_evmhoumiaaw", SPE_BUILTIN_EVMHOUMIAAW },
06464 { 0, CODE_FOR_spe_evmhoumianw, "__builtin_spe_evmhoumianw", SPE_BUILTIN_EVMHOUMIANW },
06465 { 0, CODE_FOR_spe_evmhousiaaw, "__builtin_spe_evmhousiaaw", SPE_BUILTIN_EVMHOUSIAAW },
06466 { 0, CODE_FOR_spe_evmhousianw, "__builtin_spe_evmhousianw", SPE_BUILTIN_EVMHOUSIANW },
06467 { 0, CODE_FOR_spe_evmwhsmf, "__builtin_spe_evmwhsmf", SPE_BUILTIN_EVMWHSMF },
06468 { 0, CODE_FOR_spe_evmwhsmfa, "__builtin_spe_evmwhsmfa", SPE_BUILTIN_EVMWHSMFA },
06469 { 0, CODE_FOR_spe_evmwhsmi, "__builtin_spe_evmwhsmi", SPE_BUILTIN_EVMWHSMI },
06470 { 0, CODE_FOR_spe_evmwhsmia, "__builtin_spe_evmwhsmia", SPE_BUILTIN_EVMWHSMIA },
06471 { 0, CODE_FOR_spe_evmwhssf, "__builtin_spe_evmwhssf", SPE_BUILTIN_EVMWHSSF },
06472 { 0, CODE_FOR_spe_evmwhssfa, "__builtin_spe_evmwhssfa", SPE_BUILTIN_EVMWHSSFA },
06473 { 0, CODE_FOR_spe_evmwhumi, "__builtin_spe_evmwhumi", SPE_BUILTIN_EVMWHUMI },
06474 { 0, CODE_FOR_spe_evmwhumia, "__builtin_spe_evmwhumia", SPE_BUILTIN_EVMWHUMIA },
06475 { 0, CODE_FOR_spe_evmwlsmiaaw, "__builtin_spe_evmwlsmiaaw", SPE_BUILTIN_EVMWLSMIAAW },
06476 { 0, CODE_FOR_spe_evmwlsmianw, "__builtin_spe_evmwlsmianw", SPE_BUILTIN_EVMWLSMIANW },
06477 { 0, CODE_FOR_spe_evmwlssiaaw, "__builtin_spe_evmwlssiaaw", SPE_BUILTIN_EVMWLSSIAAW },
06478 { 0, CODE_FOR_spe_evmwlssianw, "__builtin_spe_evmwlssianw", SPE_BUILTIN_EVMWLSSIANW },
06479 { 0, CODE_FOR_spe_evmwlumi, "__builtin_spe_evmwlumi", SPE_BUILTIN_EVMWLUMI },
06480 { 0, CODE_FOR_spe_evmwlumia, "__builtin_spe_evmwlumia", SPE_BUILTIN_EVMWLUMIA },
06481 { 0, CODE_FOR_spe_evmwlumiaaw, "__builtin_spe_evmwlumiaaw", SPE_BUILTIN_EVMWLUMIAAW },
06482 { 0, CODE_FOR_spe_evmwlumianw, "__builtin_spe_evmwlumianw", SPE_BUILTIN_EVMWLUMIANW },
06483 { 0, CODE_FOR_spe_evmwlusiaaw, "__builtin_spe_evmwlusiaaw", SPE_BUILTIN_EVMWLUSIAAW },
06484 { 0, CODE_FOR_spe_evmwlusianw, "__builtin_spe_evmwlusianw", SPE_BUILTIN_EVMWLUSIANW },
06485 { 0, CODE_FOR_spe_evmwsmf, "__builtin_spe_evmwsmf", SPE_BUILTIN_EVMWSMF },
06486 { 0, CODE_FOR_spe_evmwsmfa, "__builtin_spe_evmwsmfa", SPE_BUILTIN_EVMWSMFA },
06487 { 0, CODE_FOR_spe_evmwsmfaa, "__builtin_spe_evmwsmfaa", SPE_BUILTIN_EVMWSMFAA },
06488 { 0, CODE_FOR_spe_evmwsmfan, "__builtin_spe_evmwsmfan", SPE_BUILTIN_EVMWSMFAN },
06489 { 0, CODE_FOR_spe_evmwsmi, "__builtin_spe_evmwsmi", SPE_BUILTIN_EVMWSMI },
06490 { 0, CODE_FOR_spe_evmwsmia, "__builtin_spe_evmwsmia", SPE_BUILTIN_EVMWSMIA },
06491 { 0, CODE_FOR_spe_evmwsmiaa, "__builtin_spe_evmwsmiaa", SPE_BUILTIN_EVMWSMIAA },
06492 { 0, CODE_FOR_spe_evmwsmian, "__builtin_spe_evmwsmian", SPE_BUILTIN_EVMWSMIAN },
06493 { 0, CODE_FOR_spe_evmwssf, "__builtin_spe_evmwssf", SPE_BUILTIN_EVMWSSF },
06494 { 0, CODE_FOR_spe_evmwssfa, "__builtin_spe_evmwssfa", SPE_BUILTIN_EVMWSSFA },
06495 { 0, CODE_FOR_spe_evmwssfaa, "__builtin_spe_evmwssfaa", SPE_BUILTIN_EVMWSSFAA },
06496 { 0, CODE_FOR_spe_evmwssfan, "__builtin_spe_evmwssfan", SPE_BUILTIN_EVMWSSFAN },
06497 { 0, CODE_FOR_spe_evmwumi, "__builtin_spe_evmwumi", SPE_BUILTIN_EVMWUMI },
06498 { 0, CODE_FOR_spe_evmwumia, "__builtin_spe_evmwumia", SPE_BUILTIN_EVMWUMIA },
06499 { 0, CODE_FOR_spe_evmwumiaa, "__builtin_spe_evmwumiaa", SPE_BUILTIN_EVMWUMIAA },
06500 { 0, CODE_FOR_spe_evmwumian, "__builtin_spe_evmwumian", SPE_BUILTIN_EVMWUMIAN },
06501 { 0, CODE_FOR_spe_evnand, "__builtin_spe_evnand", SPE_BUILTIN_EVNAND },
06502 { 0, CODE_FOR_spe_evnor, "__builtin_spe_evnor", SPE_BUILTIN_EVNOR },
06503 { 0, CODE_FOR_spe_evor, "__builtin_spe_evor", SPE_BUILTIN_EVOR },
06504 { 0, CODE_FOR_spe_evorc, "__builtin_spe_evorc", SPE_BUILTIN_EVORC },
06505 { 0, CODE_FOR_spe_evrlw, "__builtin_spe_evrlw", SPE_BUILTIN_EVRLW },
06506 { 0, CODE_FOR_spe_evslw, "__builtin_spe_evslw", SPE_BUILTIN_EVSLW },
06507 { 0, CODE_FOR_spe_evsrws, "__builtin_spe_evsrws", SPE_BUILTIN_EVSRWS },
06508 { 0, CODE_FOR_spe_evsrwu, "__builtin_spe_evsrwu", SPE_BUILTIN_EVSRWU },
06509 { 0, CODE_FOR_spe_evsubfw, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
06510
06511
06512 { 0, CODE_FOR_spe_evaddiw, "__builtin_spe_evaddiw", SPE_BUILTIN_EVADDIW },
06513
06514 { 0, CODE_FOR_spe_evrlwi, "__builtin_spe_evrlwi", SPE_BUILTIN_EVRLWI },
06515 { 0, CODE_FOR_spe_evslwi, "__builtin_spe_evslwi", SPE_BUILTIN_EVSLWI },
06516 { 0, CODE_FOR_spe_evsrwis, "__builtin_spe_evsrwis", SPE_BUILTIN_EVSRWIS },
06517 { 0, CODE_FOR_spe_evsrwiu, "__builtin_spe_evsrwiu", SPE_BUILTIN_EVSRWIU },
06518 { 0, CODE_FOR_spe_evsubifw, "__builtin_spe_evsubifw", SPE_BUILTIN_EVSUBIFW },
06519 { 0, CODE_FOR_spe_evmwhssfaa, "__builtin_spe_evmwhssfaa", SPE_BUILTIN_EVMWHSSFAA },
06520 { 0, CODE_FOR_spe_evmwhssmaa, "__builtin_spe_evmwhssmaa", SPE_BUILTIN_EVMWHSSMAA },
06521 { 0, CODE_FOR_spe_evmwhsmfaa, "__builtin_spe_evmwhsmfaa", SPE_BUILTIN_EVMWHSMFAA },
06522 { 0, CODE_FOR_spe_evmwhsmiaa, "__builtin_spe_evmwhsmiaa", SPE_BUILTIN_EVMWHSMIAA },
06523 { 0, CODE_FOR_spe_evmwhusiaa, "__builtin_spe_evmwhusiaa", SPE_BUILTIN_EVMWHUSIAA },
06524 { 0, CODE_FOR_spe_evmwhumiaa, "__builtin_spe_evmwhumiaa", SPE_BUILTIN_EVMWHUMIAA },
06525 { 0, CODE_FOR_spe_evmwhssfan, "__builtin_spe_evmwhssfan", SPE_BUILTIN_EVMWHSSFAN },
06526 { 0, CODE_FOR_spe_evmwhssian, "__builtin_spe_evmwhssian", SPE_BUILTIN_EVMWHSSIAN },
06527 { 0, CODE_FOR_spe_evmwhsmfan, "__builtin_spe_evmwhsmfan", SPE_BUILTIN_EVMWHSMFAN },
06528 { 0, CODE_FOR_spe_evmwhsmian, "__builtin_spe_evmwhsmian", SPE_BUILTIN_EVMWHSMIAN },
06529 { 0, CODE_FOR_spe_evmwhusian, "__builtin_spe_evmwhusian", SPE_BUILTIN_EVMWHUSIAN },
06530 { 0, CODE_FOR_spe_evmwhumian, "__builtin_spe_evmwhumian", SPE_BUILTIN_EVMWHUMIAN },
06531 { 0, CODE_FOR_spe_evmwhgssfaa, "__builtin_spe_evmwhgssfaa", SPE_BUILTIN_EVMWHGSSFAA },
06532 { 0, CODE_FOR_spe_evmwhgsmfaa, "__builtin_spe_evmwhgsmfaa", SPE_BUILTIN_EVMWHGSMFAA },
06533 { 0, CODE_FOR_spe_evmwhgsmiaa, "__builtin_spe_evmwhgsmiaa", SPE_BUILTIN_EVMWHGSMIAA },
06534 { 0, CODE_FOR_spe_evmwhgumiaa, "__builtin_spe_evmwhgumiaa", SPE_BUILTIN_EVMWHGUMIAA },
06535 { 0, CODE_FOR_spe_evmwhgssfan, "__builtin_spe_evmwhgssfan", SPE_BUILTIN_EVMWHGSSFAN },
06536 { 0, CODE_FOR_spe_evmwhgsmfan, "__builtin_spe_evmwhgsmfan", SPE_BUILTIN_EVMWHGSMFAN },
06537 { 0, CODE_FOR_spe_evmwhgsmian, "__builtin_spe_evmwhgsmian", SPE_BUILTIN_EVMWHGSMIAN },
06538 { 0, CODE_FOR_spe_evmwhgumian, "__builtin_spe_evmwhgumian", SPE_BUILTIN_EVMWHGUMIAN },
06539 { 0, CODE_FOR_spe_brinc, "__builtin_spe_brinc", SPE_BUILTIN_BRINC },
06540
06541
06542 { 0, CODE_FOR_xorv2si3, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR }
06543 };
06544
06545
06546
06547 struct builtin_description_predicates
06548 {
06549 const unsigned int mask;
06550 const enum insn_code icode;
06551 const char *opcode;
06552 const char *const name;
06553 const enum rs6000_builtins code;
06554 };
06555
06556 static const struct builtin_description_predicates bdesc_altivec_preds[] =
06557 {
06558 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpbfp.", "__builtin_altivec_vcmpbfp_p", ALTIVEC_BUILTIN_VCMPBFP_P },
06559 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpeqfp.", "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
06560 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgefp.", "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
06561 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgtfp.", "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
06562 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpequw.", "__builtin_altivec_vcmpequw_p", ALTIVEC_BUILTIN_VCMPEQUW_P },
06563 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtsw.", "__builtin_altivec_vcmpgtsw_p", ALTIVEC_BUILTIN_VCMPGTSW_P },
06564 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtuw.", "__builtin_altivec_vcmpgtuw_p", ALTIVEC_BUILTIN_VCMPGTUW_P },
06565 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtuh.", "__builtin_altivec_vcmpgtuh_p", ALTIVEC_BUILTIN_VCMPGTUH_P },
06566 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtsh.", "__builtin_altivec_vcmpgtsh_p", ALTIVEC_BUILTIN_VCMPGTSH_P },
06567 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpequh.", "__builtin_altivec_vcmpequh_p", ALTIVEC_BUILTIN_VCMPEQUH_P },
06568 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpequb.", "__builtin_altivec_vcmpequb_p", ALTIVEC_BUILTIN_VCMPEQUB_P },
06569 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtsb.", "__builtin_altivec_vcmpgtsb_p", ALTIVEC_BUILTIN_VCMPGTSB_P },
06570 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P },
06571
06572 { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpeq_p", ALTIVEC_BUILTIN_VCMPEQ_P },
06573 { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpgt_p", ALTIVEC_BUILTIN_VCMPGT_P },
06574 { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpge_p", ALTIVEC_BUILTIN_VCMPGE_P }
06575 };
06576
06577
06578 static struct builtin_description bdesc_spe_predicates[] =
06579 {
06580
06581 { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evcmpeq", SPE_BUILTIN_EVCMPEQ },
06582 { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evcmpgts", SPE_BUILTIN_EVCMPGTS },
06583 { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evcmpgtu", SPE_BUILTIN_EVCMPGTU },
06584 { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evcmplts", SPE_BUILTIN_EVCMPLTS },
06585 { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evcmpltu", SPE_BUILTIN_EVCMPLTU },
06586 { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evfscmpeq", SPE_BUILTIN_EVFSCMPEQ },
06587 { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evfscmpgt", SPE_BUILTIN_EVFSCMPGT },
06588 { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evfscmplt", SPE_BUILTIN_EVFSCMPLT },
06589 { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evfststeq", SPE_BUILTIN_EVFSTSTEQ },
06590 { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evfststgt", SPE_BUILTIN_EVFSTSTGT },
06591
06592 { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evfststlt", SPE_BUILTIN_EVFSTSTLT },
06593 };
06594
06595
06596 static struct builtin_description bdesc_spe_evsel[] =
06597 {
06598
06599 { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evsel_gts", SPE_BUILTIN_EVSEL_CMPGTS },
06600 { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evsel_gtu", SPE_BUILTIN_EVSEL_CMPGTU },
06601 { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evsel_lts", SPE_BUILTIN_EVSEL_CMPLTS },
06602 { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evsel_ltu", SPE_BUILTIN_EVSEL_CMPLTU },
06603 { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evsel_eq", SPE_BUILTIN_EVSEL_CMPEQ },
06604 { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evsel_fsgt", SPE_BUILTIN_EVSEL_FSCMPGT },
06605 { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evsel_fslt", SPE_BUILTIN_EVSEL_FSCMPLT },
06606 { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evsel_fseq", SPE_BUILTIN_EVSEL_FSCMPEQ },
06607 { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evsel_fststgt", SPE_BUILTIN_EVSEL_FSTSTGT },
06608 { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evsel_fststlt", SPE_BUILTIN_EVSEL_FSTSTLT },
06609
06610 { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ },
06611 };
06612
06613
06614
06615 static const struct builtin_description bdesc_abs[] =
06616 {
06617 { MASK_ALTIVEC, CODE_FOR_absv4si2, "__builtin_altivec_abs_v4si", ALTIVEC_BUILTIN_ABS_V4SI },
06618 { MASK_ALTIVEC, CODE_FOR_absv8hi2, "__builtin_altivec_abs_v8hi", ALTIVEC_BUILTIN_ABS_V8HI },
06619 { MASK_ALTIVEC, CODE_FOR_absv4sf2, "__builtin_altivec_abs_v4sf", ALTIVEC_BUILTIN_ABS_V4SF },
06620 { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
06621 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
06622 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
06623 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
06624 };
06625
06626
06627
06628
06629 static struct builtin_description bdesc_1arg[] =
06630 {
06631 { MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
06632 { MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
06633 { MASK_ALTIVEC, CODE_FOR_altivec_vrefp, "__builtin_altivec_vrefp", ALTIVEC_BUILTIN_VREFP },
06634 { MASK_ALTIVEC, CODE_FOR_altivec_vrfim, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
06635 { MASK_ALTIVEC, CODE_FOR_altivec_vrfin, "__builtin_altivec_vrfin", ALTIVEC_BUILTIN_VRFIN },
06636 { MASK_ALTIVEC, CODE_FOR_altivec_vrfip, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
06637 { MASK_ALTIVEC, CODE_FOR_ftruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
06638 { MASK_ALTIVEC, CODE_FOR_altivec_vrsqrtefp, "__builtin_altivec_vrsqrtefp", ALTIVEC_BUILTIN_VRSQRTEFP },
06639 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisb, "__builtin_altivec_vspltisb", ALTIVEC_BUILTIN_VSPLTISB },
06640 { MASK_ALTIVEC, CODE_FOR_altivec_vspltish, "__builtin_altivec_vspltish", ALTIVEC_BUILTIN_VSPLTISH },
06641 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisw, "__builtin_altivec_vspltisw", ALTIVEC_BUILTIN_VSPLTISW },
06642 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsb, "__builtin_altivec_vupkhsb", ALTIVEC_BUILTIN_VUPKHSB },
06643 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhpx, "__builtin_altivec_vupkhpx", ALTIVEC_BUILTIN_VUPKHPX },
06644 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsh, "__builtin_altivec_vupkhsh", ALTIVEC_BUILTIN_VUPKHSH },
06645 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsb, "__builtin_altivec_vupklsb", ALTIVEC_BUILTIN_VUPKLSB },
06646 { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
06647 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
06648
06649 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
06650 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
06651 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
06652 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_expte", ALTIVEC_BUILTIN_VEC_EXPTE },
06653 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_floor", ALTIVEC_BUILTIN_VEC_FLOOR },
06654 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_loge", ALTIVEC_BUILTIN_VEC_LOGE },
06655 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mtvscr", ALTIVEC_BUILTIN_VEC_MTVSCR },
06656 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_re", ALTIVEC_BUILTIN_VEC_RE },
06657 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_round", ALTIVEC_BUILTIN_VEC_ROUND },
06658 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rsqrte", ALTIVEC_BUILTIN_VEC_RSQRTE },
06659 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_trunc", ALTIVEC_BUILTIN_VEC_TRUNC },
06660 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackh", ALTIVEC_BUILTIN_VEC_UNPACKH },
06661 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsh", ALTIVEC_BUILTIN_VEC_VUPKHSH },
06662 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhpx", ALTIVEC_BUILTIN_VEC_VUPKHPX },
06663 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsb", ALTIVEC_BUILTIN_VEC_VUPKHSB },
06664 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackl", ALTIVEC_BUILTIN_VEC_UNPACKL },
06665 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklpx", ALTIVEC_BUILTIN_VEC_VUPKLPX },
06666 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
06667 { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
06668
06669
06670
06671 { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
06672 { 0, CODE_FOR_spe_evaddsmiaaw, "__builtin_spe_evaddsmiaaw", SPE_BUILTIN_EVADDSMIAAW },
06673 { 0, CODE_FOR_spe_evaddssiaaw, "__builtin_spe_evaddssiaaw", SPE_BUILTIN_EVADDSSIAAW },
06674 { 0, CODE_FOR_spe_evaddumiaaw, "__builtin_spe_evaddumiaaw", SPE_BUILTIN_EVADDUMIAAW },
06675 { 0, CODE_FOR_spe_evaddusiaaw, "__builtin_spe_evaddusiaaw", SPE_BUILTIN_EVADDUSIAAW },
06676 { 0, CODE_FOR_spe_evcntlsw, "__builtin_spe_evcntlsw", SPE_BUILTIN_EVCNTLSW },
06677 { 0, CODE_FOR_spe_evcntlzw, "__builtin_spe_evcntlzw", SPE_BUILTIN_EVCNTLZW },
06678 { 0, CODE_FOR_spe_evextsb, "__builtin_spe_evextsb", SPE_BUILTIN_EVEXTSB },
06679 { 0, CODE_FOR_spe_evextsh, "__builtin_spe_evextsh", SPE_BUILTIN_EVEXTSH },
06680 { 0, CODE_FOR_spe_evfsabs, "__builtin_spe_evfsabs", SPE_BUILTIN_EVFSABS },
06681 { 0, CODE_FOR_spe_evfscfsf, "__builtin_spe_evfscfsf", SPE_BUILTIN_EVFSCFSF },
06682 { 0, CODE_FOR_spe_evfscfsi, "__builtin_spe_evfscfsi", SPE_BUILTIN_EVFSCFSI },
06683 { 0, CODE_FOR_spe_evfscfuf, "__builtin_spe_evfscfuf", SPE_BUILTIN_EVFSCFUF },
06684 { 0, CODE_FOR_spe_evfscfui, "__builtin_spe_evfscfui", SPE_BUILTIN_EVFSCFUI },
06685 { 0, CODE_FOR_spe_evfsctsf, "__builtin_spe_evfsctsf", SPE_BUILTIN_EVFSCTSF },
06686 { 0, CODE_FOR_spe_evfsctsi, "__builtin_spe_evfsctsi", SPE_BUILTIN_EVFSCTSI },
06687 { 0, CODE_FOR_spe_evfsctsiz, "__builtin_spe_evfsctsiz", SPE_BUILTIN_EVFSCTSIZ },
06688 { 0, CODE_FOR_spe_evfsctuf, "__builtin_spe_evfsctuf", SPE_BUILTIN_EVFSCTUF },
06689 { 0, CODE_FOR_spe_evfsctui, "__builtin_spe_evfsctui", SPE_BUILTIN_EVFSCTUI },
06690 { 0, CODE_FOR_spe_evfsctuiz, "__builtin_spe_evfsctuiz", SPE_BUILTIN_EVFSCTUIZ },
06691 { 0, CODE_FOR_spe_evfsnabs, "__builtin_spe_evfsnabs", SPE_BUILTIN_EVFSNABS },
06692 { 0, CODE_FOR_spe_evfsneg, "__builtin_spe_evfsneg", SPE_BUILTIN_EVFSNEG },
06693 { 0, CODE_FOR_spe_evmra, "__builtin_spe_evmra", SPE_BUILTIN_EVMRA },
06694 { 0, CODE_FOR_negv2si2, "__builtin_spe_evneg", SPE_BUILTIN_EVNEG },
06695 { 0, CODE_FOR_spe_evrndw, "__builtin_spe_evrndw", SPE_BUILTIN_EVRNDW },
06696 { 0, CODE_FOR_spe_evsubfsmiaaw, "__builtin_spe_evsubfsmiaaw", SPE_BUILTIN_EVSUBFSMIAAW },
06697 { 0, CODE_FOR_spe_evsubfssiaaw, "__builtin_spe_evsubfssiaaw", SPE_BUILTIN_EVSUBFSSIAAW },
06698 { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
06699
06700
06701 { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW }
06702 };
06703
06704 static rtx
06705 rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target)
06706 {
06707 rtx pat;
06708 tree arg0 = TREE_VALUE (arglist);
06709 rtx op0 = expand_normal (arg0);
06710 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06711 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06712
06713 if (icode == CODE_FOR_nothing)
06714
06715 return 0;
06716
06717
06718 if (arg0 == error_mark_node)
06719 return const0_rtx;
06720
06721 if (icode == CODE_FOR_altivec_vspltisb
06722 || icode == CODE_FOR_altivec_vspltish
06723 || icode == CODE_FOR_altivec_vspltisw
06724 || icode == CODE_FOR_spe_evsplatfi
06725 || icode == CODE_FOR_spe_evsplati)
06726 {
06727
06728 if (GET_CODE (op0) != CONST_INT
06729 || INTVAL (op0) > 15
06730 || INTVAL (op0) < -16)
06731 {
06732 error ("argument 1 must be a 5-bit signed literal");
06733 return const0_rtx;
06734 }
06735 }
06736
06737 if (target == 0
06738 || GET_MODE (target) != tmode
06739 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06740 target = gen_reg_rtx (tmode);
06741
06742 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06743 op0 = copy_to_mode_reg (mode0, op0);
06744
06745 pat = GEN_FCN (icode) (target, op0);
06746 if (! pat)
06747 return 0;
06748 emit_insn (pat);
06749
06750 return target;
06751 }
06752
06753 static rtx
06754 altivec_expand_abs_builtin (enum insn_code icode, tree arglist, rtx target)
06755 {
06756 rtx pat, scratch1, scratch2;
06757 tree arg0 = TREE_VALUE (arglist);
06758 rtx op0 = expand_normal (arg0);
06759 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06760 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06761
06762
06763 if (arg0 == error_mark_node)
06764 return const0_rtx;
06765
06766 if (target == 0
06767 || GET_MODE (target) != tmode
06768 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06769 target = gen_reg_rtx (tmode);
06770
06771 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06772 op0 = copy_to_mode_reg (mode0, op0);
06773
06774 scratch1 = gen_reg_rtx (mode0);
06775 scratch2 = gen_reg_rtx (mode0);
06776
06777 pat = GEN_FCN (icode) (target, op0, scratch1, scratch2);
06778 if (! pat)
06779 return 0;
06780 emit_insn (pat);
06781
06782 return target;
06783 }
06784
06785 static rtx
06786 rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
06787 {
06788 rtx pat;
06789 tree arg0 = TREE_VALUE (arglist);
06790 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
06791 rtx op0 = expand_normal (arg0);
06792 rtx op1 = expand_normal (arg1);
06793 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06794 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06795 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
06796
06797 if (icode == CODE_FOR_nothing)
06798
06799 return 0;
06800
06801
06802 if (arg0 == error_mark_node || arg1 == error_mark_node)
06803 return const0_rtx;
06804
06805 if (icode == CODE_FOR_altivec_vcfux
06806 || icode == CODE_FOR_altivec_vcfsx
06807 || icode == CODE_FOR_altivec_vctsxs
06808 || icode == CODE_FOR_altivec_vctuxs
06809 || icode == CODE_FOR_altivec_vspltb
06810 || icode == CODE_FOR_altivec_vsplth
06811 || icode == CODE_FOR_altivec_vspltw
06812 || icode == CODE_FOR_spe_evaddiw
06813 || icode == CODE_FOR_spe_evldd
06814 || icode == CODE_FOR_spe_evldh
06815 || icode == CODE_FOR_spe_evldw
06816 || icode == CODE_FOR_spe_evlhhesplat
06817 || icode == CODE_FOR_spe_evlhhossplat
06818 || icode == CODE_FOR_spe_evlhhousplat
06819 || icode == CODE_FOR_spe_evlwhe
06820 || icode == CODE_FOR_spe_evlwhos
06821 || icode == CODE_FOR_spe_evlwhou
06822 || icode == CODE_FOR_spe_evlwhsplat
06823 || icode == CODE_FOR_spe_evlwwsplat
06824 || icode == CODE_FOR_spe_evrlwi
06825 || icode == CODE_FOR_spe_evslwi
06826 || icode == CODE_FOR_spe_evsrwis
06827 || icode == CODE_FOR_spe_evsubifw
06828 || icode == CODE_FOR_spe_evsrwiu)
06829 {
06830
06831 STRIP_NOPS (arg1);
06832 if (TREE_CODE (arg1) != INTEGER_CST
06833 || TREE_INT_CST_LOW (arg1) & ~0x1f)
06834 {
06835 error ("argument 2 must be a 5-bit unsigned literal");
06836 return const0_rtx;
06837 }
06838 }
06839
06840 if (target == 0
06841 || GET_MODE (target) != tmode
06842 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06843 target = gen_reg_rtx (tmode);
06844
06845 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06846 op0 = copy_to_mode_reg (mode0, op0);
06847 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
06848 op1 = copy_to_mode_reg (mode1, op1);
06849
06850 pat = GEN_FCN (icode) (target, op0, op1);
06851 if (! pat)
06852 return 0;
06853 emit_insn (pat);
06854
06855 return target;
06856 }
06857
06858 static rtx
06859 altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
06860 tree arglist, rtx target)
06861 {
06862 rtx pat, scratch;
06863 tree cr6_form = TREE_VALUE (arglist);
06864 tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
06865 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
06866 rtx op0 = expand_normal (arg0);
06867 rtx op1 = expand_normal (arg1);
06868 enum machine_mode tmode = SImode;
06869 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06870 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
06871 int cr6_form_int;
06872
06873 if (TREE_CODE (cr6_form) != INTEGER_CST)
06874 {
06875 error ("argument 1 of __builtin_altivec_predicate must be a constant");
06876 return const0_rtx;
06877 }
06878 else
06879 cr6_form_int = TREE_INT_CST_LOW (cr6_form);
06880
06881 gcc_assert (mode0 == mode1);
06882
06883
06884 if (arg0 == error_mark_node || arg1 == error_mark_node)
06885 return const0_rtx;
06886
06887 if (target == 0
06888 || GET_MODE (target) != tmode
06889 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06890 target = gen_reg_rtx (tmode);
06891
06892 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06893 op0 = copy_to_mode_reg (mode0, op0);
06894 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
06895 op1 = copy_to_mode_reg (mode1, op1);
06896
06897 scratch = gen_reg_rtx (mode0);
06898
06899 pat = GEN_FCN (icode) (scratch, op0, op1,
06900 gen_rtx_SYMBOL_REF (Pmode, opcode));
06901 if (! pat)
06902 return 0;
06903 emit_insn (pat);
06904
06905
06906
06907
06908
06909
06910
06911
06912
06913 switch (cr6_form_int)
06914 {
06915 case 0:
06916 emit_insn (gen_cr6_test_for_zero (target));
06917 break;
06918 case 1:
06919 emit_insn (gen_cr6_test_for_zero_reverse (target));
06920 break;
06921 case 2:
06922 emit_insn (gen_cr6_test_for_lt (target));
06923 break;
06924 case 3:
06925 emit_insn (gen_cr6_test_for_lt_reverse (target));
06926 break;
06927 default:
06928 error ("argument 1 of __builtin_altivec_predicate is out of range");
06929 break;
06930 }
06931
06932 return target;
06933 }
06934
06935 static rtx
06936 altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target)
06937 {
06938 rtx pat, addr;
06939 tree arg0 = TREE_VALUE (arglist);
06940 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
06941 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06942 enum machine_mode mode0 = Pmode;
06943 enum machine_mode mode1 = Pmode;
06944 rtx op0 = expand_normal (arg0);
06945 rtx op1 = expand_normal (arg1);
06946
06947 if (icode == CODE_FOR_nothing)
06948
06949 return 0;
06950
06951
06952 if (arg0 == error_mark_node || arg1 == error_mark_node)
06953 return const0_rtx;
06954
06955 if (target == 0
06956 || GET_MODE (target) != tmode
06957 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06958 target = gen_reg_rtx (tmode);
06959
06960 op1 = copy_to_mode_reg (mode1, op1);
06961
06962 if (op0 == const0_rtx)
06963 {
06964 addr = gen_rtx_MEM (tmode, op1);
06965 }
06966 else
06967 {
06968 op0 = copy_to_mode_reg (mode0, op0);
06969 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1));
06970 }
06971
06972 pat = GEN_FCN (icode) (target, addr);
06973
06974 if (! pat)
06975 return 0;
06976 emit_insn (pat);
06977
06978 return target;
06979 }
06980
06981 static rtx
06982 spe_expand_stv_builtin (enum insn_code icode, tree arglist)
06983 {
06984 tree arg0 = TREE_VALUE (arglist);
06985 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
06986 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
06987 rtx op0 = expand_normal (arg0);
06988 rtx op1 = expand_normal (arg1);
06989 rtx op2 = expand_normal (arg2);
06990 rtx pat;
06991 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
06992 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
06993 enum machine_mode mode2 = insn_data[icode].operand[2].mode;
06994
06995
06996 if (arg0 == error_mark_node
06997 || arg1 == error_mark_node
06998 || arg2 == error_mark_node)
06999 return const0_rtx;
07000
07001 if (! (*insn_data[icode].operand[2].predicate) (op0, mode2))
07002 op0 = copy_to_mode_reg (mode2, op0);
07003 if (! (*insn_data[icode].operand[0].predicate) (op1, mode0))
07004 op1 = copy_to_mode_reg (mode0, op1);
07005 if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
07006 op2 = copy_to_mode_reg (mode1, op2);
07007
07008 pat = GEN_FCN (icode) (op1, op2, op0);
07009 if (pat)
07010 emit_insn (pat);
07011 return NULL_RTX;
07012 }
07013
07014 static rtx
07015 altivec_expand_stv_builtin (enum insn_code icode, tree arglist)
07016 {
07017 tree arg0 = TREE_VALUE (arglist);
07018 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07019 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07020 rtx op0 = expand_normal (arg0);
07021 rtx op1 = expand_normal (arg1);
07022 rtx op2 = expand_normal (arg2);
07023 rtx pat, addr;
07024 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07025 enum machine_mode mode1 = Pmode;
07026 enum machine_mode mode2 = Pmode;
07027
07028
07029 if (arg0 == error_mark_node
07030 || arg1 == error_mark_node
07031 || arg2 == error_mark_node)
07032 return const0_rtx;
07033
07034 if (! (*insn_data[icode].operand[1].predicate) (op0, tmode))
07035 op0 = copy_to_mode_reg (tmode, op0);
07036
07037 op2 = copy_to_mode_reg (mode2, op2);
07038
07039 if (op1 == const0_rtx)
07040 {
07041 addr = gen_rtx_MEM (tmode, op2);
07042 }
07043 else
07044 {
07045 op1 = copy_to_mode_reg (mode1, op1);
07046 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
07047 }
07048
07049 pat = GEN_FCN (icode) (addr, op0);
07050 if (pat)
07051 emit_insn (pat);
07052 return NULL_RTX;
07053 }
07054
07055 static rtx
07056 rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target)
07057 {
07058 rtx pat;
07059 tree arg0 = TREE_VALUE (arglist);
07060 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07061 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07062 rtx op0 = expand_normal (arg0);
07063 rtx op1 = expand_normal (arg1);
07064 rtx op2 = expand_normal (arg2);
07065 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07066 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07067 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07068 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
07069
07070 if (icode == CODE_FOR_nothing)
07071
07072 return 0;
07073
07074
07075 if (arg0 == error_mark_node
07076 || arg1 == error_mark_node
07077 || arg2 == error_mark_node)
07078 return const0_rtx;
07079
07080 if (icode == CODE_FOR_altivec_vsldoi_v4sf
07081 || icode == CODE_FOR_altivec_vsldoi_v4si
07082 || icode == CODE_FOR_altivec_vsldoi_v8hi
07083 || icode == CODE_FOR_altivec_vsldoi_v16qi)
07084 {
07085
07086 STRIP_NOPS (arg2);
07087 if (TREE_CODE (arg2) != INTEGER_CST
07088 || TREE_INT_CST_LOW (arg2) & ~0xf)
07089 {
07090 error ("argument 3 must be a 4-bit unsigned literal");
07091 return const0_rtx;
07092 }
07093 }
07094
07095 if (target == 0
07096 || GET_MODE (target) != tmode
07097 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07098 target = gen_reg_rtx (tmode);
07099
07100 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07101 op0 = copy_to_mode_reg (mode0, op0);
07102 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
07103 op1 = copy_to_mode_reg (mode1, op1);
07104 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
07105 op2 = copy_to_mode_reg (mode2, op2);
07106
07107 pat = GEN_FCN (icode) (target, op0, op1, op2);
07108 if (! pat)
07109 return 0;
07110 emit_insn (pat);
07111
07112 return target;
07113 }
07114
07115
07116 static rtx
07117 altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
07118 {
07119 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07120 tree arglist = TREE_OPERAND (exp, 1);
07121 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07122 tree arg0;
07123 enum machine_mode tmode, mode0;
07124 rtx pat, op0;
07125 enum insn_code icode;
07126
07127 switch (fcode)
07128 {
07129 case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
07130 icode = CODE_FOR_altivec_lvx_v16qi;
07131 break;
07132 case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
07133 icode = CODE_FOR_altivec_lvx_v8hi;
07134 break;
07135 case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
07136 icode = CODE_FOR_altivec_lvx_v4si;
07137 break;
07138 case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
07139 icode = CODE_FOR_altivec_lvx_v4sf;
07140 break;
07141 default:
07142 *expandedp = false;
07143 return NULL_RTX;
07144 }
07145
07146 *expandedp = true;
07147
07148 arg0 = TREE_VALUE (arglist);
07149 op0 = expand_normal (arg0);
07150 tmode = insn_data[icode].operand[0].mode;
07151 mode0 = insn_data[icode].operand[1].mode;
07152
07153 if (target == 0
07154 || GET_MODE (target) != tmode
07155 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07156 target = gen_reg_rtx (tmode);
07157
07158 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07159 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
07160
07161 pat = GEN_FCN (icode) (target, op0);
07162 if (! pat)
07163 return 0;
07164 emit_insn (pat);
07165 return target;
07166 }
07167
07168
07169 static rtx
07170 altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
07171 bool *expandedp)
07172 {
07173 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07174 tree arglist = TREE_OPERAND (exp, 1);
07175 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07176 tree arg0, arg1;
07177 enum machine_mode mode0, mode1;
07178 rtx pat, op0, op1;
07179 enum insn_code icode;
07180
07181 switch (fcode)
07182 {
07183 case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
07184 icode = CODE_FOR_altivec_stvx_v16qi;
07185 break;
07186 case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
07187 icode = CODE_FOR_altivec_stvx_v8hi;
07188 break;
07189 case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
07190 icode = CODE_FOR_altivec_stvx_v4si;
07191 break;
07192 case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
07193 icode = CODE_FOR_altivec_stvx_v4sf;
07194 break;
07195 default:
07196 *expandedp = false;
07197 return NULL_RTX;
07198 }
07199
07200 arg0 = TREE_VALUE (arglist);
07201 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07202 op0 = expand_normal (arg0);
07203 op1 = expand_normal (arg1);
07204 mode0 = insn_data[icode].operand[0].mode;
07205 mode1 = insn_data[icode].operand[1].mode;
07206
07207 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07208 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
07209 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
07210 op1 = copy_to_mode_reg (mode1, op1);
07211
07212 pat = GEN_FCN (icode) (op0, op1);
07213 if (pat)
07214 emit_insn (pat);
07215
07216 *expandedp = true;
07217 return NULL_RTX;
07218 }
07219
07220
07221 static rtx
07222 altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
07223 bool *expandedp)
07224 {
07225 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07226 tree arglist = TREE_OPERAND (exp, 1);
07227 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07228 tree arg0, arg1, arg2;
07229 enum machine_mode mode0, mode1, mode2;
07230 rtx pat, op0, op1, op2;
07231 struct builtin_description *d;
07232 size_t i;
07233
07234 *expandedp = false;
07235
07236
07237 d = (struct builtin_description *) bdesc_dst;
07238 for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
07239 if (d->code == fcode)
07240 {
07241 arg0 = TREE_VALUE (arglist);
07242 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07243 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07244 op0 = expand_normal (arg0);
07245 op1 = expand_normal (arg1);
07246 op2 = expand_normal (arg2);
07247 mode0 = insn_data[d->icode].operand[0].mode;
07248 mode1 = insn_data[d->icode].operand[1].mode;
07249 mode2 = insn_data[d->icode].operand[2].mode;
07250
07251
07252 if (arg0 == error_mark_node
07253 || arg1 == error_mark_node
07254 || arg2 == error_mark_node)
07255 return const0_rtx;
07256
07257 *expandedp = true;
07258 STRIP_NOPS (arg2);
07259 if (TREE_CODE (arg2) != INTEGER_CST
07260 || TREE_INT_CST_LOW (arg2) & ~0x3)
07261 {
07262 error ("argument to %qs must be a 2-bit unsigned literal", d->name);
07263 return const0_rtx;
07264 }
07265
07266 if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
07267 op0 = copy_to_mode_reg (Pmode, op0);
07268 if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
07269 op1 = copy_to_mode_reg (mode1, op1);
07270
07271 pat = GEN_FCN (d->icode) (op0, op1, op2);
07272 if (pat != 0)
07273 emit_insn (pat);
07274
07275 return NULL_RTX;
07276 }
07277
07278 return NULL_RTX;
07279 }
07280
07281
07282 static rtx
07283 altivec_expand_vec_init_builtin (tree type, tree arglist, rtx target)
07284 {
07285 enum machine_mode tmode = TYPE_MODE (type);
07286 enum machine_mode inner_mode = GET_MODE_INNER (tmode);
07287 int i, n_elt = GET_MODE_NUNITS (tmode);
07288 rtvec v = rtvec_alloc (n_elt);
07289
07290 gcc_assert (VECTOR_MODE_P (tmode));
07291
07292 for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist))
07293 {
07294 rtx x = expand_normal (TREE_VALUE (arglist));
07295 RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
07296 }
07297
07298 gcc_assert (arglist == NULL);
07299
07300 if (!target || !register_operand (target, tmode))
07301 target = gen_reg_rtx (tmode);
07302
07303 rs6000_expand_vector_init (target, gen_rtx_PARALLEL (tmode, v));
07304 return target;
07305 }
07306
07307
07308
07309
07310 static int
07311 get_element_number (tree vec_type, tree arg)
07312 {
07313 unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
07314
07315 if (!host_integerp (arg, 1)
07316 || (elt = tree_low_cst (arg, 1), elt > max))
07317 {
07318 error ("selector must be an integer constant in the range 0..%wi", max);
07319 return 0;
07320 }
07321
07322 return elt;
07323 }
07324
07325
07326 static rtx
07327 altivec_expand_vec_set_builtin (tree arglist)
07328 {
07329 enum machine_mode tmode, mode1;
07330 tree arg0, arg1, arg2;
07331 int elt;
07332 rtx op0, op1;
07333
07334 arg0 = TREE_VALUE (arglist);
07335 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07336 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07337
07338 tmode = TYPE_MODE (TREE_TYPE (arg0));
07339 mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
07340 gcc_assert (VECTOR_MODE_P (tmode));
07341
07342 op0 = expand_expr (arg0, NULL_RTX, tmode, 0);
07343 op1 = expand_expr (arg1, NULL_RTX, mode1, 0);
07344 elt = get_element_number (TREE_TYPE (arg0), arg2);
07345
07346 if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode)
07347 op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
07348
07349 op0 = force_reg (tmode, op0);
07350 op1 = force_reg (mode1, op1);
07351
07352 rs6000_expand_vector_set (op0, op1, elt);
07353
07354 return op0;
07355 }
07356
07357
07358 static rtx
07359 altivec_expand_vec_ext_builtin (tree arglist, rtx target)
07360 {
07361 enum machine_mode tmode, mode0;
07362 tree arg0, arg1;
07363 int elt;
07364 rtx op0;
07365
07366 arg0 = TREE_VALUE (arglist);
07367 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07368
07369 op0 = expand_normal (arg0);
07370 elt = get_element_number (TREE_TYPE (arg0), arg1);
07371
07372 tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
07373 mode0 = TYPE_MODE (TREE_TYPE (arg0));
07374 gcc_assert (VECTOR_MODE_P (mode0));
07375
07376 op0 = force_reg (mode0, op0);
07377
07378 if (optimize || !target || !register_operand (target, tmode))
07379 target = gen_reg_rtx (tmode);
07380
07381 rs6000_expand_vector_extract (target, op0, elt);
07382
07383 return target;
07384 }
07385
07386
07387
07388 static rtx
07389 altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
07390 {
07391 struct builtin_description *d;
07392 struct builtin_description_predicates *dp;
07393 size_t i;
07394 enum insn_code icode;
07395 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07396 tree arglist = TREE_OPERAND (exp, 1);
07397 tree arg0;
07398 rtx op0, pat;
07399 enum machine_mode tmode, mode0;
07400 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07401
07402 if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
07403 && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
07404 {
07405 *expandedp = true;
07406 error ("unresolved overload for Altivec builtin %qF", fndecl);
07407 return const0_rtx;
07408 }
07409
07410 target = altivec_expand_ld_builtin (exp, target, expandedp);
07411 if (*expandedp)
07412 return target;
07413
07414 target = altivec_expand_st_builtin (exp, target, expandedp);
07415 if (*expandedp)
07416 return target;
07417
07418 target = altivec_expand_dst_builtin (exp, target, expandedp);
07419 if (*expandedp)
07420 return target;
07421
07422 *expandedp = true;
07423
07424 switch (fcode)
07425 {
07426 case ALTIVEC_BUILTIN_STVX:
07427 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist);
07428 case ALTIVEC_BUILTIN_STVEBX:
07429 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, arglist);
07430 case ALTIVEC_BUILTIN_STVEHX:
07431 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, arglist);
07432 case ALTIVEC_BUILTIN_STVEWX:
07433 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist);
07434 case ALTIVEC_BUILTIN_STVXL:
07435 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist);
07436
07437 case ALTIVEC_BUILTIN_MFVSCR:
07438 icode = CODE_FOR_altivec_mfvscr;
07439 tmode = insn_data[icode].operand[0].mode;
07440
07441 if (target == 0
07442 || GET_MODE (target) != tmode
07443 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07444 target = gen_reg_rtx (tmode);
07445
07446 pat = GEN_FCN (icode) (target);
07447 if (! pat)
07448 return 0;
07449 emit_insn (pat);
07450 return target;
07451
07452 case ALTIVEC_BUILTIN_MTVSCR:
07453 icode = CODE_FOR_altivec_mtvscr;
07454 arg0 = TREE_VALUE (arglist);
07455 op0 = expand_normal (arg0);
07456 mode0 = insn_data[icode].operand[0].mode;
07457
07458
07459 if (arg0 == error_mark_node)
07460 return const0_rtx;
07461
07462 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07463 op0 = copy_to_mode_reg (mode0, op0);
07464
07465 pat = GEN_FCN (icode) (op0);
07466 if (pat)
07467 emit_insn (pat);
07468 return NULL_RTX;
07469
07470 case ALTIVEC_BUILTIN_DSSALL:
07471 emit_insn (gen_altivec_dssall ());
07472 return NULL_RTX;
07473
07474 case ALTIVEC_BUILTIN_DSS:
07475 icode = CODE_FOR_altivec_dss;
07476 arg0 = TREE_VALUE (arglist);
07477 STRIP_NOPS (arg0);
07478 op0 = expand_normal (arg0);
07479 mode0 = insn_data[icode].operand[0].mode;
07480
07481
07482 if (arg0 == error_mark_node)
07483 return const0_rtx;
07484
07485 if (TREE_CODE (arg0) != INTEGER_CST
07486 || TREE_INT_CST_LOW (arg0) & ~0x3)
07487 {
07488 error ("argument to dss must be a 2-bit unsigned literal");
07489 return const0_rtx;
07490 }
07491
07492 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07493 op0 = copy_to_mode_reg (mode0, op0);
07494
07495 emit_insn (gen_altivec_dss (op0));
07496 return NULL_RTX;
07497
07498 case ALTIVEC_BUILTIN_VEC_INIT_V4SI:
07499 case ALTIVEC_BUILTIN_VEC_INIT_V8HI:
07500 case ALTIVEC_BUILTIN_VEC_INIT_V16QI:
07501 case ALTIVEC_BUILTIN_VEC_INIT_V4SF:
07502 return altivec_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target);
07503
07504 case ALTIVEC_BUILTIN_VEC_SET_V4SI:
07505 case ALTIVEC_BUILTIN_VEC_SET_V8HI:
07506 case ALTIVEC_BUILTIN_VEC_SET_V16QI:
07507 case ALTIVEC_BUILTIN_VEC_SET_V4SF:
07508 return altivec_expand_vec_set_builtin (arglist);
07509
07510 case ALTIVEC_BUILTIN_VEC_EXT_V4SI:
07511 case ALTIVEC_BUILTIN_VEC_EXT_V8HI:
07512 case ALTIVEC_BUILTIN_VEC_EXT_V16QI:
07513 case ALTIVEC_BUILTIN_VEC_EXT_V4SF:
07514 return altivec_expand_vec_ext_builtin (arglist, target);
07515
07516 default:
07517 break;
07518
07519 }
07520
07521
07522 d = (struct builtin_description *) bdesc_abs;
07523 for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
07524 if (d->code == fcode)
07525 return altivec_expand_abs_builtin (d->icode, arglist, target);
07526
07527
07528 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
07529 for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
07530 if (dp->code == fcode)
07531 return altivec_expand_predicate_builtin (dp->icode, dp->opcode,
07532 arglist, target);
07533
07534
07535 switch (fcode)
07536 {
07537 case ALTIVEC_BUILTIN_LVSL:
07538 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl,
07539 arglist, target);
07540 case ALTIVEC_BUILTIN_LVSR:
07541 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr,
07542 arglist, target);
07543 case ALTIVEC_BUILTIN_LVEBX:
07544 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx,
07545 arglist, target);
07546 case ALTIVEC_BUILTIN_LVEHX:
07547 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx,
07548 arglist, target);
07549 case ALTIVEC_BUILTIN_LVEWX:
07550 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx,
07551 arglist, target);
07552 case ALTIVEC_BUILTIN_LVXL:
07553 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl,
07554 arglist, target);
07555 case ALTIVEC_BUILTIN_LVX:
07556 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx,
07557 arglist, target);
07558 default:
07559 break;
07560
07561 }
07562
07563 *expandedp = false;
07564 return NULL_RTX;
07565 }
07566
07567
07568
07569 static struct builtin_description bdesc_2arg_spe[] =
07570 {
07571 { 0, CODE_FOR_spe_evlddx, "__builtin_spe_evlddx", SPE_BUILTIN_EVLDDX },
07572 { 0, CODE_FOR_spe_evldwx, "__builtin_spe_evldwx", SPE_BUILTIN_EVLDWX },
07573 { 0, CODE_FOR_spe_evldhx, "__builtin_spe_evldhx", SPE_BUILTIN_EVLDHX },
07574 { 0, CODE_FOR_spe_evlwhex, "__builtin_spe_evlwhex", SPE_BUILTIN_EVLWHEX },
07575 { 0, CODE_FOR_spe_evlwhoux, "__builtin_spe_evlwhoux", SPE_BUILTIN_EVLWHOUX },
07576 { 0, CODE_FOR_spe_evlwhosx, "__builtin_spe_evlwhosx", SPE_BUILTIN_EVLWHOSX },
07577 { 0, CODE_FOR_spe_evlwwsplatx, "__builtin_spe_evlwwsplatx", SPE_BUILTIN_EVLWWSPLATX },
07578 { 0, CODE_FOR_spe_evlwhsplatx, "__builtin_spe_evlwhsplatx", SPE_BUILTIN_EVLWHSPLATX },
07579 { 0, CODE_FOR_spe_evlhhesplatx, "__builtin_spe_evlhhesplatx", SPE_BUILTIN_EVLHHESPLATX },
07580 { 0, CODE_FOR_spe_evlhhousplatx, "__builtin_spe_evlhhousplatx", SPE_BUILTIN_EVLHHOUSPLATX },
07581 { 0, CODE_FOR_spe_evlhhossplatx, "__builtin_spe_evlhhossplatx", SPE_BUILTIN_EVLHHOSSPLATX },
07582 { 0, CODE_FOR_spe_evldd, "__builtin_spe_evldd", SPE_BUILTIN_EVLDD },
07583 { 0, CODE_FOR_spe_evldw, "__builtin_spe_evldw", SPE_BUILTIN_EVLDW },
07584 { 0, CODE_FOR_spe_evldh, "__builtin_spe_evldh", SPE_BUILTIN_EVLDH },
07585 { 0, CODE_FOR_spe_evlwhe, "__builtin_spe_evlwhe", SPE_BUILTIN_EVLWHE },
07586 { 0, CODE_FOR_spe_evlwhou, "__builtin_spe_evlwhou", SPE_BUILTIN_EVLWHOU },
07587 { 0, CODE_FOR_spe_evlwhos, "__builtin_spe_evlwhos", SPE_BUILTIN_EVLWHOS },
07588 { 0, CODE_FOR_spe_evlwwsplat, "__builtin_spe_evlwwsplat", SPE_BUILTIN_EVLWWSPLAT },
07589 { 0, CODE_FOR_spe_evlwhsplat, "__builtin_spe_evlwhsplat", SPE_BUILTIN_EVLWHSPLAT },
07590 { 0, CODE_FOR_spe_evlhhesplat, "__builtin_spe_evlhhesplat", SPE_BUILTIN_EVLHHESPLAT },
07591 { 0, CODE_FOR_spe_evlhhousplat, "__builtin_spe_evlhhousplat", SPE_BUILTIN_EVLHHOUSPLAT },
07592 { 0, CODE_FOR_spe_evlhhossplat, "__builtin_spe_evlhhossplat", SPE_BUILTIN_EVLHHOSSPLAT }
07593 };
07594
07595
07596
07597
07598
07599
07600 static rtx
07601 spe_expand_builtin (tree exp, rtx target, bool *expandedp)
07602 {
07603 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07604 tree arglist = TREE_OPERAND (exp, 1);
07605 tree arg1, arg0;
07606 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07607 enum insn_code icode;
07608 enum machine_mode tmode, mode0;
07609 rtx pat, op0;
07610 struct builtin_description *d;
07611 size_t i;
07612
07613 *expandedp = true;
07614
07615
07616 switch (fcode)
07617 {
07618 case SPE_BUILTIN_EVSTDD:
07619 case SPE_BUILTIN_EVSTDH:
07620 case SPE_BUILTIN_EVSTDW:
07621 case SPE_BUILTIN_EVSTWHE:
07622 case SPE_BUILTIN_EVSTWHO:
07623 case SPE_BUILTIN_EVSTWWE:
07624 case SPE_BUILTIN_EVSTWWO:
07625 arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07626 if (TREE_CODE (arg1) != INTEGER_CST
07627 || TREE_INT_CST_LOW (arg1) & ~0x1f)
07628 {
07629 error ("argument 2 must be a 5-bit unsigned literal");
07630 return const0_rtx;
07631 }
07632 break;
07633 default:
07634 break;
07635 }
07636
07637
07638 switch (fcode)
07639 {
07640 case SPE_BUILTIN_EVSPLATFI:
07641 return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplatfi,
07642 arglist, target);
07643 case SPE_BUILTIN_EVSPLATI:
07644 return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplati,
07645 arglist, target);
07646 default:
07647 break;
07648 }
07649
07650 d = (struct builtin_description *) bdesc_2arg_spe;
07651 for (i = 0; i < ARRAY_SIZE (bdesc_2arg_spe); ++i, ++d)
07652 if (d->code == fcode)
07653 return rs6000_expand_binop_builtin (d->icode, arglist, target);
07654
07655 d = (struct builtin_description *) bdesc_spe_predicates;
07656 for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, ++d)
07657 if (d->code == fcode)
07658 return spe_expand_predicate_builtin (d->icode, arglist, target);
07659
07660 d = (struct builtin_description *) bdesc_spe_evsel;
07661 for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, ++d)
07662 if (d->code == fcode)
07663 return spe_expand_evsel_builtin (d->icode, arglist, target);
07664
07665 switch (fcode)
07666 {
07667 case SPE_BUILTIN_EVSTDDX:
07668 return spe_expand_stv_builtin (CODE_FOR_spe_evstddx, arglist);
07669 case SPE_BUILTIN_EVSTDHX:
07670 return spe_expand_stv_builtin (CODE_FOR_spe_evstdhx, arglist);
07671 case SPE_BUILTIN_EVSTDWX:
07672 return spe_expand_stv_builtin (CODE_FOR_spe_evstdwx, arglist);
07673 case SPE_BUILTIN_EVSTWHEX:
07674 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhex, arglist);
07675 case SPE_BUILTIN_EVSTWHOX:
07676 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhox, arglist);
07677 case SPE_BUILTIN_EVSTWWEX:
07678 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwex, arglist);
07679 case SPE_BUILTIN_EVSTWWOX:
07680 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwox, arglist);
07681 case SPE_BUILTIN_EVSTDD:
07682 return spe_expand_stv_builtin (CODE_FOR_spe_evstdd, arglist);
07683 case SPE_BUILTIN_EVSTDH:
07684 return spe_expand_stv_builtin (CODE_FOR_spe_evstdh, arglist);
07685 case SPE_BUILTIN_EVSTDW:
07686 return spe_expand_stv_builtin (CODE_FOR_spe_evstdw, arglist);
07687 case SPE_BUILTIN_EVSTWHE:
07688 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhe, arglist);
07689 case SPE_BUILTIN_EVSTWHO:
07690 return spe_expand_stv_builtin (CODE_FOR_spe_evstwho, arglist);
07691 case SPE_BUILTIN_EVSTWWE:
07692 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwe, arglist);
07693 case SPE_BUILTIN_EVSTWWO:
07694 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwo, arglist);
07695 case SPE_BUILTIN_MFSPEFSCR:
07696 icode = CODE_FOR_spe_mfspefscr;
07697 tmode = insn_data[icode].operand[0].mode;
07698
07699 if (target == 0
07700 || GET_MODE (target) != tmode
07701 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07702 target = gen_reg_rtx (tmode);
07703
07704 pat = GEN_FCN (icode) (target);
07705 if (! pat)
07706 return 0;
07707 emit_insn (pat);
07708 return target;
07709 case SPE_BUILTIN_MTSPEFSCR:
07710 icode = CODE_FOR_spe_mtspefscr;
07711 arg0 = TREE_VALUE (arglist);
07712 op0 = expand_normal (arg0);
07713 mode0 = insn_data[icode].operand[0].mode;
07714
07715 if (arg0 == error_mark_node)
07716 return const0_rtx;
07717
07718 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07719 op0 = copy_to_mode_reg (mode0, op0);
07720
07721 pat = GEN_FCN (icode) (op0);
07722 if (pat)
07723 emit_insn (pat);
07724 return NULL_RTX;
07725 default:
07726 break;
07727 }
07728
07729 *expandedp = false;
07730 return NULL_RTX;
07731 }
07732
07733 static rtx
07734 spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target)
07735 {
07736 rtx pat, scratch, tmp;
07737 tree form = TREE_VALUE (arglist);
07738 tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
07739 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07740 rtx op0 = expand_normal (arg0);
07741 rtx op1 = expand_normal (arg1);
07742 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07743 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07744 int form_int;
07745 enum rtx_code code;
07746
07747 if (TREE_CODE (form) != INTEGER_CST)
07748 {
07749 error ("argument 1 of __builtin_spe_predicate must be a constant");
07750 return const0_rtx;
07751 }
07752 else
07753 form_int = TREE_INT_CST_LOW (form);
07754
07755 gcc_assert (mode0 == mode1);
07756
07757 if (arg0 == error_mark_node || arg1 == error_mark_node)
07758 return const0_rtx;
07759
07760 if (target == 0
07761 || GET_MODE (target) != SImode
07762 || ! (*insn_data[icode].operand[0].predicate) (target, SImode))
07763 target = gen_reg_rtx (SImode);
07764
07765 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07766 op0 = copy_to_mode_reg (mode0, op0);
07767 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
07768 op1 = copy_to_mode_reg (mode1, op1);
07769
07770 scratch = gen_reg_rtx (CCmode);
07771
07772 pat = GEN_FCN (icode) (scratch, op0, op1);
07773 if (! pat)
07774 return const0_rtx;
07775 emit_insn (pat);
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795
07796
07797
07798 switch (form_int)
07799 {
07800
07801 case 0:
07802
07803
07804
07805
07806 emit_insn (gen_move_from_CR_ov_bit (target, scratch));
07807 return target;
07808
07809 case 1:
07810 code = EQ;
07811 break;
07812
07813 case 2:
07814 code = LT;
07815 break;
07816
07817 case 3:
07818 code = GT;
07819 break;
07820 default:
07821 error ("argument 1 of __builtin_spe_predicate is out of range");
07822 return const0_rtx;
07823 }
07824
07825 tmp = gen_rtx_fmt_ee (code, SImode, scratch, const0_rtx);
07826 emit_move_insn (target, tmp);
07827
07828 return target;
07829 }
07830
07831
07832
07833
07834
07835
07836
07837
07838
07839
07840
07841 static rtx
07842 spe_expand_evsel_builtin (enum insn_code icode, tree arglist, rtx target)
07843 {
07844 rtx pat, scratch;
07845 tree arg0 = TREE_VALUE (arglist);
07846 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07847 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07848 tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
07849 rtx op0 = expand_normal (arg0);
07850 rtx op1 = expand_normal (arg1);
07851 rtx op2 = expand_normal (arg2);
07852 rtx op3 = expand_normal (arg3);
07853 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07854 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07855
07856 gcc_assert (mode0 == mode1);
07857
07858 if (arg0 == error_mark_node || arg1 == error_mark_node
07859 || arg2 == error_mark_node || arg3 == error_mark_node)
07860 return const0_rtx;
07861
07862 if (target == 0
07863 || GET_MODE (target) != mode0
07864 || ! (*insn_data[icode].operand[0].predicate) (target, mode0))
07865 target = gen_reg_rtx (mode0);
07866
07867 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07868 op0 = copy_to_mode_reg (mode0, op0);
07869 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
07870 op1 = copy_to_mode_reg (mode0, op1);
07871 if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
07872 op2 = copy_to_mode_reg (mode0, op2);
07873 if (! (*insn_data[icode].operand[1].predicate) (op3, mode1))
07874 op3 = copy_to_mode_reg (mode0, op3);
07875
07876
07877 scratch = gen_reg_rtx (CCmode);
07878 pat = GEN_FCN (icode) (scratch, op0, op1);
07879 if (! pat)
07880 return const0_rtx;
07881 emit_insn (pat);
07882
07883 if (mode0 == V2SImode)
07884 emit_insn (gen_spe_evsel (target, op2, op3, scratch));
07885 else
07886 emit_insn (gen_spe_evsel_fs (target, op2, op3, scratch));
07887
07888 return target;
07889 }
07890
07891
07892
07893
07894
07895
07896
07897 static rtx
07898 rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
07899 enum machine_mode mode ATTRIBUTE_UNUSED,
07900 int ignore ATTRIBUTE_UNUSED)
07901 {
07902 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07903 tree arglist = TREE_OPERAND (exp, 1);
07904 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07905 struct builtin_description *d;
07906 size_t i;
07907 rtx ret;
07908 bool success;
07909
07910 if (fcode == ALTIVEC_BUILTIN_MASK_FOR_LOAD
07911 || fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
07912 {
07913 int icode = (int) CODE_FOR_altivec_lvsr;
07914 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07915 enum machine_mode mode = insn_data[icode].operand[1].mode;
07916 tree arg;
07917 rtx op, addr, pat;
07918
07919 gcc_assert (TARGET_ALTIVEC);
07920
07921 arg = TREE_VALUE (arglist);
07922 gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE);
07923 op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
07924 addr = memory_address (mode, op);
07925 if (fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
07926 op = addr;
07927 else
07928 {
07929
07930 op = gen_reg_rtx (GET_MODE (addr));
07931 emit_insn (gen_rtx_SET (VOIDmode, op,
07932 gen_rtx_NEG (GET_MODE (addr), addr)));
07933 }
07934 op = gen_rtx_MEM (mode, op);
07935
07936 if (target == 0
07937 || GET_MODE (target) != tmode
07938 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07939 target = gen_reg_rtx (tmode);
07940
07941
07942 pat = GEN_FCN (icode) (target, op);
07943 if (!pat)
07944 return 0;
07945 emit_insn (pat);
07946
07947 return target;
07948 }
07949
07950 if (TARGET_ALTIVEC)
07951 {
07952 ret = altivec_expand_builtin (exp, target, &success);
07953
07954 if (success)
07955 return ret;
07956 }
07957 if (TARGET_SPE)
07958 {
07959 ret = spe_expand_builtin (exp, target, &success);
07960
07961 if (success)
07962 return ret;
07963 }
07964
07965 gcc_assert (TARGET_ALTIVEC || TARGET_SPE);
07966
07967
07968 d = (struct builtin_description *) bdesc_1arg;
07969 for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
07970 if (d->code == fcode)
07971 return rs6000_expand_unop_builtin (d->icode, arglist, target);
07972
07973
07974 d = (struct builtin_description *) bdesc_2arg;
07975 for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
07976 if (d->code == fcode)
07977 return rs6000_expand_binop_builtin (d->icode, arglist, target);
07978
07979
07980 d = (struct builtin_description *) bdesc_3arg;
07981 for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
07982 if (d->code == fcode)
07983 return rs6000_expand_ternop_builtin (d->icode, arglist, target);
07984
07985 gcc_unreachable ();
07986 }
07987
07988 static tree
07989 build_opaque_vector_type (tree node, int nunits)
07990 {
07991 node = copy_node (node);
07992 TYPE_MAIN_VARIANT (node) = node;
07993 return build_vector_type (node, nunits);
07994 }
07995
07996 static void
07997 rs6000_init_builtins (void)
07998 {
07999 V2SI_type_node = build_vector_type (intSI_type_node, 2);
08000 V2SF_type_node = build_vector_type (float_type_node, 2);
08001 V4HI_type_node = build_vector_type (intHI_type_node, 4);
08002 V4SI_type_node = build_vector_type (intSI_type_node, 4);
08003 V4SF_type_node = build_vector_type (float_type_node, 4);
08004 V8HI_type_node = build_vector_type (intHI_type_node, 8);
08005 V16QI_type_node = build_vector_type (intQI_type_node, 16);
08006
08007 unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
08008 unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
08009 unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
08010
08011 opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2);
08012 opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2);
08013 opaque_p_V2SI_type_node = build_pointer_type (opaque_V2SI_type_node);
08014 opaque_V4SI_type_node = copy_node (V4SI_type_node);
08015
08016
08017
08018
08019
08020 bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
08021 bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
08022 bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
08023 pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
08024
08025 long_integer_type_internal_node = long_integer_type_node;
08026 long_unsigned_type_internal_node = long_unsigned_type_node;
08027 intQI_type_internal_node = intQI_type_node;
08028 uintQI_type_internal_node = unsigned_intQI_type_node;
08029 intHI_type_internal_node = intHI_type_node;
08030 uintHI_type_internal_node = unsigned_intHI_type_node;
08031 intSI_type_internal_node = intSI_type_node;
08032 uintSI_type_internal_node = unsigned_intSI_type_node;
08033 float_type_internal_node = float_type_node;
08034 void_type_internal_node = void_type_node;
08035
08036 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08037 get_identifier ("__bool char"),
08038 bool_char_type_node));
08039 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08040 get_identifier ("__bool short"),
08041 bool_short_type_node));
08042 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08043 get_identifier ("__bool int"),
08044 bool_int_type_node));
08045 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08046 get_identifier ("__pixel"),
08047 pixel_type_node));
08048
08049 bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16);
08050 bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8);
08051 bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
08052 pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
08053
08054 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08055 get_identifier ("__vector unsigned char"),
08056 unsigned_V16QI_type_node));
08057 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08058 get_identifier ("__vector signed char"),
08059 V16QI_type_node));
08060 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08061 get_identifier ("__vector __bool char"),
08062 bool_V16QI_type_node));
08063
08064 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08065 get_identifier ("__vector unsigned short"),
08066 unsigned_V8HI_type_node));
08067 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08068 get_identifier ("__vector signed short"),
08069 V8HI_type_node));
08070 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08071 get_identifier ("__vector __bool short"),
08072 bool_V8HI_type_node));
08073
08074 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08075 get_identifier ("__vector unsigned int"),
08076 unsigned_V4SI_type_node));
08077 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08078 get_identifier ("__vector signed int"),
08079 V4SI_type_node));
08080 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08081 get_identifier ("__vector __bool int"),
08082 bool_V4SI_type_node));
08083
08084 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08085 get_identifier ("__vector float"),
08086 V4SF_type_node));
08087 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08088 get_identifier ("__vector __pixel"),
08089 pixel_V8HI_type_node));
08090
08091 if (TARGET_SPE)
08092 spe_init_builtins ();
08093 if (TARGET_ALTIVEC)
08094 altivec_init_builtins ();
08095 if (TARGET_ALTIVEC || TARGET_SPE)
08096 rs6000_common_init_builtins ();
08097
08098 #if TARGET_XCOFF
08099
08100 if (built_in_decls [BUILT_IN_CLOG])
08101 set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
08102 #endif
08103 }
08104
08105
08106
08107
08108
08109
08110 static void
08111 enable_mask_for_builtins (struct builtin_description *desc, int size,
08112 enum rs6000_builtins start,
08113 enum rs6000_builtins end)
08114 {
08115 int i;
08116
08117 for (i = 0; i < size; ++i)
08118 if (desc[i].code == start)
08119 break;
08120
08121 if (i == size)
08122 return;
08123
08124 for (; i < size; ++i)
08125 {
08126
08127 desc[i].mask = target_flags;
08128 if (desc[i].code == end)
08129 break;
08130 }
08131 }
08132
08133 static void
08134 spe_init_builtins (void)
08135 {
08136 tree endlink = void_list_node;
08137 tree puint_type_node = build_pointer_type (unsigned_type_node);
08138 tree pushort_type_node = build_pointer_type (short_unsigned_type_node);
08139 struct builtin_description *d;
08140 size_t i;
08141
08142 tree v2si_ftype_4_v2si
08143 = build_function_type
08144 (opaque_V2SI_type_node,
08145 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08146 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08147 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08148 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08149 endlink)))));
08150
08151 tree v2sf_ftype_4_v2sf
08152 = build_function_type
08153 (opaque_V2SF_type_node,
08154 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08155 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08156 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08157 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08158 endlink)))));
08159
08160 tree int_ftype_int_v2si_v2si
08161 = build_function_type
08162 (integer_type_node,
08163 tree_cons (NULL_TREE, integer_type_node,
08164 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08165 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08166 endlink))));
08167
08168 tree int_ftype_int_v2sf_v2sf
08169 = build_function_type
08170 (integer_type_node,
08171 tree_cons (NULL_TREE, integer_type_node,
08172 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08173 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08174 endlink))));
08175
08176 tree void_ftype_v2si_puint_int
08177 = build_function_type (void_type_node,
08178 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08179 tree_cons (NULL_TREE, puint_type_node,
08180 tree_cons (NULL_TREE,
08181 integer_type_node,
08182 endlink))));
08183
08184 tree void_ftype_v2si_puint_char
08185 = build_function_type (void_type_node,
08186 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08187 tree_cons (NULL_TREE, puint_type_node,
08188 tree_cons (NULL_TREE,
08189 char_type_node,
08190 endlink))));
08191
08192 tree void_ftype_v2si_pv2si_int
08193 = build_function_type (void_type_node,
08194 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08195 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08196 tree_cons (NULL_TREE,
08197 integer_type_node,
08198 endlink))));
08199
08200 tree void_ftype_v2si_pv2si_char
08201 = build_function_type (void_type_node,
08202 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08203 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08204 tree_cons (NULL_TREE,
08205 char_type_node,
08206 endlink))));
08207
08208 tree void_ftype_int
08209 = build_function_type (void_type_node,
08210 tree_cons (NULL_TREE, integer_type_node, endlink));
08211
08212 tree int_ftype_void
08213 = build_function_type (integer_type_node, endlink);
08214
08215 tree v2si_ftype_pv2si_int
08216 = build_function_type (opaque_V2SI_type_node,
08217 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08218 tree_cons (NULL_TREE, integer_type_node,
08219 endlink)));
08220
08221 tree v2si_ftype_puint_int
08222 = build_function_type (opaque_V2SI_type_node,
08223 tree_cons (NULL_TREE, puint_type_node,
08224 tree_cons (NULL_TREE, integer_type_node,
08225 endlink)));
08226
08227 tree v2si_ftype_pushort_int
08228 = build_function_type (opaque_V2SI_type_node,
08229 tree_cons (NULL_TREE, pushort_type_node,
08230 tree_cons (NULL_TREE, integer_type_node,
08231 endlink)));
08232
08233 tree v2si_ftype_signed_char
08234 = build_function_type (opaque_V2SI_type_node,
08235 tree_cons (NULL_TREE, signed_char_type_node,
08236 endlink));
08237
08238
08239
08240
08241
08242
08243 enable_mask_for_builtins ((struct builtin_description *) bdesc_2arg,
08244 ARRAY_SIZE (bdesc_2arg),
08245 SPE_BUILTIN_EVADDW,
08246 SPE_BUILTIN_EVXOR);
08247 enable_mask_for_builtins ((struct builtin_description *) bdesc_1arg,
08248 ARRAY_SIZE (bdesc_1arg),
08249 SPE_BUILTIN_EVABS,
08250 SPE_BUILTIN_EVSUBFUSIAAW);
08251 enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_predicates,
08252 ARRAY_SIZE (bdesc_spe_predicates),
08253 SPE_BUILTIN_EVCMPEQ,
08254 SPE_BUILTIN_EVFSTSTLT);
08255 enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_evsel,
08256 ARRAY_SIZE (bdesc_spe_evsel),
08257 SPE_BUILTIN_EVSEL_CMPGTS,
08258 SPE_BUILTIN_EVSEL_FSTSTEQ);
08259
08260 (*lang_hooks.decls.pushdecl)
08261 (build_decl (TYPE_DECL, get_identifier ("__ev64_opaque__"),
08262 opaque_V2SI_type_node));
08263
08264
08265
08266 def_builtin (target_flags, "__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
08267 def_builtin (target_flags, "__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
08268 def_builtin (target_flags, "__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
08269 def_builtin (target_flags, "__builtin_spe_evstdhx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDHX);
08270 def_builtin (target_flags, "__builtin_spe_evstdwx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDWX);
08271 def_builtin (target_flags, "__builtin_spe_evstwhex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHEX);
08272 def_builtin (target_flags, "__builtin_spe_evstwhox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHOX);
08273 def_builtin (target_flags, "__builtin_spe_evstwwex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWEX);
08274 def_builtin (target_flags, "__builtin_spe_evstwwox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWOX);
08275 def_builtin (target_flags, "__builtin_spe_evstdd", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDD);
08276 def_builtin (target_flags, "__builtin_spe_evstdh", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDH);
08277 def_builtin (target_flags, "__builtin_spe_evstdw", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDW);
08278 def_builtin (target_flags, "__builtin_spe_evstwhe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHE);
08279 def_builtin (target_flags, "__builtin_spe_evstwho", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHO);
08280 def_builtin (target_flags, "__builtin_spe_evstwwe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWE);
08281 def_builtin (target_flags, "__builtin_spe_evstwwo", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWO);
08282 def_builtin (target_flags, "__builtin_spe_evsplatfi", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATFI);
08283 def_builtin (target_flags, "__builtin_spe_evsplati", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATI);
08284
08285
08286 def_builtin (target_flags, "__builtin_spe_evlddx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDDX);
08287 def_builtin (target_flags, "__builtin_spe_evldwx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDWX);
08288 def_builtin (target_flags, "__builtin_spe_evldhx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDHX);
08289 def_builtin (target_flags, "__builtin_spe_evlwhex", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHEX);
08290 def_builtin (target_flags, "__builtin_spe_evlwhoux", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOUX);
08291 def_builtin (target_flags, "__builtin_spe_evlwhosx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOSX);
08292 def_builtin (target_flags, "__builtin_spe_evlwwsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLATX);
08293 def_builtin (target_flags, "__builtin_spe_evlwhsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLATX);
08294 def_builtin (target_flags, "__builtin_spe_evlhhesplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLATX);
08295 def_builtin (target_flags, "__builtin_spe_evlhhousplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLATX);
08296 def_builtin (target_flags, "__builtin_spe_evlhhossplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLATX);
08297 def_builtin (target_flags, "__builtin_spe_evldd", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDD);
08298 def_builtin (target_flags, "__builtin_spe_evldw", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDW);
08299 def_builtin (target_flags, "__builtin_spe_evldh", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDH);
08300 def_builtin (target_flags, "__builtin_spe_evlhhesplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLAT);
08301 def_builtin (target_flags, "__builtin_spe_evlhhossplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLAT);
08302 def_builtin (target_flags, "__builtin_spe_evlhhousplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLAT);
08303 def_builtin (target_flags, "__builtin_spe_evlwhe", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHE);
08304 def_builtin (target_flags, "__builtin_spe_evlwhos", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOS);
08305 def_builtin (target_flags, "__builtin_spe_evlwhou", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOU);
08306 def_builtin (target_flags, "__builtin_spe_evlwhsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLAT);
08307 def_builtin (target_flags, "__builtin_spe_evlwwsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLAT);
08308
08309
08310 d = (struct builtin_description *) bdesc_spe_predicates;
08311 for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, d++)
08312 {
08313 tree type;
08314
08315 switch (insn_data[d->icode].operand[1].mode)
08316 {
08317 case V2SImode:
08318 type = int_ftype_int_v2si_v2si;
08319 break;
08320 case V2SFmode:
08321 type = int_ftype_int_v2sf_v2sf;
08322 break;
08323 default:
08324 gcc_unreachable ();
08325 }
08326
08327 def_builtin (d->mask, d->name, type, d->code);
08328 }
08329
08330
08331 d = (struct builtin_description *) bdesc_spe_evsel;
08332 for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, d++)
08333 {
08334 tree type;
08335
08336 switch (insn_data[d->icode].operand[1].mode)
08337 {
08338 case V2SImode:
08339 type = v2si_ftype_4_v2si;
08340 break;
08341 case V2SFmode:
08342 type = v2sf_ftype_4_v2sf;
08343 break;
08344 default:
08345 gcc_unreachable ();
08346 }
08347
08348 def_builtin (d->mask, d->name, type, d->code);
08349 }
08350 }
08351
08352 static void
08353 altivec_init_builtins (void)
08354 {
08355 struct builtin_description *d;
08356 struct builtin_description_predicates *dp;
08357 size_t i;
08358 tree ftype;
08359
08360 tree pfloat_type_node = build_pointer_type (float_type_node);
08361 tree pint_type_node = build_pointer_type (integer_type_node);
08362 tree pshort_type_node = build_pointer_type (short_integer_type_node);
08363 tree pchar_type_node = build_pointer_type (char_type_node);
08364
08365 tree pvoid_type_node = build_pointer_type (void_type_node);
08366
08367 tree pcfloat_type_node = build_pointer_type (build_qualified_type (float_type_node, TYPE_QUAL_CONST));
08368 tree pcint_type_node = build_pointer_type (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
08369 tree pcshort_type_node = build_pointer_type (build_qualified_type (short_integer_type_node, TYPE_QUAL_CONST));
08370 tree pcchar_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
08371
08372 tree pcvoid_type_node = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
08373
08374 tree int_ftype_opaque
08375 = build_function_type_list (integer_type_node,
08376 opaque_V4SI_type_node, NULL_TREE);
08377
08378 tree opaque_ftype_opaque_int
08379 = build_function_type_list (opaque_V4SI_type_node,
08380 opaque_V4SI_type_node, integer_type_node, NULL_TREE);
08381 tree opaque_ftype_opaque_opaque_int
08382 = build_function_type_list (opaque_V4SI_type_node,
08383 opaque_V4SI_type_node, opaque_V4SI_type_node,
08384 integer_type_node, NULL_TREE);
08385 tree int_ftype_int_opaque_opaque
08386 = build_function_type_list (integer_type_node,
08387 integer_type_node, opaque_V4SI_type_node,
08388 opaque_V4SI_type_node, NULL_TREE);
08389 tree int_ftype_int_v4si_v4si
08390 = build_function_type_list (integer_type_node,
08391 integer_type_node, V4SI_type_node,
08392 V4SI_type_node, NULL_TREE);
08393 tree v4sf_ftype_pcfloat
08394 = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
08395 tree void_ftype_pfloat_v4sf
08396 = build_function_type_list (void_type_node,
08397 pfloat_type_node, V4SF_type_node, NULL_TREE);
08398 tree v4si_ftype_pcint
08399 = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
08400 tree void_ftype_pint_v4si
08401 = build_function_type_list (void_type_node,
08402 pint_type_node, V4SI_type_node, NULL_TREE);
08403 tree v8hi_ftype_pcshort
08404 = build_function_type_list (V8HI_type_node, pcshort_type_node, NULL_TREE);
08405 tree void_ftype_pshort_v8hi
08406 = build_function_type_list (void_type_node,
08407 pshort_type_node, V8HI_type_node, NULL_TREE);
08408 tree v16qi_ftype_pcchar
08409 = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
08410 tree void_ftype_pchar_v16qi
08411 = build_function_type_list (void_type_node,
08412 pchar_type_node, V16QI_type_node, NULL_TREE);
08413 tree void_ftype_v4si
08414 = build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE);
08415 tree v8hi_ftype_void
08416 = build_function_type (V8HI_type_node, void_list_node);
08417 tree void_ftype_void
08418 = build_function_type (void_type_node, void_list_node);
08419 tree void_ftype_int
08420 = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
08421
08422 tree opaque_ftype_long_pcvoid
08423 = build_function_type_list (opaque_V4SI_type_node,
08424 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08425 tree v16qi_ftype_long_pcvoid
08426 = build_function_type_list (V16QI_type_node,
08427 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08428 tree v8hi_ftype_long_pcvoid
08429 = build_function_type_list (V8HI_type_node,
08430 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08431 tree v4si_ftype_long_pcvoid
08432 = build_function_type_list (V4SI_type_node,
08433 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08434
08435 tree void_ftype_opaque_long_pvoid
08436 = build_function_type_list (void_type_node,
08437 opaque_V4SI_type_node, long_integer_type_node,
08438 pvoid_type_node, NULL_TREE);
08439 tree void_ftype_v4si_long_pvoid
08440 = build_function_type_list (void_type_node,
08441 V4SI_type_node, long_integer_type_node,
08442 pvoid_type_node, NULL_TREE);
08443 tree void_ftype_v16qi_long_pvoid
08444 = build_function_type_list (void_type_node,
08445 V16QI_type_node, long_integer_type_node,
08446 pvoid_type_node, NULL_TREE);
08447 tree void_ftype_v8hi_long_pvoid
08448 = build_function_type_list (void_type_node,
08449 V8HI_type_node, long_integer_type_node,
08450 pvoid_type_node, NULL_TREE);
08451 tree int_ftype_int_v8hi_v8hi
08452 = build_function_type_list (integer_type_node,
08453 integer_type_node, V8HI_type_node,
08454 V8HI_type_node, NULL_TREE);
08455 tree int_ftype_int_v16qi_v16qi
08456 = build_function_type_list (integer_type_node,
08457 integer_type_node, V16QI_type_node,
08458 V16QI_type_node, NULL_TREE);
08459 tree int_ftype_int_v4sf_v4sf
08460 = build_function_type_list (integer_type_node,
08461 integer_type_node, V4SF_type_node,
08462 V4SF_type_node, NULL_TREE);
08463 tree v4si_ftype_v4si
08464 = build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE);
08465 tree v8hi_ftype_v8hi
08466 = build_function_type_list (V8HI_type_node, V8HI_type_node, NULL_TREE);
08467 tree v16qi_ftype_v16qi
08468 = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
08469 tree v4sf_ftype_v4sf
08470 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
08471 tree void_ftype_pcvoid_int_int
08472 = build_function_type_list (void_type_node,
08473 pcvoid_type_node, integer_type_node,
08474 integer_type_node, NULL_TREE);
08475
08476 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pcfloat,
08477 ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
08478 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf,
08479 ALTIVEC_BUILTIN_ST_INTERNAL_4sf);
08480 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4si", v4si_ftype_pcint,
08481 ALTIVEC_BUILTIN_LD_INTERNAL_4si);
08482 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4si", void_ftype_pint_v4si,
08483 ALTIVEC_BUILTIN_ST_INTERNAL_4si);
08484 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_8hi", v8hi_ftype_pcshort,
08485 ALTIVEC_BUILTIN_LD_INTERNAL_8hi);
08486 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi,
08487 ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
08488 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pcchar,
08489 ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
08490 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi,
08491 ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
08492 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
08493 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
08494 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
08495 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS);
08496 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL);
08497 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR);
08498 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX);
08499 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX);
08500 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX);
08501 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL);
08502 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX);
08503 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX);
08504 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX);
08505 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
08506 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
08507 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
08508 def_builtin (MASK_ALTIVEC, "__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD);
08509 def_builtin (MASK_ALTIVEC, "__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE);
08510 def_builtin (MASK_ALTIVEC, "__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL);
08511 def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL);
08512 def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR);
08513 def_builtin (MASK_ALTIVEC, "__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX);
08514 def_builtin (MASK_ALTIVEC, "__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX);
08515 def_builtin (MASK_ALTIVEC, "__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX);
08516 def_builtin (MASK_ALTIVEC, "__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST);
08517 def_builtin (MASK_ALTIVEC, "__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE);
08518 def_builtin (MASK_ALTIVEC, "__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL);
08519 def_builtin (MASK_ALTIVEC, "__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX);
08520 def_builtin (MASK_ALTIVEC, "__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
08521 def_builtin (MASK_ALTIVEC, "__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
08522
08523 def_builtin (MASK_ALTIVEC, "__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP);
08524
08525 def_builtin (MASK_ALTIVEC, "__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD);
08526 def_builtin (MASK_ALTIVEC, "__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT);
08527 def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW);
08528 def_builtin (MASK_ALTIVEC, "__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH);
08529 def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB);
08530 def_builtin (MASK_ALTIVEC, "__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF);
08531 def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX);
08532 def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX);
08533 def_builtin (MASK_ALTIVEC, "__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS);
08534 def_builtin (MASK_ALTIVEC, "__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU);
08535
08536
08537 d = (struct builtin_description *) bdesc_dst;
08538 for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
08539 def_builtin (d->mask, d->name, void_ftype_pcvoid_int_int, d->code);
08540
08541
08542 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
08543 for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
08544 {
08545 enum machine_mode mode1;
08546 tree type;
08547 bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
08548 && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
08549
08550 if (is_overloaded)
08551 mode1 = VOIDmode;
08552 else
08553 mode1 = insn_data[dp->icode].operand[1].mode;
08554
08555 switch (mode1)
08556 {
08557 case VOIDmode:
08558 type = int_ftype_int_opaque_opaque;
08559 break;
08560 case V4SImode:
08561 type = int_ftype_int_v4si_v4si;
08562 break;
08563 case V8HImode:
08564 type = int_ftype_int_v8hi_v8hi;
08565 break;
08566 case V16QImode:
08567 type = int_ftype_int_v16qi_v16qi;
08568 break;
08569 case V4SFmode:
08570 type = int_ftype_int_v4sf_v4sf;
08571 break;
08572 default:
08573 gcc_unreachable ();
08574 }
08575
08576 def_builtin (dp->mask, dp->name, type, dp->code);
08577 }
08578
08579
08580 d = (struct builtin_description *) bdesc_abs;
08581 for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
08582 {
08583 enum machine_mode mode0;
08584 tree type;
08585
08586 mode0 = insn_data[d->icode].operand[0].mode;
08587
08588 switch (mode0)
08589 {
08590 case V4SImode:
08591 type = v4si_ftype_v4si;
08592 break;
08593 case V8HImode:
08594 type = v8hi_ftype_v8hi;
08595 break;
08596 case V16QImode:
08597 type = v16qi_ftype_v16qi;
08598 break;
08599 case V4SFmode:
08600 type = v4sf_ftype_v4sf;
08601 break;
08602 default:
08603 gcc_unreachable ();
08604 }
08605
08606 def_builtin (d->mask, d->name, type, d->code);
08607 }
08608
08609 if (TARGET_ALTIVEC)
08610 {
08611 tree decl;
08612
08613
08614
08615
08616 decl = lang_hooks.builtin_function ("__builtin_altivec_mask_for_load",
08617 v16qi_ftype_long_pcvoid,
08618 ALTIVEC_BUILTIN_MASK_FOR_LOAD,
08619 BUILT_IN_MD, NULL,
08620 tree_cons (get_identifier ("const"),
08621 NULL_TREE, NULL_TREE));
08622
08623 altivec_builtin_mask_for_load = decl;
08624 }
08625
08626
08627 ftype = build_function_type_list (V4SI_type_node, integer_type_node,
08628 integer_type_node, integer_type_node,
08629 integer_type_node, NULL_TREE);
08630 def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4si", ftype,
08631 ALTIVEC_BUILTIN_VEC_INIT_V4SI);
08632
08633 ftype = build_function_type_list (V8HI_type_node, short_integer_type_node,
08634 short_integer_type_node,
08635 short_integer_type_node,
08636 short_integer_type_node,
08637 short_integer_type_node,
08638 short_integer_type_node,
08639 short_integer_type_node,
08640 short_integer_type_node, NULL_TREE);
08641 def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v8hi", ftype,
08642 ALTIVEC_BUILTIN_VEC_INIT_V8HI);
08643
08644 ftype = build_function_type_list (V16QI_type_node, char_type_node,
08645 char_type_node, char_type_node,
08646 char_type_node, char_type_node,
08647 char_type_node, char_type_node,
08648 char_type_node, char_type_node,
08649 char_type_node, char_type_node,
08650 char_type_node, char_type_node,
08651 char_type_node, char_type_node,
08652 char_type_node, NULL_TREE);
08653 def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v16qi", ftype,
08654 ALTIVEC_BUILTIN_VEC_INIT_V16QI);
08655
08656 ftype = build_function_type_list (V4SF_type_node, float_type_node,
08657 float_type_node, float_type_node,
08658 float_type_node, NULL_TREE);
08659 def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4sf", ftype,
08660 ALTIVEC_BUILTIN_VEC_INIT_V4SF);
08661
08662
08663 ftype = build_function_type_list (V4SI_type_node, V4SI_type_node,
08664 intSI_type_node,
08665 integer_type_node, NULL_TREE);
08666 def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4si", ftype,
08667 ALTIVEC_BUILTIN_VEC_SET_V4SI);
08668
08669 ftype = build_function_type_list (V8HI_type_node, V8HI_type_node,
08670 intHI_type_node,
08671 integer_type_node, NULL_TREE);
08672 def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v8hi", ftype,
08673 ALTIVEC_BUILTIN_VEC_SET_V8HI);
08674
08675 ftype = build_function_type_list (V8HI_type_node, V16QI_type_node,
08676 intQI_type_node,
08677 integer_type_node, NULL_TREE);
08678 def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v16qi", ftype,
08679 ALTIVEC_BUILTIN_VEC_SET_V16QI);
08680
08681 ftype = build_function_type_list (V4SF_type_node, V4SF_type_node,
08682 float_type_node,
08683 integer_type_node, NULL_TREE);
08684 def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4sf", ftype,
08685 ALTIVEC_BUILTIN_VEC_SET_V4SF);
08686
08687
08688 ftype = build_function_type_list (intSI_type_node, V4SI_type_node,
08689 integer_type_node, NULL_TREE);
08690 def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4si", ftype,
08691 ALTIVEC_BUILTIN_VEC_EXT_V4SI);
08692
08693 ftype = build_function_type_list (intHI_type_node, V8HI_type_node,
08694 integer_type_node, NULL_TREE);
08695 def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v8hi", ftype,
08696 ALTIVEC_BUILTIN_VEC_EXT_V8HI);
08697
08698 ftype = build_function_type_list (intQI_type_node, V16QI_type_node,
08699 integer_type_node, NULL_TREE);
08700 def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v16qi", ftype,
08701 ALTIVEC_BUILTIN_VEC_EXT_V16QI);
08702
08703 ftype = build_function_type_list (float_type_node, V4SF_type_node,
08704 integer_type_node, NULL_TREE);
08705 def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4sf", ftype,
08706 ALTIVEC_BUILTIN_VEC_EXT_V4SF);
08707 }
08708
08709 static void
08710 rs6000_common_init_builtins (void)
08711 {
08712 struct builtin_description *d;
08713 size_t i;
08714
08715 tree v4sf_ftype_v4sf_v4sf_v16qi
08716 = build_function_type_list (V4SF_type_node,
08717 V4SF_type_node, V4SF_type_node,
08718 V16QI_type_node, NULL_TREE);
08719 tree v4si_ftype_v4si_v4si_v16qi
08720 = build_function_type_list (V4SI_type_node,
08721 V4SI_type_node, V4SI_type_node,
08722 V16QI_type_node, NULL_TREE);
08723 tree v8hi_ftype_v8hi_v8hi_v16qi
08724 = build_function_type_list (V8HI_type_node,
08725 V8HI_type_node, V8HI_type_node,
08726 V16QI_type_node, NULL_TREE);
08727 tree v16qi_ftype_v16qi_v16qi_v16qi
08728 = build_function_type_list (V16QI_type_node,
08729 V16QI_type_node, V16QI_type_node,
08730 V16QI_type_node, NULL_TREE);
08731 tree v4si_ftype_int
08732 = build_function_type_list (V4SI_type_node, integer_type_node, NULL_TREE);
08733 tree v8hi_ftype_int
08734 = build_function_type_list (V8HI_type_node, integer_type_node, NULL_TREE);
08735 tree v16qi_ftype_int
08736 = build_function_type_list (V16QI_type_node, integer_type_node, NULL_TREE);
08737 tree v8hi_ftype_v16qi
08738 = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE);
08739 tree v4sf_ftype_v4sf
08740 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
08741
08742 tree v2si_ftype_v2si_v2si
08743 = build_function_type_list (opaque_V2SI_type_node,
08744 opaque_V2SI_type_node,
08745 opaque_V2SI_type_node, NULL_TREE);
08746
08747 tree v2sf_ftype_v2sf_v2sf
08748 = build_function_type_list (opaque_V2SF_type_node,
08749 opaque_V2SF_type_node,
08750 opaque_V2SF_type_node, NULL_TREE);
08751
08752 tree v2si_ftype_int_int
08753 = build_function_type_list (opaque_V2SI_type_node,
08754 integer_type_node, integer_type_node,
08755 NULL_TREE);
08756
08757 tree opaque_ftype_opaque
08758 = build_function_type_list (opaque_V4SI_type_node,
08759 opaque_V4SI_type_node, NULL_TREE);
08760
08761 tree v2si_ftype_v2si
08762 = build_function_type_list (opaque_V2SI_type_node,
08763 opaque_V2SI_type_node, NULL_TREE);
08764
08765 tree v2sf_ftype_v2sf
08766 = build_function_type_list (opaque_V2SF_type_node,
08767 opaque_V2SF_type_node, NULL_TREE);
08768
08769 tree v2sf_ftype_v2si
08770 = build_function_type_list (opaque_V2SF_type_node,
08771 opaque_V2SI_type_node, NULL_TREE);
08772
08773 tree v2si_ftype_v2sf
08774 = build_function_type_list (opaque_V2SI_type_node,
08775 opaque_V2SF_type_node, NULL_TREE);
08776
08777 tree v2si_ftype_v2si_char
08778 = build_function_type_list (opaque_V2SI_type_node,
08779 opaque_V2SI_type_node,
08780 char_type_node, NULL_TREE);
08781
08782 tree v2si_ftype_int_char
08783 = build_function_type_list (opaque_V2SI_type_node,
08784 integer_type_node, char_type_node, NULL_TREE);
08785
08786 tree v2si_ftype_char
08787 = build_function_type_list (opaque_V2SI_type_node,
08788 char_type_node, NULL_TREE);
08789
08790 tree int_ftype_int_int
08791 = build_function_type_list (integer_type_node,
08792 integer_type_node, integer_type_node,
08793 NULL_TREE);
08794
08795 tree opaque_ftype_opaque_opaque
08796 = build_function_type_list (opaque_V4SI_type_node,
08797 opaque_V4SI_type_node, opaque_V4SI_type_node, NULL_TREE);
08798 tree v4si_ftype_v4si_v4si
08799 = build_function_type_list (V4SI_type_node,
08800 V4SI_type_node, V4SI_type_node, NULL_TREE);
08801 tree v4sf_ftype_v4si_int
08802 = build_function_type_list (V4SF_type_node,
08803 V4SI_type_node, integer_type_node, NULL_TREE);
08804 tree v4si_ftype_v4sf_int
08805 = build_function_type_list (V4SI_type_node,
08806 V4SF_type_node, integer_type_node, NULL_TREE);
08807 tree v4si_ftype_v4si_int
08808 = build_function_type_list (V4SI_type_node,
08809 V4SI_type_node, integer_type_node, NULL_TREE);
08810 tree v8hi_ftype_v8hi_int
08811 = build_function_type_list (V8HI_type_node,
08812 V8HI_type_node, integer_type_node, NULL_TREE);
08813 tree v16qi_ftype_v16qi_int
08814 = build_function_type_list (V16QI_type_node,
08815 V16QI_type_node, integer_type_node, NULL_TREE);
08816 tree v16qi_ftype_v16qi_v16qi_int
08817 = build_function_type_list (V16QI_type_node,
08818 V16QI_type_node, V16QI_type_node,
08819 integer_type_node, NULL_TREE);
08820 tree v8hi_ftype_v8hi_v8hi_int
08821 = build_function_type_list (V8HI_type_node,
08822 V8HI_type_node, V8HI_type_node,
08823 integer_type_node, NULL_TREE);
08824 tree v4si_ftype_v4si_v4si_int
08825 = build_function_type_list (V4SI_type_node,
08826 V4SI_type_node, V4SI_type_node,
08827 integer_type_node, NULL_TREE);
08828 tree v4sf_ftype_v4sf_v4sf_int
08829 = build_function_type_list (V4SF_type_node,
08830 V4SF_type_node, V4SF_type_node,
08831 integer_type_node, NULL_TREE);
08832 tree v4sf_ftype_v4sf_v4sf
08833 = build_function_type_list (V4SF_type_node,
08834 V4SF_type_node, V4SF_type_node, NULL_TREE);
08835 tree opaque_ftype_opaque_opaque_opaque
08836 = build_function_type_list (opaque_V4SI_type_node,
08837 opaque_V4SI_type_node, opaque_V4SI_type_node,
08838 opaque_V4SI_type_node, NULL_TREE);
08839 tree v4sf_ftype_v4sf_v4sf_v4si
08840 = build_function_type_list (V4SF_type_node,
08841 V4SF_type_node, V4SF_type_node,
08842 V4SI_type_node, NULL_TREE);
08843 tree v4sf_ftype_v4sf_v4sf_v4sf
08844 = build_function_type_list (V4SF_type_node,
08845 V4SF_type_node, V4SF_type_node,
08846 V4SF_type_node, NULL_TREE);
08847 tree v4si_ftype_v4si_v4si_v4si
08848 = build_function_type_list (V4SI_type_node,
08849 V4SI_type_node, V4SI_type_node,
08850 V4SI_type_node, NULL_TREE);
08851 tree v8hi_ftype_v8hi_v8hi
08852 = build_function_type_list (V8HI_type_node,
08853 V8HI_type_node, V8HI_type_node, NULL_TREE);
08854 tree v8hi_ftype_v8hi_v8hi_v8hi
08855 = build_function_type_list (V8HI_type_node,
08856 V8HI_type_node, V8HI_type_node,
08857 V8HI_type_node, NULL_TREE);
08858 tree v4si_ftype_v8hi_v8hi_v4si
08859 = build_function_type_list (V4SI_type_node,
08860 V8HI_type_node, V8HI_type_node,
08861 V4SI_type_node, NULL_TREE);
08862 tree v4si_ftype_v16qi_v16qi_v4si
08863 = build_function_type_list (V4SI_type_node,
08864 V16QI_type_node, V16QI_type_node,
08865 V4SI_type_node, NULL_TREE);
08866 tree v16qi_ftype_v16qi_v16qi
08867 = build_function_type_list (V16QI_type_node,
08868 V16QI_type_node, V16QI_type_node, NULL_TREE);
08869 tree v4si_ftype_v4sf_v4sf
08870 = build_function_type_list (V4SI_type_node,
08871 V4SF_type_node, V4SF_type_node, NULL_TREE);
08872 tree v8hi_ftype_v16qi_v16qi
08873 = build_function_type_list (V8HI_type_node,
08874 V16QI_type_node, V16QI_type_node, NULL_TREE);
08875 tree v4si_ftype_v8hi_v8hi
08876 = build_function_type_list (V4SI_type_node,
08877 V8HI_type_node, V8HI_type_node, NULL_TREE);
08878 tree v8hi_ftype_v4si_v4si
08879 = build_function_type_list (V8HI_type_node,
08880 V4SI_type_node, V4SI_type_node, NULL_TREE);
08881 tree v16qi_ftype_v8hi_v8hi
08882 = build_function_type_list (V16QI_type_node,
08883 V8HI_type_node, V8HI_type_node, NULL_TREE);
08884 tree v4si_ftype_v16qi_v4si
08885 = build_function_type_list (V4SI_type_node,
08886 V16QI_type_node, V4SI_type_node, NULL_TREE);
08887 tree v4si_ftype_v16qi_v16qi
08888 = build_function_type_list (V4SI_type_node,
08889 V16QI_type_node, V16QI_type_node, NULL_TREE);
08890 tree v4si_ftype_v8hi_v4si
08891 = build_function_type_list (V4SI_type_node,
08892 V8HI_type_node, V4SI_type_node, NULL_TREE);
08893 tree v4si_ftype_v8hi
08894 = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE);
08895 tree int_ftype_v4si_v4si
08896 = build_function_type_list (integer_type_node,
08897 V4SI_type_node, V4SI_type_node, NULL_TREE);
08898 tree int_ftype_v4sf_v4sf
08899 = build_function_type_list (integer_type_node,
08900 V4SF_type_node, V4SF_type_node, NULL_TREE);
08901 tree int_ftype_v16qi_v16qi
08902 = build_function_type_list (integer_type_node,
08903 V16QI_type_node, V16QI_type_node, NULL_TREE);
08904 tree int_ftype_v8hi_v8hi
08905 = build_function_type_list (integer_type_node,
08906 V8HI_type_node, V8HI_type_node, NULL_TREE);
08907
08908
08909 d = (struct builtin_description *) bdesc_3arg;
08910 for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
08911 {
08912 enum machine_mode mode0, mode1, mode2, mode3;
08913 tree type;
08914 bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
08915 && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
08916
08917 if (is_overloaded)
08918 {
08919 mode0 = VOIDmode;
08920 mode1 = VOIDmode;
08921 mode2 = VOIDmode;
08922 mode3 = VOIDmode;
08923 }
08924 else
08925 {
08926 if (d->name == 0 || d->icode == CODE_FOR_nothing)
08927 continue;
08928
08929 mode0 = insn_data[d->icode].operand[0].mode;
08930 mode1 = insn_data[d->icode].operand[1].mode;
08931 mode2 = insn_data[d->icode].operand[2].mode;
08932 mode3 = insn_data[d->icode].operand[3].mode;
08933 }
08934
08935
08936 if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
08937 {
08938 switch (mode0)
08939 {
08940 case VOIDmode:
08941 type = opaque_ftype_opaque_opaque_opaque;
08942 break;
08943 case V4SImode:
08944 type = v4si_ftype_v4si_v4si_v4si;
08945 break;
08946 case V4SFmode:
08947 type = v4sf_ftype_v4sf_v4sf_v4sf;
08948 break;
08949 case V8HImode:
08950 type = v8hi_ftype_v8hi_v8hi_v8hi;
08951 break;
08952 case V16QImode:
08953 type = v16qi_ftype_v16qi_v16qi_v16qi;
08954 break;
08955 default:
08956 gcc_unreachable ();
08957 }
08958 }
08959 else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
08960 {
08961 switch (mode0)
08962 {
08963 case V4SImode:
08964 type = v4si_ftype_v4si_v4si_v16qi;
08965 break;
08966 case V4SFmode:
08967 type = v4sf_ftype_v4sf_v4sf_v16qi;
08968 break;
08969 case V8HImode:
08970 type = v8hi_ftype_v8hi_v8hi_v16qi;
08971 break;
08972 case V16QImode:
08973 type = v16qi_ftype_v16qi_v16qi_v16qi;
08974 break;
08975 default:
08976 gcc_unreachable ();
08977 }
08978 }
08979 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
08980 && mode3 == V4SImode)
08981 type = v4si_ftype_v16qi_v16qi_v4si;
08982 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
08983 && mode3 == V4SImode)
08984 type = v4si_ftype_v8hi_v8hi_v4si;
08985 else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
08986 && mode3 == V4SImode)
08987 type = v4sf_ftype_v4sf_v4sf_v4si;
08988
08989
08990 else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0
08991 && mode3 == QImode)
08992 type = v16qi_ftype_v16qi_v16qi_int;
08993
08994
08995 else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0
08996 && mode3 == QImode)
08997 type = v8hi_ftype_v8hi_v8hi_int;
08998
08999
09000 else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0
09001 && mode3 == QImode)
09002 type = v4si_ftype_v4si_v4si_int;
09003
09004
09005 else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0
09006 && mode3 == QImode)
09007 type = v4sf_ftype_v4sf_v4sf_int;
09008
09009 else
09010 gcc_unreachable ();
09011
09012 def_builtin (d->mask, d->name, type, d->code);
09013 }
09014
09015
09016 d = (struct builtin_description *) bdesc_2arg;
09017 for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
09018 {
09019 enum machine_mode mode0, mode1, mode2;
09020 tree type;
09021 bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
09022 && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
09023
09024 if (is_overloaded)
09025 {
09026 mode0 = VOIDmode;
09027 mode1 = VOIDmode;
09028 mode2 = VOIDmode;
09029 }
09030 else
09031 {
09032 if (d->name == 0 || d->icode == CODE_FOR_nothing)
09033 continue;
09034
09035 mode0 = insn_data[d->icode].operand[0].mode;
09036 mode1 = insn_data[d->icode].operand[1].mode;
09037 mode2 = insn_data[d->icode].operand[2].mode;
09038 }
09039
09040
09041 if (mode0 == mode1 && mode1 == mode2)
09042 {
09043 switch (mode0)
09044 {
09045 case VOIDmode:
09046 type = opaque_ftype_opaque_opaque;
09047 break;
09048 case V4SFmode:
09049 type = v4sf_ftype_v4sf_v4sf;
09050 break;
09051 case V4SImode:
09052 type = v4si_ftype_v4si_v4si;
09053 break;
09054 case V16QImode:
09055 type = v16qi_ftype_v16qi_v16qi;
09056 break;
09057 case V8HImode:
09058 type = v8hi_ftype_v8hi_v8hi;
09059 break;
09060 case V2SImode:
09061 type = v2si_ftype_v2si_v2si;
09062 break;
09063 case V2SFmode:
09064 type = v2sf_ftype_v2sf_v2sf;
09065 break;
09066 case SImode:
09067 type = int_ftype_int_int;
09068 break;
09069 default:
09070 gcc_unreachable ();
09071 }
09072 }
09073
09074
09075
09076
09077 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
09078 type = v4si_ftype_v4sf_v4sf;
09079
09080
09081 else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
09082 type = v8hi_ftype_v16qi_v16qi;
09083
09084
09085 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
09086 type = v4si_ftype_v8hi_v8hi;
09087
09088
09089 else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
09090 type = v8hi_ftype_v4si_v4si;
09091
09092
09093 else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
09094 type = v16qi_ftype_v8hi_v8hi;
09095
09096
09097 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
09098 type = v4si_ftype_v16qi_v4si;
09099
09100
09101 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode)
09102 type = v4si_ftype_v16qi_v16qi;
09103
09104
09105 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
09106 type = v4si_ftype_v8hi_v4si;
09107
09108
09109 else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
09110 type = v4si_ftype_v4si_int;
09111
09112
09113 else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
09114 type = v8hi_ftype_v8hi_int;
09115
09116
09117 else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
09118 type = v16qi_ftype_v16qi_int;
09119
09120
09121 else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
09122 type = v4sf_ftype_v4si_int;
09123
09124
09125 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
09126 type = v4si_ftype_v4sf_int;
09127
09128 else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode)
09129 type = v2si_ftype_int_int;
09130
09131 else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
09132 type = v2si_ftype_v2si_char;
09133
09134 else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
09135 type = v2si_ftype_int_char;
09136
09137 else
09138 {
09139
09140 gcc_assert (mode0 == SImode);
09141 switch (mode1)
09142 {
09143 case V4SImode:
09144 type = int_ftype_v4si_v4si;
09145 break;
09146 case V4SFmode:
09147 type = int_ftype_v4sf_v4sf;
09148 break;
09149 case V16QImode:
09150 type = int_ftype_v16qi_v16qi;
09151 break;
09152 case V8HImode:
09153 type = int_ftype_v8hi_v8hi;
09154 break;
09155 default:
09156 gcc_unreachable ();
09157 }
09158 }
09159
09160 def_builtin (d->mask, d->name, type, d->code);
09161 }
09162
09163
09164 d = (struct builtin_description *) bdesc_1arg;
09165 for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
09166 {
09167 enum machine_mode mode0, mode1;
09168 tree type;
09169 bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
09170 && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
09171
09172 if (is_overloaded)
09173 {
09174 mode0 = VOIDmode;
09175 mode1 = VOIDmode;
09176 }
09177 else
09178 {
09179 if (d->name == 0 || d->icode == CODE_FOR_nothing)
09180 continue;
09181
09182 mode0 = insn_data[d->icode].operand[0].mode;
09183 mode1 = insn_data[d->icode].operand[1].mode;
09184 }
09185
09186 if (mode0 == V4SImode && mode1 == QImode)
09187 type = v4si_ftype_int;
09188 else if (mode0 == V8HImode && mode1 == QImode)
09189 type = v8hi_ftype_int;
09190 else if (mode0 == V16QImode && mode1 == QImode)
09191 type = v16qi_ftype_int;
09192 else if (mode0 == VOIDmode && mode1 == VOIDmode)
09193 type = opaque_ftype_opaque;
09194 else if (mode0 == V4SFmode && mode1 == V4SFmode)
09195 type = v4sf_ftype_v4sf;
09196 else if (mode0 == V8HImode && mode1 == V16QImode)
09197 type = v8hi_ftype_v16qi;
09198 else if (mode0 == V4SImode && mode1 == V8HImode)
09199 type = v4si_ftype_v8hi;
09200 else if (mode0 == V2SImode && mode1 == V2SImode)
09201 type = v2si_ftype_v2si;
09202 else if (mode0 == V2SFmode && mode1 == V2SFmode)
09203 type = v2sf_ftype_v2sf;
09204 else if (mode0 == V2SFmode && mode1 == V2SImode)
09205 type = v2sf_ftype_v2si;
09206 else if (mode0 == V2SImode && mode1 == V2SFmode)
09207 type = v2si_ftype_v2sf;
09208 else if (mode0 == V2SImode && mode1 == QImode)
09209 type = v2si_ftype_char;
09210 else
09211 gcc_unreachable ();
09212
09213 def_builtin (d->mask, d->name, type, d->code);
09214 }
09215 }
09216
09217 static void
09218 rs6000_init_libfuncs (void)
09219 {
09220 if (DEFAULT_ABI != ABI_V4 && TARGET_XCOFF
09221 && !TARGET_POWER2 && !TARGET_POWERPC)
09222 {
09223
09224 set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc");
09225 set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc");
09226 set_conv_libfunc (sfix_optab, SImode, TFmode, "_qitrunc");
09227 set_conv_libfunc (ufix_optab, SImode, TFmode, "_quitrunc");
09228 }
09229
09230 if (!TARGET_IEEEQUAD)
09231
09232 if (!TARGET_XL_COMPAT)
09233 {
09234 set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
09235 set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
09236 set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
09237 set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
09238
09239 if (TARGET_SOFT_FLOAT)
09240 {
09241 set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
09242 set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
09243 set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
09244 set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
09245 set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
09246 set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
09247 set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
09248 set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
09249
09250 set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
09251 set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
09252 set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
09253 set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
09254 set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
09255 set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
09256 set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
09257 set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
09258 }
09259 }
09260 else
09261 {
09262 set_optab_libfunc (add_optab, TFmode, "_xlqadd");
09263 set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
09264 set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
09265 set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
09266 }
09267 else
09268 {
09269
09270
09271 set_optab_libfunc (add_optab, TFmode, "_q_add");
09272 set_optab_libfunc (sub_optab, TFmode, "_q_sub");
09273 set_optab_libfunc (neg_optab, TFmode, "_q_neg");
09274 set_optab_libfunc (smul_optab, TFmode, "_q_mul");
09275 set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
09276 if (TARGET_PPC_GPOPT || TARGET_POWER2)
09277 set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
09278
09279 set_optab_libfunc (eq_optab, TFmode, "_q_feq");
09280 set_optab_libfunc (ne_optab, TFmode, "_q_fne");
09281 set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
09282 set_optab_libfunc (ge_optab, TFmode, "_q_fge");
09283 set_optab_libfunc (lt_optab, TFmode, "_q_flt");
09284 set_optab_libfunc (le_optab, TFmode, "_q_fle");
09285
09286 set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
09287 set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
09288 set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
09289 set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
09290 set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
09291 set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
09292 set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
09293 set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
09294 }
09295 }
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305 int
09306 expand_block_clear (rtx operands[])
09307 {
09308 rtx orig_dest = operands[0];
09309 rtx bytes_rtx = operands[1];
09310 rtx align_rtx = operands[3];
09311 bool constp = (GET_CODE (bytes_rtx) == CONST_INT);
09312 HOST_WIDE_INT align;
09313 HOST_WIDE_INT bytes;
09314 int offset;
09315 int clear_bytes;
09316 int clear_step;
09317
09318
09319 if (! constp)
09320 return 0;
09321
09322
09323 gcc_assert (GET_CODE (align_rtx) == CONST_INT);
09324 align = INTVAL (align_rtx) * BITS_PER_UNIT;
09325
09326
09327 bytes = INTVAL (bytes_rtx);
09328 if (bytes <= 0)
09329 return 1;
09330
09331
09332
09333
09334
09335 if (TARGET_ALTIVEC && align >= 128)
09336 clear_step = 16;
09337 else if (TARGET_POWERPC64 && align >= 32)
09338 clear_step = 8;
09339 else
09340 clear_step = 4;
09341
09342 if (optimize_size && bytes > 3 * clear_step)
09343 return 0;
09344 if (! optimize_size && bytes > 8 * clear_step)
09345 return 0;
09346
09347 for (offset = 0; bytes > 0; offset += clear_bytes, bytes -= clear_bytes)
09348 {
09349 enum machine_mode mode = BLKmode;
09350 rtx dest;
09351
09352 if (bytes >= 16 && TARGET_ALTIVEC && align >= 128)
09353 {
09354 clear_bytes = 16;
09355 mode = V4SImode;
09356 }
09357 else if (bytes >= 8 && TARGET_POWERPC64
09358
09359
09360 && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
09361 {
09362 clear_bytes = 8;
09363 mode = DImode;
09364 }
09365 else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
09366 {
09367 clear_bytes = 4;
09368 mode = SImode;
09369 }
09370 else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
09371 {
09372 clear_bytes = 2;
09373 mode = HImode;
09374 }
09375 else
09376 {
09377 clear_bytes = 1;
09378 mode = QImode;
09379 }
09380
09381 dest = adjust_address (orig_dest, mode, offset);
09382
09383 emit_move_insn (dest, CONST0_RTX (mode));
09384 }
09385
09386 return 1;
09387 }
09388
09389
09390
09391
09392
09393
09394
09395
09396
09397
09398 #define MAX_MOVE_REG 4
09399
09400 int
09401 expand_block_move (rtx operands[])
09402 {
09403 rtx orig_dest = operands[0];
09404 rtx orig_src = operands[1];
09405 rtx bytes_rtx = operands[2];
09406 rtx align_rtx = operands[3];
09407 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
09408 int align;
09409 int bytes;
09410 int offset;
09411 int move_bytes;
09412 rtx stores[MAX_MOVE_REG];
09413 int num_reg = 0;
09414
09415
09416 if (! constp)
09417 return 0;
09418
09419
09420 gcc_assert (GET_CODE (align_rtx) == CONST_INT);
09421 align = INTVAL (align_rtx) * BITS_PER_UNIT;
09422
09423
09424 bytes = INTVAL (bytes_rtx);
09425 if (bytes <= 0)
09426 return 1;
09427
09428
09429
09430 if (bytes > (TARGET_POWERPC64 ? 64 : 32))
09431 return 0;
09432
09433 for (offset = 0; bytes > 0; offset += move_bytes, bytes -= move_bytes)
09434 {
09435 union {
09436 rtx (*movmemsi) (rtx, rtx, rtx, rtx);
09437 rtx (*mov) (rtx, rtx);
09438 } gen_func;
09439 enum machine_mode mode = BLKmode;
09440 rtx src, dest;
09441
09442
09443
09444 if (TARGET_ALTIVEC && bytes >= 16 && align >= 128)
09445 {
09446 move_bytes = 16;
09447 mode = V4SImode;
09448 gen_func.mov = gen_movv4si;
09449 }
09450 else if (TARGET_STRING
09451 && bytes > 24
09452 && ! fixed_regs[5]
09453 && ! fixed_regs[6]
09454 && ! fixed_regs[7]
09455 && ! fixed_regs[8]
09456 && ! fixed_regs[9]
09457 && ! fixed_regs[10]
09458 && ! fixed_regs[11]
09459 && ! fixed_regs[12])
09460 {
09461 move_bytes = (bytes > 32) ? 32 : bytes;
09462 gen_func.movmemsi = gen_movmemsi_8reg;
09463 }
09464 else if (TARGET_STRING
09465 && bytes > 16
09466 && ! fixed_regs[5]
09467 && ! fixed_regs[6]
09468 && ! fixed_regs[7]
09469 && ! fixed_regs[8]
09470 && ! fixed_regs[9]
09471 && ! fixed_regs[10])
09472 {
09473 move_bytes = (bytes > 24) ? 24 : bytes;
09474 gen_func.movmemsi = gen_movmemsi_6reg;
09475 }
09476 else if (TARGET_STRING
09477 && bytes > 8
09478 && ! fixed_regs[5]
09479 && ! fixed_regs[6]
09480 && ! fixed_regs[7]
09481 && ! fixed_regs[8])
09482 {
09483 move_bytes = (bytes > 16) ? 16 : bytes;
09484 gen_func.movmemsi = gen_movmemsi_4reg;
09485 }
09486 else if (bytes >= 8 && TARGET_POWERPC64
09487
09488
09489 && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
09490 {
09491 move_bytes = 8;
09492 mode = DImode;
09493 gen_func.mov = gen_movdi;
09494 }
09495 else if (TARGET_STRING && bytes > 4 && !TARGET_POWERPC64)
09496 {
09497 move_bytes = (bytes > 8) ? 8 : bytes;
09498 gen_func.movmemsi = gen_movmemsi_2reg;
09499 }
09500 else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
09501 {
09502 move_bytes = 4;
09503 mode = SImode;
09504 gen_func.mov = gen_movsi;
09505 }
09506 else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
09507 {
09508 move_bytes = 2;
09509 mode = HImode;
09510 gen_func.mov = gen_movhi;
09511 }
09512 else if (TARGET_STRING && bytes > 1)
09513 {
09514 move_bytes = (bytes > 4) ? 4 : bytes;
09515 gen_func.movmemsi = gen_movmemsi_1reg;
09516 }
09517 else
09518 {
09519 move_bytes = 1;
09520 mode = QImode;
09521 gen_func.mov = gen_movqi;
09522 }
09523
09524 src = adjust_address (orig_src, mode, offset);
09525 dest = adjust_address (orig_dest, mode, offset);
09526
09527 if (mode != BLKmode)
09528 {
09529 rtx tmp_reg = gen_reg_rtx (mode);
09530
09531 emit_insn ((*gen_func.mov) (tmp_reg, src));
09532 stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
09533 }
09534
09535 if (mode == BLKmode || num_reg >= MAX_MOVE_REG || bytes == move_bytes)
09536 {
09537 int i;
09538 for (i = 0; i < num_reg; i++)
09539 emit_insn (stores[i]);
09540 num_reg = 0;
09541 }
09542
09543 if (mode == BLKmode)
09544 {
09545
09546
09547 if (!REG_P (XEXP (src, 0)))
09548 {
09549 rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
09550 src = replace_equiv_address (src, src_reg);
09551 }
09552 set_mem_size (src, GEN_INT (move_bytes));
09553
09554 if (!REG_P (XEXP (dest, 0)))
09555 {
09556 rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
09557 dest = replace_equiv_address (dest, dest_reg);
09558 }
09559 set_mem_size (dest, GEN_INT (move_bytes));
09560
09561 emit_insn ((*gen_func.movmemsi) (dest, src,
09562 GEN_INT (move_bytes & 31),
09563 align_rtx));
09564 }
09565 }
09566
09567 return 1;
09568 }
09569
09570
09571
09572
09573
09574
09575
09576 const char *
09577 rs6000_output_load_multiple (rtx operands[3])
09578 {
09579
09580
09581 int i, j;
09582 int words = XVECLEN (operands[0], 0);
09583 rtx xop[10];
09584
09585 if (XVECLEN (operands[0], 0) == 1)
09586 return "{l|lwz} %2,0(%1)";
09587
09588 for (i = 0; i < words; i++)
09589 if (refers_to_regno_p (REGNO (operands[2]) + i,
09590 REGNO (operands[2]) + i + 1, operands[1], 0))
09591 {
09592 if (i == words-1)
09593 {
09594 xop[0] = GEN_INT (4 * (words-1));
09595 xop[1] = operands[1];
09596 xop[2] = operands[2];
09597 output_asm_insn ("{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,%0(%1)", xop);
09598 return "";
09599 }
09600 else if (i == 0)
09601 {
09602 xop[0] = GEN_INT (4 * (words-1));
09603 xop[1] = operands[1];
09604 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
09605 output_asm_insn ("{cal %1,4(%1)|addi %1,%1,4}\n\t{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,-4(%1)", xop);
09606 return "";
09607 }
09608 else
09609 {
09610 for (j = 0; j < words; j++)
09611 if (j != i)
09612 {
09613 xop[0] = GEN_INT (j * 4);
09614 xop[1] = operands[1];
09615 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + j);
09616 output_asm_insn ("{l|lwz} %2,%0(%1)", xop);
09617 }
09618 xop[0] = GEN_INT (i * 4);
09619 xop[1] = operands[1];
09620 output_asm_insn ("{l|lwz} %1,%0(%1)", xop);
09621 return "";
09622 }
09623 }
09624
09625 return "{lsi|lswi} %2,%1,%N0";
09626 }
09627
09628
09629
09630
09631
09632
09633 void
09634 validate_condition_mode (enum rtx_code code, enum machine_mode mode)
09635 {
09636 gcc_assert ((GET_RTX_CLASS (code) == RTX_COMPARE
09637 || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
09638 && GET_MODE_CLASS (mode) == MODE_CC);
09639
09640
09641 gcc_assert ((code != GT && code != LT && code != GE && code != LE)
09642 || mode != CCUNSmode);
09643
09644 gcc_assert ((code != GTU && code != LTU && code != GEU && code != LEU)
09645 || mode == CCUNSmode);
09646
09647 gcc_assert (mode == CCFPmode
09648 || (code != ORDERED && code != UNORDERED
09649 && code != UNEQ && code != LTGT
09650 && code != UNGT && code != UNLT
09651 && code != UNGE && code != UNLE));
09652
09653
09654
09655 gcc_assert (mode != CCFPmode
09656 || flag_finite_math_only
09657 || (code != LE && code != GE
09658 && code != UNEQ && code != LTGT
09659 && code != UNGT && code != UNLT));
09660
09661
09662 gcc_assert (mode != CCEQmode || code == EQ || code == NE);
09663 }
09664
09665
09666
09667
09668
09669
09670 int
09671 includes_lshift_p (rtx shiftop, rtx andop)
09672 {
09673 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
09674
09675 shift_mask <<= INTVAL (shiftop);
09676
09677 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
09678 }
09679
09680
09681
09682 int
09683 includes_rshift_p (rtx shiftop, rtx andop)
09684 {
09685 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
09686
09687 shift_mask >>= INTVAL (shiftop);
09688
09689 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
09690 }
09691
09692
09693
09694
09695
09696 int
09697 includes_rldic_lshift_p (rtx shiftop, rtx andop)
09698 {
09699 if (GET_CODE (andop) == CONST_INT)
09700 {
09701 HOST_WIDE_INT c, lsb, shift_mask;
09702
09703 c = INTVAL (andop);
09704 if (c == 0 || c == ~0)
09705 return 0;
09706
09707 shift_mask = ~0;
09708 shift_mask <<= INTVAL (shiftop);
09709
09710
09711 lsb = c & -c;
09712
09713
09714 if (-lsb != shift_mask)
09715 return 0;
09716
09717
09718 c = ~c;
09719
09720
09721 c &= -lsb;
09722
09723
09724 lsb = c & -c;
09725 return c == -lsb;
09726 }
09727 else if (GET_CODE (andop) == CONST_DOUBLE
09728 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
09729 {
09730 HOST_WIDE_INT low, high, lsb;
09731 HOST_WIDE_INT shift_mask_low, shift_mask_high;
09732
09733 low = CONST_DOUBLE_LOW (andop);
09734 if (HOST_BITS_PER_WIDE_INT < 64)
09735 high = CONST_DOUBLE_HIGH (andop);
09736
09737 if ((low == 0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == 0))
09738 || (low == ~0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0)))
09739 return 0;
09740
09741 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
09742 {
09743 shift_mask_high = ~0;
09744 if (INTVAL (shiftop) > 32)
09745 shift_mask_high <<= INTVAL (shiftop) - 32;
09746
09747 lsb = high & -high;
09748
09749 if (-lsb != shift_mask_high || INTVAL (shiftop) < 32)
09750 return 0;
09751
09752 high = ~high;
09753 high &= -lsb;
09754
09755 lsb = high & -high;
09756 return high == -lsb;
09757 }
09758
09759 shift_mask_low = ~0;
09760 shift_mask_low <<= INTVAL (shiftop);
09761
09762 lsb = low & -low;
09763
09764 if (-lsb != shift_mask_low)
09765 return 0;
09766
09767 if (HOST_BITS_PER_WIDE_INT < 64)
09768 high = ~high;
09769 low = ~low;
09770 low &= -lsb;
09771
09772 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
09773 {
09774 lsb = high & -high;
09775 return high == -lsb;
09776 }
09777
09778 lsb = low & -low;
09779 return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
09780 }
09781 else
09782 return 0;
09783 }
09784
09785
09786
09787
09788
09789 int
09790 includes_rldicr_lshift_p (rtx shiftop, rtx andop)
09791 {
09792 if (GET_CODE (andop) == CONST_INT)
09793 {
09794 HOST_WIDE_INT c, lsb, shift_mask;
09795
09796 shift_mask = ~0;
09797 shift_mask <<= INTVAL (shiftop);
09798 c = INTVAL (andop);
09799
09800
09801 lsb = c & -c;
09802
09803
09804
09805 if ((lsb & shift_mask) == 0)
09806 return 0;
09807
09808
09809 return c == -lsb && lsb != 1;
09810 }
09811 else if (GET_CODE (andop) == CONST_DOUBLE
09812 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
09813 {
09814 HOST_WIDE_INT low, lsb, shift_mask_low;
09815
09816 low = CONST_DOUBLE_LOW (andop);
09817
09818 if (HOST_BITS_PER_WIDE_INT < 64)
09819 {
09820 HOST_WIDE_INT high, shift_mask_high;
09821
09822 high = CONST_DOUBLE_HIGH (andop);
09823
09824 if (low == 0)
09825 {
09826 shift_mask_high = ~0;
09827 if (INTVAL (shiftop) > 32)
09828 shift_mask_high <<= INTVAL (shiftop) - 32;
09829
09830 lsb = high & -high;
09831
09832 if ((lsb & shift_mask_high) == 0)
09833 return 0;
09834
09835 return high == -lsb;
09836 }
09837 if (high != ~0)
09838 return 0;
09839 }
09840
09841 shift_mask_low = ~0;
09842 shift_mask_low <<= INTVAL (shiftop);
09843
09844 lsb = low & -low;
09845
09846 if ((lsb & shift_mask_low) == 0)
09847 return 0;
09848
09849 return low == -lsb && lsb != 1;
09850 }
09851 else
09852 return 0;
09853 }
09854
09855
09856
09857
09858
09859
09860 int
09861 insvdi_rshift_rlwimi_p (rtx sizeop, rtx startop, rtx shiftop)
09862 {
09863 if (INTVAL (startop) > 32
09864 && INTVAL (startop) < 64
09865 && INTVAL (sizeop) > 1
09866 && INTVAL (sizeop) + INTVAL (startop) < 64
09867 && INTVAL (shiftop) > 0
09868 && INTVAL (sizeop) + INTVAL (shiftop) < 32
09869 && (64 - (INTVAL (shiftop) & 63)) >= INTVAL (sizeop))
09870 return 1;
09871
09872 return 0;
09873 }
09874
09875
09876
09877
09878 int
09879 registers_ok_for_quad_peep (rtx reg1, rtx reg2)
09880 {
09881
09882 if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
09883 return 0;
09884
09885
09886 if (!FP_REGNO_P (REGNO (reg1))
09887 || !FP_REGNO_P (REGNO (reg2)))
09888 return 0;
09889
09890 return (REGNO (reg1) == REGNO (reg2) - 1);
09891 }
09892
09893
09894
09895
09896
09897 int
09898 mems_ok_for_quad_peep (rtx mem1, rtx mem2)
09899 {
09900 rtx addr1, addr2;
09901 unsigned int reg1, reg2;
09902 int offset1, offset2;
09903
09904
09905 if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
09906 return 0;
09907
09908 addr1 = XEXP (mem1, 0);
09909 addr2 = XEXP (mem2, 0);
09910
09911
09912 if (GET_CODE (addr1) == PLUS)
09913 {
09914
09915 if (GET_CODE (XEXP (addr1, 0)) != REG)
09916 return 0;
09917 else
09918 {
09919 reg1 = REGNO (XEXP (addr1, 0));
09920
09921 if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
09922 return 0;
09923 offset1 = INTVAL (XEXP (addr1, 1));
09924 }
09925 }
09926 else if (GET_CODE (addr1) != REG)
09927 return 0;
09928 else
09929 {
09930 reg1 = REGNO (addr1);
09931
09932 offset1 = 0;
09933 }
09934
09935
09936 if (GET_CODE (addr2) == PLUS)
09937 {
09938
09939 if (GET_CODE (XEXP (addr2, 0)) != REG)
09940 return 0;
09941 else
09942 {
09943 reg2 = REGNO (XEXP (addr2, 0));
09944
09945 if (GET_CODE (XEXP (addr2, 1)) != CONST_INT)
09946 return 0;
09947 offset2 = INTVAL (XEXP (addr2, 1));
09948 }
09949 }
09950 else if (GET_CODE (addr2) != REG)
09951 return 0;
09952 else
09953 {
09954 reg2 = REGNO (addr2);
09955
09956 offset2 = 0;
09957 }
09958
09959
09960 if (reg1 != reg2)
09961 return 0;
09962
09963
09964 if (offset2 != offset1 + 8)
09965 return 0;
09966
09967
09968
09969 return 1;
09970 }
09971
09972
09973
09974
09975
09976 enum reg_class
09977 rs6000_secondary_reload_class (enum reg_class class,
09978 enum machine_mode mode ATTRIBUTE_UNUSED,
09979 rtx in)
09980 {
09981 int regno;
09982
09983 if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN
09984 #if TARGET_MACHO
09985 && MACHOPIC_INDIRECT
09986 #endif
09987 ))
09988 {
09989
09990
09991
09992
09993
09994
09995
09996 if (class != BASE_REGS
09997 && (GET_CODE (in) == SYMBOL_REF
09998 || GET_CODE (in) == HIGH
09999 || GET_CODE (in) == LABEL_REF
10000 || GET_CODE (in) == CONST))
10001 return BASE_REGS;
10002 }
10003
10004 if (GET_CODE (in) == REG)
10005 {
10006 regno = REGNO (in);
10007 if (regno >= FIRST_PSEUDO_REGISTER)
10008 {
10009 regno = true_regnum (in);
10010 if (regno >= FIRST_PSEUDO_REGISTER)
10011 regno = -1;
10012 }
10013 }
10014 else if (GET_CODE (in) == SUBREG)
10015 {
10016 regno = true_regnum (in);
10017 if (regno >= FIRST_PSEUDO_REGISTER)
10018 regno = -1;
10019 }
10020 else
10021 regno = -1;
10022
10023
10024
10025 if (class == GENERAL_REGS || class == BASE_REGS
10026 || (regno >= 0 && INT_REGNO_P (regno)))
10027 return NO_REGS;
10028
10029
10030 if ((regno == -1 || FP_REGNO_P (regno))
10031 && (class == FLOAT_REGS || class == NON_SPECIAL_REGS))
10032 return NO_REGS;
10033
10034
10035 if ((regno == -1 || ALTIVEC_REGNO_P (regno))
10036 && class == ALTIVEC_REGS)
10037 return NO_REGS;
10038
10039
10040 if ((class == CR_REGS || class == CR0_REGS)
10041 && regno >= 0 && CR_REGNO_P (regno))
10042 return NO_REGS;
10043
10044
10045 return GENERAL_REGS;
10046 }
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056 int
10057 ccr_bit (rtx op, int scc_p)
10058 {
10059 enum rtx_code code = GET_CODE (op);
10060 enum machine_mode cc_mode;
10061 int cc_regnum;
10062 int base_bit;
10063 rtx reg;
10064
10065 if (!COMPARISON_P (op))
10066 return -1;
10067
10068 reg = XEXP (op, 0);
10069
10070 gcc_assert (GET_CODE (reg) == REG && CR_REGNO_P (REGNO (reg)));
10071
10072 cc_mode = GET_MODE (reg);
10073 cc_regnum = REGNO (reg);
10074 base_bit = 4 * (cc_regnum - CR0_REGNO);
10075
10076 validate_condition_mode (code, cc_mode);
10077
10078
10079
10080 gcc_assert (!scc_p
10081 || code == EQ || code == GT || code == LT || code == UNORDERED
10082 || code == GTU || code == LTU);
10083
10084 switch (code)
10085 {
10086 case NE:
10087 return scc_p ? base_bit + 3 : base_bit + 2;
10088 case EQ:
10089 return base_bit + 2;
10090 case GT: case GTU: case UNLE:
10091 return base_bit + 1;
10092 case LT: case LTU: case UNGE:
10093 return base_bit;
10094 case ORDERED: case UNORDERED:
10095 return base_bit + 3;
10096
10097 case GE: case GEU:
10098
10099
10100
10101 return scc_p ? base_bit + 3 : base_bit;
10102
10103 case LE: case LEU:
10104 return scc_p ? base_bit + 3 : base_bit + 1;
10105
10106 default:
10107 gcc_unreachable ();
10108 }
10109 }
10110
10111
10112
10113 rtx
10114 rs6000_got_register (rtx value ATTRIBUTE_UNUSED)
10115 {
10116
10117
10118
10119 if (no_new_pseudos && ! regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM])
10120 regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
10121
10122 current_function_uses_pic_offset_table = 1;
10123
10124 return pic_offset_table_rtx;
10125 }
10126
10127
10128
10129
10130
10131 static struct machine_function *
10132 rs6000_init_machine_status (void)
10133 {
10134 return ggc_alloc_cleared (sizeof (machine_function));
10135 }
10136
10137
10138 #define INT_P(X) \
10139 ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
10140 && GET_MODE (X) == VOIDmode)
10141
10142 #define INT_LOWPART(X) \
10143 (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
10144
10145 int
10146 extract_MB (rtx op)
10147 {
10148 int i;
10149 unsigned long val = INT_LOWPART (op);
10150
10151
10152
10153 if ((val & 0x80000000) == 0)
10154 {
10155 gcc_assert (val & 0xffffffff);
10156
10157 i = 1;
10158 while (((val <<= 1) & 0x80000000) == 0)
10159 ++i;
10160 return i;
10161 }
10162
10163
10164
10165 if ((val & 1) == 0 || (val & 0xffffffff) == 0xffffffff)
10166 return 0;
10167
10168
10169
10170 i = 31;
10171 while (((val >>= 1) & 1) != 0)
10172 --i;
10173
10174 return i;
10175 }
10176
10177 int
10178 extract_ME (rtx op)
10179 {
10180 int i;
10181 unsigned long val = INT_LOWPART (op);
10182
10183
10184
10185 if ((val & 1) == 0)
10186 {
10187 gcc_assert (val & 0xffffffff);
10188
10189 i = 30;
10190 while (((val >>= 1) & 1) == 0)
10191 --i;
10192
10193 return i;
10194 }
10195
10196
10197
10198 if ((val & 0x80000000) == 0 || (val & 0xffffffff) == 0xffffffff)
10199 return 31;
10200
10201
10202
10203 i = 0;
10204 while (((val <<= 1) & 0x80000000) != 0)
10205 ++i;
10206
10207 return i;
10208 }
10209
10210
10211
10212
10213 static const char *
10214 rs6000_get_some_local_dynamic_name (void)
10215 {
10216 rtx insn;
10217
10218 if (cfun->machine->some_ld_name)
10219 return cfun->machine->some_ld_name;
10220
10221 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
10222 if (INSN_P (insn)
10223 && for_each_rtx (&PATTERN (insn),
10224 rs6000_get_some_local_dynamic_name_1, 0))
10225 return cfun->machine->some_ld_name;
10226
10227 gcc_unreachable ();
10228 }
10229
10230
10231
10232 static int
10233 rs6000_get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
10234 {
10235 rtx x = *px;
10236
10237 if (GET_CODE (x) == SYMBOL_REF)
10238 {
10239 const char *str = XSTR (x, 0);
10240 if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
10241 {
10242 cfun->machine->some_ld_name = str;
10243 return 1;
10244 }
10245 }
10246
10247 return 0;
10248 }
10249
10250
10251
10252 void
10253 rs6000_output_function_entry (FILE *file, const char *fname)
10254 {
10255 if (fname[0] != '.')
10256 {
10257 switch (DEFAULT_ABI)
10258 {
10259 default:
10260 gcc_unreachable ();
10261
10262 case ABI_AIX:
10263 if (DOT_SYMBOLS)
10264 putc ('.', file);
10265 else
10266 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "L.");
10267 break;
10268
10269 case ABI_V4:
10270 case ABI_DARWIN:
10271 break;
10272 }
10273 }
10274 if (TARGET_AIX)
10275 RS6000_OUTPUT_BASENAME (file, fname);
10276 else
10277 assemble_name (file, fname);
10278 }
10279
10280
10281
10282 #if TARGET_ELF
10283 #define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
10284 #define SMALL_DATA_REG ((rs6000_sdata == SDATA_EABI) ? 0 : 13)
10285 #else
10286 #define SMALL_DATA_RELOC "sda21"
10287 #define SMALL_DATA_REG 0
10288 #endif
10289
10290 void
10291 print_operand (FILE *file, rtx x, int code)
10292 {
10293 int i;
10294 HOST_WIDE_INT val;
10295 unsigned HOST_WIDE_INT uval;
10296
10297 switch (code)
10298 {
10299 case '.':
10300
10301
10302 asm_fprintf (file, RS6000_CALL_GLUE);
10303 return;
10304
10305
10306
10307 case 'A':
10308
10309
10310
10311
10312 if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0)
10313 putc ('l', file);
10314 else
10315 putc ('r', file);
10316 return;
10317
10318 case 'b':
10319
10320
10321 if (INT_P (x))
10322 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 0xffff);
10323 else
10324 print_operand (file, x, 0);
10325 return;
10326
10327 case 'B':
10328
10329
10330 putc (((INT_LOWPART (x) & 1) == 0 ? 'r' : 'l'), file);
10331 return;
10332
10333
10334
10335
10336 case 'c':
10337
10338 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10339 output_operand_lossage ("invalid %%E value");
10340 else
10341 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
10342 return;
10343
10344 case 'D':
10345
10346 gcc_assert (GET_CODE (x) == REG);
10347
10348
10349 i = 4 * (REGNO (x) - CR0_REGNO) + 1;
10350
10351
10352 fprintf (file, "%d", i + 1);
10353 return;
10354
10355 case 'E':
10356
10357 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10358 output_operand_lossage ("invalid %%E value");
10359 else
10360 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 2);
10361 return;
10362
10363 case 'f':
10364
10365
10366 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10367 output_operand_lossage ("invalid %%f value");
10368 else
10369 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO));
10370 return;
10371
10372 case 'F':
10373
10374
10375 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10376 output_operand_lossage ("invalid %%F value");
10377 else
10378 fprintf (file, "%d", 32 - 4 * (REGNO (x) - CR0_REGNO));
10379 return;
10380
10381 case 'G':
10382
10383
10384 if (GET_CODE (x) != CONST_INT)
10385 output_operand_lossage ("invalid %%G value");
10386 else if (INTVAL (x) >= 0)
10387 putc ('z', file);
10388 else
10389 putc ('m', file);
10390 return;
10391
10392 case 'h':
10393
10394
10395 if (INT_P (x))
10396 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 31);
10397 else
10398 print_operand (file, x, 0);
10399 return;
10400
10401 case 'H':
10402
10403
10404 if (INT_P (x))
10405 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 63);
10406 else
10407 print_operand (file, x, 0);
10408 return;
10409
10410 case 'I':
10411
10412 if (INT_P (x))
10413 putc ('i', file);
10414 return;
10415
10416 case 'j':
10417
10418 i = ccr_bit (x, 0);
10419 if (i == -1)
10420 output_operand_lossage ("invalid %%j code");
10421 else
10422 fprintf (file, "%d", i);
10423 return;
10424
10425 case 'J':
10426
10427
10428 i = ccr_bit (x, 1);
10429 if (i == -1)
10430 output_operand_lossage ("invalid %%J code");
10431 else
10432
10433 fprintf (file, "%d", i == 31 ? 0 : i + 1);
10434 return;
10435
10436 case 'k':
10437
10438
10439 if (! INT_P (x))
10440 output_operand_lossage ("invalid %%k value");
10441 else
10442 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INT_LOWPART (x));
10443 return;
10444
10445 case 'K':
10446
10447
10448
10449 if (GET_CODE (x) != CONST)
10450 {
10451 print_operand_address (file, x);
10452 fputs ("@l", file);
10453 }
10454 else
10455 {
10456 if (GET_CODE (XEXP (x, 0)) != PLUS
10457 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
10458 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
10459 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
10460 output_operand_lossage ("invalid %%K value");
10461 print_operand_address (file, XEXP (XEXP (x, 0), 0));
10462 fputs ("@l", file);
10463
10464
10465
10466 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
10467 fputs ("+", file);
10468 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
10469 }
10470 return;
10471
10472
10473
10474 case 'L':
10475
10476
10477 if (GET_CODE (x) == REG)
10478 fputs (reg_names[REGNO (x) + 1], file);
10479 else if (GET_CODE (x) == MEM)
10480 {
10481
10482
10483 if (GET_CODE (XEXP (x, 0)) == PRE_INC
10484 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
10485 output_address (plus_constant (XEXP (XEXP (x, 0), 0),
10486 UNITS_PER_WORD));
10487 else
10488 output_address (XEXP (adjust_address_nv (x, SImode,
10489 UNITS_PER_WORD),
10490 0));
10491
10492 if (small_data_operand (x, GET_MODE (x)))
10493 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
10494 reg_names[SMALL_DATA_REG]);
10495 }
10496 return;
10497
10498 case 'm':
10499
10500 if (! mask_operand (x, SImode))
10501 output_operand_lossage ("invalid %%m value");
10502
10503 fprintf (file, "%d", extract_MB (x));
10504 return;
10505
10506 case 'M':
10507
10508 if (! mask_operand (x, SImode))
10509 output_operand_lossage ("invalid %%M value");
10510
10511 fprintf (file, "%d", extract_ME (x));
10512 return;
10513
10514
10515
10516 case 'N':
10517
10518 if (GET_CODE (x) != PARALLEL)
10519 output_operand_lossage ("invalid %%N value");
10520 else
10521 fprintf (file, "%d", XVECLEN (x, 0) * 4);
10522 return;
10523
10524 case 'O':
10525
10526 if (GET_CODE (x) != PARALLEL)
10527 output_operand_lossage ("invalid %%O value");
10528 else
10529 fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4);
10530 return;
10531
10532 case 'p':
10533
10534 if (! INT_P (x)
10535 || INT_LOWPART (x) < 0
10536 || (i = exact_log2 (INT_LOWPART (x))) < 0)
10537 output_operand_lossage ("invalid %%p value");
10538 else
10539 fprintf (file, "%d", i);
10540 return;
10541
10542 case 'P':
10543
10544
10545 if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG
10546 || REGNO (XEXP (x, 0)) >= 32)
10547 output_operand_lossage ("invalid %%P value");
10548 else
10549 fputs (reg_names[REGNO (XEXP (x, 0))], file);
10550 return;
10551
10552 case 'q':
10553
10554
10555
10556
10557
10558 {
10559 const char *const *t = 0;
10560 const char *s;
10561 enum rtx_code code = GET_CODE (x);
10562 static const char * const tbl[3][3] = {
10563 { "and", "andc", "nor" },
10564 { "or", "orc", "nand" },
10565 { "xor", "eqv", "xor" } };
10566
10567 if (code == AND)
10568 t = tbl[0];
10569 else if (code == IOR)
10570 t = tbl[1];
10571 else if (code == XOR)
10572 t = tbl[2];
10573 else
10574 output_operand_lossage ("invalid %%q value");
10575
10576 if (GET_CODE (XEXP (x, 0)) != NOT)
10577 s = t[0];
10578 else
10579 {
10580 if (GET_CODE (XEXP (x, 1)) == NOT)
10581 s = t[2];
10582 else
10583 s = t[1];
10584 }
10585
10586 fputs (s, file);
10587 }
10588 return;
10589
10590 case 'Q':
10591 if (TARGET_MFCRF)
10592 fputc (',', file);
10593
10594 else
10595 return;
10596
10597 case 'R':
10598
10599 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10600 output_operand_lossage ("invalid %%R value");
10601 else
10602 fprintf (file, "%d", 128 >> (REGNO (x) - CR0_REGNO));
10603 return;
10604
10605 case 's':
10606
10607 if (! INT_P (x))
10608 output_operand_lossage ("invalid %%s value");
10609 else
10610 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INT_LOWPART (x)) & 31);
10611 return;
10612
10613 case 'S':
10614
10615
10616
10617 if (! mask64_operand (x, DImode))
10618 output_operand_lossage ("invalid %%S value");
10619
10620 uval = INT_LOWPART (x);
10621
10622 if (uval & 1)
10623 {
10624 #if HOST_BITS_PER_WIDE_INT > 64
10625 uval &= ((unsigned HOST_WIDE_INT) 1 << 64) - 1;
10626 #endif
10627 i = 64;
10628 }
10629 else
10630 {
10631 uval = ~uval;
10632 #if HOST_BITS_PER_WIDE_INT > 64
10633 uval &= ((unsigned HOST_WIDE_INT) 1 << 64) - 1;
10634 #endif
10635 i = 63;
10636 }
10637 while (uval != 0)
10638 --i, uval >>= 1;
10639 gcc_assert (i >= 0);
10640 fprintf (file, "%d", i);
10641 return;
10642
10643 case 't':
10644
10645 gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == CCmode);
10646
10647
10648 i = 4 * (REGNO (x) - CR0_REGNO) + 3;
10649
10650
10651 fprintf (file, "%d", i == 31 ? 0 : i + 1);
10652 return;
10653
10654 case 'T':
10655
10656 if (GET_CODE (x) != REG || (REGNO (x) != LINK_REGISTER_REGNUM
10657 && REGNO (x) != COUNT_REGISTER_REGNUM))
10658 output_operand_lossage ("invalid %%T value");
10659 else if (REGNO (x) == LINK_REGISTER_REGNUM)
10660 fputs (TARGET_NEW_MNEMONICS ? "lr" : "r", file);
10661 else
10662 fputs ("ctr", file);
10663 return;
10664
10665 case 'u':
10666
10667 if (! INT_P (x))
10668 output_operand_lossage ("invalid %%u value");
10669 else
10670 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
10671 (INT_LOWPART (x) >> 16) & 0xffff);
10672 return;
10673
10674 case 'v':
10675
10676 if (! INT_P (x))
10677 output_operand_lossage ("invalid %%v value");
10678 else
10679 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
10680 (INT_LOWPART (x) >> 16) & 0xffff);
10681 return;
10682
10683 case 'U':
10684
10685 if (GET_CODE (x) == MEM
10686 && (GET_CODE (XEXP (x, 0)) == PRE_INC
10687 || GET_CODE (XEXP (x, 0)) == PRE_DEC))
10688 putc ('u', file);
10689 return;
10690
10691 case 'V':
10692
10693 switch (GET_CODE (x))
10694 {
10695 case EQ:
10696 fputs ("eq", file);
10697 break;
10698 case NE:
10699 fputs ("ne", file);
10700 break;
10701 case LT:
10702 fputs ("lt", file);
10703 break;
10704 case LE:
10705 fputs ("le", file);
10706 break;
10707 case GT:
10708 fputs ("gt", file);
10709 break;
10710 case GE:
10711 fputs ("ge", file);
10712 break;
10713 case LTU:
10714 fputs ("llt", file);
10715 break;
10716 case LEU:
10717 fputs ("lle", file);
10718 break;
10719 case GTU:
10720 fputs ("lgt", file);
10721 break;
10722 case GEU:
10723 fputs ("lge", file);
10724 break;
10725 default:
10726 gcc_unreachable ();
10727 }
10728 break;
10729
10730 case 'w':
10731
10732
10733 if (INT_P (x))
10734 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
10735 ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000);
10736 else
10737 print_operand (file, x, 0);
10738 return;
10739
10740 case 'W':
10741
10742 val = (GET_CODE (x) == CONST_INT
10743 ? INTVAL (x) : CONST_DOUBLE_HIGH (x));
10744
10745 if (val < 0)
10746 i = -1;
10747 else
10748 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
10749 if ((val <<= 1) < 0)
10750 break;
10751
10752 #if HOST_BITS_PER_WIDE_INT == 32
10753 if (GET_CODE (x) == CONST_INT && i >= 0)
10754 i += 32;
10755 else if (GET_CODE (x) == CONST_DOUBLE && i == 32)
10756 {
10757 val = CONST_DOUBLE_LOW (x);
10758
10759 gcc_assert (val);
10760 if (val < 0)
10761 --i;
10762 else
10763 for ( ; i < 64; i++)
10764 if ((val <<= 1) < 0)
10765 break;
10766 }
10767 #endif
10768
10769 fprintf (file, "%d", i + 1);
10770 return;
10771
10772 case 'X':
10773 if (GET_CODE (x) == MEM
10774 && legitimate_indexed_address_p (XEXP (x, 0), 0))
10775 putc ('x', file);
10776 return;
10777
10778 case 'Y':
10779
10780 if (GET_CODE (x) == REG)
10781 fputs (reg_names[REGNO (x) + 2], file);
10782 else if (GET_CODE (x) == MEM)
10783 {
10784 if (GET_CODE (XEXP (x, 0)) == PRE_INC
10785 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
10786 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8));
10787 else
10788 output_address (XEXP (adjust_address_nv (x, SImode, 8), 0));
10789 if (small_data_operand (x, GET_MODE (x)))
10790 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
10791 reg_names[SMALL_DATA_REG]);
10792 }
10793 return;
10794
10795 case 'z':
10796
10797
10798
10799
10800
10801 gcc_assert (GET_CODE (x) == SYMBOL_REF);
10802
10803
10804
10805 if (SYMBOL_REF_DECL (x))
10806 mark_decl_referenced (SYMBOL_REF_DECL (x));
10807
10808
10809 if (TARGET_MACHO)
10810 {
10811 const char *name = XSTR (x, 0);
10812 #if TARGET_MACHO
10813 if (MACHOPIC_INDIRECT
10814 && machopic_classify_symbol (x) == MACHOPIC_UNDEFINED_FUNCTION)
10815 name = machopic_indirection_name (x, true);
10816 #endif
10817 assemble_name (file, name);
10818 }
10819 else if (!DOT_SYMBOLS)
10820 assemble_name (file, XSTR (x, 0));
10821 else
10822 rs6000_output_function_entry (file, XSTR (x, 0));
10823 return;
10824
10825 case 'Z':
10826
10827 if (GET_CODE (x) == REG)
10828 fputs (reg_names[REGNO (x) + 3], file);
10829 else if (GET_CODE (x) == MEM)
10830 {
10831 if (GET_CODE (XEXP (x, 0)) == PRE_INC
10832 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
10833 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12));
10834 else
10835 output_address (XEXP (adjust_address_nv (x, SImode, 12), 0));
10836 if (small_data_operand (x, GET_MODE (x)))
10837 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
10838 reg_names[SMALL_DATA_REG]);
10839 }
10840 return;
10841
10842
10843 case 'y':
10844 {
10845 rtx tmp;
10846
10847 gcc_assert (GET_CODE (x) == MEM);
10848
10849 tmp = XEXP (x, 0);
10850
10851
10852 if (TARGET_E500 && GET_MODE_SIZE (GET_MODE (x)) == 8)
10853 {
10854
10855 if (GET_CODE (tmp) == REG)
10856 {
10857 fprintf (file, "0(%s)", reg_names[REGNO (tmp)]);
10858 break;
10859 }
10860
10861 else if (GET_CODE (tmp) == PLUS &&
10862 GET_CODE (XEXP (tmp, 1)) == CONST_INT)
10863 {
10864 int x;
10865
10866 gcc_assert (GET_CODE (XEXP (tmp, 0)) == REG);
10867
10868 x = INTVAL (XEXP (tmp, 1));
10869 fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
10870 break;
10871 }
10872
10873
10874 }
10875 if (TARGET_ALTIVEC
10876 && GET_CODE (tmp) == AND
10877 && GET_CODE (XEXP (tmp, 1)) == CONST_INT
10878 && INTVAL (XEXP (tmp, 1)) == -16)
10879 tmp = XEXP (tmp, 0);
10880 if (GET_CODE (tmp) == REG)
10881 fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
10882 else
10883 {
10884 gcc_assert (GET_CODE (tmp) == PLUS
10885 && REG_P (XEXP (tmp, 0))
10886 && REG_P (XEXP (tmp, 1)));
10887
10888 if (REGNO (XEXP (tmp, 0)) == 0)
10889 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
10890 reg_names[ REGNO (XEXP (tmp, 0)) ]);
10891 else
10892 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
10893 reg_names[ REGNO (XEXP (tmp, 1)) ]);
10894 }
10895 break;
10896 }
10897
10898 case 0:
10899 if (GET_CODE (x) == REG)
10900 fprintf (file, "%s", reg_names[REGNO (x)]);
10901 else if (GET_CODE (x) == MEM)
10902 {
10903
10904
10905 if (GET_CODE (XEXP (x, 0)) == PRE_INC)
10906 fprintf (file, "%d(%s)", GET_MODE_SIZE (GET_MODE (x)),
10907 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
10908 else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
10909 fprintf (file, "%d(%s)", - GET_MODE_SIZE (GET_MODE (x)),
10910 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
10911 else
10912 output_address (XEXP (x, 0));
10913 }
10914 else
10915 output_addr_const (file, x);
10916 return;
10917
10918 case '&':
10919 assemble_name (file, rs6000_get_some_local_dynamic_name ());
10920 return;
10921
10922 default:
10923 output_operand_lossage ("invalid %%xn code");
10924 }
10925 }
10926
10927
10928
10929 void
10930 print_operand_address (FILE *file, rtx x)
10931 {
10932 if (GET_CODE (x) == REG)
10933 fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
10934 else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST
10935 || GET_CODE (x) == LABEL_REF)
10936 {
10937 output_addr_const (file, x);
10938 if (small_data_operand (x, GET_MODE (x)))
10939 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
10940 reg_names[SMALL_DATA_REG]);
10941 else
10942 gcc_assert (!TARGET_TOC);
10943 }
10944 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
10945 {
10946 gcc_assert (REG_P (XEXP (x, 0)));
10947 if (REGNO (XEXP (x, 0)) == 0)
10948 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
10949 reg_names[ REGNO (XEXP (x, 0)) ]);
10950 else
10951 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
10952 reg_names[ REGNO (XEXP (x, 1)) ]);
10953 }
10954 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
10955 fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
10956 INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
10957 #if TARGET_ELF
10958 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
10959 && CONSTANT_P (XEXP (x, 1)))
10960 {
10961 output_addr_const (file, XEXP (x, 1));
10962 fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
10963 }
10964 #endif
10965 #if TARGET_MACHO
10966 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
10967 && CONSTANT_P (XEXP (x, 1)))
10968 {
10969 fprintf (file, "lo16(");
10970 output_addr_const (file, XEXP (x, 1));
10971 fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
10972 }
10973 #endif
10974 else if (legitimate_constant_pool_address_p (x))
10975 {
10976 if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
10977 {
10978 rtx contains_minus = XEXP (x, 1);
10979 rtx minus, symref;
10980 const char *name;
10981
10982
10983
10984 while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
10985 contains_minus = XEXP (contains_minus, 0);
10986
10987 minus = XEXP (contains_minus, 0);
10988 symref = XEXP (minus, 0);
10989 XEXP (contains_minus, 0) = symref;
10990 if (TARGET_ELF)
10991 {
10992 char *newname;
10993
10994 name = XSTR (symref, 0);
10995 newname = alloca (strlen (name) + sizeof ("@toc"));
10996 strcpy (newname, name);
10997 strcat (newname, "@toc");
10998 XSTR (symref, 0) = newname;
10999 }
11000 output_addr_const (file, XEXP (x, 1));
11001 if (TARGET_ELF)
11002 XSTR (symref, 0) = name;
11003 XEXP (contains_minus, 0) = minus;
11004 }
11005 else
11006 output_addr_const (file, XEXP (x, 1));
11007
11008 fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
11009 }
11010 else
11011 gcc_unreachable ();
11012 }
11013
11014
11015
11016
11017
11018
11019 static bool
11020 rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
11021 {
11022 #ifdef RELOCATABLE_NEEDS_FIXUP
11023
11024 if (RELOCATABLE_NEEDS_FIXUP && size == 4 && aligned_p)
11025 {
11026 static int recurse = 0;
11027
11028
11029
11030 if (TARGET_RELOCATABLE
11031 && in_section != toc_section
11032 && in_section != text_section
11033 && !unlikely_text_section_p (in_section)
11034 && !recurse
11035 && GET_CODE (x) != CONST_INT
11036 && GET_CODE (x) != CONST_DOUBLE
11037 && CONSTANT_P (x))
11038 {
11039 char buf[256];
11040
11041 recurse = 1;
11042 ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno);
11043 fixuplabelno++;
11044 ASM_OUTPUT_LABEL (asm_out_file, buf);
11045 fprintf (asm_out_file, "\t.long\t(");
11046 output_addr_const (asm_out_file, x);
11047 fprintf (asm_out_file, ")@fixup\n");
11048 fprintf (asm_out_file, "\t.section\t\".fixup\",\"aw\"\n");
11049 ASM_OUTPUT_ALIGN (asm_out_file, 2);
11050 fprintf (asm_out_file, "\t.long\t");
11051 assemble_name (asm_out_file, buf);
11052 fprintf (asm_out_file, "\n\t.previous\n");
11053 recurse = 0;
11054 return true;
11055 }
11056
11057
11058
11059 else if (GET_CODE (x) == SYMBOL_REF
11060 && XSTR (x, 0)[0] == '.'
11061 && DEFAULT_ABI == ABI_AIX)
11062 {
11063 const char *name = XSTR (x, 0);
11064 while (*name == '.')
11065 name++;
11066
11067 fprintf (asm_out_file, "\t.long\t%s\n", name);
11068 return true;
11069 }
11070 }
11071 #endif
11072 return default_assemble_integer (x, size, aligned_p);
11073 }
11074
11075 #ifdef HAVE_GAS_HIDDEN
11076
11077
11078
11079 static void
11080 rs6000_assemble_visibility (tree decl, int vis)
11081 {
11082
11083
11084 if (DEFAULT_ABI == ABI_AIX
11085 && DOT_SYMBOLS
11086 && TREE_CODE (decl) == FUNCTION_DECL)
11087 {
11088 static const char * const visibility_types[] = {
11089 NULL, "internal", "hidden", "protected"
11090 };
11091
11092 const char *name, *type;
11093
11094 name = ((* targetm.strip_name_encoding)
11095 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
11096 type = visibility_types[vis];
11097
11098 fprintf (asm_out_file, "\t.%s\t%s\n", type, name);
11099 fprintf (asm_out_file, "\t.%s\t.%s\n", type, name);
11100 }
11101 else
11102 default_assemble_visibility (decl, vis);
11103 }
11104 #endif
11105
11106 enum rtx_code
11107 rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code)
11108 {
11109
11110
11111 if (mode == CCFPmode
11112 && (!flag_finite_math_only
11113 || code == UNLT || code == UNLE || code == UNGT || code == UNGE
11114 || code == UNEQ || code == LTGT))
11115 return reverse_condition_maybe_unordered (code);
11116 else
11117 return reverse_condition (code);
11118 }
11119
11120
11121
11122
11123 static rtx
11124 rs6000_generate_compare (enum rtx_code code)
11125 {
11126 enum machine_mode comp_mode;
11127 rtx compare_result;
11128
11129 if (rs6000_compare_fp_p)
11130 comp_mode = CCFPmode;
11131 else if (code == GTU || code == LTU
11132 || code == GEU || code == LEU)
11133 comp_mode = CCUNSmode;
11134 else if ((code == EQ || code == NE)
11135 && GET_CODE (rs6000_compare_op0) == SUBREG
11136 && GET_CODE (rs6000_compare_op1) == SUBREG
11137 && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0)
11138 && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1))
11139
11140
11141
11142
11143 comp_mode = CCUNSmode;
11144 else
11145 comp_mode = CCmode;
11146
11147
11148 compare_result = gen_reg_rtx (comp_mode);
11149
11150
11151 if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
11152 && rs6000_compare_fp_p)
11153 {
11154 rtx cmp, or_result, compare_result2;
11155 enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
11156
11157 if (op_mode == VOIDmode)
11158 op_mode = GET_MODE (rs6000_compare_op1);
11159
11160
11161
11162
11163 switch (code)
11164 {
11165 case EQ: case UNEQ: case NE: case LTGT:
11166 switch (op_mode)
11167 {
11168 case SFmode:
11169 cmp = flag_unsafe_math_optimizations
11170 ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
11171 rs6000_compare_op1)
11172 : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
11173 rs6000_compare_op1);
11174 break;
11175
11176 case DFmode:
11177 cmp = flag_unsafe_math_optimizations
11178 ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
11179 rs6000_compare_op1)
11180 : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
11181 rs6000_compare_op1);
11182 break;
11183
11184 default:
11185 gcc_unreachable ();
11186 }
11187 break;
11188
11189 case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
11190 switch (op_mode)
11191 {
11192 case SFmode:
11193 cmp = flag_unsafe_math_optimizations
11194 ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
11195 rs6000_compare_op1)
11196 : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
11197 rs6000_compare_op1);
11198 break;
11199
11200 case DFmode:
11201 cmp = flag_unsafe_math_optimizations
11202 ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
11203 rs6000_compare_op1)
11204 : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
11205 rs6000_compare_op1);
11206 break;
11207
11208 default:
11209 gcc_unreachable ();
11210 }
11211 break;
11212
11213 case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
11214 switch (op_mode)
11215 {
11216 case SFmode:
11217 cmp = flag_unsafe_math_optimizations
11218 ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
11219 rs6000_compare_op1)
11220 : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
11221 rs6000_compare_op1);
11222 break;
11223
11224 case DFmode:
11225 cmp = flag_unsafe_math_optimizations
11226 ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
11227 rs6000_compare_op1)
11228 : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
11229 rs6000_compare_op1);
11230 break;
11231
11232 default:
11233 gcc_unreachable ();
11234 }
11235 break;
11236 default:
11237 gcc_unreachable ();
11238 }
11239
11240
11241 if (code == LE || code == GE || code == LEU || code == GEU)
11242 {
11243 emit_insn (cmp);
11244
11245 switch (code)
11246 {
11247 case LE: code = LT; break;
11248 case GE: code = GT; break;
11249 case LEU: code = LT; break;
11250 case GEU: code = GT; break;
11251 default: gcc_unreachable ();
11252 }
11253
11254 compare_result2 = gen_reg_rtx (CCFPmode);
11255
11256
11257 switch (op_mode)
11258 {
11259 case SFmode:
11260 cmp = flag_unsafe_math_optimizations
11261 ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
11262 rs6000_compare_op1)
11263 : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
11264 rs6000_compare_op1);
11265 break;
11266
11267 case DFmode:
11268 cmp = flag_unsafe_math_optimizations
11269 ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
11270 rs6000_compare_op1)
11271 : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
11272 rs6000_compare_op1);
11273 break;
11274
11275 default:
11276 gcc_unreachable ();
11277 }
11278 emit_insn (cmp);
11279
11280
11281 or_result = gen_reg_rtx (CCFPmode);
11282 cmp = gen_e500_cr_ior_compare (or_result, compare_result,
11283 compare_result2);
11284 compare_result = or_result;
11285 code = EQ;
11286 }
11287 else
11288 {
11289 if (code == NE || code == LTGT)
11290 code = NE;
11291 else
11292 code = EQ;
11293 }
11294
11295 emit_insn (cmp);
11296 }
11297 else
11298 {
11299
11300
11301 if (comp_mode == CCFPmode && TARGET_XL_COMPAT
11302 && GET_MODE (rs6000_compare_op0) == TFmode
11303 && !TARGET_IEEEQUAD
11304 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
11305 emit_insn (gen_rtx_PARALLEL (VOIDmode,
11306 gen_rtvec (9,
11307 gen_rtx_SET (VOIDmode,
11308 compare_result,
11309 gen_rtx_COMPARE (comp_mode,
11310 rs6000_compare_op0,
11311 rs6000_compare_op1)),
11312 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11313 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11314 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11315 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11316 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11317 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11318 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11319 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
11320 else if (GET_CODE (rs6000_compare_op1) == UNSPEC
11321 && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST)
11322 {
11323 rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0);
11324 comp_mode = CCEQmode;
11325 compare_result = gen_reg_rtx (CCEQmode);
11326 if (TARGET_64BIT)
11327 emit_insn (gen_stack_protect_testdi (compare_result,
11328 rs6000_compare_op0, op1));
11329 else
11330 emit_insn (gen_stack_protect_testsi (compare_result,
11331 rs6000_compare_op0, op1));
11332 }
11333 else
11334 emit_insn (gen_rtx_SET (VOIDmode, compare_result,
11335 gen_rtx_COMPARE (comp_mode,
11336 rs6000_compare_op0,
11337 rs6000_compare_op1)));
11338 }
11339
11340
11341
11342 if (rs6000_compare_fp_p
11343 && !flag_finite_math_only
11344 && !(TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
11345 && (code == LE || code == GE
11346 || code == UNEQ || code == LTGT
11347 || code == UNGT || code == UNLT))
11348 {
11349 enum rtx_code or1, or2;
11350 rtx or1_rtx, or2_rtx, compare2_rtx;
11351 rtx or_result = gen_reg_rtx (CCEQmode);
11352
11353 switch (code)
11354 {
11355 case LE: or1 = LT; or2 = EQ; break;
11356 case GE: or1 = GT; or2 = EQ; break;
11357 case UNEQ: or1 = UNORDERED; or2 = EQ; break;
11358 case LTGT: or1 = LT; or2 = GT; break;
11359 case UNGT: or1 = UNORDERED; or2 = GT; break;
11360 case UNLT: or1 = UNORDERED; or2 = LT; break;
11361 default: gcc_unreachable ();
11362 }
11363 validate_condition_mode (or1, comp_mode);
11364 validate_condition_mode (or2, comp_mode);
11365 or1_rtx = gen_rtx_fmt_ee (or1, SImode, compare_result, const0_rtx);
11366 or2_rtx = gen_rtx_fmt_ee (or2, SImode, compare_result, const0_rtx);
11367 compare2_rtx = gen_rtx_COMPARE (CCEQmode,
11368 gen_rtx_IOR (SImode, or1_rtx, or2_rtx),
11369 const_true_rtx);
11370 emit_insn (gen_rtx_SET (VOIDmode, or_result, compare2_rtx));
11371
11372 compare_result = or_result;
11373 code = EQ;
11374 }
11375
11376 validate_condition_mode (code, GET_MODE (compare_result));
11377
11378 return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
11379 }
11380
11381
11382
11383
11384 void
11385 rs6000_emit_sCOND (enum rtx_code code, rtx result)
11386 {
11387 rtx condition_rtx;
11388 enum machine_mode op_mode;
11389 enum rtx_code cond_code;
11390
11391 condition_rtx = rs6000_generate_compare (code);
11392 cond_code = GET_CODE (condition_rtx);
11393
11394 if (TARGET_E500 && rs6000_compare_fp_p
11395 && !TARGET_FPRS && TARGET_HARD_FLOAT)
11396 {
11397 rtx t;
11398
11399 PUT_MODE (condition_rtx, SImode);
11400 t = XEXP (condition_rtx, 0);
11401
11402 gcc_assert (cond_code == NE || cond_code == EQ);
11403
11404 if (cond_code == NE)
11405 emit_insn (gen_e500_flip_gt_bit (t, t));
11406
11407 emit_insn (gen_move_from_CR_gt_bit (result, t));
11408 return;
11409 }
11410
11411 if (cond_code == NE
11412 || cond_code == GE || cond_code == LE
11413 || cond_code == GEU || cond_code == LEU
11414 || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE)
11415 {
11416 rtx not_result = gen_reg_rtx (CCEQmode);
11417 rtx not_op, rev_cond_rtx;
11418 enum machine_mode cc_mode;
11419
11420 cc_mode = GET_MODE (XEXP (condition_rtx, 0));
11421
11422 rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, cond_code),
11423 SImode, XEXP (condition_rtx, 0), const0_rtx);
11424 not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
11425 emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
11426 condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
11427 }
11428
11429 op_mode = GET_MODE (rs6000_compare_op0);
11430 if (op_mode == VOIDmode)
11431 op_mode = GET_MODE (rs6000_compare_op1);
11432
11433 if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p))
11434 {
11435 PUT_MODE (condition_rtx, DImode);
11436 convert_move (result, condition_rtx, 0);
11437 }
11438 else
11439 {
11440 PUT_MODE (condition_rtx, SImode);
11441 emit_insn (gen_rtx_SET (VOIDmode, result, condition_rtx));
11442 }
11443 }
11444
11445
11446
11447 void
11448 rs6000_emit_cbranch (enum rtx_code code, rtx loc)
11449 {
11450 rtx condition_rtx, loc_ref;
11451
11452 condition_rtx = rs6000_generate_compare (code);
11453 loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
11454 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
11455 gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
11456 loc_ref, pc_rtx)));
11457 }
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471 char *
11472 output_cbranch (rtx op, const char *label, int reversed, rtx insn)
11473 {
11474 static char string[64];
11475 enum rtx_code code = GET_CODE (op);
11476 rtx cc_reg = XEXP (op, 0);
11477 enum machine_mode mode = GET_MODE (cc_reg);
11478 int cc_regno = REGNO (cc_reg) - CR0_REGNO;
11479 int need_longbranch = label != NULL && get_attr_length (insn) == 8;
11480 int really_reversed = reversed ^ need_longbranch;
11481 char *s = string;
11482 const char *ccode;
11483 const char *pred;
11484 rtx note;
11485
11486 validate_condition_mode (code, mode);
11487
11488
11489
11490
11491 if (really_reversed)
11492 {
11493
11494
11495 if (mode == CCFPmode)
11496 code = reverse_condition_maybe_unordered (code);
11497 else
11498 code = reverse_condition (code);
11499 }
11500
11501 if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT) && mode == CCFPmode)
11502 {
11503
11504
11505 switch (code)
11506 {
11507 case EQ:
11508
11509 code = GT;
11510 break;
11511
11512 case NE:
11513 code = UNLE;
11514 break;
11515
11516 default:
11517 gcc_unreachable ();
11518 }
11519 }
11520
11521 switch (code)
11522 {
11523
11524
11525 case NE: case LTGT:
11526 ccode = "ne"; break;
11527 case EQ: case UNEQ:
11528 ccode = "eq"; break;
11529 case GE: case GEU:
11530 ccode = "ge"; break;
11531 case GT: case GTU: case UNGT:
11532 ccode = "gt"; break;
11533 case LE: case LEU:
11534 ccode = "le"; break;
11535 case LT: case LTU: case UNLT:
11536 ccode = "lt"; break;
11537 case UNORDERED: ccode = "un"; break;
11538 case ORDERED: ccode = "nu"; break;
11539 case UNGE: ccode = "nl"; break;
11540 case UNLE: ccode = "ng"; break;
11541 default:
11542 gcc_unreachable ();
11543 }
11544
11545
11546
11547 pred = "";
11548 note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
11549 if (note != NULL_RTX)
11550 {
11551
11552 int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
11553
11554
11555
11556
11557
11558
11559
11560 if (rs6000_always_hint
11561 || (abs (prob) > REG_BR_PROB_BASE / 100 * 48
11562 && br_prob_note_reliable_p (note)))
11563 {
11564 if (abs (prob) > REG_BR_PROB_BASE / 20
11565 && ((prob > 0) ^ need_longbranch))
11566 pred = "+";
11567 else
11568 pred = "-";
11569 }
11570 }
11571
11572 if (label == NULL)
11573 s += sprintf (s, "{b%sr|b%slr%s} ", ccode, ccode, pred);
11574 else
11575 s += sprintf (s, "{b%s|b%s%s} ", ccode, ccode, pred);
11576
11577
11578
11579 if (reg_names[cc_regno + CR0_REGNO][0] == '%')
11580 *s++ = '%';
11581 s += sprintf (s, "%s", reg_names[cc_regno + CR0_REGNO]);
11582
11583 if (label != NULL)
11584 {
11585
11586
11587 if (need_longbranch)
11588 s += sprintf (s, ",$+8\n\tb %s", label);
11589 else
11590 s += sprintf (s, ",%s", label);
11591 }
11592
11593 return string;
11594 }
11595
11596
11597 char *
11598 output_e500_flip_gt_bit (rtx dst, rtx src)
11599 {
11600 static char string[64];
11601 int a, b;
11602
11603 gcc_assert (GET_CODE (dst) == REG && CR_REGNO_P (REGNO (dst))
11604 && GET_CODE (src) == REG && CR_REGNO_P (REGNO (src)));
11605
11606
11607 a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
11608 b = 4 * (REGNO (src) - CR0_REGNO) + 1;
11609
11610 sprintf (string, "crnot %d,%d", a, b);
11611 return string;
11612 }
11613
11614
11615
11616
11617
11618 static int
11619 get_vec_cmp_insn (enum rtx_code code,
11620 enum machine_mode dest_mode,
11621 enum machine_mode op_mode)
11622 {
11623 if (!TARGET_ALTIVEC)
11624 return INSN_NOT_AVAILABLE;
11625
11626 switch (code)
11627 {
11628 case EQ:
11629 if (dest_mode == V16QImode && op_mode == V16QImode)
11630 return UNSPEC_VCMPEQUB;
11631 if (dest_mode == V8HImode && op_mode == V8HImode)
11632 return UNSPEC_VCMPEQUH;
11633 if (dest_mode == V4SImode && op_mode == V4SImode)
11634 return UNSPEC_VCMPEQUW;
11635 if (dest_mode == V4SImode && op_mode == V4SFmode)
11636 return UNSPEC_VCMPEQFP;
11637 break;
11638 case GE:
11639 if (dest_mode == V4SImode && op_mode == V4SFmode)
11640 return UNSPEC_VCMPGEFP;
11641 case GT:
11642 if (dest_mode == V16QImode && op_mode == V16QImode)
11643 return UNSPEC_VCMPGTSB;
11644 if (dest_mode == V8HImode && op_mode == V8HImode)
11645 return UNSPEC_VCMPGTSH;
11646 if (dest_mode == V4SImode && op_mode == V4SImode)
11647 return UNSPEC_VCMPGTSW;
11648 if (dest_mode == V4SImode && op_mode == V4SFmode)
11649 return UNSPEC_VCMPGTFP;
11650 break;
11651 case GTU:
11652 if (dest_mode == V16QImode && op_mode == V16QImode)
11653 return UNSPEC_VCMPGTUB;
11654 if (dest_mode == V8HImode && op_mode == V8HImode)
11655 return UNSPEC_VCMPGTUH;
11656 if (dest_mode == V4SImode && op_mode == V4SImode)
11657 return UNSPEC_VCMPGTUW;
11658 break;
11659 default:
11660 break;
11661 }
11662 return INSN_NOT_AVAILABLE;
11663 }
11664
11665
11666
11667
11668 static rtx
11669 rs6000_emit_vector_compare (enum rtx_code rcode,
11670 rtx op0, rtx op1,
11671 enum machine_mode dmode)
11672 {
11673 int vec_cmp_insn;
11674 rtx mask;
11675 enum machine_mode dest_mode;
11676 enum machine_mode op_mode = GET_MODE (op1);
11677
11678 gcc_assert (TARGET_ALTIVEC);
11679 gcc_assert (GET_MODE (op0) == GET_MODE (op1));
11680
11681
11682
11683 if (dmode == V4SFmode)
11684 dest_mode = V4SImode;
11685 else
11686 dest_mode = dmode;
11687
11688 mask = gen_reg_rtx (dest_mode);
11689 vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
11690
11691 if (vec_cmp_insn == INSN_NOT_AVAILABLE)
11692 {
11693 bool swap_operands = false;
11694 bool try_again = false;
11695 switch (rcode)
11696 {
11697 case LT:
11698 rcode = GT;
11699 swap_operands = true;
11700 try_again = true;
11701 break;
11702 case LTU:
11703 rcode = GTU;
11704 swap_operands = true;
11705 try_again = true;
11706 break;
11707 case NE:
11708
11709 {
11710 enum insn_code nor_code;
11711 rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
11712 dest_mode);
11713
11714 nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code;
11715 gcc_assert (nor_code != CODE_FOR_nothing);
11716 emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
11717
11718 if (dmode != dest_mode)
11719 {
11720 rtx temp = gen_reg_rtx (dest_mode);
11721 convert_move (temp, mask, 0);
11722 return temp;
11723 }
11724 return mask;
11725 }
11726 break;
11727 case GE:
11728 case GEU:
11729 case LE:
11730 case LEU:
11731
11732 {
11733 rtx c_rtx, eq_rtx;
11734 enum insn_code ior_code;
11735 enum rtx_code new_code;
11736
11737 switch (rcode)
11738 {
11739 case GE:
11740 new_code = GT;
11741 break;
11742
11743 case GEU:
11744 new_code = GTU;
11745 break;
11746
11747 case LE:
11748 new_code = LT;
11749 break;
11750
11751 case LEU:
11752 new_code = LTU;
11753 break;
11754
11755 default:
11756 gcc_unreachable ();
11757 }
11758
11759 c_rtx = rs6000_emit_vector_compare (new_code,
11760 op0, op1, dest_mode);
11761 eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
11762 dest_mode);
11763
11764 ior_code = ior_optab->handlers[(int)dest_mode].insn_code;
11765 gcc_assert (ior_code != CODE_FOR_nothing);
11766 emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
11767 if (dmode != dest_mode)
11768 {
11769 rtx temp = gen_reg_rtx (dest_mode);
11770 convert_move (temp, mask, 0);
11771 return temp;
11772 }
11773 return mask;
11774 }
11775 break;
11776 default:
11777 gcc_unreachable ();
11778 }
11779
11780 if (try_again)
11781 {
11782 vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
11783
11784 gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
11785 }
11786
11787 if (swap_operands)
11788 {
11789 rtx tmp;
11790 tmp = op0;
11791 op0 = op1;
11792 op1 = tmp;
11793 }
11794 }
11795
11796 emit_insn (gen_rtx_SET (VOIDmode, mask,
11797 gen_rtx_UNSPEC (dest_mode,
11798 gen_rtvec (2, op0, op1),
11799 vec_cmp_insn)));
11800 if (dmode != dest_mode)
11801 {
11802 rtx temp = gen_reg_rtx (dest_mode);
11803 convert_move (temp, mask, 0);
11804 return temp;
11805 }
11806 return mask;
11807 }
11808
11809
11810
11811
11812 static int
11813 get_vsel_insn (enum machine_mode mode)
11814 {
11815 switch (mode)
11816 {
11817 case V4SImode:
11818 return UNSPEC_VSEL4SI;
11819 break;
11820 case V4SFmode:
11821 return UNSPEC_VSEL4SF;
11822 break;
11823 case V8HImode:
11824 return UNSPEC_VSEL8HI;
11825 break;
11826 case V16QImode:
11827 return UNSPEC_VSEL16QI;
11828 break;
11829 default:
11830 return INSN_NOT_AVAILABLE;
11831 break;
11832 }
11833 return INSN_NOT_AVAILABLE;
11834 }
11835
11836
11837
11838
11839 static void
11840 rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
11841 {
11842 rtx t, temp;
11843 enum machine_mode dest_mode = GET_MODE (dest);
11844 int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
11845
11846 temp = gen_reg_rtx (dest_mode);
11847
11848
11849
11850 t = gen_rtx_SET (VOIDmode, temp,
11851 gen_rtx_UNSPEC (dest_mode,
11852 gen_rtvec (3, op2, op1, mask),
11853 vsel_insn_index));
11854 emit_insn (t);
11855 emit_move_insn (dest, temp);
11856 return;
11857 }
11858
11859
11860
11861
11862
11863 int
11864 rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
11865 rtx cond, rtx cc_op0, rtx cc_op1)
11866 {
11867 enum machine_mode dest_mode = GET_MODE (dest);
11868 enum rtx_code rcode = GET_CODE (cond);
11869 rtx mask;
11870
11871 if (!TARGET_ALTIVEC)
11872 return 0;
11873
11874
11875 mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
11876
11877 rs6000_emit_vector_select (dest, op1, op2, mask);
11878
11879 return 1;
11880 }
11881
11882
11883
11884
11885
11886 int
11887 rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
11888 {
11889 enum rtx_code code = GET_CODE (op);
11890 rtx op0 = rs6000_compare_op0;
11891 rtx op1 = rs6000_compare_op1;
11892 REAL_VALUE_TYPE c1;
11893 enum machine_mode compare_mode = GET_MODE (op0);
11894 enum machine_mode result_mode = GET_MODE (dest);
11895 rtx temp;
11896 bool is_against_zero;
11897
11898
11899 if (GET_MODE (op1) != compare_mode
11900
11901
11902 && (!TARGET_ISEL || !short_cint_operand (op1, VOIDmode)))
11903 return 0;
11904 if (GET_MODE (true_cond) != result_mode)
11905 return 0;
11906 if (GET_MODE (false_cond) != result_mode)
11907 return 0;
11908
11909
11910
11911 if (! rs6000_compare_fp_p)
11912 {
11913 if (TARGET_ISEL)
11914 return rs6000_emit_int_cmove (dest, op, true_cond, false_cond);
11915 return 0;
11916 }
11917 else if (TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS
11918 && SCALAR_FLOAT_MODE_P (compare_mode))
11919 return 0;
11920
11921 is_against_zero = op1 == CONST0_RTX (compare_mode);
11922
11923
11924
11925
11926
11927
11928 if (SCALAR_FLOAT_MODE_P (compare_mode)
11929 && flag_trapping_math && ! is_against_zero)
11930 return 0;
11931
11932
11933
11934 if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
11935 || code == LTGT || code == LT || code == UNLE)
11936 {
11937 code = reverse_condition_maybe_unordered (code);
11938 temp = true_cond;
11939 true_cond = false_cond;
11940 false_cond = temp;
11941 }
11942
11943
11944
11945 if (code == UNEQ && HONOR_NANS (compare_mode))
11946 return 0;
11947
11948 if (GET_CODE (op1) == CONST_DOUBLE)
11949 REAL_VALUE_FROM_CONST_DOUBLE (c1, op1);
11950
11951
11952
11953
11954
11955
11956 if (HONOR_INFINITIES (compare_mode)
11957 && code != GT && code != UNGE
11958 && (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1))
11959
11960 && ((! rtx_equal_p (op0, false_cond) && ! rtx_equal_p (op1, false_cond))
11961 || (! rtx_equal_p (op0, true_cond)
11962 && ! rtx_equal_p (op1, true_cond))))
11963 return 0;
11964
11965
11966
11967
11968 if (! is_against_zero)
11969 {
11970 temp = gen_reg_rtx (compare_mode);
11971 emit_insn (gen_rtx_SET (VOIDmode, temp,
11972 gen_rtx_MINUS (compare_mode, op0, op1)));
11973 op0 = temp;
11974 op1 = CONST0_RTX (compare_mode);
11975 }
11976
11977
11978
11979 if (! HONOR_NANS (compare_mode))
11980 switch (code)
11981 {
11982 case GT:
11983 code = LE;
11984 temp = true_cond;
11985 true_cond = false_cond;
11986 false_cond = temp;
11987 break;
11988 case UNGE:
11989 code = GE;
11990 break;
11991 case UNEQ:
11992 code = EQ;
11993 break;
11994 default:
11995 break;
11996 }
11997
11998
11999 switch (code)
12000 {
12001 case GE:
12002 break;
12003
12004 case LE:
12005 temp = gen_reg_rtx (compare_mode);
12006 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12007 op0 = temp;
12008 break;
12009
12010 case ORDERED:
12011 temp = gen_reg_rtx (compare_mode);
12012 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (compare_mode, op0)));
12013 op0 = temp;
12014 break;
12015
12016 case EQ:
12017 temp = gen_reg_rtx (compare_mode);
12018 emit_insn (gen_rtx_SET (VOIDmode, temp,
12019 gen_rtx_NEG (compare_mode,
12020 gen_rtx_ABS (compare_mode, op0))));
12021 op0 = temp;
12022 break;
12023
12024 case UNGE:
12025
12026 temp = gen_reg_rtx (result_mode);
12027 emit_insn (gen_rtx_SET (VOIDmode, temp,
12028 gen_rtx_IF_THEN_ELSE (result_mode,
12029 gen_rtx_GE (VOIDmode,
12030 op0, op1),
12031 true_cond, false_cond)));
12032 false_cond = true_cond;
12033 true_cond = temp;
12034
12035 temp = gen_reg_rtx (compare_mode);
12036 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12037 op0 = temp;
12038 break;
12039
12040 case GT:
12041
12042 temp = gen_reg_rtx (result_mode);
12043 emit_insn (gen_rtx_SET (VOIDmode, temp,
12044 gen_rtx_IF_THEN_ELSE (result_mode,
12045 gen_rtx_GE (VOIDmode,
12046 op0, op1),
12047 true_cond, false_cond)));
12048 true_cond = false_cond;
12049 false_cond = temp;
12050
12051 temp = gen_reg_rtx (compare_mode);
12052 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12053 op0 = temp;
12054 break;
12055
12056 default:
12057 gcc_unreachable ();
12058 }
12059
12060 emit_insn (gen_rtx_SET (VOIDmode, dest,
12061 gen_rtx_IF_THEN_ELSE (result_mode,
12062 gen_rtx_GE (VOIDmode,
12063 op0, op1),
12064 true_cond, false_cond)));
12065 return 1;
12066 }
12067
12068
12069
12070 static int
12071 rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
12072 {
12073 rtx condition_rtx, cr;
12074
12075
12076 if (GET_MODE (rs6000_compare_op0) != SImode)
12077 return 0;
12078
12079
12080
12081
12082 condition_rtx = rs6000_generate_compare (GET_CODE (op));
12083 cr = XEXP (condition_rtx, 0);
12084
12085 if (GET_MODE (cr) == CCmode)
12086 emit_insn (gen_isel_signed (dest, condition_rtx,
12087 true_cond, false_cond, cr));
12088 else
12089 emit_insn (gen_isel_unsigned (dest, condition_rtx,
12090 true_cond, false_cond, cr));
12091
12092 return 1;
12093 }
12094
12095 const char *
12096 output_isel (rtx *operands)
12097 {
12098 enum rtx_code code;
12099
12100 code = GET_CODE (operands[1]);
12101 if (code == GE || code == GEU || code == LE || code == LEU || code == NE)
12102 {
12103 PUT_CODE (operands[1], reverse_condition (code));
12104 return "isel %0,%3,%2,%j1";
12105 }
12106 else
12107 return "isel %0,%2,%3,%j1";
12108 }
12109
12110 void
12111 rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
12112 {
12113 enum machine_mode mode = GET_MODE (op0);
12114 enum rtx_code c;
12115 rtx target;
12116
12117 if (code == SMAX || code == SMIN)
12118 c = GE;
12119 else
12120 c = GEU;
12121
12122 if (code == SMAX || code == UMAX)
12123 target = emit_conditional_move (dest, c, op0, op1, mode,
12124 op0, op1, mode, 0);
12125 else
12126 target = emit_conditional_move (dest, c, op0, op1, mode,
12127 op1, op0, mode, 0);
12128 gcc_assert (target);
12129 if (target != dest)
12130 emit_move_insn (dest, target);
12131 }
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141 void
12142 rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
12143 rtx m, rtx op, rtx before_param, rtx after_param,
12144 bool sync_p)
12145 {
12146 enum machine_mode used_mode;
12147 rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
12148 rtx used_m;
12149 rtvec vec;
12150 HOST_WIDE_INT imask = GET_MODE_MASK (mode);
12151 rtx shift = NULL_RTX;
12152
12153 if (sync_p)
12154 emit_insn (gen_memory_barrier ());
12155
12156 if (GET_CODE (m) == NOT)
12157 used_m = XEXP (m, 0);
12158 else
12159 used_m = m;
12160
12161
12162
12163 if (mode == QImode || mode == HImode)
12164 {
12165 rtx newop, oldop;
12166
12167 if (MEM_ALIGN (used_m) >= 32)
12168 {
12169 int ishift = 0;
12170 if (BYTES_BIG_ENDIAN)
12171 ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
12172
12173 shift = GEN_INT (ishift);
12174 }
12175 else
12176 {
12177 rtx addrSI, aligned_addr;
12178 int shift_mask = mode == QImode ? 0x18 : 0x10;
12179
12180 addrSI = force_reg (SImode, gen_lowpart_common (SImode,
12181 XEXP (used_m, 0)));
12182 shift = gen_reg_rtx (SImode);
12183
12184 emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
12185 GEN_INT (shift_mask)));
12186 emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
12187
12188 aligned_addr = expand_binop (Pmode, and_optab,
12189 XEXP (used_m, 0),
12190 GEN_INT (-4), NULL_RTX,
12191 1, OPTAB_LIB_WIDEN);
12192 used_m = change_address (used_m, SImode, aligned_addr);
12193 set_mem_align (used_m, 32);
12194
12195
12196
12197 if (GET_CODE (m) == NOT)
12198 m = gen_rtx_NOT (SImode, used_m);
12199 else
12200 m = used_m;
12201 }
12202
12203 if (GET_CODE (op) == NOT)
12204 {
12205 oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
12206 oldop = gen_rtx_NOT (SImode, oldop);
12207 }
12208 else
12209 oldop = lowpart_subreg (SImode, op, mode);
12210
12211 switch (code)
12212 {
12213 case IOR:
12214 case XOR:
12215 newop = expand_binop (SImode, and_optab,
12216 oldop, GEN_INT (imask), NULL_RTX,
12217 1, OPTAB_LIB_WIDEN);
12218 emit_insn (gen_ashlsi3 (newop, newop, shift));
12219 break;
12220
12221 case AND:
12222 newop = expand_binop (SImode, ior_optab,
12223 oldop, GEN_INT (~imask), NULL_RTX,
12224 1, OPTAB_LIB_WIDEN);
12225 emit_insn (gen_rotlsi3 (newop, newop, shift));
12226 break;
12227
12228 case PLUS:
12229 case MINUS:
12230 {
12231 rtx mask;
12232
12233 newop = expand_binop (SImode, and_optab,
12234 oldop, GEN_INT (imask), NULL_RTX,
12235 1, OPTAB_LIB_WIDEN);
12236 emit_insn (gen_ashlsi3 (newop, newop, shift));
12237
12238 mask = gen_reg_rtx (SImode);
12239 emit_move_insn (mask, GEN_INT (imask));
12240 emit_insn (gen_ashlsi3 (mask, mask, shift));
12241
12242 if (code == PLUS)
12243 newop = gen_rtx_PLUS (SImode, m, newop);
12244 else
12245 newop = gen_rtx_MINUS (SImode, m, newop);
12246 newop = gen_rtx_AND (SImode, newop, mask);
12247 newop = gen_rtx_IOR (SImode, newop,
12248 gen_rtx_AND (SImode,
12249 gen_rtx_NOT (SImode, mask),
12250 m));
12251 break;
12252 }
12253
12254 default:
12255 gcc_unreachable ();
12256 }
12257
12258 if (GET_CODE (m) == NOT)
12259 {
12260 rtx mask, xorm;
12261
12262 mask = gen_reg_rtx (SImode);
12263 emit_move_insn (mask, GEN_INT (imask));
12264 emit_insn (gen_ashlsi3 (mask, mask, shift));
12265
12266 xorm = gen_rtx_XOR (SImode, used_m, mask);
12267
12268
12269 newop = simplify_gen_binary (code, SImode, xorm, newop);
12270 }
12271 op = newop;
12272 used_mode = SImode;
12273 before = gen_reg_rtx (used_mode);
12274 after = gen_reg_rtx (used_mode);
12275 }
12276 else
12277 {
12278 used_mode = mode;
12279 before = before_param;
12280 after = after_param;
12281
12282 if (before == NULL_RTX)
12283 before = gen_reg_rtx (used_mode);
12284 if (after == NULL_RTX)
12285 after = gen_reg_rtx (used_mode);
12286 }
12287
12288 if ((code == PLUS || code == MINUS || GET_CODE (m) == NOT)
12289 && used_mode != mode)
12290 the_op = op;
12291 else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
12292 the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
12293 else
12294 the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
12295
12296 set_after = gen_rtx_SET (VOIDmode, after, the_op);
12297 set_before = gen_rtx_SET (VOIDmode, before, used_m);
12298 set_atomic = gen_rtx_SET (VOIDmode, used_m,
12299 gen_rtx_UNSPEC (used_mode,
12300 gen_rtvec (1, the_op),
12301 UNSPEC_SYNC_OP));
12302 cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
12303
12304 if ((code == PLUS || code == MINUS) && used_mode != mode)
12305 vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
12306 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
12307 else
12308 vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
12309 emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
12310
12311
12312 if (used_mode != mode && before_param)
12313 {
12314 emit_insn (gen_lshrsi3 (before, before, shift));
12315 convert_move (before_param, before, 1);
12316 }
12317
12318 if (used_mode != mode && after_param)
12319 {
12320 emit_insn (gen_lshrsi3 (after, after, shift));
12321 convert_move (after_param, after, 1);
12322 }
12323
12324
12325
12326
12327
12328 if (sync_p)
12329 emit_insn (gen_isync ());
12330 }
12331
12332
12333
12334
12335 static void
12336 emit_unlikely_jump (rtx cond, rtx label)
12337 {
12338 rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
12339 rtx x;
12340
12341 x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
12342 x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
12343 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
12344 }
12345
12346
12347
12348
12349 static void
12350 emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
12351 {
12352 rtx (*fn) (rtx, rtx) = NULL;
12353 if (mode == SImode)
12354 fn = gen_load_locked_si;
12355 else if (mode == DImode)
12356 fn = gen_load_locked_di;
12357 emit_insn (fn (reg, mem));
12358 }
12359
12360
12361
12362
12363 static void
12364 emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
12365 {
12366 rtx (*fn) (rtx, rtx, rtx) = NULL;
12367 if (mode == SImode)
12368 fn = gen_store_conditional_si;
12369 else if (mode == DImode)
12370 fn = gen_store_conditional_di;
12371
12372
12373 if (PPC405_ERRATUM77)
12374 emit_insn (gen_memory_barrier ());
12375
12376 emit_insn (fn (res, mem, val));
12377 }
12378
12379
12380
12381
12382
12383
12384
12385 void
12386 rs6000_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
12387 rtx before, rtx after, rtx scratch)
12388 {
12389 enum machine_mode mode = GET_MODE (mem);
12390 rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
12391
12392 emit_insn (gen_memory_barrier ());
12393
12394 label = gen_label_rtx ();
12395 emit_label (label);
12396 label = gen_rtx_LABEL_REF (VOIDmode, label);
12397
12398 if (before == NULL_RTX)
12399 before = scratch;
12400 emit_load_locked (mode, before, mem);
12401
12402 if (code == NOT)
12403 x = gen_rtx_AND (mode, gen_rtx_NOT (mode, before), val);
12404 else if (code == AND)
12405 x = gen_rtx_UNSPEC (mode, gen_rtvec (2, before, val), UNSPEC_AND);
12406 else
12407 x = gen_rtx_fmt_ee (code, mode, before, val);
12408
12409 if (after != NULL_RTX)
12410 emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
12411 emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
12412
12413 emit_store_conditional (mode, cond, mem, scratch);
12414
12415 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12416 emit_unlikely_jump (x, label);
12417
12418 emit_insn (gen_isync ());
12419 }
12420
12421
12422
12423
12424
12425 void
12426 rs6000_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
12427 rtx scratch)
12428 {
12429 enum machine_mode mode = GET_MODE (mem);
12430 rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
12431
12432 emit_insn (gen_memory_barrier ());
12433
12434 label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
12435 label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
12436 emit_label (XEXP (label1, 0));
12437
12438 emit_load_locked (mode, retval, mem);
12439
12440 x = gen_rtx_COMPARE (CCmode, retval, oldval);
12441 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
12442
12443 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12444 emit_unlikely_jump (x, label2);
12445
12446 emit_move_insn (scratch, newval);
12447 emit_store_conditional (mode, cond, mem, scratch);
12448
12449 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12450 emit_unlikely_jump (x, label1);
12451
12452 emit_insn (gen_isync ());
12453 emit_label (XEXP (label2, 0));
12454 }
12455
12456
12457
12458
12459 void
12460 rs6000_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
12461 {
12462 enum machine_mode mode = GET_MODE (mem);
12463 rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
12464
12465 emit_insn (gen_memory_barrier ());
12466
12467 label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
12468 emit_label (XEXP (label, 0));
12469
12470 emit_load_locked (mode, retval, mem);
12471 emit_move_insn (scratch, val);
12472 emit_store_conditional (mode, cond, mem, scratch);
12473
12474 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12475 emit_unlikely_jump (x, label);
12476
12477 emit_insn (gen_isync ());
12478 }
12479
12480 void
12481 rs6000_expand_compare_and_swapqhi (rtx dst, rtx mem, rtx oldval, rtx newval)
12482 {
12483 enum machine_mode mode = GET_MODE (mem);
12484 rtx addrSI, align, wdst, shift, mask;
12485 HOST_WIDE_INT shift_mask = mode == QImode ? 0x18 : 0x10;
12486 HOST_WIDE_INT imask = GET_MODE_MASK (mode);
12487
12488
12489 addrSI = force_reg (SImode, gen_lowpart_common (SImode, XEXP (mem, 0)));
12490 shift = gen_reg_rtx (SImode);
12491 emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
12492 GEN_INT (shift_mask)));
12493 emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
12494
12495
12496 oldval = convert_modes (SImode, mode, oldval, 1);
12497 oldval = expand_binop (SImode, and_optab,
12498 oldval, GEN_INT (imask), NULL_RTX,
12499 1, OPTAB_LIB_WIDEN);
12500 emit_insn (gen_ashlsi3 (oldval, oldval, shift));
12501
12502
12503 newval = convert_modes (SImode, mode, newval, 1);
12504 newval = expand_binop (SImode, and_optab,
12505 newval, GEN_INT (imask), NULL_RTX,
12506 1, OPTAB_LIB_WIDEN);
12507 emit_insn (gen_ashlsi3 (newval, newval, shift));
12508
12509
12510 mask = gen_reg_rtx (SImode);
12511 emit_move_insn (mask, GEN_INT (imask));
12512 emit_insn (gen_ashlsi3 (mask, mask, shift));
12513
12514
12515 align = expand_binop (Pmode, and_optab, XEXP (mem, 0), GEN_INT (-4),
12516 NULL_RTX, 1, OPTAB_LIB_WIDEN);
12517 mem = change_address (mem, SImode, align);
12518 set_mem_align (mem, 32);
12519 MEM_VOLATILE_P (mem) = 1;
12520
12521 wdst = gen_reg_rtx (SImode);
12522 emit_insn (gen_sync_compare_and_swapqhi_internal (wdst, mask,
12523 oldval, newval, mem));
12524
12525 emit_move_insn (dst, gen_lowpart (mode, wdst));
12526 }
12527
12528 void
12529 rs6000_split_compare_and_swapqhi (rtx dest, rtx mask,
12530 rtx oldval, rtx newval, rtx mem,
12531 rtx scratch)
12532 {
12533 rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
12534
12535 emit_insn (gen_memory_barrier ());
12536 label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
12537 label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
12538 emit_label (XEXP (label1, 0));
12539
12540 emit_load_locked (SImode, scratch, mem);
12541
12542
12543
12544 emit_insn (gen_rtx_SET (SImode, dest,
12545 gen_rtx_UNSPEC (SImode,
12546 gen_rtvec (2, scratch, mask),
12547 UNSPEC_AND)));
12548
12549 x = gen_rtx_COMPARE (CCmode, dest, oldval);
12550 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
12551
12552 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12553 emit_unlikely_jump (x, label2);
12554
12555
12556 emit_insn (gen_rtx_SET (SImode, scratch,
12557 gen_rtx_AND (SImode,
12558 gen_rtx_NOT (SImode, mask), scratch)));
12559 emit_insn (gen_iorsi3 (scratch, scratch, newval));
12560 emit_store_conditional (SImode, cond, mem, scratch);
12561
12562 x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
12563 emit_unlikely_jump (x, label1);
12564
12565 emit_insn (gen_isync ());
12566 emit_label (XEXP (label2, 0));
12567 }
12568
12569
12570
12571
12572
12573
12574
12575
12576 void
12577 rs6000_split_multireg_move (rtx dst, rtx src)
12578 {
12579
12580 int reg;
12581
12582 enum machine_mode mode;
12583
12584 enum machine_mode reg_mode;
12585 int reg_mode_size;
12586
12587 int nregs;
12588
12589 reg = REG_P (dst) ? REGNO (dst) : REGNO (src);
12590 mode = GET_MODE (dst);
12591 nregs = hard_regno_nregs[reg][mode];
12592 if (FP_REGNO_P (reg))
12593 reg_mode = DFmode;
12594 else if (ALTIVEC_REGNO_P (reg))
12595 reg_mode = V16QImode;
12596 else if (TARGET_E500_DOUBLE && mode == TFmode)
12597 reg_mode = DFmode;
12598 else
12599 reg_mode = word_mode;
12600 reg_mode_size = GET_MODE_SIZE (reg_mode);
12601
12602 gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
12603
12604 if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
12605 {
12606
12607
12608 int i;
12609 for (i = nregs - 1; i >= 0; i--)
12610 emit_insn (gen_rtx_SET (VOIDmode,
12611 simplify_gen_subreg (reg_mode, dst, mode,
12612 i * reg_mode_size),
12613 simplify_gen_subreg (reg_mode, src, mode,
12614 i * reg_mode_size)));
12615 }
12616 else
12617 {
12618 int i;
12619 int j = -1;
12620 bool used_update = false;
12621
12622 if (MEM_P (src) && INT_REGNO_P (reg))
12623 {
12624 rtx breg;
12625
12626 if (GET_CODE (XEXP (src, 0)) == PRE_INC
12627 || GET_CODE (XEXP (src, 0)) == PRE_DEC)
12628 {
12629 rtx delta_rtx;
12630 breg = XEXP (XEXP (src, 0), 0);
12631 delta_rtx = (GET_CODE (XEXP (src, 0)) == PRE_INC
12632 ? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
12633 : GEN_INT (-GET_MODE_SIZE (GET_MODE (src))));
12634 emit_insn (TARGET_32BIT
12635 ? gen_addsi3 (breg, breg, delta_rtx)
12636 : gen_adddi3 (breg, breg, delta_rtx));
12637 src = replace_equiv_address (src, breg);
12638 }
12639 else if (! rs6000_offsettable_memref_p (src))
12640 {
12641 rtx basereg;
12642 basereg = gen_rtx_REG (Pmode, reg);
12643 emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
12644 src = replace_equiv_address (src, basereg);
12645 }
12646
12647 breg = XEXP (src, 0);
12648 if (GET_CODE (breg) == PLUS || GET_CODE (breg) == LO_SUM)
12649 breg = XEXP (breg, 0);
12650
12651
12652
12653 if (REG_P (breg)
12654 && REGNO (breg) >= REGNO (dst)
12655 && REGNO (breg) < REGNO (dst) + nregs)
12656 j = REGNO (breg) - REGNO (dst);
12657 }
12658
12659 if (GET_CODE (dst) == MEM && INT_REGNO_P (reg))
12660 {
12661 rtx breg;
12662
12663 if (GET_CODE (XEXP (dst, 0)) == PRE_INC
12664 || GET_CODE (XEXP (dst, 0)) == PRE_DEC)
12665 {
12666 rtx delta_rtx;
12667 breg = XEXP (XEXP (dst, 0), 0);
12668 delta_rtx = (GET_CODE (XEXP (dst, 0)) == PRE_INC
12669 ? GEN_INT (GET_MODE_SIZE (GET_MODE (dst)))
12670 : GEN_INT (-GET_MODE_SIZE (GET_MODE (dst))));
12671
12672
12673
12674
12675 if (TARGET_UPDATE)
12676 {
12677 rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
12678 emit_insn (TARGET_32BIT
12679 ? (TARGET_POWERPC64
12680 ? gen_movdi_si_update (breg, breg, delta_rtx, nsrc)
12681 : gen_movsi_update (breg, breg, delta_rtx, nsrc))
12682 : gen_movdi_di_update (breg, breg, delta_rtx, nsrc));
12683 used_update = true;
12684 }
12685 else
12686 emit_insn (TARGET_32BIT
12687 ? gen_addsi3 (breg, breg, delta_rtx)
12688 : gen_adddi3 (breg, breg, delta_rtx));
12689 dst = replace_equiv_address (dst, breg);
12690 }
12691 else
12692 gcc_assert (rs6000_offsettable_memref_p (dst));
12693 }
12694
12695 for (i = 0; i < nregs; i++)
12696 {
12697
12698 ++j;
12699 if (j == nregs)
12700 j = 0;
12701
12702
12703
12704 if (j == 0 && used_update)
12705 continue;
12706
12707 emit_insn (gen_rtx_SET (VOIDmode,
12708 simplify_gen_subreg (reg_mode, dst, mode,
12709 j * reg_mode_size),
12710 simplify_gen_subreg (reg_mode, src, mode,
12711 j * reg_mode_size)));
12712 }
12713 }
12714 }
12715
12716
12717
12718
12719
12720
12721
12722
12723 int
12724 first_reg_to_save (void)
12725 {
12726 int first_reg;
12727
12728
12729 for (first_reg = 13; first_reg <= 31; first_reg++)
12730 if (regs_ever_live[first_reg]
12731 && (! call_used_regs[first_reg]
12732 || (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
12733 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
12734 || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
12735 || (TARGET_TOC && TARGET_MINIMAL_TOC)))))
12736 break;
12737
12738 #if TARGET_MACHO
12739 if (flag_pic
12740 && current_function_uses_pic_offset_table
12741 && first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM)
12742 return RS6000_PIC_OFFSET_TABLE_REGNUM;
12743 #endif
12744
12745 return first_reg;
12746 }
12747
12748
12749
12750 int
12751 first_fp_reg_to_save (void)
12752 {
12753 int first_reg;
12754
12755
12756 for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
12757 if (regs_ever_live[first_reg])
12758 break;
12759
12760 return first_reg;
12761 }
12762
12763
12764
12765 static int
12766 first_altivec_reg_to_save (void)
12767 {
12768 int i;
12769
12770
12771 if (! TARGET_ALTIVEC_ABI)
12772 return LAST_ALTIVEC_REGNO + 1;
12773
12774
12775
12776
12777 if (DEFAULT_ABI == ABI_DARWIN && current_function_calls_eh_return
12778 && ! TARGET_ALTIVEC)
12779 return FIRST_ALTIVEC_REGNO + 20;
12780
12781
12782 for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
12783 if (regs_ever_live[i])
12784 break;
12785
12786 return i;
12787 }
12788
12789
12790
12791
12792
12793 static unsigned int
12794 compute_vrsave_mask (void)
12795 {
12796 unsigned int i, mask = 0;
12797
12798
12799
12800
12801 if (DEFAULT_ABI == ABI_DARWIN && current_function_calls_eh_return
12802 && ! TARGET_ALTIVEC)
12803 mask |= 0xFFF;
12804
12805
12806 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
12807 if (regs_ever_live[i])
12808 mask |= ALTIVEC_REG_BIT (i);
12809
12810 if (mask == 0)
12811 return mask;
12812
12813
12814
12815
12816
12817
12818 for (i = cfun->args_info.vregno - 1; i >= ALTIVEC_ARG_MIN_REG; --i)
12819 mask &= ~ALTIVEC_REG_BIT (i);
12820
12821
12822 {
12823 bool yes = false;
12824 diddle_return_value (is_altivec_return_reg, &yes);
12825 if (yes)
12826 mask &= ~ALTIVEC_REG_BIT (ALTIVEC_ARG_RETURN);
12827 }
12828
12829 return mask;
12830 }
12831
12832
12833
12834
12835
12836 static void
12837 compute_save_world_info (rs6000_stack_t *info_ptr)
12838 {
12839 info_ptr->world_save_p = 1;
12840 info_ptr->world_save_p
12841 = (WORLD_SAVE_P (info_ptr)
12842 && DEFAULT_ABI == ABI_DARWIN
12843 && ! (current_function_calls_setjmp && flag_exceptions)
12844 && info_ptr->first_fp_reg_save == FIRST_SAVED_FP_REGNO
12845 && info_ptr->first_gp_reg_save == FIRST_SAVED_GP_REGNO
12846 && info_ptr->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
12847 && info_ptr->cr_save_p);
12848
12849
12850
12851 if (WORLD_SAVE_P (info_ptr))
12852 {
12853 rtx insn;
12854 for ( insn = get_last_insn_anywhere (); insn; insn = PREV_INSN (insn))
12855 if ( GET_CODE (insn) == CALL_INSN
12856 && SIBLING_CALL_P (insn))
12857 {
12858 info_ptr->world_save_p = 0;
12859 break;
12860 }
12861 }
12862
12863 if (WORLD_SAVE_P (info_ptr))
12864 {
12865
12866
12867
12868 info_ptr->vrsave_size = 4;
12869
12870
12871 if (info_ptr->vrsave_mask == 0)
12872 info_ptr->vrsave_mask = compute_vrsave_mask ();
12873
12874
12875
12876
12877 gcc_assert (info_ptr->first_fp_reg_save >= FIRST_SAVED_FP_REGNO
12878 && (info_ptr->first_altivec_reg_save
12879 >= FIRST_SAVED_ALTIVEC_REGNO));
12880 }
12881 return;
12882 }
12883
12884
12885 static void
12886 is_altivec_return_reg (rtx reg, void *xyes)
12887 {
12888 bool *yes = (bool *) xyes;
12889 if (REGNO (reg) == ALTIVEC_ARG_RETURN)
12890 *yes = true;
12891 }
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
12955
12956
12957
12958
12959
12960
12961
12962
12963
12964
12965
12966
12967
12968
12969
12970
12971
12972
12973
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987 #ifndef ABI_STACK_BOUNDARY
12988 #define ABI_STACK_BOUNDARY STACK_BOUNDARY
12989 #endif
12990
12991 static rs6000_stack_t *
12992 rs6000_stack_info (void)
12993 {
12994 static rs6000_stack_t info;
12995 rs6000_stack_t *info_ptr = &info;
12996 int reg_size = TARGET_32BIT ? 4 : 8;
12997 int ehrd_size;
12998 int save_align;
12999 HOST_WIDE_INT non_fixed_size;
13000
13001 memset (&info, 0, sizeof (info));
13002
13003 if (TARGET_SPE)
13004 {
13005
13006 if (cfun->machine->insn_chain_scanned_p == 0)
13007 cfun->machine->insn_chain_scanned_p
13008 = spe_func_has_64bit_regs_p () + 1;
13009 info_ptr->spe_64bit_regs_used = cfun->machine->insn_chain_scanned_p - 1;
13010 }
13011
13012
13013 info_ptr->abi = DEFAULT_ABI;
13014
13015
13016 info_ptr->first_gp_reg_save = first_reg_to_save ();
13017
13018
13019 if (((TARGET_TOC && TARGET_MINIMAL_TOC)
13020 || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
13021 || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
13022 && info_ptr->first_gp_reg_save > RS6000_PIC_OFFSET_TABLE_REGNUM)
13023 info_ptr->gp_size = reg_size * (32 - RS6000_PIC_OFFSET_TABLE_REGNUM);
13024 else
13025 info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save);
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
13040 info_ptr->gp_size = 0;
13041
13042 info_ptr->first_fp_reg_save = first_fp_reg_to_save ();
13043 info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);
13044
13045 info_ptr->first_altivec_reg_save = first_altivec_reg_to_save ();
13046 info_ptr->altivec_size = 16 * (LAST_ALTIVEC_REGNO + 1
13047 - info_ptr->first_altivec_reg_save);
13048
13049
13050 info_ptr->calls_p = (! current_function_is_leaf
13051 || cfun->machine->ra_needs_full_frame);
13052
13053
13054 if ((DEFAULT_ABI == ABI_AIX
13055 && current_function_profile
13056 && !TARGET_PROFILE_KERNEL)
13057 #ifdef TARGET_RELOCATABLE
13058 || (TARGET_RELOCATABLE && (get_pool_size () != 0))
13059 #endif
13060 || (info_ptr->first_fp_reg_save != 64
13061 && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
13062 || info_ptr->first_altivec_reg_save <= LAST_ALTIVEC_REGNO
13063 || (DEFAULT_ABI == ABI_V4 && current_function_calls_alloca)
13064 || info_ptr->calls_p
13065 || rs6000_ra_ever_killed ())
13066 {
13067 info_ptr->lr_save_p = 1;
13068 regs_ever_live[LINK_REGISTER_REGNUM] = 1;
13069 }
13070
13071
13072 if (regs_ever_live[CR2_REGNO]
13073 || regs_ever_live[CR3_REGNO]
13074 || regs_ever_live[CR4_REGNO])
13075 {
13076 info_ptr->cr_save_p = 1;
13077 if (DEFAULT_ABI == ABI_V4)
13078 info_ptr->cr_size = reg_size;
13079 }
13080
13081
13082
13083
13084 if (current_function_calls_eh_return)
13085 {
13086 unsigned int i;
13087 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
13088 continue;
13089
13090
13091 ehrd_size = i * (TARGET_SPE_ABI
13092 && info_ptr->spe_64bit_regs_used != 0
13093 ? UNITS_PER_SPE_WORD : UNITS_PER_WORD);
13094 }
13095 else
13096 ehrd_size = 0;
13097
13098
13099 info_ptr->reg_size = reg_size;
13100 info_ptr->fixed_size = RS6000_SAVE_AREA;
13101 info_ptr->vars_size = RS6000_ALIGN (get_frame_size (), 8);
13102 info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
13103 TARGET_ALTIVEC ? 16 : 8);
13104 if (FRAME_GROWS_DOWNWARD)
13105 info_ptr->vars_size
13106 += RS6000_ALIGN (info_ptr->fixed_size + info_ptr->vars_size
13107 + info_ptr->parm_size,
13108 ABI_STACK_BOUNDARY / BITS_PER_UNIT)
13109 - (info_ptr->fixed_size + info_ptr->vars_size
13110 + info_ptr->parm_size);
13111
13112 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
13113 info_ptr->spe_gp_size = 8 * (32 - info_ptr->first_gp_reg_save);
13114 else
13115 info_ptr->spe_gp_size = 0;
13116
13117 if (TARGET_ALTIVEC_ABI)
13118 info_ptr->vrsave_mask = compute_vrsave_mask ();
13119 else
13120 info_ptr->vrsave_mask = 0;
13121
13122 if (TARGET_ALTIVEC_VRSAVE && info_ptr->vrsave_mask)
13123 info_ptr->vrsave_size = 4;
13124 else
13125 info_ptr->vrsave_size = 0;
13126
13127 compute_save_world_info (info_ptr);
13128
13129
13130 switch (DEFAULT_ABI)
13131 {
13132 case ABI_NONE:
13133 default:
13134 gcc_unreachable ();
13135
13136 case ABI_AIX:
13137 case ABI_DARWIN:
13138 info_ptr->fp_save_offset = - info_ptr->fp_size;
13139 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
13140
13141 if (TARGET_ALTIVEC_ABI)
13142 {
13143 info_ptr->vrsave_save_offset
13144 = info_ptr->gp_save_offset - info_ptr->vrsave_size;
13145
13146
13147
13148 if (info_ptr->altivec_size != 0)
13149 info_ptr->altivec_padding_size
13150 = info_ptr->vrsave_save_offset & 0xF;
13151 else
13152 info_ptr->altivec_padding_size = 0;
13153
13154 info_ptr->altivec_save_offset
13155 = info_ptr->vrsave_save_offset
13156 - info_ptr->altivec_padding_size
13157 - info_ptr->altivec_size;
13158 gcc_assert (info_ptr->altivec_size == 0
13159 || info_ptr->altivec_save_offset % 16 == 0);
13160
13161
13162 info_ptr->ehrd_offset = info_ptr->altivec_save_offset - ehrd_size;
13163 }
13164 else
13165 info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
13166 info_ptr->cr_save_offset = reg_size;
13167 info_ptr->lr_save_offset = 2*reg_size;
13168 break;
13169
13170 case ABI_V4:
13171 info_ptr->fp_save_offset = - info_ptr->fp_size;
13172 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
13173 info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
13174
13175 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
13176 {
13177
13178
13179 if (info_ptr->spe_gp_size != 0)
13180 info_ptr->spe_padding_size
13181 = 8 - (-info_ptr->cr_save_offset % 8);
13182 else
13183 info_ptr->spe_padding_size = 0;
13184
13185 info_ptr->spe_gp_save_offset
13186 = info_ptr->cr_save_offset
13187 - info_ptr->spe_padding_size
13188 - info_ptr->spe_gp_size;
13189
13190
13191 info_ptr->ehrd_offset = info_ptr->spe_gp_save_offset;
13192 }
13193 else if (TARGET_ALTIVEC_ABI)
13194 {
13195 info_ptr->vrsave_save_offset
13196 = info_ptr->cr_save_offset - info_ptr->vrsave_size;
13197
13198
13199 if (info_ptr->altivec_size != 0)
13200 info_ptr->altivec_padding_size
13201 = 16 - (-info_ptr->vrsave_save_offset % 16);
13202 else
13203 info_ptr->altivec_padding_size = 0;
13204
13205 info_ptr->altivec_save_offset
13206 = info_ptr->vrsave_save_offset
13207 - info_ptr->altivec_padding_size
13208 - info_ptr->altivec_size;
13209
13210
13211 info_ptr->ehrd_offset = info_ptr->altivec_save_offset;
13212 }
13213 else
13214 info_ptr->ehrd_offset = info_ptr->cr_save_offset;
13215 info_ptr->ehrd_offset -= ehrd_size;
13216 info_ptr->lr_save_offset = reg_size;
13217 break;
13218 }
13219
13220 save_align = (TARGET_ALTIVEC_ABI || DEFAULT_ABI == ABI_DARWIN) ? 16 : 8;
13221 info_ptr->save_size = RS6000_ALIGN (info_ptr->fp_size
13222 + info_ptr->gp_size
13223 + info_ptr->altivec_size
13224 + info_ptr->altivec_padding_size
13225 + info_ptr->spe_gp_size
13226 + info_ptr->spe_padding_size
13227 + ehrd_size
13228 + info_ptr->cr_size
13229 + info_ptr->vrsave_size,
13230 save_align);
13231
13232 non_fixed_size = (info_ptr->vars_size
13233 + info_ptr->parm_size
13234 + info_ptr->save_size);
13235
13236 info_ptr->total_size = RS6000_ALIGN (non_fixed_size + info_ptr->fixed_size,
13237 ABI_STACK_BOUNDARY / BITS_PER_UNIT);
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251 if (info_ptr->calls_p)
13252 info_ptr->push_p = 1;
13253
13254 else if (DEFAULT_ABI == ABI_V4)
13255 info_ptr->push_p = non_fixed_size != 0;
13256
13257 else if (frame_pointer_needed)
13258 info_ptr->push_p = 1;
13259
13260 else if (TARGET_XCOFF && write_symbols != NO_DEBUG)
13261 info_ptr->push_p = 1;
13262
13263 else
13264 info_ptr->push_p = non_fixed_size > (TARGET_32BIT ? 220 : 288);
13265
13266
13267 if (info_ptr->fp_size == 0)
13268 info_ptr->fp_save_offset = 0;
13269
13270 if (info_ptr->gp_size == 0)
13271 info_ptr->gp_save_offset = 0;
13272
13273 if (! TARGET_ALTIVEC_ABI || info_ptr->altivec_size == 0)
13274 info_ptr->altivec_save_offset = 0;
13275
13276 if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
13277 info_ptr->vrsave_save_offset = 0;
13278
13279 if (! TARGET_SPE_ABI
13280 || info_ptr->spe_64bit_regs_used == 0
13281 || info_ptr->spe_gp_size == 0)
13282 info_ptr->spe_gp_save_offset = 0;
13283
13284 if (! info_ptr->lr_save_p)
13285 info_ptr->lr_save_offset = 0;
13286
13287 if (! info_ptr->cr_save_p)
13288 info_ptr->cr_save_offset = 0;
13289
13290 return info_ptr;
13291 }
13292
13293
13294
13295
13296 static bool
13297 spe_func_has_64bit_regs_p (void)
13298 {
13299 rtx insns, insn;
13300
13301
13302
13303 if (current_function_calls_eh_return
13304 || current_function_calls_setjmp
13305 || current_function_has_nonlocal_goto)
13306 return true;
13307
13308 insns = get_insns ();
13309
13310 for (insn = NEXT_INSN (insns); insn != NULL_RTX; insn = NEXT_INSN (insn))
13311 {
13312 if (INSN_P (insn))
13313 {
13314 rtx i;
13315
13316
13317
13318
13319
13320
13321
13322
13323 i = PATTERN (insn);
13324 if (GET_CODE (i) == SET)
13325 {
13326 enum machine_mode mode = GET_MODE (SET_SRC (i));
13327
13328 if (SPE_VECTOR_MODE (mode))
13329 return true;
13330 if (TARGET_E500_DOUBLE && mode == DFmode)
13331 return true;
13332 }
13333 }
13334 }
13335
13336 return false;
13337 }
13338
13339 static void
13340 debug_stack_info (rs6000_stack_t *info)
13341 {
13342 const char *abi_string;
13343
13344 if (! info)
13345 info = rs6000_stack_info ();
13346
13347 fprintf (stderr, "\nStack information for function %s:\n",
13348 ((current_function_decl && DECL_NAME (current_function_decl))
13349 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
13350 : "<unknown>"));
13351
13352 switch (info->abi)
13353 {
13354 default: abi_string = "Unknown"; break;
13355 case ABI_NONE: abi_string = "NONE"; break;
13356 case ABI_AIX: abi_string = "AIX"; break;
13357 case ABI_DARWIN: abi_string = "Darwin"; break;
13358 case ABI_V4: abi_string = "V.4"; break;
13359 }
13360
13361 fprintf (stderr, "\tABI = %5s\n", abi_string);
13362
13363 if (TARGET_ALTIVEC_ABI)
13364 fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
13365
13366 if (TARGET_SPE_ABI)
13367 fprintf (stderr, "\tSPE ABI extensions enabled.\n");
13368
13369 if (info->first_gp_reg_save != 32)
13370 fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
13371
13372 if (info->first_fp_reg_save != 64)
13373 fprintf (stderr, "\tfirst_fp_reg_save = %5d\n", info->first_fp_reg_save);
13374
13375 if (info->first_altivec_reg_save <= LAST_ALTIVEC_REGNO)
13376 fprintf (stderr, "\tfirst_altivec_reg_save = %5d\n",
13377 info->first_altivec_reg_save);
13378
13379 if (info->lr_save_p)
13380 fprintf (stderr, "\tlr_save_p = %5d\n", info->lr_save_p);
13381
13382 if (info->cr_save_p)
13383 fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
13384
13385 if (info->vrsave_mask)
13386 fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
13387
13388 if (info->push_p)
13389 fprintf (stderr, "\tpush_p = %5d\n", info->push_p);
13390
13391 if (info->calls_p)
13392 fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p);
13393
13394 if (info->gp_save_offset)
13395 fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
13396
13397 if (info->fp_save_offset)
13398 fprintf (stderr, "\tfp_save_offset = %5d\n", info->fp_save_offset);
13399
13400 if (info->altivec_save_offset)
13401 fprintf (stderr, "\taltivec_save_offset = %5d\n",
13402 info->altivec_save_offset);
13403
13404 if (info->spe_gp_save_offset)
13405 fprintf (stderr, "\tspe_gp_save_offset = %5d\n",
13406 info->spe_gp_save_offset);
13407
13408 if (info->vrsave_save_offset)
13409 fprintf (stderr, "\tvrsave_save_offset = %5d\n",
13410 info->vrsave_save_offset);
13411
13412 if (info->lr_save_offset)
13413 fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
13414
13415 if (info->cr_save_offset)
13416 fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
13417
13418 if (info->varargs_save_offset)
13419 fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
13420
13421 if (info->total_size)
13422 fprintf (stderr, "\ttotal_size = "HOST_WIDE_INT_PRINT_DEC"\n",
13423 info->total_size);
13424
13425 if (info->vars_size)
13426 fprintf (stderr, "\tvars_size = "HOST_WIDE_INT_PRINT_DEC"\n",
13427 info->vars_size);
13428
13429 if (info->parm_size)
13430 fprintf (stderr, "\tparm_size = %5d\n", info->parm_size);
13431
13432 if (info->fixed_size)
13433 fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
13434
13435 if (info->gp_size)
13436 fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
13437
13438 if (info->spe_gp_size)
13439 fprintf (stderr, "\tspe_gp_size = %5d\n", info->spe_gp_size);
13440
13441 if (info->fp_size)
13442 fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
13443
13444 if (info->altivec_size)
13445 fprintf (stderr, "\taltivec_size = %5d\n", info->altivec_size);
13446
13447 if (info->vrsave_size)
13448 fprintf (stderr, "\tvrsave_size = %5d\n", info->vrsave_size);
13449
13450 if (info->altivec_padding_size)
13451 fprintf (stderr, "\taltivec_padding_size= %5d\n",
13452 info->altivec_padding_size);
13453
13454 if (info->spe_padding_size)
13455 fprintf (stderr, "\tspe_padding_size = %5d\n",
13456 info->spe_padding_size);
13457
13458 if (info->cr_size)
13459 fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
13460
13461 if (info->save_size)
13462 fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
13463
13464 if (info->reg_size != 4)
13465 fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
13466
13467 fprintf (stderr, "\n");
13468 }
13469
13470 rtx
13471 rs6000_return_addr (int count, rtx frame)
13472 {
13473
13474
13475
13476 if (count != 0 || (DEFAULT_ABI != ABI_AIX && flag_pic))
13477 {
13478 cfun->machine->ra_needs_full_frame = 1;
13479
13480 return
13481 gen_rtx_MEM
13482 (Pmode,
13483 memory_address
13484 (Pmode,
13485 plus_constant (copy_to_reg
13486 (gen_rtx_MEM (Pmode,
13487 memory_address (Pmode, frame))),
13488 RETURN_ADDRESS_OFFSET)));
13489 }
13490
13491 cfun->machine->ra_need_lr = 1;
13492 return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
13493 }
13494
13495
13496
13497
13498
13499
13500
13501
13502 static bool
13503 rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
13504 {
13505 tree type;
13506 if (decl)
13507 {
13508 if (TARGET_ALTIVEC_VRSAVE)
13509 {
13510 for (type = TYPE_ARG_TYPES (TREE_TYPE (decl));
13511 type; type = TREE_CHAIN (type))
13512 {
13513 if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE)
13514 return false;
13515 }
13516 }
13517 if (DEFAULT_ABI == ABI_DARWIN
13518 || (*targetm.binds_local_p) (decl))
13519 {
13520 tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl));
13521
13522 if (!lookup_attribute ("longcall", attr_list)
13523 || lookup_attribute ("shortcall", attr_list))
13524 return true;
13525 }
13526 }
13527 return false;
13528 }
13529
13530
13531
13532
13533
13534 static const char *
13535 rs6000_invalid_within_doloop (rtx insn)
13536 {
13537 if (CALL_P (insn))
13538 return "Function call in the loop.";
13539
13540 if (JUMP_P (insn)
13541 && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
13542 || GET_CODE (PATTERN (insn)) == ADDR_VEC))
13543 return "Computed branch in the loop.";
13544
13545 return NULL;
13546 }
13547
13548 static int
13549 rs6000_ra_ever_killed (void)
13550 {
13551 rtx top;
13552 rtx reg;
13553 rtx insn;
13554
13555 if (current_function_is_thunk)
13556 return 0;
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570
13571
13572
13573
13574 push_topmost_sequence ();
13575 top = get_insns ();
13576 pop_topmost_sequence ();
13577 reg = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
13578
13579 for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
13580 {
13581 if (INSN_P (insn))
13582 {
13583 if (CALL_P (insn))
13584 {
13585 if (!SIBLING_CALL_P (insn))
13586 return 1;
13587 }
13588 else if (find_regno_note (insn, REG_INC, LINK_REGISTER_REGNUM))
13589 return 1;
13590 else if (set_of (reg, insn) != NULL_RTX
13591 && !prologue_epilogue_contains (insn))
13592 return 1;
13593 }
13594 }
13595 return 0;
13596 }
13597
13598
13599 static void
13600 rs6000_maybe_dead (rtx insn)
13601 {
13602 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
13603 const0_rtx,
13604 REG_NOTES (insn));
13605 }
13606
13607
13608
13609
13610
13611 void
13612 rs6000_emit_load_toc_table (int fromprolog)
13613 {
13614 rtx dest, insn;
13615 dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
13616
13617 if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic)
13618 {
13619 char buf[30];
13620 rtx lab, tmp1, tmp2, got, tempLR;
13621
13622 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
13623 lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13624 if (flag_pic == 2)
13625 got = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
13626 else
13627 got = rs6000_got_sym ();
13628 tmp1 = tmp2 = dest;
13629 if (!fromprolog)
13630 {
13631 tmp1 = gen_reg_rtx (Pmode);
13632 tmp2 = gen_reg_rtx (Pmode);
13633 }
13634 tempLR = (fromprolog
13635 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
13636 : gen_reg_rtx (Pmode));
13637 insn = emit_insn (gen_load_toc_v4_PIC_1 (tempLR, lab));
13638 if (fromprolog)
13639 rs6000_maybe_dead (insn);
13640 insn = emit_move_insn (tmp1, tempLR);
13641 if (fromprolog)
13642 rs6000_maybe_dead (insn);
13643 insn = emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
13644 if (fromprolog)
13645 rs6000_maybe_dead (insn);
13646 insn = emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
13647 if (fromprolog)
13648 rs6000_maybe_dead (insn);
13649 }
13650 else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
13651 {
13652 rtx tempLR = (fromprolog
13653 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
13654 : gen_reg_rtx (Pmode));
13655
13656 insn = emit_insn (gen_load_toc_v4_pic_si (tempLR));
13657 if (fromprolog)
13658 rs6000_maybe_dead (insn);
13659 insn = emit_move_insn (dest, tempLR);
13660 if (fromprolog)
13661 rs6000_maybe_dead (insn);
13662 }
13663 else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
13664 {
13665 char buf[30];
13666 rtx tempLR = (fromprolog
13667 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
13668 : gen_reg_rtx (Pmode));
13669 rtx temp0 = (fromprolog
13670 ? gen_rtx_REG (Pmode, 0)
13671 : gen_reg_rtx (Pmode));
13672
13673 if (fromprolog)
13674 {
13675 rtx symF, symL;
13676
13677 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
13678 symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13679
13680 ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
13681 symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13682
13683 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1 (tempLR,
13684 symF)));
13685 rs6000_maybe_dead (emit_move_insn (dest, tempLR));
13686 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest,
13687 symL,
13688 symF)));
13689 }
13690 else
13691 {
13692 rtx tocsym;
13693
13694 tocsym = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
13695 emit_insn (gen_load_toc_v4_PIC_1b (tempLR, tocsym));
13696 emit_move_insn (dest, tempLR);
13697 emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
13698 }
13699 insn = emit_insn (gen_addsi3 (dest, temp0, dest));
13700 if (fromprolog)
13701 rs6000_maybe_dead (insn);
13702 }
13703 else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
13704 {
13705
13706 char buf[30];
13707 rtx realsym;
13708 ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
13709 realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13710
13711 insn = emit_insn (gen_elf_high (dest, realsym));
13712 if (fromprolog)
13713 rs6000_maybe_dead (insn);
13714 insn = emit_insn (gen_elf_low (dest, dest, realsym));
13715 if (fromprolog)
13716 rs6000_maybe_dead (insn);
13717 }
13718 else
13719 {
13720 gcc_assert (DEFAULT_ABI == ABI_AIX);
13721
13722 if (TARGET_32BIT)
13723 insn = emit_insn (gen_load_toc_aix_si (dest));
13724 else
13725 insn = emit_insn (gen_load_toc_aix_di (dest));
13726 if (fromprolog)
13727 rs6000_maybe_dead (insn);
13728 }
13729 }
13730
13731
13732
13733
13734 void
13735 rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
13736 {
13737 rs6000_stack_t *info = rs6000_stack_info ();
13738 rtx operands[2];
13739
13740 operands[0] = source;
13741 operands[1] = scratch;
13742
13743 if (info->lr_save_p)
13744 {
13745 rtx frame_rtx = stack_pointer_rtx;
13746 HOST_WIDE_INT sp_offset = 0;
13747 rtx tmp;
13748
13749 if (frame_pointer_needed
13750 || current_function_calls_alloca
13751 || info->total_size > 32767)
13752 {
13753 tmp = gen_frame_mem (Pmode, frame_rtx);
13754 emit_move_insn (operands[1], tmp);
13755 frame_rtx = operands[1];
13756 }
13757 else if (info->push_p)
13758 sp_offset = info->total_size;
13759
13760 tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
13761 tmp = gen_frame_mem (Pmode, tmp);
13762 emit_move_insn (tmp, operands[0]);
13763 }
13764 else
13765 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
13766 }
13767
13768 static GTY(()) int set = -1;
13769
13770 int
13771 get_TOC_alias_set (void)
13772 {
13773 if (set == -1)
13774 set = new_alias_set ();
13775 return set;
13776 }
13777
13778
13779
13780
13781 #if TARGET_ELF
13782 static int
13783 uses_TOC (void)
13784 {
13785 rtx insn;
13786
13787 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
13788 if (INSN_P (insn))
13789 {
13790 rtx pat = PATTERN (insn);
13791 int i;
13792
13793 if (GET_CODE (pat) == PARALLEL)
13794 for (i = 0; i < XVECLEN (pat, 0); i++)
13795 {
13796 rtx sub = XVECEXP (pat, 0, i);
13797 if (GET_CODE (sub) == USE)
13798 {
13799 sub = XEXP (sub, 0);
13800 if (GET_CODE (sub) == UNSPEC
13801 && XINT (sub, 1) == UNSPEC_TOC)
13802 return 1;
13803 }
13804 }
13805 }
13806 return 0;
13807 }
13808 #endif
13809
13810 rtx
13811 create_TOC_reference (rtx symbol)
13812 {
13813 if (no_new_pseudos)
13814 regs_ever_live[TOC_REGISTER] = 1;
13815 return gen_rtx_PLUS (Pmode,
13816 gen_rtx_REG (Pmode, TOC_REGISTER),
13817 gen_rtx_CONST (Pmode,
13818 gen_rtx_MINUS (Pmode, symbol,
13819 gen_rtx_SYMBOL_REF (Pmode, toc_label_name))));
13820 }
13821
13822
13823
13824
13825
13826 void
13827 rs6000_aix_emit_builtin_unwind_init (void)
13828 {
13829 rtx mem;
13830 rtx stack_top = gen_reg_rtx (Pmode);
13831 rtx opcode_addr = gen_reg_rtx (Pmode);
13832 rtx opcode = gen_reg_rtx (SImode);
13833 rtx tocompare = gen_reg_rtx (SImode);
13834 rtx no_toc_save_needed = gen_label_rtx ();
13835
13836 mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
13837 emit_move_insn (stack_top, mem);
13838
13839 mem = gen_frame_mem (Pmode,
13840 gen_rtx_PLUS (Pmode, stack_top,
13841 GEN_INT (2 * GET_MODE_SIZE (Pmode))));
13842 emit_move_insn (opcode_addr, mem);
13843 emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
13844 emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
13845 : 0xE8410028, SImode));
13846
13847 do_compare_rtx_and_jump (opcode, tocompare, EQ, 1,
13848 SImode, NULL_RTX, NULL_RTX,
13849 no_toc_save_needed);
13850
13851 mem = gen_frame_mem (Pmode,
13852 gen_rtx_PLUS (Pmode, stack_top,
13853 GEN_INT (5 * GET_MODE_SIZE (Pmode))));
13854 emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
13855 emit_label (no_toc_save_needed);
13856 }
13857
13858
13859
13860
13861 static void
13862 rs6000_emit_stack_tie (void)
13863 {
13864 rtx mem = gen_frame_mem (BLKmode,
13865 gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
13866
13867 emit_insn (gen_stack_tie (mem));
13868 }
13869
13870
13871
13872
13873
13874 static void
13875 rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
13876 {
13877 rtx insn;
13878 rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
13879 rtx tmp_reg = gen_rtx_REG (Pmode, 0);
13880 rtx todec = gen_int_mode (-size, Pmode);
13881
13882 if (INTVAL (todec) != -size)
13883 {
13884 warning (0, "stack frame too large");
13885 emit_insn (gen_trap ());
13886 return;
13887 }
13888
13889 if (current_function_limit_stack)
13890 {
13891 if (REG_P (stack_limit_rtx)
13892 && REGNO (stack_limit_rtx) > 1
13893 && REGNO (stack_limit_rtx) <= 31)
13894 {
13895 emit_insn (TARGET_32BIT
13896 ? gen_addsi3 (tmp_reg,
13897 stack_limit_rtx,
13898 GEN_INT (size))
13899 : gen_adddi3 (tmp_reg,
13900 stack_limit_rtx,
13901 GEN_INT (size)));
13902
13903 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
13904 const0_rtx));
13905 }
13906 else if (GET_CODE (stack_limit_rtx) == SYMBOL_REF
13907 && TARGET_32BIT
13908 && DEFAULT_ABI == ABI_V4)
13909 {
13910 rtx toload = gen_rtx_CONST (VOIDmode,
13911 gen_rtx_PLUS (Pmode,
13912 stack_limit_rtx,
13913 GEN_INT (size)));
13914
13915 emit_insn (gen_elf_high (tmp_reg, toload));
13916 emit_insn (gen_elf_low (tmp_reg, tmp_reg, toload));
13917 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
13918 const0_rtx));
13919 }
13920 else
13921 warning (0, "stack limit expression is not supported");
13922 }
13923
13924 if (copy_r12 || ! TARGET_UPDATE)
13925 emit_move_insn (gen_rtx_REG (Pmode, 12), stack_reg);
13926
13927 if (TARGET_UPDATE)
13928 {
13929 if (size > 32767)
13930 {
13931
13932 if (get_last_insn () == NULL_RTX)
13933 emit_note (NOTE_INSN_DELETED);
13934 insn = emit_move_insn (tmp_reg, todec);
13935 try_split (PATTERN (insn), insn, 0);
13936 todec = tmp_reg;
13937 }
13938
13939 insn = emit_insn (TARGET_32BIT
13940 ? gen_movsi_update (stack_reg, stack_reg,
13941 todec, stack_reg)
13942 : gen_movdi_di_update (stack_reg, stack_reg,
13943 todec, stack_reg));
13944 }
13945 else
13946 {
13947 insn = emit_insn (TARGET_32BIT
13948 ? gen_addsi3 (stack_reg, stack_reg, todec)
13949 : gen_adddi3 (stack_reg, stack_reg, todec));
13950 emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
13951 gen_rtx_REG (Pmode, 12));
13952 }
13953
13954 RTX_FRAME_RELATED_P (insn) = 1;
13955 REG_NOTES (insn) =
13956 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
13957 gen_rtx_SET (VOIDmode, stack_reg,
13958 gen_rtx_PLUS (Pmode, stack_reg,
13959 GEN_INT (-size))),
13960 REG_NOTES (insn));
13961 }
13962
13963
13964
13965
13966
13967
13968
13969 static void
13970 rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
13971 rtx reg2, rtx rreg)
13972 {
13973 rtx real, temp;
13974
13975
13976
13977 if (reg == reg2)
13978 reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
13979
13980 if (reg == rreg)
13981 reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
13982
13983 real = copy_rtx (PATTERN (insn));
13984
13985 if (reg2 != NULL_RTX)
13986 real = replace_rtx (real, reg2, rreg);
13987
13988 real = replace_rtx (real, reg,
13989 gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
13990 STACK_POINTER_REGNUM),
13991 GEN_INT (val)));
13992
13993
13994
13995
13996
13997 if (GET_CODE (real) == SET)
13998 {
13999 rtx set = real;
14000
14001 temp = simplify_rtx (SET_SRC (set));
14002 if (temp)
14003 SET_SRC (set) = temp;
14004 temp = simplify_rtx (SET_DEST (set));
14005 if (temp)
14006 SET_DEST (set) = temp;
14007 if (GET_CODE (SET_DEST (set)) == MEM)
14008 {
14009 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
14010 if (temp)
14011 XEXP (SET_DEST (set), 0) = temp;
14012 }
14013 }
14014 else
14015 {
14016 int i;
14017
14018 gcc_assert (GET_CODE (real) == PARALLEL);
14019 for (i = 0; i < XVECLEN (real, 0); i++)
14020 if (GET_CODE (XVECEXP (real, 0, i)) == SET)
14021 {
14022 rtx set = XVECEXP (real, 0, i);
14023
14024 temp = simplify_rtx (SET_SRC (set));
14025 if (temp)
14026 SET_SRC (set) = temp;
14027 temp = simplify_rtx (SET_DEST (set));
14028 if (temp)
14029 SET_DEST (set) = temp;
14030 if (GET_CODE (SET_DEST (set)) == MEM)
14031 {
14032 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
14033 if (temp)
14034 XEXP (SET_DEST (set), 0) = temp;
14035 }
14036 RTX_FRAME_RELATED_P (set) = 1;
14037 }
14038 }
14039
14040 if (TARGET_SPE)
14041 real = spe_synthesize_frame_save (real);
14042
14043 RTX_FRAME_RELATED_P (insn) = 1;
14044 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
14045 real,
14046 REG_NOTES (insn));
14047 }
14048
14049
14050
14051
14052 static rtx
14053 spe_synthesize_frame_save (rtx real)
14054 {
14055 rtx synth, offset, reg, real2;
14056
14057 if (GET_CODE (real) != SET
14058 || GET_MODE (SET_SRC (real)) != V2SImode)
14059 return real;
14060
14061
14062
14063
14064
14065
14066
14067 gcc_assert (GET_CODE (SET_DEST (real)) == MEM
14068 && GET_CODE (XEXP (SET_DEST (real), 0)) == PLUS
14069 && GET_CODE (SET_SRC (real)) == REG);
14070
14071
14072
14073
14074
14075
14076
14077
14078
14079 real2 = copy_rtx (real);
14080 PUT_MODE (SET_DEST (real2), SImode);
14081 reg = SET_SRC (real2);
14082 real2 = replace_rtx (real2, reg, gen_rtx_REG (SImode, REGNO (reg)));
14083 synth = copy_rtx (real2);
14084
14085 if (BYTES_BIG_ENDIAN)
14086 {
14087 offset = XEXP (XEXP (SET_DEST (real2), 0), 1);
14088 real2 = replace_rtx (real2, offset, GEN_INT (INTVAL (offset) + 4));
14089 }
14090
14091 reg = SET_SRC (synth);
14092
14093 synth = replace_rtx (synth, reg,
14094 gen_rtx_REG (SImode, REGNO (reg) + 1200));
14095
14096 offset = XEXP (XEXP (SET_DEST (synth), 0), 1);
14097 synth = replace_rtx (synth, offset,
14098 GEN_INT (INTVAL (offset)
14099 + (BYTES_BIG_ENDIAN ? 0 : 4)));
14100
14101 RTX_FRAME_RELATED_P (synth) = 1;
14102 RTX_FRAME_RELATED_P (real2) = 1;
14103 if (BYTES_BIG_ENDIAN)
14104 real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, synth, real2));
14105 else
14106 real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, real2, synth));
14107
14108 return real;
14109 }
14110
14111
14112
14113
14114 static rtx
14115 generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
14116 {
14117 int nclobs, i;
14118 rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
14119 rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
14120
14121 clobs[0]
14122 = gen_rtx_SET (VOIDmode,
14123 vrsave,
14124 gen_rtx_UNSPEC_VOLATILE (SImode,
14125 gen_rtvec (2, reg, vrsave),
14126 UNSPECV_SET_VRSAVE));
14127
14128 nclobs = 1;
14129
14130
14131
14132
14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
14145 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
14146 {
14147 if (!epiloguep || call_used_regs [i])
14148 clobs[nclobs++] = gen_rtx_CLOBBER (VOIDmode,
14149 gen_rtx_REG (V4SImode, i));
14150 else
14151 {
14152 rtx reg = gen_rtx_REG (V4SImode, i);
14153
14154 clobs[nclobs++]
14155 = gen_rtx_SET (VOIDmode,
14156 reg,
14157 gen_rtx_UNSPEC (V4SImode,
14158 gen_rtvec (1, reg), 27));
14159 }
14160 }
14161
14162 insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
14163
14164 for (i = 0; i < nclobs; ++i)
14165 XVECEXP (insn, 0, i) = clobs[i];
14166
14167 return insn;
14168 }
14169
14170
14171
14172
14173 static void
14174 emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
14175 unsigned int regno, int offset, HOST_WIDE_INT total_size)
14176 {
14177 rtx reg, offset_rtx, insn, mem, addr, int_rtx;
14178 rtx replacea, replaceb;
14179
14180 int_rtx = GEN_INT (offset);
14181
14182
14183 if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
14184 || (TARGET_E500_DOUBLE && mode == DFmode)
14185 || (TARGET_SPE_ABI
14186 && SPE_VECTOR_MODE (mode)
14187 && !SPE_CONST_OFFSET_OK (offset)))
14188 {
14189
14190
14191 offset_rtx = gen_rtx_REG (Pmode, 11);
14192 emit_move_insn (offset_rtx, int_rtx);
14193
14194 replacea = offset_rtx;
14195 replaceb = int_rtx;
14196 }
14197 else
14198 {
14199 offset_rtx = int_rtx;
14200 replacea = NULL_RTX;
14201 replaceb = NULL_RTX;
14202 }
14203
14204 reg = gen_rtx_REG (mode, regno);
14205 addr = gen_rtx_PLUS (Pmode, frame_reg, offset_rtx);
14206 mem = gen_frame_mem (mode, addr);
14207
14208 insn = emit_move_insn (mem, reg);
14209
14210 rs6000_frame_related (insn, frame_ptr, total_size, replacea, replaceb);
14211 }
14212
14213
14214
14215
14216 static rtx
14217 gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
14218 {
14219 rtx int_rtx, offset_rtx;
14220
14221 int_rtx = GEN_INT (offset);
14222
14223 if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
14224 || (TARGET_E500_DOUBLE && mode == DFmode))
14225 {
14226 offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
14227 emit_move_insn (offset_rtx, int_rtx);
14228 }
14229 else
14230 offset_rtx = int_rtx;
14231
14232 return gen_frame_mem (mode, gen_rtx_PLUS (Pmode, reg, offset_rtx));
14233 }
14234
14235
14236
14237
14238 static bool
14239 no_global_regs_above (int first_greg)
14240 {
14241 int i;
14242 for (i = 0; i < 32 - first_greg; i++)
14243 if (global_regs[first_greg + i])
14244 return false;
14245 return true;
14246 }
14247
14248 #ifndef TARGET_FIX_AND_CONTINUE
14249 #define TARGET_FIX_AND_CONTINUE 0
14250 #endif
14251
14252
14253
14254 void
14255 rs6000_emit_prologue (void)
14256 {
14257 rs6000_stack_t *info = rs6000_stack_info ();
14258 enum machine_mode reg_mode = Pmode;
14259 int reg_size = TARGET_32BIT ? 4 : 8;
14260 rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
14261 rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
14262 rtx frame_reg_rtx = sp_reg_rtx;
14263 rtx cr_save_rtx = NULL_RTX;
14264 rtx insn;
14265 int saving_FPRs_inline;
14266 int using_store_multiple;
14267 HOST_WIDE_INT sp_offset = 0;
14268
14269 if (TARGET_FIX_AND_CONTINUE)
14270 {
14271
14272
14273
14274
14275
14276 emit_insn (gen_nop ());
14277 emit_insn (gen_nop ());
14278 emit_insn (gen_nop ());
14279 emit_insn (gen_nop ());
14280 emit_insn (gen_nop ());
14281 }
14282
14283 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14284 {
14285 reg_mode = V2SImode;
14286 reg_size = 8;
14287 }
14288
14289 using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
14290 && (!TARGET_SPE_ABI
14291 || info->spe_64bit_regs_used == 0)
14292 && info->first_gp_reg_save < 31
14293 && no_global_regs_above (info->first_gp_reg_save));
14294 saving_FPRs_inline = (info->first_fp_reg_save == 64
14295 || FP_SAVE_INLINE (info->first_fp_reg_save)
14296 || current_function_calls_eh_return
14297 || cfun->machine->ra_need_lr);
14298
14299
14300 if (! WORLD_SAVE_P (info)
14301 && info->push_p
14302 && (DEFAULT_ABI == ABI_V4
14303 || current_function_calls_eh_return))
14304 {
14305 if (info->total_size < 32767)
14306 sp_offset = info->total_size;
14307 else
14308 frame_reg_rtx = frame_ptr_rtx;
14309 rs6000_emit_allocate_stack (info->total_size,
14310 (frame_reg_rtx != sp_reg_rtx
14311 && (info->cr_save_p
14312 || info->lr_save_p
14313 || info->first_fp_reg_save < 64
14314 || info->first_gp_reg_save < 32
14315 )));
14316 if (frame_reg_rtx != sp_reg_rtx)
14317 rs6000_emit_stack_tie ();
14318 }
14319
14320
14321 if (WORLD_SAVE_P (info))
14322 {
14323 int i, j, sz;
14324 rtx treg;
14325 rtvec p;
14326 rtx reg0;
14327
14328
14329 reg0 = gen_rtx_REG (Pmode, 0);
14330 if (info->lr_save_p)
14331 {
14332 insn = emit_move_insn (reg0,
14333 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
14334 RTX_FRAME_RELATED_P (insn) = 1;
14335 }
14336
14337
14338
14339
14340 gcc_assert (info->gp_save_offset == -220
14341 && info->fp_save_offset == -144
14342 && info->lr_save_offset == 8
14343 && info->cr_save_offset == 4
14344 && info->push_p
14345 && info->lr_save_p
14346 && (!current_function_calls_eh_return
14347 || info->ehrd_offset == -432)
14348 && info->vrsave_save_offset == -224
14349 && info->altivec_save_offset == -416);
14350
14351 treg = gen_rtx_REG (SImode, 11);
14352 emit_move_insn (treg, GEN_INT (-info->total_size));
14353
14354
14355
14356
14357
14358 sz = 5;
14359 sz += 32 - info->first_gp_reg_save;
14360 sz += 64 - info->first_fp_reg_save;
14361 sz += LAST_ALTIVEC_REGNO - info->first_altivec_reg_save + 1;
14362 p = rtvec_alloc (sz);
14363 j = 0;
14364 RTVEC_ELT (p, j++) = gen_rtx_CLOBBER (VOIDmode,
14365 gen_rtx_REG (Pmode,
14366 LINK_REGISTER_REGNUM));
14367 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
14368 gen_rtx_SYMBOL_REF (Pmode,
14369 "*save_world"));
14370
14371
14372 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14373 {
14374 rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14375 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14376 GEN_INT (info->fp_save_offset
14377 + sp_offset + 8 * i));
14378 rtx mem = gen_frame_mem (DFmode, addr);
14379
14380 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14381 }
14382 for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
14383 {
14384 rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
14385 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14386 GEN_INT (info->altivec_save_offset
14387 + sp_offset + 16 * i));
14388 rtx mem = gen_frame_mem (V4SImode, addr);
14389
14390 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14391 }
14392 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14393 {
14394 rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14395 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14396 GEN_INT (info->gp_save_offset
14397 + sp_offset + reg_size * i));
14398 rtx mem = gen_frame_mem (reg_mode, addr);
14399
14400 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14401 }
14402
14403 {
14404
14405 rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
14406 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14407 GEN_INT (info->cr_save_offset
14408 + sp_offset));
14409 rtx mem = gen_frame_mem (reg_mode, addr);
14410
14411 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14412 }
14413
14414 if (info->lr_save_p)
14415 {
14416 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14417 GEN_INT (info->lr_save_offset
14418 + sp_offset));
14419 rtx mem = gen_frame_mem (reg_mode, addr);
14420
14421 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg0);
14422 }
14423
14424 {
14425 rtx newval = gen_rtx_PLUS (Pmode, sp_reg_rtx, treg);
14426 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, sp_reg_rtx, newval);
14427 }
14428
14429 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14430 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14431 treg, GEN_INT (-info->total_size));
14432 sp_offset = info->total_size;
14433 }
14434
14435
14436 if (!WORLD_SAVE_P (info) && TARGET_ALTIVEC_ABI && info->altivec_size != 0)
14437 {
14438 int i;
14439
14440
14441
14442 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
14443 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
14444 {
14445 rtx areg, savereg, mem;
14446 int offset;
14447
14448 offset = info->altivec_save_offset + sp_offset
14449 + 16 * (i - info->first_altivec_reg_save);
14450
14451 savereg = gen_rtx_REG (V4SImode, i);
14452
14453 areg = gen_rtx_REG (Pmode, 0);
14454 emit_move_insn (areg, GEN_INT (offset));
14455
14456
14457 mem = gen_frame_mem (V4SImode,
14458 gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
14459
14460 insn = emit_move_insn (mem, savereg);
14461
14462 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14463 areg, GEN_INT (offset));
14464 }
14465 }
14466
14467
14468
14469
14470
14471
14472
14473
14474 if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
14475 && info->vrsave_mask != 0)
14476 {
14477 rtx reg, mem, vrsave;
14478 int offset;
14479
14480
14481
14482
14483 reg = gen_rtx_REG (SImode, 0);
14484 vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
14485 if (TARGET_MACHO)
14486 emit_insn (gen_get_vrsave_internal (reg));
14487 else
14488 emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
14489
14490 if (!WORLD_SAVE_P (info))
14491 {
14492
14493 offset = info->vrsave_save_offset + sp_offset;
14494 mem = gen_frame_mem (SImode,
14495 gen_rtx_PLUS (Pmode, frame_reg_rtx,
14496 GEN_INT (offset)));
14497 insn = emit_move_insn (mem, reg);
14498 }
14499
14500
14501 emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
14502
14503 insn = emit_insn (generate_set_vrsave (reg, info, 0));
14504 }
14505
14506
14507 if (!WORLD_SAVE_P (info) && info->lr_save_p)
14508 {
14509 insn = emit_move_insn (gen_rtx_REG (Pmode, 0),
14510 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
14511 RTX_FRAME_RELATED_P (insn) = 1;
14512 }
14513
14514
14515 if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
14516 {
14517 rtx set;
14518
14519 cr_save_rtx = gen_rtx_REG (SImode, 12);
14520 insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
14521 RTX_FRAME_RELATED_P (insn) = 1;
14522
14523
14524
14525
14526
14527
14528 set = gen_rtx_SET (VOIDmode, cr_save_rtx,
14529 gen_rtx_REG (SImode, CR2_REGNO));
14530 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
14531 set,
14532 REG_NOTES (insn));
14533 }
14534
14535
14536
14537 if (!WORLD_SAVE_P (info) && saving_FPRs_inline)
14538 {
14539 int i;
14540 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14541 if ((regs_ever_live[info->first_fp_reg_save+i]
14542 && ! call_used_regs[info->first_fp_reg_save+i]))
14543 emit_frame_save (frame_reg_rtx, frame_ptr_rtx, DFmode,
14544 info->first_fp_reg_save + i,
14545 info->fp_save_offset + sp_offset + 8 * i,
14546 info->total_size);
14547 }
14548 else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
14549 {
14550 int i;
14551 char rname[30];
14552 const char *alloc_rname;
14553 rtvec p;
14554 p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
14555
14556 RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
14557 gen_rtx_REG (Pmode,
14558 LINK_REGISTER_REGNUM));
14559 sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
14560 info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
14561 alloc_rname = ggc_strdup (rname);
14562 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
14563 gen_rtx_SYMBOL_REF (Pmode,
14564 alloc_rname));
14565 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14566 {
14567 rtx addr, reg, mem;
14568 reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14569 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14570 GEN_INT (info->fp_save_offset
14571 + sp_offset + 8*i));
14572 mem = gen_frame_mem (DFmode, addr);
14573
14574 RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
14575 }
14576 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14577 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14578 NULL_RTX, NULL_RTX);
14579 }
14580
14581
14582
14583 if (!WORLD_SAVE_P (info) && using_store_multiple)
14584 {
14585 rtvec p;
14586 int i;
14587 p = rtvec_alloc (32 - info->first_gp_reg_save);
14588 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14589 {
14590 rtx addr, reg, mem;
14591 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14592 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14593 GEN_INT (info->gp_save_offset
14594 + sp_offset
14595 + reg_size * i));
14596 mem = gen_frame_mem (reg_mode, addr);
14597
14598 RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, mem, reg);
14599 }
14600 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14601 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14602 NULL_RTX, NULL_RTX);
14603 }
14604 else if (!WORLD_SAVE_P (info))
14605 {
14606 int i;
14607 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14608 if ((regs_ever_live[info->first_gp_reg_save + i]
14609 && (!call_used_regs[info->first_gp_reg_save + i]
14610 || (i + info->first_gp_reg_save
14611 == RS6000_PIC_OFFSET_TABLE_REGNUM
14612 && TARGET_TOC && TARGET_MINIMAL_TOC)))
14613 || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
14614 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
14615 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
14616 {
14617 rtx addr, reg, mem;
14618 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14619
14620 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14621 {
14622 int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
14623 rtx b;
14624
14625 if (!SPE_CONST_OFFSET_OK (offset))
14626 {
14627 b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
14628 emit_move_insn (b, GEN_INT (offset));
14629 }
14630 else
14631 b = GEN_INT (offset);
14632
14633 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
14634 mem = gen_frame_mem (V2SImode, addr);
14635 insn = emit_move_insn (mem, reg);
14636
14637 if (GET_CODE (b) == CONST_INT)
14638 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14639 NULL_RTX, NULL_RTX);
14640 else
14641 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14642 b, GEN_INT (offset));
14643 }
14644 else
14645 {
14646 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14647 GEN_INT (info->gp_save_offset
14648 + sp_offset
14649 + reg_size * i));
14650 mem = gen_frame_mem (reg_mode, addr);
14651
14652 insn = emit_move_insn (mem, reg);
14653 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14654 NULL_RTX, NULL_RTX);
14655 }
14656 }
14657 }
14658
14659
14660
14661 if (current_function_calls_eh_return)
14662 {
14663 unsigned int i, regno;
14664
14665
14666 if (TARGET_AIX)
14667 {
14668 rtx addr, reg, mem;
14669
14670 reg = gen_rtx_REG (reg_mode, 2);
14671 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14672 GEN_INT (sp_offset + 5 * reg_size));
14673 mem = gen_frame_mem (reg_mode, addr);
14674
14675 insn = emit_move_insn (mem, reg);
14676 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14677 NULL_RTX, NULL_RTX);
14678 PATTERN (insn) = gen_blockage ();
14679 }
14680
14681 for (i = 0; ; ++i)
14682 {
14683 regno = EH_RETURN_DATA_REGNO (i);
14684 if (regno == INVALID_REGNUM)
14685 break;
14686
14687 emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, regno,
14688 info->ehrd_offset + sp_offset
14689 + reg_size * (int) i,
14690 info->total_size);
14691 }
14692 }
14693
14694
14695 if (!WORLD_SAVE_P (info) && info->lr_save_p)
14696 {
14697 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14698 GEN_INT (info->lr_save_offset + sp_offset));
14699 rtx reg = gen_rtx_REG (Pmode, 0);
14700 rtx mem = gen_rtx_MEM (Pmode, addr);
14701
14702
14703
14704 insn = emit_move_insn (mem, reg);
14705 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14706 NULL_RTX, NULL_RTX);
14707 }
14708
14709
14710 if (!WORLD_SAVE_P (info) && info->cr_save_p)
14711 {
14712 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14713 GEN_INT (info->cr_save_offset + sp_offset));
14714 rtx mem = gen_frame_mem (SImode, addr);
14715
14716 rtx magic_eh_cr_reg = gen_rtx_REG (SImode, CR2_REGNO);
14717
14718
14719
14720 if (REGNO (frame_reg_rtx) == 12)
14721 {
14722 rtx set;
14723
14724 cr_save_rtx = gen_rtx_REG (SImode, 0);
14725 insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
14726 RTX_FRAME_RELATED_P (insn) = 1;
14727 set = gen_rtx_SET (VOIDmode, cr_save_rtx, magic_eh_cr_reg);
14728 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
14729 set,
14730 REG_NOTES (insn));
14731
14732 }
14733 insn = emit_move_insn (mem, cr_save_rtx);
14734
14735 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14736 NULL_RTX, NULL_RTX);
14737 }
14738
14739
14740
14741 if (!WORLD_SAVE_P (info) && info->push_p
14742 && !(DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return))
14743 rs6000_emit_allocate_stack (info->total_size, FALSE);
14744
14745
14746 if (frame_pointer_needed)
14747 {
14748 insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
14749 sp_reg_rtx);
14750 RTX_FRAME_RELATED_P (insn) = 1;
14751 }
14752
14753
14754 if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
14755 || (DEFAULT_ABI == ABI_V4
14756 && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
14757 && regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]))
14758 {
14759
14760
14761
14762
14763 int save_LR_around_toc_setup = (TARGET_ELF
14764 && DEFAULT_ABI != ABI_AIX
14765 && flag_pic
14766 && ! info->lr_save_p
14767 && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0);
14768 if (save_LR_around_toc_setup)
14769 {
14770 rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
14771
14772 insn = emit_move_insn (frame_ptr_rtx, lr);
14773 rs6000_maybe_dead (insn);
14774 RTX_FRAME_RELATED_P (insn) = 1;
14775
14776 rs6000_emit_load_toc_table (TRUE);
14777
14778 insn = emit_move_insn (lr, frame_ptr_rtx);
14779 rs6000_maybe_dead (insn);
14780 RTX_FRAME_RELATED_P (insn) = 1;
14781 }
14782 else
14783 rs6000_emit_load_toc_table (TRUE);
14784 }
14785
14786 #if TARGET_MACHO
14787 if (DEFAULT_ABI == ABI_DARWIN
14788 && flag_pic && current_function_uses_pic_offset_table)
14789 {
14790 rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
14791 rtx src = machopic_function_base_sym ();
14792
14793
14794 if (!info->lr_save_p)
14795 rs6000_maybe_dead (emit_move_insn (gen_rtx_REG (Pmode, 0), lr));
14796
14797 rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (lr, src)));
14798
14799 insn = emit_move_insn (gen_rtx_REG (Pmode,
14800 RS6000_PIC_OFFSET_TABLE_REGNUM),
14801 lr);
14802 rs6000_maybe_dead (insn);
14803
14804 if (!info->lr_save_p)
14805 rs6000_maybe_dead (emit_move_insn (lr, gen_rtx_REG (Pmode, 0)));
14806 }
14807 #endif
14808 }
14809
14810
14811
14812 static void
14813 rs6000_output_function_prologue (FILE *file,
14814 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
14815 {
14816 rs6000_stack_t *info = rs6000_stack_info ();
14817
14818 if (TARGET_DEBUG_STACK)
14819 debug_stack_info (info);
14820
14821
14822
14823 if (info->first_fp_reg_save < 64
14824 && !FP_SAVE_INLINE (info->first_fp_reg_save))
14825 fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
14826 SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
14827 RESTORE_FP_PREFIX, info->first_fp_reg_save - 32,
14828 RESTORE_FP_SUFFIX);
14829
14830
14831 if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined)
14832 {
14833 fputs ("\t.extern __mulh\n", file);
14834 fputs ("\t.extern __mull\n", file);
14835 fputs ("\t.extern __divss\n", file);
14836 fputs ("\t.extern __divus\n", file);
14837 fputs ("\t.extern __quoss\n", file);
14838 fputs ("\t.extern __quous\n", file);
14839 common_mode_defined = 1;
14840 }
14841
14842 if (! HAVE_prologue)
14843 {
14844 start_sequence ();
14845
14846
14847
14848 emit_note (NOTE_INSN_DELETED);
14849 rs6000_emit_prologue ();
14850 emit_note (NOTE_INSN_DELETED);
14851
14852
14853 {
14854 rtx insn;
14855 unsigned addr = 0;
14856 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
14857 {
14858 INSN_ADDRESSES_NEW (insn, addr);
14859 addr += 4;
14860 }
14861 }
14862
14863 if (TARGET_DEBUG_STACK)
14864 debug_rtx_list (get_insns (), 100);
14865 final (get_insns (), file, FALSE);
14866 end_sequence ();
14867 }
14868
14869 rs6000_pic_labelno++;
14870 }
14871
14872
14873
14874
14875
14876
14877
14878
14879 void
14880 rs6000_emit_epilogue (int sibcall)
14881 {
14882 rs6000_stack_t *info;
14883 int restoring_FPRs_inline;
14884 int using_load_multiple;
14885 int using_mfcr_multiple;
14886 int use_backchain_to_restore_sp;
14887 int sp_offset = 0;
14888 rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
14889 rtx frame_reg_rtx = sp_reg_rtx;
14890 enum machine_mode reg_mode = Pmode;
14891 int reg_size = TARGET_32BIT ? 4 : 8;
14892 int i;
14893
14894 info = rs6000_stack_info ();
14895
14896 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14897 {
14898 reg_mode = V2SImode;
14899 reg_size = 8;
14900 }
14901
14902 using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
14903 && (!TARGET_SPE_ABI
14904 || info->spe_64bit_regs_used == 0)
14905 && info->first_gp_reg_save < 31
14906 && no_global_regs_above (info->first_gp_reg_save));
14907 restoring_FPRs_inline = (sibcall
14908 || current_function_calls_eh_return
14909 || info->first_fp_reg_save == 64
14910 || FP_SAVE_INLINE (info->first_fp_reg_save));
14911 use_backchain_to_restore_sp = (frame_pointer_needed
14912 || current_function_calls_alloca
14913 || info->total_size > 32767);
14914 using_mfcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
14915 || rs6000_cpu == PROCESSOR_PPC603
14916 || rs6000_cpu == PROCESSOR_PPC750
14917 || optimize_size);
14918
14919 if (WORLD_SAVE_P (info))
14920 {
14921 int i, j;
14922 char rname[30];
14923 const char *alloc_rname;
14924 rtvec p;
14925
14926
14927
14928
14929
14930
14931
14932
14933 p = rtvec_alloc (9
14934 + 1
14935 + 32 - info->first_gp_reg_save
14936 + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
14937 + 63 + 1 - info->first_fp_reg_save);
14938
14939 strcpy (rname, ((current_function_calls_eh_return) ?
14940 "*eh_rest_world_r10" : "*rest_world"));
14941 alloc_rname = ggc_strdup (rname);
14942
14943 j = 0;
14944 RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
14945 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
14946 gen_rtx_REG (Pmode,
14947 LINK_REGISTER_REGNUM));
14948 RTVEC_ELT (p, j++)
14949 = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
14950
14951
14952 RTVEC_ELT (p, j++)
14953 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
14954
14955 {
14956
14957 rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
14958 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14959 GEN_INT (info->cr_save_offset));
14960 rtx mem = gen_frame_mem (reg_mode, addr);
14961
14962 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14963 }
14964
14965 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14966 {
14967 rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14968 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14969 GEN_INT (info->gp_save_offset
14970 + reg_size * i));
14971 rtx mem = gen_frame_mem (reg_mode, addr);
14972
14973 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14974 }
14975 for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
14976 {
14977 rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
14978 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14979 GEN_INT (info->altivec_save_offset
14980 + 16 * i));
14981 rtx mem = gen_frame_mem (V4SImode, addr);
14982
14983 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14984 }
14985 for (i = 0; info->first_fp_reg_save + i <= 63; i++)
14986 {
14987 rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14988 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14989 GEN_INT (info->fp_save_offset
14990 + 8 * i));
14991 rtx mem = gen_frame_mem (DFmode, addr);
14992
14993 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14994 }
14995 RTVEC_ELT (p, j++)
14996 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
14997 RTVEC_ELT (p, j++)
14998 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 12));
14999 RTVEC_ELT (p, j++)
15000 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 7));
15001 RTVEC_ELT (p, j++)
15002 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
15003 RTVEC_ELT (p, j++)
15004 = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
15005 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
15006
15007 return;
15008 }
15009
15010
15011
15012
15013 if (use_backchain_to_restore_sp)
15014 {
15015
15016
15017 if (DEFAULT_ABI == ABI_V4)
15018 frame_reg_rtx = gen_rtx_REG (Pmode, 11);
15019
15020 emit_move_insn (frame_reg_rtx,
15021 gen_rtx_MEM (Pmode, sp_reg_rtx));
15022 }
15023 else if (info->push_p)
15024 {
15025 if (DEFAULT_ABI == ABI_V4
15026 || current_function_calls_eh_return)
15027 sp_offset = info->total_size;
15028 else
15029 {
15030 emit_insn (TARGET_32BIT
15031 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
15032 GEN_INT (info->total_size))
15033 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
15034 GEN_INT (info->total_size)));
15035 }
15036 }
15037
15038
15039 if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
15040 {
15041 int i;
15042
15043 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
15044 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
15045 {
15046 rtx addr, areg, mem;
15047
15048 areg = gen_rtx_REG (Pmode, 0);
15049 emit_move_insn
15050 (areg, GEN_INT (info->altivec_save_offset
15051 + sp_offset
15052 + 16 * (i - info->first_altivec_reg_save)));
15053
15054
15055 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
15056 mem = gen_frame_mem (V4SImode, addr);
15057
15058 emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
15059 }
15060 }
15061
15062
15063 if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
15064 && info->vrsave_mask != 0)
15065 {
15066 rtx addr, mem, reg;
15067
15068 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15069 GEN_INT (info->vrsave_save_offset + sp_offset));
15070 mem = gen_frame_mem (SImode, addr);
15071 reg = gen_rtx_REG (SImode, 12);
15072 emit_move_insn (reg, mem);
15073
15074 emit_insn (generate_set_vrsave (reg, info, 1));
15075 }
15076
15077
15078 if (info->lr_save_p)
15079 {
15080 rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
15081 info->lr_save_offset + sp_offset);
15082
15083 emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
15084 }
15085
15086
15087 if (info->cr_save_p)
15088 {
15089 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15090 GEN_INT (info->cr_save_offset + sp_offset));
15091 rtx mem = gen_frame_mem (SImode, addr);
15092
15093 emit_move_insn (gen_rtx_REG (SImode, 12), mem);
15094 }
15095
15096
15097 if (info->lr_save_p)
15098 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
15099 gen_rtx_REG (Pmode, 0));
15100
15101
15102 if (current_function_calls_eh_return)
15103 {
15104 unsigned int i, regno;
15105
15106 if (TARGET_AIX)
15107 {
15108 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15109 GEN_INT (sp_offset + 5 * reg_size));
15110 rtx mem = gen_frame_mem (reg_mode, addr);
15111
15112 emit_move_insn (gen_rtx_REG (reg_mode, 2), mem);
15113 }
15114
15115 for (i = 0; ; ++i)
15116 {
15117 rtx mem;
15118
15119 regno = EH_RETURN_DATA_REGNO (i);
15120 if (regno == INVALID_REGNUM)
15121 break;
15122
15123 mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
15124 info->ehrd_offset + sp_offset
15125 + reg_size * (int) i);
15126
15127 emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
15128 }
15129 }
15130
15131
15132
15133 if (using_load_multiple)
15134 {
15135 rtvec p;
15136 p = rtvec_alloc (32 - info->first_gp_reg_save);
15137 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
15138 {
15139 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15140 GEN_INT (info->gp_save_offset
15141 + sp_offset
15142 + reg_size * i));
15143 rtx mem = gen_frame_mem (reg_mode, addr);
15144
15145 RTVEC_ELT (p, i) =
15146 gen_rtx_SET (VOIDmode,
15147 gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
15148 mem);
15149 }
15150 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
15151 }
15152 else
15153 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
15154 if ((regs_ever_live[info->first_gp_reg_save + i]
15155 && (!call_used_regs[info->first_gp_reg_save + i]
15156 || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
15157 && TARGET_TOC && TARGET_MINIMAL_TOC)))
15158 || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
15159 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
15160 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
15161 {
15162 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15163 GEN_INT (info->gp_save_offset
15164 + sp_offset
15165 + reg_size * i));
15166 rtx mem = gen_frame_mem (reg_mode, addr);
15167
15168
15169 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
15170 {
15171 int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
15172 rtx b;
15173
15174 if (!SPE_CONST_OFFSET_OK (offset))
15175 {
15176 b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
15177 emit_move_insn (b, GEN_INT (offset));
15178 }
15179 else
15180 b = GEN_INT (offset);
15181
15182 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
15183 mem = gen_frame_mem (V2SImode, addr);
15184 }
15185
15186 emit_move_insn (gen_rtx_REG (reg_mode,
15187 info->first_gp_reg_save + i), mem);
15188 }
15189
15190
15191 if (restoring_FPRs_inline)
15192 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
15193 if ((regs_ever_live[info->first_fp_reg_save+i]
15194 && ! call_used_regs[info->first_fp_reg_save+i]))
15195 {
15196 rtx addr, mem;
15197 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15198 GEN_INT (info->fp_save_offset
15199 + sp_offset
15200 + 8 * i));
15201 mem = gen_frame_mem (DFmode, addr);
15202
15203 emit_move_insn (gen_rtx_REG (DFmode,
15204 info->first_fp_reg_save + i),
15205 mem);
15206 }
15207
15208
15209 if (info->cr_save_p)
15210 {
15211 rtx r12_rtx = gen_rtx_REG (SImode, 12);
15212 int count = 0;
15213
15214 if (using_mfcr_multiple)
15215 {
15216 for (i = 0; i < 8; i++)
15217 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15218 count++;
15219 gcc_assert (count);
15220 }
15221
15222 if (using_mfcr_multiple && count > 1)
15223 {
15224 rtvec p;
15225 int ndx;
15226
15227 p = rtvec_alloc (count);
15228
15229 ndx = 0;
15230 for (i = 0; i < 8; i++)
15231 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15232 {
15233 rtvec r = rtvec_alloc (2);
15234 RTVEC_ELT (r, 0) = r12_rtx;
15235 RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
15236 RTVEC_ELT (p, ndx) =
15237 gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
15238 gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
15239 ndx++;
15240 }
15241 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
15242 gcc_assert (ndx == count);
15243 }
15244 else
15245 for (i = 0; i < 8; i++)
15246 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15247 {
15248 emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode,
15249 CR0_REGNO+i),
15250 r12_rtx));
15251 }
15252 }
15253
15254
15255
15256 if (frame_reg_rtx != sp_reg_rtx)
15257 {
15258
15259
15260 rs6000_emit_stack_tie ();
15261 emit_move_insn (sp_reg_rtx, frame_reg_rtx);
15262 }
15263 else if (sp_offset != 0)
15264 emit_insn (TARGET_32BIT
15265 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
15266 GEN_INT (sp_offset))
15267 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
15268 GEN_INT (sp_offset)));
15269
15270 if (current_function_calls_eh_return)
15271 {
15272 rtx sa = EH_RETURN_STACKADJ_RTX;
15273 emit_insn (TARGET_32BIT
15274 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
15275 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
15276 }
15277
15278 if (!sibcall)
15279 {
15280 rtvec p;
15281 if (! restoring_FPRs_inline)
15282 p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
15283 else
15284 p = rtvec_alloc (2);
15285
15286 RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
15287 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
15288 gen_rtx_REG (Pmode,
15289 LINK_REGISTER_REGNUM));
15290
15291
15292
15293 if (! restoring_FPRs_inline)
15294 {
15295 int i;
15296 char rname[30];
15297 const char *alloc_rname;
15298
15299 sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
15300 info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
15301 alloc_rname = ggc_strdup (rname);
15302 RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
15303 gen_rtx_SYMBOL_REF (Pmode,
15304 alloc_rname));
15305
15306 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
15307 {
15308 rtx addr, mem;
15309 addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
15310 GEN_INT (info->fp_save_offset + 8*i));
15311 mem = gen_frame_mem (DFmode, addr);
15312
15313 RTVEC_ELT (p, i+3) =
15314 gen_rtx_SET (VOIDmode,
15315 gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
15316 mem);
15317 }
15318 }
15319
15320 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
15321 }
15322 }
15323
15324
15325
15326 static void
15327 rs6000_output_function_epilogue (FILE *file,
15328 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
15329 {
15330 if (! HAVE_epilogue)
15331 {
15332 rtx insn = get_last_insn ();
15333
15334
15335 if (GET_CODE (insn) == NOTE)
15336 insn = prev_nonnote_insn (insn);
15337 if (insn == 0 || GET_CODE (insn) != BARRIER)
15338 {
15339
15340
15341 start_sequence ();
15342
15343
15344
15345 emit_note (NOTE_INSN_DELETED);
15346 rs6000_emit_epilogue (FALSE);
15347 emit_note (NOTE_INSN_DELETED);
15348
15349
15350 {
15351 rtx insn;
15352 unsigned addr = 0;
15353 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
15354 {
15355 INSN_ADDRESSES_NEW (insn, addr);
15356 addr += 4;
15357 }
15358 }
15359
15360 if (TARGET_DEBUG_STACK)
15361 debug_rtx_list (get_insns (), 100);
15362 final (get_insns (), file, FALSE);
15363 end_sequence ();
15364 }
15365 }
15366
15367 #if TARGET_MACHO
15368 macho_branch_islands ();
15369
15370
15371 {
15372 rtx insn = get_last_insn ();
15373 while (insn
15374 && NOTE_P (insn)
15375 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL)
15376 insn = PREV_INSN (insn);
15377 if (insn
15378 && (LABEL_P (insn)
15379 || (NOTE_P (insn)
15380 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
15381 fputs ("\tnop\n", file);
15382 }
15383 #endif
15384
15385
15386
15387
15388
15389
15390
15391
15392
15393
15394
15395
15396
15397
15398
15399 if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
15400 && rs6000_traceback != traceback_none && !current_function_is_thunk)
15401 {
15402 const char *fname = NULL;
15403 const char *language_string = lang_hooks.name;
15404 int fixed_parms = 0, float_parms = 0, parm_info = 0;
15405 int i;
15406 int optional_tbtab;
15407 rs6000_stack_t *info = rs6000_stack_info ();
15408
15409 if (rs6000_traceback == traceback_full)
15410 optional_tbtab = 1;
15411 else if (rs6000_traceback == traceback_part)
15412 optional_tbtab = 0;
15413 else
15414 optional_tbtab = !optimize_size && !TARGET_ELF;
15415
15416 if (optional_tbtab)
15417 {
15418 fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
15419 while (*fname == '.')
15420 fname++;
15421
15422
15423
15424 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
15425 ASM_OUTPUT_LABEL (file, fname);
15426 }
15427
15428
15429
15430
15431
15432
15433
15434
15435
15436
15437
15438
15439 fputs ("\t.long 0\n", file);
15440
15441
15442 fputs ("\t.byte 0,", file);
15443
15444
15445
15446
15447
15448
15449
15450 if (! strcmp (language_string, "GNU C"))
15451 i = 0;
15452 else if (! strcmp (language_string, "GNU F77")
15453 || ! strcmp (language_string, "GNU F95"))
15454 i = 1;
15455 else if (! strcmp (language_string, "GNU Pascal"))
15456 i = 2;
15457 else if (! strcmp (language_string, "GNU Ada"))
15458 i = 3;
15459 else if (! strcmp (language_string, "GNU C++")
15460 || ! strcmp (language_string, "GNU Objective-C++"))
15461 i = 9;
15462 else if (! strcmp (language_string, "GNU Java"))
15463 i = 13;
15464 else if (! strcmp (language_string, "GNU Objective-C"))
15465 i = 14;
15466 else
15467 gcc_unreachable ();
15468 fprintf (file, "%d,", i);
15469
15470
15471
15472
15473
15474
15475
15476 fprintf (file, "%d,",
15477 (optional_tbtab << 5) | ((info->first_fp_reg_save != 64) << 1));
15478
15479
15480
15481
15482
15483
15484
15485 fprintf (file, "%d,",
15486 ((optional_tbtab << 6)
15487 | ((optional_tbtab & frame_pointer_needed) << 5)
15488 | (info->cr_save_p << 1)
15489 | (info->lr_save_p)));
15490
15491
15492
15493 fprintf (file, "%d,",
15494 (info->push_p << 7) | (64 - info->first_fp_reg_save));
15495
15496
15497 fprintf (file, "%d,", (32 - first_reg_to_save ()));
15498
15499 if (optional_tbtab)
15500 {
15501
15502
15503 tree decl;
15504 int next_parm_info_bit = 31;
15505
15506 for (decl = DECL_ARGUMENTS (current_function_decl);
15507 decl; decl = TREE_CHAIN (decl))
15508 {
15509 rtx parameter = DECL_INCOMING_RTL (decl);
15510 enum machine_mode mode = GET_MODE (parameter);
15511
15512 if (GET_CODE (parameter) == REG)
15513 {
15514 if (SCALAR_FLOAT_MODE_P (mode))
15515 {
15516 int bits;
15517
15518 float_parms++;
15519
15520 switch (mode)
15521 {
15522 case SFmode:
15523 bits = 0x2;
15524 break;
15525
15526 case DFmode:
15527 case TFmode:
15528 bits = 0x3;
15529 break;
15530
15531 default:
15532 gcc_unreachable ();
15533 }
15534
15535
15536 if (next_parm_info_bit > 0)
15537 parm_info |= (bits << (next_parm_info_bit - 1));
15538 next_parm_info_bit -= 2;
15539 }
15540 else
15541 {
15542 fixed_parms += ((GET_MODE_SIZE (mode)
15543 + (UNITS_PER_WORD - 1))
15544 / UNITS_PER_WORD);
15545 next_parm_info_bit -= 1;
15546 }
15547 }
15548 }
15549 }
15550
15551
15552
15553
15554 fprintf (file, "%d,", fixed_parms);
15555
15556
15557
15558
15559
15560
15561
15562
15563 fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));
15564
15565 if (! optional_tbtab)
15566 return;
15567
15568
15569
15570
15571
15572
15573
15574
15575
15576
15577 if (fixed_parms || float_parms)
15578 fprintf (file, "\t.long %d\n", parm_info);
15579
15580
15581 fputs ("\t.long ", file);
15582 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
15583 if (TARGET_AIX)
15584 RS6000_OUTPUT_BASENAME (file, fname);
15585 else
15586 assemble_name (file, fname);
15587 putc ('-', file);
15588 rs6000_output_function_entry (file, fname);
15589 putc ('\n', file);
15590
15591
15592
15593
15594
15595
15596
15597
15598
15599
15600
15601
15602 if (*fname == '*')
15603 ++fname;
15604 fprintf (file, "\t.short %d\n", (int) strlen (fname));
15605
15606
15607 assemble_string (fname, strlen (fname));
15608
15609
15610
15611 if (frame_pointer_needed)
15612 fputs ("\t.byte 31\n", file);
15613
15614 fputs ("\t.align 2\n", file);
15615 }
15616 }
15617
15618
15619
15620
15621
15622
15623
15624
15625
15626
15627
15628
15629
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650 static void
15651 rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
15652 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
15653 tree function)
15654 {
15655 rtx this, insn, funexp;
15656
15657 reload_completed = 1;
15658 epilogue_completed = 1;
15659 no_new_pseudos = 1;
15660 reset_block_changes ();
15661
15662
15663 emit_note (NOTE_INSN_PROLOGUE_END);
15664
15665
15666
15667 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
15668 this = gen_rtx_REG (Pmode, 4);
15669 else
15670 this = gen_rtx_REG (Pmode, 3);
15671
15672
15673 if (delta)
15674 {
15675 rtx delta_rtx = GEN_INT (delta);
15676 emit_insn (TARGET_32BIT
15677 ? gen_addsi3 (this, this, delta_rtx)
15678 : gen_adddi3 (this, this, delta_rtx));
15679 }
15680
15681
15682 if (vcall_offset)
15683 {
15684 rtx vcall_offset_rtx = GEN_INT (vcall_offset);
15685 rtx tmp = gen_rtx_REG (Pmode, 12);
15686
15687 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
15688 if (((unsigned HOST_WIDE_INT) vcall_offset) + 0x8000 >= 0x10000)
15689 {
15690 emit_insn (TARGET_32BIT
15691 ? gen_addsi3 (tmp, tmp, vcall_offset_rtx)
15692 : gen_adddi3 (tmp, tmp, vcall_offset_rtx));
15693 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
15694 }
15695 else
15696 {
15697 rtx loc = gen_rtx_PLUS (Pmode, tmp, vcall_offset_rtx);
15698
15699 emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc));
15700 }
15701 emit_insn (TARGET_32BIT
15702 ? gen_addsi3 (this, this, tmp)
15703 : gen_adddi3 (this, this, tmp));
15704 }
15705
15706
15707 if (!TREE_USED (function))
15708 {
15709 assemble_external (function);
15710 TREE_USED (function) = 1;
15711 }
15712 funexp = XEXP (DECL_RTL (function), 0);
15713 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
15714
15715 #if TARGET_MACHO
15716 if (MACHOPIC_INDIRECT)
15717 funexp = machopic_indirect_call_target (funexp);
15718 #endif
15719
15720
15721
15722 insn = emit_call_insn (
15723 gen_rtx_PARALLEL (VOIDmode,
15724 gen_rtvec (4,
15725 gen_rtx_CALL (VOIDmode,
15726 funexp, const0_rtx),
15727 gen_rtx_USE (VOIDmode, const0_rtx),
15728 gen_rtx_USE (VOIDmode,
15729 gen_rtx_REG (SImode,
15730 LINK_REGISTER_REGNUM)),
15731 gen_rtx_RETURN (VOIDmode))));
15732 SIBLING_CALL_P (insn) = 1;
15733 emit_barrier ();
15734
15735
15736
15737
15738
15739 insn = get_insns ();
15740 insn_locators_initialize ();
15741 shorten_branches (insn);
15742 final_start_function (insn, file, 1);
15743 final (insn, file, 1);
15744 final_end_function ();
15745
15746 reload_completed = 0;
15747 epilogue_completed = 0;
15748 no_new_pseudos = 0;
15749 }
15750
15751
15752
15753
15754
15755
15756
15757
15758
15759
15760
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772
15773
15774
15775
15776
15777
15778
15779
15780 static unsigned
15781 rs6000_hash_constant (rtx k)
15782 {
15783 enum rtx_code code = GET_CODE (k);
15784 enum machine_mode mode = GET_MODE (k);
15785 unsigned result = (code << 3) ^ mode;
15786 const char *format;
15787 int flen, fidx;
15788
15789 format = GET_RTX_FORMAT (code);
15790 flen = strlen (format);
15791 fidx = 0;
15792
15793 switch (code)
15794 {
15795 case LABEL_REF:
15796 return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
15797
15798 case CONST_DOUBLE:
15799 if (mode != VOIDmode)
15800 return real_hash (CONST_DOUBLE_REAL_VALUE (k)) * result;
15801 flen = 2;
15802 break;
15803
15804 case CODE_LABEL:
15805 fidx = 3;
15806 break;
15807
15808 default:
15809 break;
15810 }
15811
15812 for (; fidx < flen; fidx++)
15813 switch (format[fidx])
15814 {
15815 case 's':
15816 {
15817 unsigned i, len;
15818 const char *str = XSTR (k, fidx);
15819 len = strlen (str);
15820 result = result * 613 + len;
15821 for (i = 0; i < len; i++)
15822 result = result * 613 + (unsigned) str[i];
15823 break;
15824 }
15825 case 'u':
15826 case 'e':
15827 result = result * 1231 + rs6000_hash_constant (XEXP (k, fidx));
15828 break;
15829 case 'i':
15830 case 'n':
15831 result = result * 613 + (unsigned) XINT (k, fidx);
15832 break;
15833 case 'w':
15834 if (sizeof (unsigned) >= sizeof (HOST_WIDE_INT))
15835 result = result * 613 + (unsigned) XWINT (k, fidx);
15836 else
15837 {
15838 size_t i;
15839 for (i = 0; i < sizeof (HOST_WIDE_INT) / sizeof (unsigned); i++)
15840 result = result * 613 + (unsigned) (XWINT (k, fidx)
15841 >> CHAR_BIT * i);
15842 }
15843 break;
15844 case '0':
15845 break;
15846 default:
15847 gcc_unreachable ();
15848 }
15849
15850 return result;
15851 }
15852
15853 static unsigned
15854 toc_hash_function (const void *hash_entry)
15855 {
15856 const struct toc_hash_struct *thc =
15857 (const struct toc_hash_struct *) hash_entry;
15858 return rs6000_hash_constant (thc->key) ^ thc->key_mode;
15859 }
15860
15861
15862
15863 static int
15864 toc_hash_eq (const void *h1, const void *h2)
15865 {
15866 rtx r1 = ((const struct toc_hash_struct *) h1)->key;
15867 rtx r2 = ((const struct toc_hash_struct *) h2)->key;
15868
15869 if (((const struct toc_hash_struct *) h1)->key_mode
15870 != ((const struct toc_hash_struct *) h2)->key_mode)
15871 return 0;
15872
15873 return rtx_equal_p (r1, r2);
15874 }
15875
15876
15877
15878
15879
15880
15881 #define VTABLE_NAME_P(NAME) \
15882 (strncmp ("_vt.", name, strlen ("_vt.")) == 0 \
15883 || strncmp ("_ZTV", name, strlen ("_ZTV")) == 0 \
15884 || strncmp ("_ZTT", name, strlen ("_ZTT")) == 0 \
15885 || strncmp ("_ZTI", name, strlen ("_ZTI")) == 0 \
15886 || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
15887
15888 void
15889 rs6000_output_symbol_ref (FILE *file, rtx x)
15890 {
15891
15892
15893
15894
15895
15896
15897 const char *name = XSTR (x, 0);
15898
15899 if (VTABLE_NAME_P (name))
15900 {
15901 RS6000_OUTPUT_BASENAME (file, name);
15902 }
15903 else
15904 assemble_name (file, name);
15905 }
15906
15907
15908
15909
15910 void
15911 output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
15912 {
15913 char buf[256];
15914 const char *name = buf;
15915 const char *real_name;
15916 rtx base = x;
15917 HOST_WIDE_INT offset = 0;
15918
15919 gcc_assert (!TARGET_NO_TOC);
15920
15921
15922
15923
15924
15925 if (TARGET_TOC && GET_CODE (x) != LABEL_REF)
15926 {
15927 struct toc_hash_struct *h;
15928 void * * found;
15929
15930
15931
15932 if (toc_hash_table == NULL)
15933 toc_hash_table = htab_create_ggc (1021, toc_hash_function,
15934 toc_hash_eq, NULL);
15935
15936 h = ggc_alloc (sizeof (*h));
15937 h->key = x;
15938 h->key_mode = mode;
15939 h->labelno = labelno;
15940
15941 found = htab_find_slot (toc_hash_table, h, 1);
15942 if (*found == NULL)
15943 *found = h;
15944 else
15945
15946 {
15947 fputs ("\t.set ", file);
15948 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
15949 fprintf (file, "%d,", labelno);
15950 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
15951 fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
15952 found)->labelno));
15953 return;
15954 }
15955 }
15956
15957
15958
15959 if (GET_CODE (x) == CONST_DOUBLE
15960 && STRICT_ALIGNMENT
15961 && GET_MODE_BITSIZE (mode) >= 64
15962 && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
15963 ASM_OUTPUT_ALIGN (file, 3);
15964 }
15965
15966 (*targetm.asm_out.internal_label) (file, "LC", labelno);
15967
15968
15969
15970
15971 if (GET_CODE (x) == CONST_DOUBLE &&
15972 (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode))
15973 {
15974 REAL_VALUE_TYPE rv;
15975 long k[4];
15976
15977 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
15978 if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
15979 REAL_VALUE_TO_TARGET_DECIMAL128 (rv, k);
15980 else
15981 REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
15982
15983 if (TARGET_64BIT)
15984 {
15985 if (TARGET_MINIMAL_TOC)
15986 fputs (DOUBLE_INT_ASM_OP, file);
15987 else
15988 fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
15989 k[0] & 0xffffffff, k[1] & 0xffffffff,
15990 k[2] & 0xffffffff, k[3] & 0xffffffff);
15991 fprintf (file, "0x%lx%08lx,0x%lx%08lx\n",
15992 k[0] & 0xffffffff, k[1] & 0xffffffff,
15993 k[2] & 0xffffffff, k[3] & 0xffffffff);
15994 return;
15995 }
15996 else
15997 {
15998 if (TARGET_MINIMAL_TOC)
15999 fputs ("\t.long ", file);
16000 else
16001 fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
16002 k[0] & 0xffffffff, k[1] & 0xffffffff,
16003 k[2] & 0xffffffff, k[3] & 0xffffffff);
16004 fprintf (file, "0x%lx,0x%lx,0x%lx,0x%lx\n",
16005 k[0] & 0xffffffff, k[1] & 0xffffffff,
16006 k[2] & 0xffffffff, k[3] & 0xffffffff);
16007 return;
16008 }
16009 }
16010 else if (GET_CODE (x) == CONST_DOUBLE &&
16011 (GET_MODE (x) == DFmode || GET_MODE (x) == DDmode))
16012 {
16013 REAL_VALUE_TYPE rv;
16014 long k[2];
16015
16016 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
16017
16018 if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
16019 REAL_VALUE_TO_TARGET_DECIMAL64 (rv, k);
16020 else
16021 REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
16022
16023 if (TARGET_64BIT)
16024 {
16025 if (TARGET_MINIMAL_TOC)
16026 fputs (DOUBLE_INT_ASM_OP, file);
16027 else
16028 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
16029 k[0] & 0xffffffff, k[1] & 0xffffffff);
16030 fprintf (file, "0x%lx%08lx\n",
16031 k[0] & 0xffffffff, k[1] & 0xffffffff);
16032 return;
16033 }
16034 else
16035 {
16036 if (TARGET_MINIMAL_TOC)
16037 fputs ("\t.long ", file);
16038 else
16039 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
16040 k[0] & 0xffffffff, k[1] & 0xffffffff);
16041 fprintf (file, "0x%lx,0x%lx\n",
16042 k[0] & 0xffffffff, k[1] & 0xffffffff);
16043 return;
16044 }
16045 }
16046 else if (GET_CODE (x) == CONST_DOUBLE &&
16047 (GET_MODE (x) == SFmode || GET_MODE (x) == SDmode))
16048 {
16049 REAL_VALUE_TYPE rv;
16050 long l;
16051
16052 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
16053 if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
16054 REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
16055 else
16056 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
16057
16058 if (TARGET_64BIT)
16059 {
16060 if (TARGET_MINIMAL_TOC)
16061 fputs (DOUBLE_INT_ASM_OP, file);
16062 else
16063 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
16064 fprintf (file, "0x%lx00000000\n", l & 0xffffffff);
16065 return;
16066 }
16067 else
16068 {
16069 if (TARGET_MINIMAL_TOC)
16070 fputs ("\t.long ", file);
16071 else
16072 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
16073 fprintf (file, "0x%lx\n", l & 0xffffffff);
16074 return;
16075 }
16076 }
16077 else if (GET_MODE (x) == VOIDmode
16078 && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
16079 {
16080 unsigned HOST_WIDE_INT low;
16081 HOST_WIDE_INT high;
16082
16083 if (GET_CODE (x) == CONST_DOUBLE)
16084 {
16085 low = CONST_DOUBLE_LOW (x);
16086 high = CONST_DOUBLE_HIGH (x);
16087 }
16088 else
16089 #if HOST_BITS_PER_WIDE_INT == 32
16090 {
16091 low = INTVAL (x);
16092 high = (low & 0x80000000) ? ~0 : 0;
16093 }
16094 #else
16095 {
16096 low = INTVAL (x) & 0xffffffff;
16097 high = (HOST_WIDE_INT) INTVAL (x) >> 32;
16098 }
16099 #endif
16100
16101
16102
16103
16104
16105
16106
16107
16108
16109
16110
16111
16112 gcc_assert (!TARGET_64BIT || POINTER_SIZE >= GET_MODE_BITSIZE (mode));
16113
16114 if (POINTER_SIZE > GET_MODE_BITSIZE (mode))
16115 {
16116 #if HOST_BITS_PER_WIDE_INT == 32
16117 lshift_double (low, high, POINTER_SIZE - GET_MODE_BITSIZE (mode),
16118 POINTER_SIZE, &low, &high, 0);
16119 #else
16120 low |= high << 32;
16121 low <<= POINTER_SIZE - GET_MODE_BITSIZE (mode);
16122 high = (HOST_WIDE_INT) low >> 32;
16123 low &= 0xffffffff;
16124 #endif
16125 }
16126
16127 if (TARGET_64BIT)
16128 {
16129 if (TARGET_MINIMAL_TOC)
16130 fputs (DOUBLE_INT_ASM_OP, file);
16131 else
16132 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
16133 (long) high & 0xffffffff, (long) low & 0xffffffff);
16134 fprintf (file, "0x%lx%08lx\n",
16135 (long) high & 0xffffffff, (long) low & 0xffffffff);
16136 return;
16137 }
16138 else
16139 {
16140 if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
16141 {
16142 if (TARGET_MINIMAL_TOC)
16143 fputs ("\t.long ", file);
16144 else
16145 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
16146 (long) high & 0xffffffff, (long) low & 0xffffffff);
16147 fprintf (file, "0x%lx,0x%lx\n",
16148 (long) high & 0xffffffff, (long) low & 0xffffffff);
16149 }
16150 else
16151 {
16152 if (TARGET_MINIMAL_TOC)
16153 fputs ("\t.long ", file);
16154 else
16155 fprintf (file, "\t.tc IS_%lx[TC],", (long) low & 0xffffffff);
16156 fprintf (file, "0x%lx\n", (long) low & 0xffffffff);
16157 }
16158 return;
16159 }
16160 }
16161
16162 if (GET_CODE (x) == CONST)
16163 {
16164 gcc_assert (GET_CODE (XEXP (x, 0)) == PLUS);
16165
16166 base = XEXP (XEXP (x, 0), 0);
16167 offset = INTVAL (XEXP (XEXP (x, 0), 1));
16168 }
16169
16170 switch (GET_CODE (base))
16171 {
16172 case SYMBOL_REF:
16173 name = XSTR (base, 0);
16174 break;
16175
16176 case LABEL_REF:
16177 ASM_GENERATE_INTERNAL_LABEL (buf, "L",
16178 CODE_LABEL_NUMBER (XEXP (base, 0)));
16179 break;
16180
16181 case CODE_LABEL:
16182 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));
16183 break;
16184
16185 default:
16186 gcc_unreachable ();
16187 }
16188
16189 real_name = (*targetm.strip_name_encoding) (name);
16190 if (TARGET_MINIMAL_TOC)
16191 fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
16192 else
16193 {
16194 fprintf (file, "\t.tc %s", real_name);
16195
16196 if (offset < 0)
16197 fprintf (file, ".N" HOST_WIDE_INT_PRINT_UNSIGNED, - offset);
16198 else if (offset)
16199 fprintf (file, ".P" HOST_WIDE_INT_PRINT_UNSIGNED, offset);
16200
16201 fputs ("[TC],", file);
16202 }
16203
16204
16205
16206
16207
16208
16209
16210 if (VTABLE_NAME_P (name))
16211 {
16212 RS6000_OUTPUT_BASENAME (file, name);
16213 if (offset < 0)
16214 fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
16215 else if (offset > 0)
16216 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
16217 }
16218 else
16219 output_addr_const (file, x);
16220 putc ('\n', file);
16221 }
16222
16223
16224
16225
16226
16227
16228
16229
16230
16231 void
16232 output_ascii (FILE *file, const char *p, int n)
16233 {
16234 char c;
16235 int i, count_string;
16236 const char *for_string = "\t.byte \"";
16237 const char *for_decimal = "\t.byte ";
16238 const char *to_close = NULL;
16239
16240 count_string = 0;
16241 for (i = 0; i < n; i++)
16242 {
16243 c = *p++;
16244 if (c >= ' ' && c < 0177)
16245 {
16246 if (for_string)
16247 fputs (for_string, file);
16248 putc (c, file);
16249
16250
16251 if (c == '"')
16252 {
16253 putc (c, file);
16254 ++count_string;
16255 }
16256
16257 for_string = NULL;
16258 for_decimal = "\"\n\t.byte ";
16259 to_close = "\"\n";
16260 ++count_string;
16261
16262 if (count_string >= 512)
16263 {
16264 fputs (to_close, file);
16265
16266 for_string = "\t.byte \"";
16267 for_decimal = "\t.byte ";
16268 to_close = NULL;
16269 count_string = 0;
16270 }
16271 }
16272 else
16273 {
16274 if (for_decimal)
16275 fputs (for_decimal, file);
16276 fprintf (file, "%d", c);
16277
16278 for_string = "\n\t.byte \"";
16279 for_decimal = ", ";
16280 to_close = "\n";
16281 count_string = 0;
16282 }
16283 }
16284
16285
16286 if (to_close)
16287 fputs (to_close, file);
16288 }
16289
16290
16291
16292
16293
16294
16295
16296
16297
16298
16299
16300
16301
16302 void
16303 rs6000_gen_section_name (char **buf, const char *filename,
16304 const char *section_desc)
16305 {
16306 const char *q, *after_last_slash, *last_period = 0;
16307 char *p;
16308 int len;
16309
16310 after_last_slash = filename;
16311 for (q = filename; *q; q++)
16312 {
16313 if (*q == '/')
16314 after_last_slash = q + 1;
16315 else if (*q == '.')
16316 last_period = q;
16317 }
16318
16319 len = strlen (after_last_slash) + strlen (section_desc) + 2;
16320 *buf = (char *) xmalloc (len);
16321
16322 p = *buf;
16323 *p++ = '_';
16324
16325 for (q = after_last_slash; *q; q++)
16326 {
16327 if (q == last_period)
16328 {
16329 strcpy (p, section_desc);
16330 p += strlen (section_desc);
16331 break;
16332 }
16333
16334 else if (ISALNUM (*q))
16335 *p++ = *q;
16336 }
16337
16338 if (last_period == 0)
16339 strcpy (p, section_desc);
16340 else
16341 *p = '\0';
16342 }
16343
16344
16345
16346 void
16347 output_profile_hook (int labelno ATTRIBUTE_UNUSED)
16348 {
16349
16350
16351
16352
16353 if (TARGET_PROFILE_KERNEL)
16354 return;
16355
16356 if (DEFAULT_ABI == ABI_AIX)
16357 {
16358 #ifndef NO_PROFILE_COUNTERS
16359 # define NO_PROFILE_COUNTERS 0
16360 #endif
16361 if (NO_PROFILE_COUNTERS)
16362 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 0);
16363 else
16364 {
16365 char buf[30];
16366 const char *label_name;
16367 rtx fun;
16368
16369 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
16370 label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
16371 fun = gen_rtx_SYMBOL_REF (Pmode, label_name);
16372
16373 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
16374 fun, Pmode);
16375 }
16376 }
16377 else if (DEFAULT_ABI == ABI_DARWIN)
16378 {
16379 const char *mcount_name = RS6000_MCOUNT;
16380 int caller_addr_regno = LINK_REGISTER_REGNUM;
16381
16382
16383 current_function_uses_pic_offset_table = 1;
16384
16385 #if TARGET_MACHO
16386
16387
16388 if (MACHOPIC_INDIRECT
16389 && current_function_uses_pic_offset_table)
16390 caller_addr_regno = 0;
16391 #endif
16392 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name),
16393 0, VOIDmode, 1,
16394 gen_rtx_REG (Pmode, caller_addr_regno), Pmode);
16395 }
16396 }
16397
16398
16399
16400 void
16401 output_function_profiler (FILE *file, int labelno)
16402 {
16403 char buf[100];
16404
16405 switch (DEFAULT_ABI)
16406 {
16407 default:
16408 gcc_unreachable ();
16409
16410 case ABI_V4:
16411 if (!TARGET_32BIT)
16412 {
16413 warning (0, "no profiling of 64-bit code for this ABI");
16414 return;
16415 }
16416 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
16417 fprintf (file, "\tmflr %s\n", reg_names[0]);
16418 if (NO_PROFILE_COUNTERS)
16419 {
16420 asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
16421 reg_names[0], reg_names[1]);
16422 }
16423 else if (TARGET_SECURE_PLT && flag_pic)
16424 {
16425 asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n",
16426 reg_names[0], reg_names[1]);
16427 asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
16428 asm_fprintf (file, "\t{cau|addis} %s,%s,",
16429 reg_names[12], reg_names[12]);
16430 assemble_name (file, buf);
16431 asm_fprintf (file, "-1b@ha\n\t{cal|la} %s,", reg_names[0]);
16432 assemble_name (file, buf);
16433 asm_fprintf (file, "-1b@l(%s)\n", reg_names[12]);
16434 }
16435 else if (flag_pic == 1)
16436 {
16437 fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
16438 asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
16439 reg_names[0], reg_names[1]);
16440 asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
16441 asm_fprintf (file, "\t{l|lwz} %s,", reg_names[0]);
16442 assemble_name (file, buf);
16443 asm_fprintf (file, "@got(%s)\n", reg_names[12]);
16444 }
16445 else if (flag_pic > 1)
16446 {
16447 asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
16448 reg_names[0], reg_names[1]);
16449
16450 fputs ("\tbcl 20,31,1f\n\t.long ", file);
16451 assemble_name (file, buf);
16452 fputs ("-.\n1:", file);
16453 asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
16454 asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
16455 reg_names[0], reg_names[11]);
16456 asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
16457 reg_names[0], reg_names[0], reg_names[11]);
16458 }
16459 else
16460 {
16461 asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
16462 assemble_name (file, buf);
16463 fputs ("@ha\n", file);
16464 asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
16465 reg_names[0], reg_names[1]);
16466 asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
16467 assemble_name (file, buf);
16468 asm_fprintf (file, "@l(%s)\n", reg_names[12]);
16469 }
16470
16471
16472 fprintf (file, "\tbl %s%s\n",
16473 RS6000_MCOUNT, flag_pic ? "@plt" : "");
16474 break;
16475
16476 case ABI_AIX:
16477 case ABI_DARWIN:
16478 if (!TARGET_PROFILE_KERNEL)
16479 {
16480
16481 }
16482 else
16483 {
16484 gcc_assert (!TARGET_32BIT);
16485
16486 asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
16487 asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
16488
16489 if (cfun->static_chain_decl != NULL)
16490 {
16491 asm_fprintf (file, "\tstd %s,24(%s)\n",
16492 reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
16493 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
16494 asm_fprintf (file, "\tld %s,24(%s)\n",
16495 reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
16496 }
16497 else
16498 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
16499 }
16500 break;
16501 }
16502 }
16503
16504
16505
16506
16507
16508
16509
16510
16511 static int
16512 rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
16513 int verbose ATTRIBUTE_UNUSED,
16514 rtx insn, int more)
16515 {
16516 if (GET_CODE (PATTERN (insn)) == USE
16517 || GET_CODE (PATTERN (insn)) == CLOBBER)
16518 return more;
16519
16520 if (rs6000_sched_groups)
16521 {
16522 if (is_microcoded_insn (insn))
16523 return 0;
16524 else if (is_cracked_insn (insn))
16525 return more > 2 ? more - 2 : 0;
16526 }
16527
16528 return more - 1;
16529 }
16530
16531
16532
16533
16534 static int
16535 rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
16536 {
16537 if (! recog_memoized (insn))
16538 return 0;
16539
16540 if (REG_NOTE_KIND (link) != 0)
16541 return 0;
16542
16543 if (REG_NOTE_KIND (link) == 0)
16544 {
16545
16546
16547
16548
16549 if (rs6000_sched_groups
16550 && GET_CODE (PATTERN (insn)) == SET
16551 && GET_CODE (PATTERN (dep_insn)) == SET
16552 && GET_CODE (XEXP (PATTERN (insn), 1)) == MEM
16553 && GET_CODE (XEXP (PATTERN (dep_insn), 0)) == MEM
16554 && (GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (insn), 1)))
16555 > GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (dep_insn), 0)))))
16556 return cost + 14;
16557
16558 switch (get_attr_type (insn))
16559 {
16560 case TYPE_JMPREG:
16561
16562
16563
16564
16565
16566 return TARGET_POWER ? 5 : 4;
16567 case TYPE_BRANCH:
16568
16569
16570 if ((rs6000_cpu_attr == CPU_PPC603
16571 || rs6000_cpu_attr == CPU_PPC604
16572 || rs6000_cpu_attr == CPU_PPC604E
16573 || rs6000_cpu_attr == CPU_PPC620
16574 || rs6000_cpu_attr == CPU_PPC630
16575 || rs6000_cpu_attr == CPU_PPC750
16576 || rs6000_cpu_attr == CPU_PPC7400
16577 || rs6000_cpu_attr == CPU_PPC7450
16578 || rs6000_cpu_attr == CPU_POWER4
16579 || rs6000_cpu_attr == CPU_POWER5)
16580 && recog_memoized (dep_insn)
16581 && (INSN_CODE (dep_insn) >= 0)
16582 && (get_attr_type (dep_insn) == TYPE_CMP
16583 || get_attr_type (dep_insn) == TYPE_COMPARE
16584 || get_attr_type (dep_insn) == TYPE_DELAYED_COMPARE
16585 || get_attr_type (dep_insn) == TYPE_IMUL_COMPARE
16586 || get_attr_type (dep_insn) == TYPE_LMUL_COMPARE
16587 || get_attr_type (dep_insn) == TYPE_FPCOMPARE
16588 || get_attr_type (dep_insn) == TYPE_CR_LOGICAL
16589 || get_attr_type (dep_insn) == TYPE_DELAYED_CR))
16590 return cost + 2;
16591 default:
16592 break;
16593 }
16594
16595 }
16596
16597 return cost;
16598 }
16599
16600
16601
16602
16603 static bool
16604 is_microcoded_insn (rtx insn)
16605 {
16606 if (!insn || !INSN_P (insn)
16607 || GET_CODE (PATTERN (insn)) == USE
16608 || GET_CODE (PATTERN (insn)) == CLOBBER)
16609 return false;
16610
16611 if (rs6000_sched_groups)
16612 {
16613 enum attr_type type = get_attr_type (insn);
16614 if (type == TYPE_LOAD_EXT_U
16615 || type == TYPE_LOAD_EXT_UX
16616 || type == TYPE_LOAD_UX
16617 || type == TYPE_STORE_UX
16618 || type == TYPE_MFCR)
16619 return true;
16620 }
16621
16622 return false;
16623 }
16624
16625
16626
16627
16628
16629
16630
16631 static int
16632 is_dispatch_slot_restricted (rtx insn)
16633 {
16634 enum attr_type type;
16635
16636 if (!rs6000_sched_groups)
16637 return 0;
16638
16639 if (!insn
16640 || insn == NULL_RTX
16641 || GET_CODE (insn) == NOTE
16642 || GET_CODE (PATTERN (insn)) == USE
16643 || GET_CODE (PATTERN (insn)) == CLOBBER)
16644 return 0;
16645
16646 type = get_attr_type (insn);
16647
16648 switch (type)
16649 {
16650 case TYPE_MFCR:
16651 case TYPE_MFCRF:
16652 case TYPE_MTCR:
16653 case TYPE_DELAYED_CR:
16654 case TYPE_CR_LOGICAL:
16655 case TYPE_MTJMPR:
16656 case TYPE_MFJMPR:
16657 return 1;
16658 case TYPE_IDIV:
16659 case TYPE_LDIV:
16660 return 2;
16661 case TYPE_LOAD_L:
16662 case TYPE_STORE_C:
16663 case TYPE_ISYNC:
16664 case TYPE_SYNC:
16665 return 4;
16666 default:
16667 if (rs6000_cpu == PROCESSOR_POWER5
16668 && is_cracked_insn (insn))
16669 return 2;
16670 return 0;
16671 }
16672 }
16673
16674
16675
16676
16677 static bool
16678 is_cracked_insn (rtx insn)
16679 {
16680 if (!insn || !INSN_P (insn)
16681 || GET_CODE (PATTERN (insn)) == USE
16682 || GET_CODE (PATTERN (insn)) == CLOBBER)
16683 return false;
16684
16685 if (rs6000_sched_groups)
16686 {
16687 enum attr_type type = get_attr_type (insn);
16688 if (type == TYPE_LOAD_U || type == TYPE_STORE_U
16689 || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
16690 || type == TYPE_FPLOAD_UX || type == TYPE_FPSTORE_UX
16691 || type == TYPE_LOAD_EXT || type == TYPE_DELAYED_CR
16692 || type == TYPE_COMPARE || type == TYPE_DELAYED_COMPARE
16693 || type == TYPE_IMUL_COMPARE || type == TYPE_LMUL_COMPARE
16694 || type == TYPE_IDIV || type == TYPE_LDIV
16695 || type == TYPE_INSERT_WORD)
16696 return true;
16697 }
16698
16699 return false;
16700 }
16701
16702
16703
16704
16705 static bool
16706 is_branch_slot_insn (rtx insn)
16707 {
16708 if (!insn || !INSN_P (insn)
16709 || GET_CODE (PATTERN (insn)) == USE
16710 || GET_CODE (PATTERN (insn)) == CLOBBER)
16711 return false;
16712
16713 if (rs6000_sched_groups)
16714 {
16715 enum attr_type type = get_attr_type (insn);
16716 if (type == TYPE_BRANCH || type == TYPE_JMPREG)
16717 return true;
16718 return false;
16719 }
16720
16721 return false;
16722 }
16723
16724
16725
16726
16727
16728
16729
16730 static int
16731 rs6000_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
16732 {
16733
16734
16735
16736
16737
16738 #if 0
16739 if (! INSN_P (insn))
16740 return priority;
16741
16742 if (GET_CODE (PATTERN (insn)) == USE)
16743 return priority;
16744
16745 switch (rs6000_cpu_attr) {
16746 case CPU_PPC750:
16747 switch (get_attr_type (insn))
16748 {
16749 default:
16750 break;
16751
16752 case TYPE_IMUL:
16753 case TYPE_IDIV:
16754 fprintf (stderr, "priority was %#x (%d) before adjustment\n",
16755 priority, priority);
16756 if (priority >= 0 && priority < 0x01000000)
16757 priority >>= 3;
16758 break;
16759 }
16760 }
16761 #endif
16762
16763 if (is_dispatch_slot_restricted (insn)
16764 && reload_completed
16765 && current_sched_info->sched_max_insns_priority
16766 && rs6000_sched_restricted_insns_priority)
16767 {
16768
16769
16770
16771 if (rs6000_sched_restricted_insns_priority == 1)
16772
16773
16774
16775 return current_sched_info->sched_max_insns_priority;
16776 else if (rs6000_sched_restricted_insns_priority == 2)
16777
16778
16779
16780 return (priority + 1);
16781 }
16782
16783 return priority;
16784 }
16785
16786
16787
16788 static int
16789 rs6000_issue_rate (void)
16790 {
16791
16792 if (!reload_completed)
16793 return 1;
16794
16795 switch (rs6000_cpu_attr) {
16796 case CPU_RIOS1:
16797 case CPU_RS64A:
16798 case CPU_PPC601:
16799 case CPU_PPC7450:
16800 return 3;
16801 case CPU_PPC440:
16802 case CPU_PPC603:
16803 case CPU_PPC750:
16804 case CPU_PPC7400:
16805 case CPU_PPC8540:
16806 return 2;
16807 case CPU_RIOS2:
16808 case CPU_PPC604:
16809 case CPU_PPC604E:
16810 case CPU_PPC620:
16811 case CPU_PPC630:
16812 return 4;
16813 case CPU_POWER4:
16814 case CPU_POWER5:
16815 return 5;
16816 default:
16817 return 1;
16818 }
16819 }
16820
16821
16822
16823
16824 static int
16825 rs6000_use_sched_lookahead (void)
16826 {
16827 if (rs6000_cpu_attr == CPU_PPC8540)
16828 return 4;
16829 return 0;
16830 }
16831
16832
16833
16834 static bool
16835 is_mem_ref (rtx pat)
16836 {
16837 const char * fmt;
16838 int i, j;
16839 bool ret = false;
16840
16841 if (GET_CODE (pat) == MEM)
16842 return true;
16843
16844
16845 fmt = GET_RTX_FORMAT (GET_CODE (pat));
16846
16847 for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0 && !ret; i--)
16848 {
16849 if (fmt[i] == 'e')
16850 ret |= is_mem_ref (XEXP (pat, i));
16851 else if (fmt[i] == 'E')
16852 for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
16853 ret |= is_mem_ref (XVECEXP (pat, i, j));
16854 }
16855
16856 return ret;
16857 }
16858
16859
16860
16861 static bool
16862 is_load_insn1 (rtx pat)
16863 {
16864 if (!pat || pat == NULL_RTX)
16865 return false;
16866
16867 if (GET_CODE (pat) == SET)
16868 return is_mem_ref (SET_SRC (pat));
16869
16870 if (GET_CODE (pat) == PARALLEL)
16871 {
16872 int i;
16873
16874 for (i = 0; i < XVECLEN (pat, 0); i++)
16875 if (is_load_insn1 (XVECEXP (pat, 0, i)))
16876 return true;
16877 }
16878
16879 return false;
16880 }
16881
16882
16883
16884 static bool
16885 is_load_insn (rtx insn)
16886 {
16887 if (!insn || !INSN_P (insn))
16888 return false;
16889
16890 if (GET_CODE (insn) == CALL_INSN)
16891 return false;
16892
16893 return is_load_insn1 (PATTERN (insn));
16894 }
16895
16896
16897
16898 static bool
16899 is_store_insn1 (rtx pat)
16900 {
16901 if (!pat || pat == NULL_RTX)
16902 return false;
16903
16904 if (GET_CODE (pat) == SET)
16905 return is_mem_ref (SET_DEST (pat));
16906
16907 if (GET_CODE (pat) == PARALLEL)
16908 {
16909 int i;
16910
16911 for (i = 0; i < XVECLEN (pat, 0); i++)
16912 if (is_store_insn1 (XVECEXP (pat, 0, i)))
16913 return true;
16914 }
16915
16916 return false;
16917 }
16918
16919
16920
16921 static bool
16922 is_store_insn (rtx insn)
16923 {
16924 if (!insn || !INSN_P (insn))
16925 return false;
16926
16927 return is_store_insn1 (PATTERN (insn));
16928 }
16929
16930
16931
16932
16933 static bool
16934 rs6000_is_costly_dependence (rtx insn, rtx next, rtx link, int cost,
16935 int distance)
16936 {
16937
16938
16939
16940 if (rs6000_sched_costly_dep == no_dep_costly)
16941 return false;
16942
16943
16944
16945
16946 if (rs6000_sched_costly_dep == all_deps_costly)
16947 return true;
16948
16949 if (rs6000_sched_costly_dep == store_to_load_dep_costly
16950 && is_load_insn (next)
16951 && is_store_insn (insn))
16952
16953 return true;
16954
16955 if (rs6000_sched_costly_dep == true_store_to_load_dep_costly
16956 && is_load_insn (next)
16957 && is_store_insn (insn)
16958 && (!link || (int) REG_NOTE_KIND (link) == 0))
16959
16960
16961 return true;
16962
16963
16964
16965 if (rs6000_sched_costly_dep <= max_dep_latency
16966 && ((cost - distance) >= (int)rs6000_sched_costly_dep))
16967 return true;
16968
16969 return false;
16970 }
16971
16972
16973
16974
16975
16976 static rtx
16977 get_next_active_insn (rtx insn, rtx tail)
16978 {
16979 if (insn == NULL_RTX || insn == tail)
16980 return NULL_RTX;
16981
16982 while (1)
16983 {
16984 insn = NEXT_INSN (insn);
16985 if (insn == NULL_RTX || insn == tail)
16986 return NULL_RTX;
16987
16988 if (CALL_P (insn)
16989 || JUMP_P (insn)
16990 || (NONJUMP_INSN_P (insn)
16991 && GET_CODE (PATTERN (insn)) != USE
16992 && GET_CODE (PATTERN (insn)) != CLOBBER
16993 && INSN_CODE (insn) != CODE_FOR_stack_tie))
16994 break;
16995 }
16996 return insn;
16997 }
16998
16999
17000
17001
17002
17003
17004
17005
17006
17007
17008
17009
17010
17011
17012 static bool
17013 insn_terminates_group_p (rtx insn, enum group_termination which_group)
17014 {
17015 enum attr_type type;
17016
17017 if (! insn)
17018 return false;
17019
17020 type = get_attr_type (insn);
17021
17022 if (is_microcoded_insn (insn))
17023 return true;
17024
17025 if (which_group == current_group)
17026 {
17027 if (is_branch_slot_insn (insn))
17028 return true;
17029 return false;
17030 }
17031 else if (which_group == previous_group)
17032 {
17033 if (is_dispatch_slot_restricted (insn))
17034 return true;
17035 return false;
17036 }
17037
17038 return false;
17039 }
17040
17041
17042
17043
17044 static bool
17045 is_costly_group (rtx *group_insns, rtx next_insn)
17046 {
17047 int i;
17048 rtx link;
17049 int cost;
17050 int issue_rate = rs6000_issue_rate ();
17051
17052 for (i = 0; i < issue_rate; i++)
17053 {
17054 rtx insn = group_insns[i];
17055 if (!insn)
17056 continue;
17057 for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
17058 {
17059 rtx next = XEXP (link, 0);
17060 if (next == next_insn)
17061 {
17062 cost = insn_cost (insn, link, next_insn);
17063 if (rs6000_is_costly_dependence (insn, next_insn, link, cost, 0))
17064 return true;
17065 }
17066 }
17067 }
17068
17069 return false;
17070 }
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085 static int
17086 force_new_group (int sched_verbose, FILE *dump, rtx *group_insns,
17087 rtx next_insn, bool *group_end, int can_issue_more,
17088 int *group_count)
17089 {
17090 rtx nop;
17091 bool force;
17092 int issue_rate = rs6000_issue_rate ();
17093 bool end = *group_end;
17094 int i;
17095
17096 if (next_insn == NULL_RTX)
17097 return can_issue_more;
17098
17099 if (rs6000_sched_insert_nops > sched_finish_regroup_exact)
17100 return can_issue_more;
17101
17102 force = is_costly_group (group_insns, next_insn);
17103 if (!force)
17104 return can_issue_more;
17105
17106 if (sched_verbose > 6)
17107 fprintf (dump,"force: group count = %d, can_issue_more = %d\n",
17108 *group_count ,can_issue_more);
17109
17110 if (rs6000_sched_insert_nops == sched_finish_regroup_exact)
17111 {
17112 if (*group_end)
17113 can_issue_more = 0;
17114
17115
17116
17117
17118
17119
17120 if (can_issue_more && !is_branch_slot_insn (next_insn))
17121 can_issue_more--;
17122
17123 while (can_issue_more > 0)
17124 {
17125 nop = gen_nop ();
17126 emit_insn_before (nop, next_insn);
17127 can_issue_more--;
17128 }
17129
17130 *group_end = true;
17131 return 0;
17132 }
17133
17134 if (rs6000_sched_insert_nops < sched_finish_regroup_exact)
17135 {
17136 int n_nops = rs6000_sched_insert_nops;
17137
17138
17139
17140 if (can_issue_more == 0)
17141 can_issue_more = issue_rate;
17142 can_issue_more--;
17143 if (can_issue_more == 0)
17144 {
17145 can_issue_more = issue_rate - 1;
17146 (*group_count)++;
17147 end = true;
17148 for (i = 0; i < issue_rate; i++)
17149 {
17150 group_insns[i] = 0;
17151 }
17152 }
17153
17154 while (n_nops > 0)
17155 {
17156 nop = gen_nop ();
17157 emit_insn_before (nop, next_insn);
17158 if (can_issue_more == issue_rate - 1)
17159 end = false;
17160 can_issue_more--;
17161 if (can_issue_more == 0)
17162 {
17163 can_issue_more = issue_rate - 1;
17164 (*group_count)++;
17165 end = true;
17166 for (i = 0; i < issue_rate; i++)
17167 {
17168 group_insns[i] = 0;
17169 }
17170 }
17171 n_nops--;
17172 }
17173
17174
17175 can_issue_more++;
17176
17177
17178 *group_end
17179 = (end
17180 || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
17181 || (can_issue_more <= 2 && is_cracked_insn (next_insn))
17182 || (can_issue_more < issue_rate &&
17183 insn_terminates_group_p (next_insn, previous_group)));
17184 if (*group_end && end)
17185 (*group_count)--;
17186
17187 if (sched_verbose > 6)
17188 fprintf (dump, "done force: group count = %d, can_issue_more = %d\n",
17189 *group_count, can_issue_more);
17190 return can_issue_more;
17191 }
17192
17193 return can_issue_more;
17194 }
17195
17196
17197
17198
17199
17200
17201
17202
17203
17204
17205
17206
17207
17208
17209
17210
17211
17212
17213
17214
17215
17216
17217
17218
17219
17220
17221
17222
17223
17224 static int
17225 redefine_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
17226 {
17227 rtx insn, next_insn;
17228 int issue_rate;
17229 int can_issue_more;
17230 int slot, i;
17231 bool group_end;
17232 int group_count = 0;
17233 rtx *group_insns;
17234
17235
17236 issue_rate = rs6000_issue_rate ();
17237 group_insns = alloca (issue_rate * sizeof (rtx));
17238 for (i = 0; i < issue_rate; i++)
17239 {
17240 group_insns[i] = 0;
17241 }
17242 can_issue_more = issue_rate;
17243 slot = 0;
17244 insn = get_next_active_insn (prev_head_insn, tail);
17245 group_end = false;
17246
17247 while (insn != NULL_RTX)
17248 {
17249 slot = (issue_rate - can_issue_more);
17250 group_insns[slot] = insn;
17251 can_issue_more =
17252 rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
17253 if (insn_terminates_group_p (insn, current_group))
17254 can_issue_more = 0;
17255
17256 next_insn = get_next_active_insn (insn, tail);
17257 if (next_insn == NULL_RTX)
17258 return group_count + 1;
17259
17260
17261 group_end
17262 = (can_issue_more == 0
17263 || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
17264 || (can_issue_more <= 2 && is_cracked_insn (next_insn))
17265 || (can_issue_more < issue_rate &&
17266 insn_terminates_group_p (next_insn, previous_group)));
17267
17268 can_issue_more = force_new_group (sched_verbose, dump, group_insns,
17269 next_insn, &group_end, can_issue_more,
17270 &group_count);
17271
17272 if (group_end)
17273 {
17274 group_count++;
17275 can_issue_more = 0;
17276 for (i = 0; i < issue_rate; i++)
17277 {
17278 group_insns[i] = 0;
17279 }
17280 }
17281
17282 if (GET_MODE (next_insn) == TImode && can_issue_more)
17283 PUT_MODE (next_insn, VOIDmode);
17284 else if (!can_issue_more && GET_MODE (next_insn) != TImode)
17285 PUT_MODE (next_insn, TImode);
17286
17287 insn = next_insn;
17288 if (can_issue_more == 0)
17289 can_issue_more = issue_rate;
17290 }
17291
17292 return group_count;
17293 }
17294
17295
17296
17297
17298
17299
17300
17301 static int
17302 pad_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
17303 {
17304 rtx insn, next_insn;
17305 rtx nop;
17306 int issue_rate;
17307 int can_issue_more;
17308 int group_end;
17309 int group_count = 0;
17310
17311
17312 issue_rate = rs6000_issue_rate ();
17313 can_issue_more = issue_rate;
17314
17315 insn = get_next_active_insn (prev_head_insn, tail);
17316 next_insn = get_next_active_insn (insn, tail);
17317
17318 while (insn != NULL_RTX)
17319 {
17320 can_issue_more =
17321 rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
17322
17323 group_end = (next_insn == NULL_RTX || GET_MODE (next_insn) == TImode);
17324
17325 if (next_insn == NULL_RTX)
17326 break;
17327
17328 if (group_end)
17329 {
17330
17331
17332
17333
17334 if (can_issue_more
17335 && (rs6000_sched_insert_nops == sched_finish_pad_groups)
17336 && !insn_terminates_group_p (insn, current_group)
17337 && !insn_terminates_group_p (next_insn, previous_group))
17338 {
17339 if (!is_branch_slot_insn (next_insn))
17340 can_issue_more--;
17341
17342 while (can_issue_more)
17343 {
17344 nop = gen_nop ();
17345 emit_insn_before (nop, next_insn);
17346 can_issue_more--;
17347 }
17348 }
17349
17350 can_issue_more = issue_rate;
17351 group_count++;
17352 }
17353
17354 insn = next_insn;
17355 next_insn = get_next_active_insn (insn, tail);
17356 }
17357
17358 return group_count;
17359 }
17360
17361
17362
17363
17364 static void
17365 rs6000_sched_finish (FILE *dump, int sched_verbose)
17366 {
17367 int n_groups;
17368
17369 if (sched_verbose)
17370 fprintf (dump, "=== Finishing schedule.\n");
17371
17372 if (reload_completed && rs6000_sched_groups)
17373 {
17374 if (rs6000_sched_insert_nops == sched_finish_none)
17375 return;
17376
17377 if (rs6000_sched_insert_nops == sched_finish_pad_groups)
17378 n_groups = pad_groups (dump, sched_verbose,
17379 current_sched_info->prev_head,
17380 current_sched_info->next_tail);
17381 else
17382 n_groups = redefine_groups (dump, sched_verbose,
17383 current_sched_info->prev_head,
17384 current_sched_info->next_tail);
17385
17386 if (sched_verbose >= 6)
17387 {
17388 fprintf (dump, "ngroups = %d\n", n_groups);
17389 print_rtl (dump, current_sched_info->prev_head);
17390 fprintf (dump, "Done finish_sched\n");
17391 }
17392 }
17393 }
17394
17395
17396
17397 int
17398 rs6000_trampoline_size (void)
17399 {
17400 int ret = 0;
17401
17402 switch (DEFAULT_ABI)
17403 {
17404 default:
17405 gcc_unreachable ();
17406
17407 case ABI_AIX:
17408 ret = (TARGET_32BIT) ? 12 : 24;
17409 break;
17410
17411 case ABI_DARWIN:
17412 case ABI_V4:
17413 ret = (TARGET_32BIT) ? 40 : 48;
17414 break;
17415 }
17416
17417 return ret;
17418 }
17419
17420
17421
17422
17423
17424 void
17425 rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
17426 {
17427 int regsize = (TARGET_32BIT) ? 4 : 8;
17428 rtx ctx_reg = force_reg (Pmode, cxt);
17429
17430 switch (DEFAULT_ABI)
17431 {
17432 default:
17433 gcc_unreachable ();
17434
17435
17436 #define MEM_DEREF(addr) gen_rtx_MEM (Pmode, memory_address (Pmode, addr))
17437 #define MEM_PLUS(addr,offset) \
17438 gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (addr, offset)))
17439
17440
17441 case ABI_AIX:
17442 {
17443 rtx fn_reg = gen_reg_rtx (Pmode);
17444 rtx toc_reg = gen_reg_rtx (Pmode);
17445 emit_move_insn (fn_reg, MEM_DEREF (fnaddr));
17446 emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize));
17447 emit_move_insn (MEM_DEREF (addr), fn_reg);
17448 emit_move_insn (MEM_PLUS (addr, regsize), toc_reg);
17449 emit_move_insn (MEM_PLUS (addr, 2*regsize), ctx_reg);
17450 }
17451 break;
17452
17453
17454 case ABI_DARWIN:
17455 case ABI_V4:
17456 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
17457 FALSE, VOIDmode, 4,
17458 addr, Pmode,
17459 GEN_INT (rs6000_trampoline_size ()), SImode,
17460 fnaddr, Pmode,
17461 ctx_reg, Pmode);
17462 break;
17463 }
17464
17465 return;
17466 }
17467
17468
17469
17470
17471 const struct attribute_spec rs6000_attribute_table[] =
17472 {
17473
17474 { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute },
17475 { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
17476 { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
17477 { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
17478 { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
17479 #ifdef SUBTARGET_ATTRIBUTE_TABLE
17480 SUBTARGET_ATTRIBUTE_TABLE,
17481 #endif
17482 { NULL, 0, 0, false, false, false, NULL }
17483 };
17484
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495 static tree
17496 rs6000_handle_altivec_attribute (tree *node,
17497 tree name ATTRIBUTE_UNUSED,
17498 tree args,
17499 int flags ATTRIBUTE_UNUSED,
17500 bool *no_add_attrs)
17501 {
17502 tree type = *node, result = NULL_TREE;
17503 enum machine_mode mode;
17504 int unsigned_p;
17505 char altivec_type
17506 = ((args && TREE_CODE (args) == TREE_LIST && TREE_VALUE (args)
17507 && TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
17508 ? *IDENTIFIER_POINTER (TREE_VALUE (args))
17509 : '?');
17510
17511 while (POINTER_TYPE_P (type)
17512 || TREE_CODE (type) == FUNCTION_TYPE
17513 || TREE_CODE (type) == METHOD_TYPE
17514 || TREE_CODE (type) == ARRAY_TYPE)
17515 type = TREE_TYPE (type);
17516
17517 mode = TYPE_MODE (type);
17518
17519
17520 if (type == long_unsigned_type_node || type == long_integer_type_node)
17521 {
17522 if (TARGET_64BIT)
17523 error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
17524 else if (rs6000_warn_altivec_long)
17525 warning (0, "use of %<long%> in AltiVec types is deprecated; use %<int%>");
17526 }
17527 else if (type == long_long_unsigned_type_node
17528 || type == long_long_integer_type_node)
17529 error ("use of %<long long%> in AltiVec types is invalid");
17530 else if (type == double_type_node)
17531 error ("use of %<double%> in AltiVec types is invalid");
17532 else if (type == long_double_type_node)
17533 error ("use of %<long double%> in AltiVec types is invalid");
17534 else if (type == boolean_type_node)
17535 error ("use of boolean types in AltiVec types is invalid");
17536 else if (TREE_CODE (type) == COMPLEX_TYPE)
17537 error ("use of %<complex%> in AltiVec types is invalid");
17538 else if (DECIMAL_FLOAT_MODE_P (mode))
17539 error ("use of decimal floating point types in AltiVec types is invalid");
17540
17541 switch (altivec_type)
17542 {
17543 case 'v':
17544 unsigned_p = TYPE_UNSIGNED (type);
17545 switch (mode)
17546 {
17547 case SImode:
17548 result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
17549 break;
17550 case HImode:
17551 result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
17552 break;
17553 case QImode:
17554 result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
17555 break;
17556 case SFmode: result = V4SF_type_node; break;
17557
17558
17559
17560 case V4SImode: case V8HImode: case V16QImode: case V4SFmode:
17561 result = type;
17562 default: break;
17563 }
17564 break;
17565 case 'b':
17566 switch (mode)
17567 {
17568 case SImode: case V4SImode: result = bool_V4SI_type_node; break;
17569 case HImode: case V8HImode: result = bool_V8HI_type_node; break;
17570 case QImode: case V16QImode: result = bool_V16QI_type_node;
17571 default: break;
17572 }
17573 break;
17574 case 'p':
17575 switch (mode)
17576 {
17577 case V8HImode: result = pixel_V8HI_type_node;
17578 default: break;
17579 }
17580 default: break;
17581 }
17582
17583 if (result && result != type && TYPE_READONLY (type))
17584 result = build_qualified_type (result, TYPE_QUAL_CONST);
17585
17586 *no_add_attrs = true;
17587
17588 if (result)
17589 *node = reconstruct_complex_type (*node, result);
17590
17591 return NULL_TREE;
17592 }
17593
17594
17595
17596
17597 static const char *
17598 rs6000_mangle_fundamental_type (tree type)
17599 {
17600 if (type == bool_char_type_node) return "U6__boolc";
17601 if (type == bool_short_type_node) return "U6__bools";
17602 if (type == pixel_type_node) return "u7__pixel";
17603 if (type == bool_int_type_node) return "U6__booli";
17604
17605
17606
17607 if (TYPE_MAIN_VARIANT (type) == long_double_type_node
17608 && TARGET_ELF
17609 && TARGET_LONG_DOUBLE_128
17610 && !TARGET_IEEEQUAD)
17611 return "g";
17612
17613
17614 return NULL;
17615 }
17616
17617
17618
17619
17620 static tree
17621 rs6000_handle_longcall_attribute (tree *node, tree name,
17622 tree args ATTRIBUTE_UNUSED,
17623 int flags ATTRIBUTE_UNUSED,
17624 bool *no_add_attrs)
17625 {
17626 if (TREE_CODE (*node) != FUNCTION_TYPE
17627 && TREE_CODE (*node) != FIELD_DECL
17628 && TREE_CODE (*node) != TYPE_DECL)
17629 {
17630 warning (OPT_Wattributes, "%qs attribute only applies to functions",
17631 IDENTIFIER_POINTER (name));
17632 *no_add_attrs = true;
17633 }
17634
17635 return NULL_TREE;
17636 }
17637
17638
17639
17640 static void
17641 rs6000_set_default_type_attributes (tree type)
17642 {
17643 if (rs6000_default_long_calls
17644 && (TREE_CODE (type) == FUNCTION_TYPE
17645 || TREE_CODE (type) == METHOD_TYPE))
17646 TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
17647 NULL_TREE,
17648 TYPE_ATTRIBUTES (type));
17649
17650 #if TARGET_MACHO
17651 darwin_set_default_type_attributes (type);
17652 #endif
17653 }
17654
17655
17656
17657
17658 rtx
17659 rs6000_longcall_ref (rtx call_ref)
17660 {
17661 const char *call_name;
17662 tree node;
17663
17664 if (GET_CODE (call_ref) != SYMBOL_REF)
17665 return call_ref;
17666
17667
17668 call_name = XSTR (call_ref, 0);
17669 if (*call_name == '.')
17670 {
17671 while (*call_name == '.')
17672 call_name++;
17673
17674 node = get_identifier (call_name);
17675 call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node));
17676 }
17677
17678 return force_reg (Pmode, call_ref);
17679 }
17680
17681 #ifndef TARGET_USE_MS_BITFIELD_LAYOUT
17682 #define TARGET_USE_MS_BITFIELD_LAYOUT 0
17683 #endif
17684
17685
17686
17687 static tree
17688 rs6000_handle_struct_attribute (tree *node, tree name,
17689 tree args ATTRIBUTE_UNUSED,
17690 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
17691 {
17692 tree *type = NULL;
17693 if (DECL_P (*node))
17694 {
17695 if (TREE_CODE (*node) == TYPE_DECL)
17696 type = &TREE_TYPE (*node);
17697 }
17698 else
17699 type = node;
17700
17701 if (!(type && (TREE_CODE (*type) == RECORD_TYPE
17702 || TREE_CODE (*type) == UNION_TYPE)))
17703 {
17704 warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name));
17705 *no_add_attrs = true;
17706 }
17707
17708 else if ((is_attribute_p ("ms_struct", name)
17709 && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
17710 || ((is_attribute_p ("gcc_struct", name)
17711 && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
17712 {
17713 warning (OPT_Wattributes, "%qs incompatible attribute ignored",
17714 IDENTIFIER_POINTER (name));
17715 *no_add_attrs = true;
17716 }
17717
17718 return NULL_TREE;
17719 }
17720
17721 static bool
17722 rs6000_ms_bitfield_layout_p (tree record_type)
17723 {
17724 return (TARGET_USE_MS_BITFIELD_LAYOUT &&
17725 !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
17726 || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
17727 }
17728
17729 #ifdef USING_ELFOS_H
17730
17731
17732
17733 static void
17734 rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
17735 {
17736 if (DEFAULT_ABI == ABI_AIX
17737 && TARGET_MINIMAL_TOC
17738 && !TARGET_RELOCATABLE)
17739 {
17740 if (!toc_initialized)
17741 {
17742 toc_initialized = 1;
17743 fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
17744 (*targetm.asm_out.internal_label) (asm_out_file, "LCTOC", 0);
17745 fprintf (asm_out_file, "\t.tc ");
17746 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],");
17747 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
17748 fprintf (asm_out_file, "\n");
17749
17750 fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
17751 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
17752 fprintf (asm_out_file, " = .+32768\n");
17753 }
17754 else
17755 fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
17756 }
17757 else if (DEFAULT_ABI == ABI_AIX && !TARGET_RELOCATABLE)
17758 fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
17759 else
17760 {
17761 fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
17762 if (!toc_initialized)
17763 {
17764 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
17765 fprintf (asm_out_file, " = .+32768\n");
17766 toc_initialized = 1;
17767 }
17768 }
17769 }
17770
17771
17772
17773 static void
17774 rs6000_elf_asm_init_sections (void)
17775 {
17776 toc_section
17777 = get_unnamed_section (0, rs6000_elf_output_toc_section_asm_op, NULL);
17778
17779 sdata2_section
17780 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
17781 SDATA2_SECTION_ASM_OP);
17782 }
17783
17784
17785
17786 static section *
17787 rs6000_elf_select_rtx_section (enum machine_mode mode, rtx x,
17788 unsigned HOST_WIDE_INT align)
17789 {
17790 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
17791 return toc_section;
17792 else
17793 return default_elf_select_rtx_section (mode, x, align);
17794 }
17795
17796
17797
17798
17799
17800
17801
17802
17803
17804 static void
17805 rs6000_elf_encode_section_info (tree decl, rtx rtl, int first)
17806 {
17807 default_encode_section_info (decl, rtl, first);
17808
17809 if (first
17810 && TREE_CODE (decl) == FUNCTION_DECL
17811 && !TARGET_AIX
17812 && DEFAULT_ABI == ABI_AIX)
17813 {
17814 rtx sym_ref = XEXP (rtl, 0);
17815 size_t len = strlen (XSTR (sym_ref, 0));
17816 char *str = alloca (len + 2);
17817 str[0] = '.';
17818 memcpy (str + 1, XSTR (sym_ref, 0), len + 1);
17819 XSTR (sym_ref, 0) = ggc_alloc_string (str, len + 1);
17820 }
17821 }
17822
17823 bool
17824 rs6000_elf_in_small_data_p (tree decl)
17825 {
17826 if (rs6000_sdata == SDATA_NONE)
17827 return false;
17828
17829
17830 if (TREE_CODE (decl) == STRING_CST)
17831 return false;
17832
17833
17834 if (TREE_CODE (decl) == FUNCTION_DECL)
17835 return false;
17836
17837 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
17838 {
17839 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
17840 if (strcmp (section, ".sdata") == 0
17841 || strcmp (section, ".sdata2") == 0
17842 || strcmp (section, ".sbss") == 0
17843 || strcmp (section, ".sbss2") == 0
17844 || strcmp (section, ".PPC.EMB.sdata0") == 0
17845 || strcmp (section, ".PPC.EMB.sbss0") == 0)
17846 return true;
17847 }
17848 else
17849 {
17850 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
17851
17852 if (size > 0
17853 && (unsigned HOST_WIDE_INT) size <= g_switch_value
17854
17855
17856 && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)))
17857 return true;
17858 }
17859
17860 return false;
17861 }
17862
17863 #endif
17864
17865
17866
17867 static bool
17868 rs6000_use_blocks_for_constant_p (enum machine_mode mode, rtx x)
17869 {
17870 return !ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode);
17871 }
17872
17873
17874
17875
17876
17877
17878
17879
17880 rtx
17881 find_addr_reg (rtx addr)
17882 {
17883 while (GET_CODE (addr) == PLUS)
17884 {
17885 if (GET_CODE (XEXP (addr, 0)) == REG
17886 && REGNO (XEXP (addr, 0)) != 0)
17887 addr = XEXP (addr, 0);
17888 else if (GET_CODE (XEXP (addr, 1)) == REG
17889 && REGNO (XEXP (addr, 1)) != 0)
17890 addr = XEXP (addr, 1);
17891 else if (CONSTANT_P (XEXP (addr, 0)))
17892 addr = XEXP (addr, 1);
17893 else if (CONSTANT_P (XEXP (addr, 1)))
17894 addr = XEXP (addr, 0);
17895 else
17896 gcc_unreachable ();
17897 }
17898 gcc_assert (GET_CODE (addr) == REG && REGNO (addr) != 0);
17899 return addr;
17900 }
17901
17902 void
17903 rs6000_fatal_bad_address (rtx op)
17904 {
17905 fatal_insn ("bad address", op);
17906 }
17907
17908 #if TARGET_MACHO
17909
17910 static tree branch_island_list = 0;
17911
17912
17913
17914
17915 static void
17916 add_compiler_branch_island (tree label_name, tree function_name,
17917 int line_number)
17918 {
17919 tree branch_island = build_tree_list (function_name, label_name);
17920 TREE_TYPE (branch_island) = build_int_cst (NULL_TREE, line_number);
17921 TREE_CHAIN (branch_island) = branch_island_list;
17922 branch_island_list = branch_island;
17923 }
17924
17925 #define BRANCH_ISLAND_LABEL_NAME(BRANCH_ISLAND) TREE_VALUE (BRANCH_ISLAND)
17926 #define BRANCH_ISLAND_FUNCTION_NAME(BRANCH_ISLAND) TREE_PURPOSE (BRANCH_ISLAND)
17927 #define BRANCH_ISLAND_LINE_NUMBER(BRANCH_ISLAND) \
17928 TREE_INT_CST_LOW (TREE_TYPE (BRANCH_ISLAND))
17929
17930
17931
17932
17933
17934
17935
17936 static void
17937 macho_branch_islands (void)
17938 {
17939 char tmp_buf[512];
17940 tree branch_island;
17941
17942 for (branch_island = branch_island_list;
17943 branch_island;
17944 branch_island = TREE_CHAIN (branch_island))
17945 {
17946 const char *label =
17947 IDENTIFIER_POINTER (BRANCH_ISLAND_LABEL_NAME (branch_island));
17948 const char *name =
17949 IDENTIFIER_POINTER (BRANCH_ISLAND_FUNCTION_NAME (branch_island));
17950 char name_buf[512];
17951
17952 if (name[0] == '*' || name[0] == '&')
17953 strcpy (name_buf, name+1);
17954 else
17955 {
17956 name_buf[0] = '_';
17957 strcpy (name_buf+1, name);
17958 }
17959 strcpy (tmp_buf, "\n");
17960 strcat (tmp_buf, label);
17961 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
17962 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
17963 dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
17964 #endif
17965 if (flag_pic)
17966 {
17967 strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
17968 strcat (tmp_buf, label);
17969 strcat (tmp_buf, "_pic\n");
17970 strcat (tmp_buf, label);
17971 strcat (tmp_buf, "_pic:\n\tmflr r11\n");
17972
17973 strcat (tmp_buf, "\taddis r11,r11,ha16(");
17974 strcat (tmp_buf, name_buf);
17975 strcat (tmp_buf, " - ");
17976 strcat (tmp_buf, label);
17977 strcat (tmp_buf, "_pic)\n");
17978
17979 strcat (tmp_buf, "\tmtlr r0\n");
17980
17981 strcat (tmp_buf, "\taddi r12,r11,lo16(");
17982 strcat (tmp_buf, name_buf);
17983 strcat (tmp_buf, " - ");
17984 strcat (tmp_buf, label);
17985 strcat (tmp_buf, "_pic)\n");
17986
17987 strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
17988 }
17989 else
17990 {
17991 strcat (tmp_buf, ":\nlis r12,hi16(");
17992 strcat (tmp_buf, name_buf);
17993 strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
17994 strcat (tmp_buf, name_buf);
17995 strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
17996 }
17997 output_asm_insn (tmp_buf, 0);
17998 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
17999 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
18000 dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
18001 #endif
18002 }
18003
18004 branch_island_list = 0;
18005 }
18006
18007
18008
18009
18010 static int
18011 no_previous_def (tree function_name)
18012 {
18013 tree branch_island;
18014 for (branch_island = branch_island_list;
18015 branch_island;
18016 branch_island = TREE_CHAIN (branch_island))
18017 if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
18018 return 0;
18019 return 1;
18020 }
18021
18022
18023
18024
18025 static tree
18026 get_prev_label (tree function_name)
18027 {
18028 tree branch_island;
18029 for (branch_island = branch_island_list;
18030 branch_island;
18031 branch_island = TREE_CHAIN (branch_island))
18032 if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
18033 return BRANCH_ISLAND_LABEL_NAME (branch_island);
18034 return 0;
18035 }
18036
18037 #ifndef DARWIN_LINKER_GENERATES_ISLANDS
18038 #define DARWIN_LINKER_GENERATES_ISLANDS 0
18039 #endif
18040
18041
18042 #define DARWIN_GENERATE_ISLANDS (!DARWIN_LINKER_GENERATES_ISLANDS \
18043 || flag_mkernel || flag_apple_kext)
18044
18045
18046
18047
18048
18049
18050 char *
18051 output_call (rtx insn, rtx *operands, int dest_operand_number,
18052 int cookie_operand_number)
18053 {
18054 static char buf[256];
18055 if (DARWIN_GENERATE_ISLANDS
18056 && GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
18057 && (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
18058 {
18059 tree labelname;
18060 tree funname = get_identifier (XSTR (operands[dest_operand_number], 0));
18061
18062 if (no_previous_def (funname))
18063 {
18064 int line_number = 0;
18065 rtx label_rtx = gen_label_rtx ();
18066 char *label_buf, temp_buf[256];
18067 ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
18068 CODE_LABEL_NUMBER (label_rtx));
18069 label_buf = temp_buf[0] == '*' ? temp_buf + 1 : temp_buf;
18070 labelname = get_identifier (label_buf);
18071 for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
18072 if (insn)
18073 line_number = NOTE_LINE_NUMBER (insn);
18074 add_compiler_branch_island (labelname, funname, line_number);
18075 }
18076 else
18077 labelname = get_prev_label (funname);
18078
18079
18080
18081
18082
18083
18084 sprintf (buf, "jbsr %%z%d,%.246s",
18085 dest_operand_number, IDENTIFIER_POINTER (labelname));
18086 }
18087 else
18088 sprintf (buf, "bl %%z%d", dest_operand_number);
18089 return buf;
18090 }
18091
18092
18093
18094 void
18095 machopic_output_stub (FILE *file, const char *symb, const char *stub)
18096 {
18097 unsigned int length;
18098 char *symbol_name, *lazy_ptr_name;
18099 char *local_label_0;
18100 static int label = 0;
18101
18102
18103 symb = (*targetm.strip_name_encoding) (symb);
18104
18105
18106 length = strlen (symb);
18107 symbol_name = alloca (length + 32);
18108 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
18109
18110 lazy_ptr_name = alloca (length + 32);
18111 GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name, symb, length);
18112
18113 if (flag_pic == 2)
18114 switch_to_section (darwin_sections[machopic_picsymbol_stub1_section]);
18115 else
18116 switch_to_section (darwin_sections[machopic_symbol_stub1_section]);
18117
18118 if (flag_pic == 2)
18119 {
18120 fprintf (file, "\t.align 5\n");
18121
18122 fprintf (file, "%s:\n", stub);
18123 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
18124
18125 label++;
18126 local_label_0 = alloca (sizeof ("\"L00000000000$spb\""));
18127 sprintf (local_label_0, "\"L%011d$spb\"", label);
18128
18129 fprintf (file, "\tmflr r0\n");
18130 fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
18131 fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
18132 fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
18133 lazy_ptr_name, local_label_0);
18134 fprintf (file, "\tmtlr r0\n");
18135 fprintf (file, "\t%s r12,lo16(%s-%s)(r11)\n",
18136 (TARGET_64BIT ? "ldu" : "lwzu"),
18137 lazy_ptr_name, local_label_0);
18138 fprintf (file, "\tmtctr r12\n");
18139 fprintf (file, "\tbctr\n");
18140 }
18141 else
18142 {
18143 fprintf (file, "\t.align 4\n");
18144
18145 fprintf (file, "%s:\n", stub);
18146 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
18147
18148 fprintf (file, "\tlis r11,ha16(%s)\n", lazy_ptr_name);
18149 fprintf (file, "\t%s r12,lo16(%s)(r11)\n",
18150 (TARGET_64BIT ? "ldu" : "lwzu"),
18151 lazy_ptr_name);
18152 fprintf (file, "\tmtctr r12\n");
18153 fprintf (file, "\tbctr\n");
18154 }
18155
18156 switch_to_section (darwin_sections[machopic_lazy_symbol_ptr_section]);
18157 fprintf (file, "%s:\n", lazy_ptr_name);
18158 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
18159 fprintf (file, "%sdyld_stub_binding_helper\n",
18160 (TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t"));
18161 }
18162
18163
18164
18165
18166
18167
18168 #define SMALL_INT(X) ((UINTVAL (X) + 0x8000) < 0x10000)
18169
18170 rtx
18171 rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
18172 rtx reg)
18173 {
18174 rtx base, offset;
18175
18176 if (reg == NULL && ! reload_in_progress && ! reload_completed)
18177 reg = gen_reg_rtx (Pmode);
18178
18179 if (GET_CODE (orig) == CONST)
18180 {
18181 rtx reg_temp;
18182
18183 if (GET_CODE (XEXP (orig, 0)) == PLUS
18184 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
18185 return orig;
18186
18187 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
18188
18189
18190
18191 reg_temp = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
18192 base = rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
18193 Pmode, reg_temp);
18194 offset =
18195 rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
18196 Pmode, reg);
18197
18198 if (GET_CODE (offset) == CONST_INT)
18199 {
18200 if (SMALL_INT (offset))
18201 return plus_constant (base, INTVAL (offset));
18202 else if (! reload_in_progress && ! reload_completed)
18203 offset = force_reg (Pmode, offset);
18204 else
18205 {
18206 rtx mem = force_const_mem (Pmode, orig);
18207 return machopic_legitimize_pic_address (mem, Pmode, reg);
18208 }
18209 }
18210 return gen_rtx_PLUS (Pmode, base, offset);
18211 }
18212
18213
18214 return machopic_legitimize_pic_address (orig, mode, reg);
18215 }
18216
18217
18218
18219
18220 static void
18221 rs6000_darwin_file_start (void)
18222 {
18223 static const struct
18224 {
18225 const char *arg;
18226 const char *name;
18227 int if_set;
18228 } mapping[] = {
18229 { "ppc64", "ppc64", MASK_64BIT },
18230 { "970", "ppc970", MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64 },
18231 { "power4", "ppc970", 0 },
18232 { "G5", "ppc970", 0 },
18233 { "7450", "ppc7450", 0 },
18234 { "7400", "ppc7400", MASK_ALTIVEC },
18235 { "G4", "ppc7400", 0 },
18236 { "750", "ppc750", 0 },
18237 { "740", "ppc750", 0 },
18238 { "G3", "ppc750", 0 },
18239 { "604e", "ppc604e", 0 },
18240 { "604", "ppc604", 0 },
18241 { "603e", "ppc603", 0 },
18242 { "603", "ppc603", 0 },
18243 { "601", "ppc601", 0 },
18244 { NULL, "ppc", 0 } };
18245 const char *cpu_id = "";
18246 size_t i;
18247
18248 rs6000_file_start ();
18249 darwin_file_start ();
18250
18251
18252 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
18253 if (rs6000_select[i].set_arch_p && rs6000_select[i].string
18254 && rs6000_select[i].string[0] != '\0')
18255 cpu_id = rs6000_select[i].string;
18256
18257
18258
18259
18260
18261 i = 0;
18262 while (mapping[i].arg != NULL
18263 && strcmp (mapping[i].arg, cpu_id) != 0
18264 && (mapping[i].if_set & target_flags) == 0)
18265 i++;
18266
18267 fprintf (asm_out_file, "\t.machine %s\n", mapping[i].name);
18268 }
18269
18270 #endif
18271
18272 #if TARGET_ELF
18273 static int
18274 rs6000_elf_reloc_rw_mask (void)
18275 {
18276 if (flag_pic)
18277 return 3;
18278 else if (DEFAULT_ABI == ABI_AIX)
18279 return 2;
18280 else
18281 return 0;
18282 }
18283
18284
18285
18286
18287
18288
18289
18290
18291 static void
18292 rs6000_elf_asm_out_constructor (rtx symbol, int priority)
18293 {
18294 const char *section = ".ctors";
18295 char buf[16];
18296
18297 if (priority != DEFAULT_INIT_PRIORITY)
18298 {
18299 sprintf (buf, ".ctors.%.5u",
18300
18301
18302
18303 MAX_INIT_PRIORITY - priority);
18304 section = buf;
18305 }
18306
18307 switch_to_section (get_section (section, SECTION_WRITE, NULL));
18308 assemble_align (POINTER_SIZE);
18309
18310 if (TARGET_RELOCATABLE)
18311 {
18312 fputs ("\t.long (", asm_out_file);
18313 output_addr_const (asm_out_file, symbol);
18314 fputs (")@fixup\n", asm_out_file);
18315 }
18316 else
18317 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
18318 }
18319
18320 static void
18321 rs6000_elf_asm_out_destructor (rtx symbol, int priority)
18322 {
18323 const char *section = ".dtors";
18324 char buf[16];
18325
18326 if (priority != DEFAULT_INIT_PRIORITY)
18327 {
18328 sprintf (buf, ".dtors.%.5u",
18329
18330
18331
18332 MAX_INIT_PRIORITY - priority);
18333 section = buf;
18334 }
18335
18336 switch_to_section (get_section (section, SECTION_WRITE, NULL));
18337 assemble_align (POINTER_SIZE);
18338
18339 if (TARGET_RELOCATABLE)
18340 {
18341 fputs ("\t.long (", asm_out_file);
18342 output_addr_const (asm_out_file, symbol);
18343 fputs (")@fixup\n", asm_out_file);
18344 }
18345 else
18346 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
18347 }
18348
18349 void
18350 rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
18351 {
18352 if (TARGET_64BIT)
18353 {
18354 fputs ("\t.section\t\".opd\",\"aw\"\n\t.align 3\n", file);
18355 ASM_OUTPUT_LABEL (file, name);
18356 fputs (DOUBLE_INT_ASM_OP, file);
18357 rs6000_output_function_entry (file, name);
18358 fputs (",.TOC.@tocbase,0\n\t.previous\n", file);
18359 if (DOT_SYMBOLS)
18360 {
18361 fputs ("\t.size\t", file);
18362 assemble_name (file, name);
18363 fputs (",24\n\t.type\t.", file);
18364 assemble_name (file, name);
18365 fputs (",@function\n", file);
18366 if (TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
18367 {
18368 fputs ("\t.globl\t.", file);
18369 assemble_name (file, name);
18370 putc ('\n', file);
18371 }
18372 }
18373 else
18374 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
18375 ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
18376 rs6000_output_function_entry (file, name);
18377 fputs (":\n", file);
18378 return;
18379 }
18380
18381 if (TARGET_RELOCATABLE
18382 && !TARGET_SECURE_PLT
18383 && (get_pool_size () != 0 || current_function_profile)
18384 && uses_TOC ())
18385 {
18386 char buf[256];
18387
18388 (*targetm.asm_out.internal_label) (file, "LCL", rs6000_pic_labelno);
18389
18390 ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
18391 fprintf (file, "\t.long ");
18392 assemble_name (file, buf);
18393 putc ('-', file);
18394 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
18395 assemble_name (file, buf);
18396 putc ('\n', file);
18397 }
18398
18399 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
18400 ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
18401
18402 if (DEFAULT_ABI == ABI_AIX)
18403 {
18404 const char *desc_name, *orig_name;
18405
18406 orig_name = (*targetm.strip_name_encoding) (name);
18407 desc_name = orig_name;
18408 while (*desc_name == '.')
18409 desc_name++;
18410
18411 if (TREE_PUBLIC (decl))
18412 fprintf (file, "\t.globl %s\n", desc_name);
18413
18414 fprintf (file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
18415 fprintf (file, "%s:\n", desc_name);
18416 fprintf (file, "\t.long %s\n", orig_name);
18417 fputs ("\t.long _GLOBAL_OFFSET_TABLE_\n", file);
18418 if (DEFAULT_ABI == ABI_AIX)
18419 fputs ("\t.long 0\n", file);
18420 fprintf (file, "\t.previous\n");
18421 }
18422 ASM_OUTPUT_LABEL (file, name);
18423 }
18424
18425 static void
18426 rs6000_elf_end_indicate_exec_stack (void)
18427 {
18428 if (TARGET_32BIT)
18429 file_end_indicate_exec_stack ();
18430 }
18431 #endif
18432
18433 #if TARGET_XCOFF
18434 static void
18435 rs6000_xcoff_asm_output_anchor (rtx symbol)
18436 {
18437 char buffer[100];
18438
18439 sprintf (buffer, "$ + " HOST_WIDE_INT_PRINT_DEC,
18440 SYMBOL_REF_BLOCK_OFFSET (symbol));
18441 ASM_OUTPUT_DEF (asm_out_file, XSTR (symbol, 0), buffer);
18442 }
18443
18444 static void
18445 rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
18446 {
18447 fputs (GLOBAL_ASM_OP, stream);
18448 RS6000_OUTPUT_BASENAME (stream, name);
18449 putc ('\n', stream);
18450 }
18451
18452
18453
18454
18455 static void
18456 rs6000_xcoff_output_readonly_section_asm_op (const void *directive)
18457 {
18458 fprintf (asm_out_file, "\t.csect %s[RO],3\n",
18459 *(const char *const *) directive);
18460 }
18461
18462
18463
18464 static void
18465 rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
18466 {
18467 fprintf (asm_out_file, "\t.csect %s[RW],3\n",
18468 *(const char *const *) directive);
18469 }
18470
18471
18472
18473 static void
18474 rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
18475 {
18476 if (TARGET_MINIMAL_TOC)
18477 {
18478
18479
18480
18481 if (!toc_initialized)
18482 {
18483 fputs ("\t.toc\nLCTOC..1:\n", asm_out_file);
18484 fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file);
18485 toc_initialized = 1;
18486 }
18487 fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n",
18488 (TARGET_32BIT ? "" : ",3"));
18489 }
18490 else
18491 fputs ("\t.toc\n", asm_out_file);
18492 }
18493
18494
18495
18496 static void
18497 rs6000_xcoff_asm_init_sections (void)
18498 {
18499 read_only_data_section
18500 = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
18501 &xcoff_read_only_section_name);
18502
18503 private_data_section
18504 = get_unnamed_section (SECTION_WRITE,
18505 rs6000_xcoff_output_readwrite_section_asm_op,
18506 &xcoff_private_data_section_name);
18507
18508 read_only_private_data_section
18509 = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
18510 &xcoff_private_data_section_name);
18511
18512 toc_section
18513 = get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
18514
18515 readonly_data_section = read_only_data_section;
18516 exception_section = data_section;
18517 }
18518
18519 static int
18520 rs6000_xcoff_reloc_rw_mask (void)
18521 {
18522 return 3;
18523 }
18524
18525 static void
18526 rs6000_xcoff_asm_named_section (const char *name, unsigned int flags,
18527 tree decl ATTRIBUTE_UNUSED)
18528 {
18529 int smclass;
18530 static const char * const suffix[3] = { "PR", "RO", "RW" };
18531
18532 if (flags & SECTION_CODE)
18533 smclass = 0;
18534 else if (flags & SECTION_WRITE)
18535 smclass = 2;
18536 else
18537 smclass = 1;
18538
18539 fprintf (asm_out_file, "\t.csect %s%s[%s],%u\n",
18540 (flags & SECTION_CODE) ? "." : "",
18541 name, suffix[smclass], flags & SECTION_ENTSIZE);
18542 }
18543
18544 static section *
18545 rs6000_xcoff_select_section (tree decl, int reloc,
18546 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
18547 {
18548 if (decl_readonly_section (decl, reloc))
18549 {
18550 if (TREE_PUBLIC (decl))
18551 return read_only_data_section;
18552 else
18553 return read_only_private_data_section;
18554 }
18555 else
18556 {
18557 if (TREE_PUBLIC (decl))
18558 return data_section;
18559 else
18560 return private_data_section;
18561 }
18562 }
18563
18564 static void
18565 rs6000_xcoff_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
18566 {
18567 const char *name;
18568
18569
18570 if (!TREE_PUBLIC (decl)
18571 || DECL_COMMON (decl)
18572 || DECL_INITIAL (decl) == NULL_TREE
18573 || DECL_INITIAL (decl) == error_mark_node
18574 || (flag_zero_initialized_in_bss
18575 && initializer_zerop (DECL_INITIAL (decl))))
18576 return;
18577
18578 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
18579 name = (*targetm.strip_name_encoding) (name);
18580 DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
18581 }
18582
18583
18584
18585
18586
18587
18588
18589 static section *
18590 rs6000_xcoff_select_rtx_section (enum machine_mode mode, rtx x,
18591 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
18592 {
18593 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
18594 return toc_section;
18595 else
18596 return read_only_private_data_section;
18597 }
18598
18599
18600
18601 static const char *
18602 rs6000_xcoff_strip_name_encoding (const char *name)
18603 {
18604 size_t len;
18605 if (*name == '*')
18606 name++;
18607 len = strlen (name);
18608 if (name[len - 1] == ']')
18609 return ggc_alloc_string (name, len - 4);
18610 else
18611 return name;
18612 }
18613
18614
18615
18616 static unsigned int
18617 rs6000_xcoff_section_type_flags (tree decl, const char *name, int reloc)
18618 {
18619 unsigned int align;
18620 unsigned int flags = default_section_type_flags (decl, name, reloc);
18621
18622
18623 if (flags & SECTION_CODE)
18624 align = MIN_UNITS_PER_WORD;
18625 else
18626
18627 align = MAX ((DECL_ALIGN (decl) / BITS_PER_UNIT),
18628 int_size_in_bytes (TREE_TYPE (decl)) > MIN_UNITS_PER_WORD
18629 ? UNITS_PER_FP_WORD : MIN_UNITS_PER_WORD);
18630
18631 return flags | (exact_log2 (align) & SECTION_ENTSIZE);
18632 }
18633
18634
18635
18636
18637
18638
18639
18640
18641
18642
18643
18644
18645
18646 static void
18647 rs6000_xcoff_file_start (void)
18648 {
18649 rs6000_gen_section_name (&xcoff_bss_section_name,
18650 main_input_filename, ".bss_");
18651 rs6000_gen_section_name (&xcoff_private_data_section_name,
18652 main_input_filename, ".rw_");
18653 rs6000_gen_section_name (&xcoff_read_only_section_name,
18654 main_input_filename, ".ro_");
18655
18656 fputs ("\t.file\t", asm_out_file);
18657 output_quoted_string (asm_out_file, main_input_filename);
18658 fputc ('\n', asm_out_file);
18659 if (write_symbols != NO_DEBUG)
18660 switch_to_section (private_data_section);
18661 switch_to_section (text_section);
18662 if (profile_flag)
18663 fprintf (asm_out_file, "\t.extern %s\n", RS6000_MCOUNT);
18664 rs6000_file_start ();
18665 }
18666
18667
18668
18669
18670 static void
18671 rs6000_xcoff_file_end (void)
18672 {
18673 switch_to_section (text_section);
18674 fputs ("_section_.text:\n", asm_out_file);
18675 switch_to_section (data_section);
18676 fputs (TARGET_32BIT
18677 ? "\t.long _section_.text\n" : "\t.llong _section_.text\n",
18678 asm_out_file);
18679 }
18680 #endif
18681
18682
18683
18684
18685
18686 static bool
18687 rs6000_rtx_costs (rtx x, int code, int outer_code, int *total)
18688 {
18689 enum machine_mode mode = GET_MODE (x);
18690
18691 switch (code)
18692 {
18693
18694 case CONST_INT:
18695 if (((outer_code == SET
18696 || outer_code == PLUS
18697 || outer_code == MINUS)
18698 && (satisfies_constraint_I (x)
18699 || satisfies_constraint_L (x)))
18700 || (outer_code == AND
18701 && (satisfies_constraint_K (x)
18702 || (mode == SImode
18703 ? satisfies_constraint_L (x)
18704 : satisfies_constraint_J (x))
18705 || mask_operand (x, mode)
18706 || (mode == DImode
18707 && mask64_operand (x, DImode))))
18708 || ((outer_code == IOR || outer_code == XOR)
18709 && (satisfies_constraint_K (x)
18710 || (mode == SImode
18711 ? satisfies_constraint_L (x)
18712 : satisfies_constraint_J (x))))
18713 || outer_code == ASHIFT
18714 || outer_code == ASHIFTRT
18715 || outer_code == LSHIFTRT
18716 || outer_code == ROTATE
18717 || outer_code == ROTATERT
18718 || outer_code == ZERO_EXTRACT
18719 || (outer_code == MULT
18720 && satisfies_constraint_I (x))
18721 || ((outer_code == DIV || outer_code == UDIV
18722 || outer_code == MOD || outer_code == UMOD)
18723 && exact_log2 (INTVAL (x)) >= 0)
18724 || (outer_code == COMPARE
18725 && (satisfies_constraint_I (x)
18726 || satisfies_constraint_K (x)))
18727 || (outer_code == EQ
18728 && (satisfies_constraint_I (x)
18729 || satisfies_constraint_K (x)
18730 || (mode == SImode
18731 ? satisfies_constraint_L (x)
18732 : satisfies_constraint_J (x))))
18733 || (outer_code == GTU
18734 && satisfies_constraint_I (x))
18735 || (outer_code == LTU
18736 && satisfies_constraint_P (x)))
18737 {
18738 *total = 0;
18739 return true;
18740 }
18741 else if ((outer_code == PLUS
18742 && reg_or_add_cint_operand (x, VOIDmode))
18743 || (outer_code == MINUS
18744 && reg_or_sub_cint_operand (x, VOIDmode))
18745 || ((outer_code == SET
18746 || outer_code == IOR
18747 || outer_code == XOR)
18748 && (INTVAL (x)
18749 & ~ (unsigned HOST_WIDE_INT) 0xffffffff) == 0))
18750 {
18751 *total = COSTS_N_INSNS (1);
18752 return true;
18753 }
18754
18755
18756 case CONST_DOUBLE:
18757 if (mode == DImode && code == CONST_DOUBLE)
18758 {
18759 if ((outer_code == IOR || outer_code == XOR)
18760 && CONST_DOUBLE_HIGH (x) == 0
18761 && (CONST_DOUBLE_LOW (x)
18762 & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)
18763 {
18764 *total = 0;
18765 return true;
18766 }
18767 else if ((outer_code == AND && and64_2_operand (x, DImode))
18768 || ((outer_code == SET
18769 || outer_code == IOR
18770 || outer_code == XOR)
18771 && CONST_DOUBLE_HIGH (x) == 0))
18772 {
18773 *total = COSTS_N_INSNS (1);
18774 return true;
18775 }
18776 }
18777
18778
18779 case CONST:
18780 case HIGH:
18781 case SYMBOL_REF:
18782 case MEM:
18783
18784
18785
18786 *total = optimize_size ? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (2);
18787 return true;
18788
18789 case LABEL_REF:
18790 *total = 0;
18791 return true;
18792
18793 case PLUS:
18794 if (mode == DFmode)
18795 {
18796 if (GET_CODE (XEXP (x, 0)) == MULT)
18797 {
18798
18799 if (outer_code == NEG)
18800 *total = rs6000_cost->dmul - rs6000_cost->fp;
18801 else
18802 *total = rs6000_cost->dmul;
18803 }
18804 else
18805 *total = rs6000_cost->fp;
18806 }
18807 else if (mode == SFmode)
18808 {
18809
18810 if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
18811 *total = 0;
18812 else
18813 *total = rs6000_cost->fp;
18814 }
18815 else
18816 *total = COSTS_N_INSNS (1);
18817 return false;
18818
18819 case MINUS:
18820 if (mode == DFmode)
18821 {
18822 if (GET_CODE (XEXP (x, 0)) == MULT)
18823 {
18824
18825 if (outer_code == NEG)
18826 *total = 0;
18827 else
18828 *total = rs6000_cost->dmul;
18829 }
18830 else
18831 *total = rs6000_cost->fp;
18832 }
18833 else if (mode == SFmode)
18834 {
18835
18836 if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
18837 *total = 0;
18838 else
18839 *total = rs6000_cost->fp;
18840 }
18841 else
18842 *total = COSTS_N_INSNS (1);
18843 return false;
18844
18845 case MULT:
18846 if (GET_CODE (XEXP (x, 1)) == CONST_INT
18847 && satisfies_constraint_I (XEXP (x, 1)))
18848 {
18849 if (INTVAL (XEXP (x, 1)) >= -256
18850 && INTVAL (XEXP (x, 1)) <= 255)
18851 *total = rs6000_cost->mulsi_const9;
18852 else
18853 *total = rs6000_cost->mulsi_const;
18854 }
18855
18856 else if ((mode == DFmode || mode == SFmode)
18857 && (outer_code == PLUS || outer_code == MINUS))
18858 *total = 0;
18859 else if (mode == DFmode)
18860 *total = rs6000_cost->dmul;
18861 else if (mode == SFmode)
18862 *total = rs6000_cost->fp;
18863 else if (mode == DImode)
18864 *total = rs6000_cost->muldi;
18865 else
18866 *total = rs6000_cost->mulsi;
18867 return false;
18868
18869 case DIV:
18870 case MOD:
18871 if (FLOAT_MODE_P (mode))
18872 {
18873 *total = mode == DFmode ? rs6000_cost->ddiv
18874 : rs6000_cost->sdiv;
18875 return false;
18876 }
18877
18878
18879 case UDIV:
18880 case UMOD:
18881 if (GET_CODE (XEXP (x, 1)) == CONST_INT
18882 && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
18883 {
18884 if (code == DIV || code == MOD)
18885
18886 *total = COSTS_N_INSNS (2);
18887 else
18888
18889 *total = COSTS_N_INSNS (1);
18890 }
18891 else
18892 {
18893 if (GET_MODE (XEXP (x, 1)) == DImode)
18894 *total = rs6000_cost->divdi;
18895 else
18896 *total = rs6000_cost->divsi;
18897 }
18898
18899 if (code == MOD || code == UMOD)
18900 *total += COSTS_N_INSNS (2);
18901 return false;
18902
18903 case FFS:
18904 *total = COSTS_N_INSNS (4);
18905 return false;
18906
18907 case NOT:
18908 if (outer_code == AND || outer_code == IOR || outer_code == XOR)
18909 {
18910 *total = 0;
18911 return false;
18912 }
18913
18914
18915 case AND:
18916 case IOR:
18917 case XOR:
18918 case ZERO_EXTRACT:
18919 *total = COSTS_N_INSNS (1);
18920 return false;
18921
18922 case ASHIFT:
18923 case ASHIFTRT:
18924 case LSHIFTRT:
18925 case ROTATE:
18926 case ROTATERT:
18927
18928 if (outer_code == TRUNCATE
18929 && GET_CODE (XEXP (x, 0)) == MULT)
18930 {
18931 if (mode == DImode)
18932 *total = rs6000_cost->muldi;
18933 else
18934 *total = rs6000_cost->mulsi;
18935 return true;
18936 }
18937 else if (outer_code == AND)
18938 *total = 0;
18939 else
18940 *total = COSTS_N_INSNS (1);
18941 return false;
18942
18943 case SIGN_EXTEND:
18944 case ZERO_EXTEND:
18945 if (GET_CODE (XEXP (x, 0)) == MEM)
18946 *total = 0;
18947 else
18948 *total = COSTS_N_INSNS (1);
18949 return false;
18950
18951 case COMPARE:
18952 case NEG:
18953 case ABS:
18954 if (!FLOAT_MODE_P (mode))
18955 {
18956 *total = COSTS_N_INSNS (1);
18957 return false;
18958 }
18959
18960
18961 case FLOAT:
18962 case UNSIGNED_FLOAT:
18963 case FIX:
18964 case UNSIGNED_FIX:
18965 case FLOAT_TRUNCATE:
18966 *total = rs6000_cost->fp;
18967 return false;
18968
18969 case FLOAT_EXTEND:
18970 if (mode == DFmode)
18971 *total = 0;
18972 else
18973 *total = rs6000_cost->fp;
18974 return false;
18975
18976 case UNSPEC:
18977 switch (XINT (x, 1))
18978 {
18979 case UNSPEC_FRSP:
18980 *total = rs6000_cost->fp;
18981 return true;
18982
18983 default:
18984 break;
18985 }
18986 break;
18987
18988 case CALL:
18989 case IF_THEN_ELSE:
18990 if (optimize_size)
18991 {
18992 *total = COSTS_N_INSNS (1);
18993 return true;
18994 }
18995 else if (FLOAT_MODE_P (mode)
18996 && TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS)
18997 {
18998 *total = rs6000_cost->fp;
18999 return false;
19000 }
19001 break;
19002
19003 case EQ:
19004 case GTU:
19005 case LTU:
19006
19007
19008 if (mode == Pmode
19009 && (outer_code == NEG || outer_code == PLUS))
19010 {
19011 *total = COSTS_N_INSNS (1);
19012 return true;
19013 }
19014 if (outer_code == SET)
19015 {
19016 if (XEXP (x, 1) == const0_rtx)
19017 {
19018 *total = COSTS_N_INSNS (2);
19019 return true;
19020 }
19021 else if (mode == Pmode)
19022 {
19023 *total = COSTS_N_INSNS (3);
19024 return false;
19025 }
19026 }
19027
19028
19029 case GT:
19030 case LT:
19031 case UNORDERED:
19032 if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
19033 {
19034 *total = COSTS_N_INSNS (2);
19035 return true;
19036 }
19037
19038 if (outer_code == COMPARE)
19039 {
19040 *total = 0;
19041 return true;
19042 }
19043 break;
19044
19045 default:
19046 break;
19047 }
19048
19049 return false;
19050 }
19051
19052
19053
19054
19055 int
19056 rs6000_register_move_cost (enum machine_mode mode,
19057 enum reg_class from, enum reg_class to)
19058 {
19059
19060 if (reg_classes_intersect_p (to, GENERAL_REGS)
19061 || reg_classes_intersect_p (from, GENERAL_REGS))
19062 {
19063 if (! reg_classes_intersect_p (to, GENERAL_REGS))
19064 from = to;
19065
19066 if (from == FLOAT_REGS || from == ALTIVEC_REGS)
19067 return (rs6000_memory_move_cost (mode, from, 0)
19068 + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
19069
19070
19071
19072 else if (from == CR_REGS)
19073 return 4;
19074
19075 else
19076
19077 return 2 * hard_regno_nregs[0][mode];
19078 }
19079
19080
19081 else if (reg_classes_intersect_p (to, from))
19082 return mode == TFmode ? 4 : 2;
19083
19084
19085 else
19086 return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
19087 + rs6000_register_move_cost (mode, from, GENERAL_REGS));
19088 }
19089
19090
19091
19092
19093 int
19094 rs6000_memory_move_cost (enum machine_mode mode, enum reg_class class,
19095 int in ATTRIBUTE_UNUSED)
19096 {
19097 if (reg_classes_intersect_p (class, GENERAL_REGS))
19098 return 4 * hard_regno_nregs[0][mode];
19099 else if (reg_classes_intersect_p (class, FLOAT_REGS))
19100 return 4 * hard_regno_nregs[32][mode];
19101 else if (reg_classes_intersect_p (class, ALTIVEC_REGS))
19102 return 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
19103 else
19104 return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
19105 }
19106
19107
19108
19109
19110 void
19111 rs6000_emit_swdivsf (rtx res, rtx n, rtx d)
19112 {
19113 rtx x0, e0, e1, y1, u0, v0, one;
19114
19115 x0 = gen_reg_rtx (SFmode);
19116 e0 = gen_reg_rtx (SFmode);
19117 e1 = gen_reg_rtx (SFmode);
19118 y1 = gen_reg_rtx (SFmode);
19119 u0 = gen_reg_rtx (SFmode);
19120 v0 = gen_reg_rtx (SFmode);
19121 one = force_reg (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (dconst1, SFmode));
19122
19123
19124 emit_insn (gen_rtx_SET (VOIDmode, x0,
19125 gen_rtx_UNSPEC (SFmode, gen_rtvec (1, d),
19126 UNSPEC_FRES)));
19127
19128 emit_insn (gen_rtx_SET (VOIDmode, e0,
19129 gen_rtx_MINUS (SFmode, one,
19130 gen_rtx_MULT (SFmode, d, x0))));
19131
19132 emit_insn (gen_rtx_SET (VOIDmode, e1,
19133 gen_rtx_PLUS (SFmode,
19134 gen_rtx_MULT (SFmode, e0, e0), e0)));
19135
19136 emit_insn (gen_rtx_SET (VOIDmode, y1,
19137 gen_rtx_PLUS (SFmode,
19138 gen_rtx_MULT (SFmode, e1, x0), x0)));
19139
19140 emit_insn (gen_rtx_SET (VOIDmode, u0,
19141 gen_rtx_MULT (SFmode, n, y1)));
19142
19143 emit_insn (gen_rtx_SET (VOIDmode, v0,
19144 gen_rtx_MINUS (SFmode, n,
19145 gen_rtx_MULT (SFmode, d, u0))));
19146
19147 emit_insn (gen_rtx_SET (VOIDmode, res,
19148 gen_rtx_PLUS (SFmode,
19149 gen_rtx_MULT (SFmode, v0, y1), u0)));
19150 }
19151
19152
19153
19154
19155 void
19156 rs6000_emit_swdivdf (rtx res, rtx n, rtx d)
19157 {
19158 rtx x0, e0, e1, e2, y1, y2, y3, u0, v0, one;
19159
19160 x0 = gen_reg_rtx (DFmode);
19161 e0 = gen_reg_rtx (DFmode);
19162 e1 = gen_reg_rtx (DFmode);
19163 e2 = gen_reg_rtx (DFmode);
19164 y1 = gen_reg_rtx (DFmode);
19165 y2 = gen_reg_rtx (DFmode);
19166 y3 = gen_reg_rtx (DFmode);
19167 u0 = gen_reg_rtx (DFmode);
19168 v0 = gen_reg_rtx (DFmode);
19169 one = force_reg (DFmode, CONST_DOUBLE_FROM_REAL_VALUE (dconst1, DFmode));
19170
19171
19172 emit_insn (gen_rtx_SET (VOIDmode, x0,
19173 gen_rtx_UNSPEC (DFmode, gen_rtvec (1, d),
19174 UNSPEC_FRES)));
19175
19176 emit_insn (gen_rtx_SET (VOIDmode, e0,
19177 gen_rtx_MINUS (DFmode, one,
19178 gen_rtx_MULT (SFmode, d, x0))));
19179
19180 emit_insn (gen_rtx_SET (VOIDmode, y1,
19181 gen_rtx_PLUS (DFmode,
19182 gen_rtx_MULT (DFmode, e0, x0), x0)));
19183
19184 emit_insn (gen_rtx_SET (VOIDmode, e1,
19185 gen_rtx_MULT (DFmode, e0, e0)));
19186
19187 emit_insn (gen_rtx_SET (VOIDmode, y2,
19188 gen_rtx_PLUS (DFmode,
19189 gen_rtx_MULT (DFmode, e1, y1), y1)));
19190
19191 emit_insn (gen_rtx_SET (VOIDmode, e2,
19192 gen_rtx_MULT (DFmode, e1, e1)));
19193
19194 emit_insn (gen_rtx_SET (VOIDmode, y3,
19195 gen_rtx_PLUS (DFmode,
19196 gen_rtx_MULT (DFmode, e2, y2), y2)));
19197
19198 emit_insn (gen_rtx_SET (VOIDmode, u0,
19199 gen_rtx_MULT (DFmode, n, y3)));
19200
19201 emit_insn (gen_rtx_SET (VOIDmode, v0,
19202 gen_rtx_MINUS (DFmode, n,
19203 gen_rtx_MULT (DFmode, d, u0))));
19204
19205 emit_insn (gen_rtx_SET (VOIDmode, res,
19206 gen_rtx_PLUS (DFmode,
19207 gen_rtx_MULT (DFmode, v0, y3), u0)));
19208 }
19209
19210
19211
19212 static rtx
19213 rs6000_complex_function_value (enum machine_mode mode)
19214 {
19215 unsigned int regno;
19216 rtx r1, r2;
19217 enum machine_mode inner = GET_MODE_INNER (mode);
19218 unsigned int inner_bytes = GET_MODE_SIZE (inner);
19219
19220 if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
19221 regno = FP_ARG_RETURN;
19222 else
19223 {
19224 regno = GP_ARG_RETURN;
19225
19226
19227 if (TARGET_32BIT && inner_bytes >= 4)
19228 return gen_rtx_REG (mode, regno);
19229 }
19230
19231 if (inner_bytes >= 8)
19232 return gen_rtx_REG (mode, regno);
19233
19234 r1 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno),
19235 const0_rtx);
19236 r2 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno + 1),
19237 GEN_INT (inner_bytes));
19238 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
19239 }
19240
19241
19242
19243
19244
19245
19246
19247
19248
19249
19250
19251 rtx
19252 rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
19253 {
19254 enum machine_mode mode;
19255 unsigned int regno;
19256
19257
19258 if (rs6000_darwin64_abi
19259 && TYPE_MODE (valtype) == BLKmode
19260 && TREE_CODE (valtype) == RECORD_TYPE
19261 && int_size_in_bytes (valtype) > 0)
19262 {
19263 CUMULATIVE_ARGS valcum;
19264 rtx valret;
19265
19266 valcum.words = 0;
19267 valcum.fregno = FP_ARG_MIN_REG;
19268 valcum.vregno = ALTIVEC_ARG_MIN_REG;
19269
19270
19271 valret = rs6000_darwin64_record_arg (&valcum, valtype, 1, true);
19272 if (valret)
19273 return valret;
19274
19275 }
19276
19277 if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
19278 {
19279
19280 return gen_rtx_PARALLEL (DImode,
19281 gen_rtvec (2,
19282 gen_rtx_EXPR_LIST (VOIDmode,
19283 gen_rtx_REG (SImode, GP_ARG_RETURN),
19284 const0_rtx),
19285 gen_rtx_EXPR_LIST (VOIDmode,
19286 gen_rtx_REG (SImode,
19287 GP_ARG_RETURN + 1),
19288 GEN_INT (4))));
19289 }
19290 if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DCmode)
19291 {
19292 return gen_rtx_PARALLEL (DCmode,
19293 gen_rtvec (4,
19294 gen_rtx_EXPR_LIST (VOIDmode,
19295 gen_rtx_REG (SImode, GP_ARG_RETURN),
19296 const0_rtx),
19297 gen_rtx_EXPR_LIST (VOIDmode,
19298 gen_rtx_REG (SImode,
19299 GP_ARG_RETURN + 1),
19300 GEN_INT (4)),
19301 gen_rtx_EXPR_LIST (VOIDmode,
19302 gen_rtx_REG (SImode,
19303 GP_ARG_RETURN + 2),
19304 GEN_INT (8)),
19305 gen_rtx_EXPR_LIST (VOIDmode,
19306 gen_rtx_REG (SImode,
19307 GP_ARG_RETURN + 3),
19308 GEN_INT (12))));
19309 }
19310
19311 mode = TYPE_MODE (valtype);
19312 if ((INTEGRAL_TYPE_P (valtype) && GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
19313 || POINTER_TYPE_P (valtype))
19314 mode = TARGET_32BIT ? SImode : DImode;
19315
19316 if (DECIMAL_FLOAT_MODE_P (mode))
19317 regno = GP_ARG_RETURN;
19318 else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
19319 regno = FP_ARG_RETURN;
19320 else if (TREE_CODE (valtype) == COMPLEX_TYPE
19321 && targetm.calls.split_complex_arg)
19322 return rs6000_complex_function_value (mode);
19323 else if (TREE_CODE (valtype) == VECTOR_TYPE
19324 && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
19325 && ALTIVEC_VECTOR_MODE (mode))
19326 regno = ALTIVEC_ARG_RETURN;
19327 else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
19328 && (mode == DFmode || mode == DCmode))
19329 return spe_build_register_parallel (mode, GP_ARG_RETURN);
19330 else
19331 regno = GP_ARG_RETURN;
19332
19333 return gen_rtx_REG (mode, regno);
19334 }
19335
19336
19337
19338 rtx
19339 rs6000_libcall_value (enum machine_mode mode)
19340 {
19341 unsigned int regno;
19342
19343 if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
19344 {
19345
19346 return gen_rtx_PARALLEL (DImode,
19347 gen_rtvec (2,
19348 gen_rtx_EXPR_LIST (VOIDmode,
19349 gen_rtx_REG (SImode, GP_ARG_RETURN),
19350 const0_rtx),
19351 gen_rtx_EXPR_LIST (VOIDmode,
19352 gen_rtx_REG (SImode,
19353 GP_ARG_RETURN + 1),
19354 GEN_INT (4))));
19355 }
19356
19357 if (DECIMAL_FLOAT_MODE_P (mode))
19358 regno = GP_ARG_RETURN;
19359 else if (SCALAR_FLOAT_MODE_P (mode)
19360 && TARGET_HARD_FLOAT && TARGET_FPRS)
19361 regno = FP_ARG_RETURN;
19362 else if (ALTIVEC_VECTOR_MODE (mode)
19363 && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI)
19364 regno = ALTIVEC_ARG_RETURN;
19365 else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
19366 return rs6000_complex_function_value (mode);
19367 else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
19368 && (mode == DFmode || mode == DCmode))
19369 return spe_build_register_parallel (mode, GP_ARG_RETURN);
19370 else
19371 regno = GP_ARG_RETURN;
19372
19373 return gen_rtx_REG (mode, regno);
19374 }
19375
19376
19377
19378 HOST_WIDE_INT
19379 rs6000_initial_elimination_offset (int from, int to)
19380 {
19381 rs6000_stack_t *info = rs6000_stack_info ();
19382 HOST_WIDE_INT offset;
19383
19384 if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
19385 offset = info->push_p ? 0 : -info->total_size;
19386 else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
19387 {
19388 offset = info->push_p ? 0 : -info->total_size;
19389 if (FRAME_GROWS_DOWNWARD)
19390 offset += info->fixed_size + info->vars_size + info->parm_size;
19391 }
19392 else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
19393 offset = FRAME_GROWS_DOWNWARD
19394 ? info->fixed_size + info->vars_size + info->parm_size
19395 : 0;
19396 else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
19397 offset = info->total_size;
19398 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
19399 offset = info->push_p ? info->total_size : 0;
19400 else if (from == RS6000_PIC_OFFSET_TABLE_REGNUM)
19401 offset = 0;
19402 else
19403 gcc_unreachable ();
19404
19405 return offset;
19406 }
19407
19408
19409
19410 static bool
19411 rs6000_is_opaque_type (tree type)
19412 {
19413 return (type == opaque_V2SI_type_node
19414 || type == opaque_V2SF_type_node
19415 || type == opaque_p_V2SI_type_node
19416 || type == opaque_V4SI_type_node);
19417 }
19418
19419 static rtx
19420 rs6000_dwarf_register_span (rtx reg)
19421 {
19422 unsigned regno;
19423
19424 if (TARGET_SPE
19425 && (SPE_VECTOR_MODE (GET_MODE (reg))
19426 || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
19427 ;
19428 else
19429 return NULL_RTX;
19430
19431 regno = REGNO (reg);
19432
19433
19434
19435
19436 return
19437 gen_rtx_PARALLEL (VOIDmode,
19438 BYTES_BIG_ENDIAN
19439 ? gen_rtvec (2,
19440 gen_rtx_REG (SImode, regno + 1200),
19441 gen_rtx_REG (SImode, regno))
19442 : gen_rtvec (2,
19443 gen_rtx_REG (SImode, regno),
19444 gen_rtx_REG (SImode, regno + 1200)));
19445 }
19446
19447
19448
19449 unsigned int
19450 rs6000_dbx_register_number (unsigned int regno)
19451 {
19452 if (regno <= 63 || write_symbols != DWARF2_DEBUG)
19453 return regno;
19454 if (regno == MQ_REGNO)
19455 return 100;
19456 if (regno == LINK_REGISTER_REGNUM)
19457 return 108;
19458 if (regno == COUNT_REGISTER_REGNUM)
19459 return 109;
19460 if (CR_REGNO_P (regno))
19461 return regno - CR0_REGNO + 86;
19462 if (regno == XER_REGNO)
19463 return 101;
19464 if (ALTIVEC_REGNO_P (regno))
19465 return regno - FIRST_ALTIVEC_REGNO + 1124;
19466 if (regno == VRSAVE_REGNO)
19467 return 356;
19468 if (regno == VSCR_REGNO)
19469 return 67;
19470 if (regno == SPE_ACC_REGNO)
19471 return 99;
19472 if (regno == SPEFSCR_REGNO)
19473 return 612;
19474
19475
19476 gcc_assert (regno >= 1200 && regno < 1232);
19477 return regno;
19478 }
19479
19480
19481 static enum machine_mode
19482 rs6000_eh_return_filter_mode (void)
19483 {
19484 return TARGET_32BIT ? SImode : word_mode;
19485 }
19486
19487
19488 static bool
19489 rs6000_scalar_mode_supported_p (enum machine_mode mode)
19490 {
19491 if (DECIMAL_FLOAT_MODE_P (mode))
19492 return true;
19493 else
19494 return default_scalar_mode_supported_p (mode);
19495 }
19496
19497
19498 static bool
19499 rs6000_vector_mode_supported_p (enum machine_mode mode)
19500 {
19501
19502 if (TARGET_SPE && SPE_VECTOR_MODE (mode))
19503 return true;
19504
19505 else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
19506 return true;
19507
19508 else
19509 return false;
19510 }
19511
19512
19513 static const char *
19514 invalid_arg_for_unprototyped_fn (tree typelist, tree funcdecl, tree val)
19515 {
19516 return (!rs6000_darwin64_abi
19517 && typelist == 0
19518 && TREE_CODE (TREE_TYPE (val)) == VECTOR_TYPE
19519 && (funcdecl == NULL_TREE
19520 || (TREE_CODE (funcdecl) == FUNCTION_DECL
19521 && DECL_BUILT_IN_CLASS (funcdecl) != BUILT_IN_MD)))
19522 ? N_("AltiVec argument passed to unprototyped function")
19523 : NULL;
19524 }
19525
19526
19527
19528
19529
19530
19531 static tree
19532 rs6000_stack_protect_fail (void)
19533 {
19534 return (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
19535 ? default_hidden_stack_protect_fail ()
19536 : default_external_stack_protect_fail ();
19537 }
19538
19539 #include "gt-rs6000.h"