00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "recog.h"
00036 #include "obstack.h"
00037 #include "tree.h"
00038 #include "expr.h"
00039 #include "optabs.h"
00040 #include "except.h"
00041 #include "function.h"
00042 #include "output.h"
00043 #include "basic-block.h"
00044 #include "integrate.h"
00045 #include "toplev.h"
00046 #include "ggc.h"
00047 #include "hashtab.h"
00048 #include "tm_p.h"
00049 #include "target.h"
00050 #include "target-def.h"
00051 #include "langhooks.h"
00052 #include "reload.h"
00053 #include "cfglayout.h"
00054 #include "sched-int.h"
00055 #include "tree-gimple.h"
00056 #if TARGET_XCOFF
00057 #include "xcoffout.h"
00058 #endif
00059 #if TARGET_MACHO
00060 #include "gstab.h"
00061 #endif
00062
00063 #ifndef TARGET_NO_PROTOTYPE
00064 #define TARGET_NO_PROTOTYPE 0
00065 #endif
00066
00067 #define EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
00068 #define EASY_VECTOR_15_ADD_SELF(n) ((n) >= 0x10 && (n) <= 0x1e && !((n) & 1))
00069
00070 #define min(A,B) ((A) < (B) ? (A) : (B))
00071 #define max(A,B) ((A) > (B) ? (A) : (B))
00072
00073
00074 typedef struct rs6000_stack {
00075 int first_gp_reg_save;
00076 int first_fp_reg_save;
00077 int first_altivec_reg_save;
00078 int lr_save_p;
00079 int cr_save_p;
00080 unsigned int vrsave_mask;
00081 int toc_save_p;
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 toc_save_offset;
00095 int varargs_save_offset;
00096 int ehrd_offset;
00097 int reg_size;
00098 int varargs_size;
00099 HOST_WIDE_INT vars_size;
00100 int parm_size;
00101 int save_size;
00102 int fixed_size;
00103 int gp_size;
00104 int fp_size;
00105 int altivec_size;
00106 int cr_size;
00107 int lr_size;
00108 int vrsave_size;
00109 int altivec_padding_size;
00110
00111 int spe_gp_size;
00112 int spe_padding_size;
00113 int toc_size;
00114 HOST_WIDE_INT total_size;
00115 int spe_64bit_regs_used;
00116 } rs6000_stack_t;
00117
00118
00119
00120 enum processor_type rs6000_cpu;
00121 struct rs6000_cpu_select rs6000_select[3] =
00122 {
00123
00124 { (const char *)0, "--with-cpu=", 1, 1 },
00125 { (const char *)0, "-mcpu=", 1, 1 },
00126 { (const char *)0, "-mtune=", 1, 0 },
00127 };
00128
00129
00130 static GTY(()) bool rs6000_always_hint;
00131
00132
00133 static GTY(()) bool rs6000_sched_groups;
00134
00135
00136
00137 const char *rs6000_sched_restricted_insns_priority_str;
00138 int rs6000_sched_restricted_insns_priority;
00139
00140
00141 const char *rs6000_sched_costly_dep_str;
00142 enum rs6000_dependence_cost rs6000_sched_costly_dep;
00143
00144
00145 const char *rs6000_sched_insert_nops_str;
00146 enum rs6000_nop_insertion rs6000_sched_insert_nops;
00147
00148
00149 static GTY(()) tree altivec_builtin_mask_for_load;
00150
00151
00152 const char *rs6000_long_double_size_string;
00153 int rs6000_long_double_type_size;
00154
00155
00156 int rs6000_altivec_abi;
00157
00158
00159 int rs6000_altivec_vrsave;
00160
00161
00162 const char *rs6000_altivec_vrsave_string;
00163
00164
00165 int rs6000_spe_abi;
00166
00167
00168 int rs6000_isel;
00169
00170
00171 int rs6000_spe;
00172
00173
00174 int rs6000_float_gprs = 0;
00175
00176
00177 int rs6000_darwin64_abi;
00178
00179
00180 const char *rs6000_float_gprs_string;
00181
00182
00183 const char *rs6000_isel_string;
00184
00185
00186 const char *rs6000_spe_string;
00187
00188
00189 static GTY(()) int common_mode_defined;
00190
00191
00192
00193 rtx rs6000_compare_op0, rs6000_compare_op1;
00194 int rs6000_compare_fp_p;
00195
00196
00197
00198 int rs6000_pic_labelno;
00199
00200 #ifdef USING_ELFOS_H
00201
00202 const char *rs6000_abi_name;
00203
00204
00205 enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
00206
00207
00208 const char *rs6000_sdata_name = (char *)0;
00209
00210
00211 int fixuplabelno = 0;
00212 #endif
00213
00214
00215 int rs6000_tls_size = 32;
00216 const char *rs6000_tls_size_string;
00217
00218
00219 enum rs6000_abi rs6000_current_abi;
00220
00221
00222 const char *rs6000_abi_string;
00223
00224
00225 int dot_symbols;
00226
00227
00228 const char *rs6000_debug_name;
00229 int rs6000_debug_stack;
00230 int rs6000_debug_arg;
00231
00232
00233 bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
00234
00235
00236 static GTY(()) tree opaque_V2SI_type_node;
00237 static GTY(()) tree opaque_V2SF_type_node;
00238 static GTY(()) tree opaque_p_V2SI_type_node;
00239 static GTY(()) tree V16QI_type_node;
00240 static GTY(()) tree V2SI_type_node;
00241 static GTY(()) tree V2SF_type_node;
00242 static GTY(()) tree V4HI_type_node;
00243 static GTY(()) tree V4SI_type_node;
00244 static GTY(()) tree V4SF_type_node;
00245 static GTY(()) tree V8HI_type_node;
00246 static GTY(()) tree unsigned_V16QI_type_node;
00247 static GTY(()) tree unsigned_V8HI_type_node;
00248 static GTY(()) tree unsigned_V4SI_type_node;
00249 static GTY(()) tree bool_char_type_node;
00250 static GTY(()) tree bool_short_type_node;
00251 static GTY(()) tree bool_int_type_node;
00252 static GTY(()) tree pixel_type_node;
00253 static GTY(()) tree bool_V16QI_type_node;
00254 static GTY(()) tree bool_V8HI_type_node;
00255 static GTY(()) tree bool_V4SI_type_node;
00256 static GTY(()) tree pixel_V8HI_type_node;
00257
00258 int rs6000_warn_altivec_long = 1;
00259 const char *rs6000_warn_altivec_long_switch;
00260
00261 const char *rs6000_traceback_name;
00262 static enum {
00263 traceback_default = 0,
00264 traceback_none,
00265 traceback_part,
00266 traceback_full
00267 } rs6000_traceback;
00268
00269
00270 int toc_initialized;
00271 char toc_label_name[10];
00272
00273
00274 static GTY(()) int rs6000_sr_alias_set;
00275
00276
00277
00278
00279
00280
00281 int rs6000_default_long_calls;
00282 const char *rs6000_longcall_switch;
00283
00284
00285
00286 const char *rs6000_alignment_string;
00287 int rs6000_alignment_flags;
00288
00289 struct builtin_description
00290 {
00291
00292
00293
00294 unsigned int mask;
00295 const enum insn_code icode;
00296 const char *const name;
00297 const enum rs6000_builtins code;
00298 };
00299
00300
00301
00302 struct processor_costs {
00303 const int mulsi;
00304 const int mulsi_const;
00305 const int mulsi_const9;
00306 const int muldi;
00307 const int divsi;
00308 const int divdi;
00309 const int fp;
00310 const int dmul;
00311 const int sdiv;
00312 const int ddiv;
00313 };
00314
00315 const struct processor_costs *rs6000_cost;
00316
00317
00318
00319
00320 static const
00321 struct processor_costs size32_cost = {
00322 COSTS_N_INSNS (1),
00323 COSTS_N_INSNS (1),
00324 COSTS_N_INSNS (1),
00325 COSTS_N_INSNS (1),
00326 COSTS_N_INSNS (1),
00327 COSTS_N_INSNS (1),
00328 COSTS_N_INSNS (1),
00329 COSTS_N_INSNS (1),
00330 COSTS_N_INSNS (1),
00331 COSTS_N_INSNS (1),
00332 };
00333
00334
00335 static const
00336 struct processor_costs size64_cost = {
00337 COSTS_N_INSNS (1),
00338 COSTS_N_INSNS (1),
00339 COSTS_N_INSNS (1),
00340 COSTS_N_INSNS (1),
00341 COSTS_N_INSNS (1),
00342 COSTS_N_INSNS (1),
00343 COSTS_N_INSNS (1),
00344 COSTS_N_INSNS (1),
00345 COSTS_N_INSNS (1),
00346 COSTS_N_INSNS (1),
00347 };
00348
00349
00350 static const
00351 struct processor_costs rios1_cost = {
00352 COSTS_N_INSNS (5),
00353 COSTS_N_INSNS (4),
00354 COSTS_N_INSNS (3),
00355 COSTS_N_INSNS (5),
00356 COSTS_N_INSNS (19),
00357 COSTS_N_INSNS (19),
00358 COSTS_N_INSNS (2),
00359 COSTS_N_INSNS (2),
00360 COSTS_N_INSNS (19),
00361 COSTS_N_INSNS (19),
00362 };
00363
00364
00365 static const
00366 struct processor_costs rios2_cost = {
00367 COSTS_N_INSNS (2),
00368 COSTS_N_INSNS (2),
00369 COSTS_N_INSNS (2),
00370 COSTS_N_INSNS (2),
00371 COSTS_N_INSNS (13),
00372 COSTS_N_INSNS (13),
00373 COSTS_N_INSNS (2),
00374 COSTS_N_INSNS (2),
00375 COSTS_N_INSNS (17),
00376 COSTS_N_INSNS (17),
00377 };
00378
00379
00380 static const
00381 struct processor_costs rs64a_cost = {
00382 COSTS_N_INSNS (20),
00383 COSTS_N_INSNS (12),
00384 COSTS_N_INSNS (8),
00385 COSTS_N_INSNS (34),
00386 COSTS_N_INSNS (65),
00387 COSTS_N_INSNS (67),
00388 COSTS_N_INSNS (4),
00389 COSTS_N_INSNS (4),
00390 COSTS_N_INSNS (31),
00391 COSTS_N_INSNS (31),
00392 };
00393
00394
00395 static const
00396 struct processor_costs mpccore_cost = {
00397 COSTS_N_INSNS (2),
00398 COSTS_N_INSNS (2),
00399 COSTS_N_INSNS (2),
00400 COSTS_N_INSNS (2),
00401 COSTS_N_INSNS (6),
00402 COSTS_N_INSNS (6),
00403 COSTS_N_INSNS (4),
00404 COSTS_N_INSNS (5),
00405 COSTS_N_INSNS (10),
00406 COSTS_N_INSNS (17),
00407 };
00408
00409
00410 static const
00411 struct processor_costs ppc403_cost = {
00412 COSTS_N_INSNS (4),
00413 COSTS_N_INSNS (4),
00414 COSTS_N_INSNS (4),
00415 COSTS_N_INSNS (4),
00416 COSTS_N_INSNS (33),
00417 COSTS_N_INSNS (33),
00418 COSTS_N_INSNS (11),
00419 COSTS_N_INSNS (11),
00420 COSTS_N_INSNS (11),
00421 COSTS_N_INSNS (11),
00422 };
00423
00424
00425 static const
00426 struct processor_costs ppc405_cost = {
00427 COSTS_N_INSNS (5),
00428 COSTS_N_INSNS (4),
00429 COSTS_N_INSNS (3),
00430 COSTS_N_INSNS (5),
00431 COSTS_N_INSNS (35),
00432 COSTS_N_INSNS (35),
00433 COSTS_N_INSNS (11),
00434 COSTS_N_INSNS (11),
00435 COSTS_N_INSNS (11),
00436 COSTS_N_INSNS (11),
00437 };
00438
00439
00440 static const
00441 struct processor_costs ppc440_cost = {
00442 COSTS_N_INSNS (3),
00443 COSTS_N_INSNS (2),
00444 COSTS_N_INSNS (2),
00445 COSTS_N_INSNS (3),
00446 COSTS_N_INSNS (34),
00447 COSTS_N_INSNS (34),
00448 COSTS_N_INSNS (5),
00449 COSTS_N_INSNS (5),
00450 COSTS_N_INSNS (19),
00451 COSTS_N_INSNS (33),
00452 };
00453
00454
00455 static const
00456 struct processor_costs ppc601_cost = {
00457 COSTS_N_INSNS (5),
00458 COSTS_N_INSNS (5),
00459 COSTS_N_INSNS (5),
00460 COSTS_N_INSNS (5),
00461 COSTS_N_INSNS (36),
00462 COSTS_N_INSNS (36),
00463 COSTS_N_INSNS (4),
00464 COSTS_N_INSNS (5),
00465 COSTS_N_INSNS (17),
00466 COSTS_N_INSNS (31),
00467 };
00468
00469
00470 static const
00471 struct processor_costs ppc603_cost = {
00472 COSTS_N_INSNS (5),
00473 COSTS_N_INSNS (3),
00474 COSTS_N_INSNS (2),
00475 COSTS_N_INSNS (5),
00476 COSTS_N_INSNS (37),
00477 COSTS_N_INSNS (37),
00478 COSTS_N_INSNS (3),
00479 COSTS_N_INSNS (4),
00480 COSTS_N_INSNS (18),
00481 COSTS_N_INSNS (33),
00482 };
00483
00484
00485 static const
00486 struct processor_costs ppc604_cost = {
00487 COSTS_N_INSNS (4),
00488 COSTS_N_INSNS (4),
00489 COSTS_N_INSNS (4),
00490 COSTS_N_INSNS (4),
00491 COSTS_N_INSNS (20),
00492 COSTS_N_INSNS (20),
00493 COSTS_N_INSNS (3),
00494 COSTS_N_INSNS (3),
00495 COSTS_N_INSNS (18),
00496 COSTS_N_INSNS (32),
00497 };
00498
00499
00500 static const
00501 struct processor_costs ppc604e_cost = {
00502 COSTS_N_INSNS (2),
00503 COSTS_N_INSNS (2),
00504 COSTS_N_INSNS (2),
00505 COSTS_N_INSNS (2),
00506 COSTS_N_INSNS (20),
00507 COSTS_N_INSNS (20),
00508 COSTS_N_INSNS (3),
00509 COSTS_N_INSNS (3),
00510 COSTS_N_INSNS (18),
00511 COSTS_N_INSNS (32),
00512 };
00513
00514
00515 static const
00516 struct processor_costs ppc620_cost = {
00517 COSTS_N_INSNS (5),
00518 COSTS_N_INSNS (4),
00519 COSTS_N_INSNS (3),
00520 COSTS_N_INSNS (7),
00521 COSTS_N_INSNS (21),
00522 COSTS_N_INSNS (37),
00523 COSTS_N_INSNS (3),
00524 COSTS_N_INSNS (3),
00525 COSTS_N_INSNS (18),
00526 COSTS_N_INSNS (32),
00527 };
00528
00529
00530 static const
00531 struct processor_costs ppc630_cost = {
00532 COSTS_N_INSNS (5),
00533 COSTS_N_INSNS (4),
00534 COSTS_N_INSNS (3),
00535 COSTS_N_INSNS (7),
00536 COSTS_N_INSNS (21),
00537 COSTS_N_INSNS (37),
00538 COSTS_N_INSNS (3),
00539 COSTS_N_INSNS (3),
00540 COSTS_N_INSNS (17),
00541 COSTS_N_INSNS (21),
00542 };
00543
00544
00545 static const
00546 struct processor_costs ppc750_cost = {
00547 COSTS_N_INSNS (5),
00548 COSTS_N_INSNS (3),
00549 COSTS_N_INSNS (2),
00550 COSTS_N_INSNS (5),
00551 COSTS_N_INSNS (17),
00552 COSTS_N_INSNS (17),
00553 COSTS_N_INSNS (3),
00554 COSTS_N_INSNS (3),
00555 COSTS_N_INSNS (17),
00556 COSTS_N_INSNS (31),
00557 };
00558
00559
00560 static const
00561 struct processor_costs ppc7450_cost = {
00562 COSTS_N_INSNS (4),
00563 COSTS_N_INSNS (3),
00564 COSTS_N_INSNS (3),
00565 COSTS_N_INSNS (4),
00566 COSTS_N_INSNS (23),
00567 COSTS_N_INSNS (23),
00568 COSTS_N_INSNS (5),
00569 COSTS_N_INSNS (5),
00570 COSTS_N_INSNS (21),
00571 COSTS_N_INSNS (35),
00572 };
00573
00574
00575 static const
00576 struct processor_costs ppc8540_cost = {
00577 COSTS_N_INSNS (4),
00578 COSTS_N_INSNS (4),
00579 COSTS_N_INSNS (4),
00580 COSTS_N_INSNS (4),
00581 COSTS_N_INSNS (19),
00582 COSTS_N_INSNS (19),
00583 COSTS_N_INSNS (4),
00584 COSTS_N_INSNS (4),
00585 COSTS_N_INSNS (29),
00586 COSTS_N_INSNS (29),
00587 };
00588
00589
00590 static const
00591 struct processor_costs power4_cost = {
00592 COSTS_N_INSNS (3),
00593 COSTS_N_INSNS (2),
00594 COSTS_N_INSNS (2),
00595 COSTS_N_INSNS (4),
00596 COSTS_N_INSNS (18),
00597 COSTS_N_INSNS (34),
00598 COSTS_N_INSNS (3),
00599 COSTS_N_INSNS (3),
00600 COSTS_N_INSNS (17),
00601 COSTS_N_INSNS (17),
00602 };
00603
00604
00605 static bool rs6000_function_ok_for_sibcall (tree, tree);
00606 static int num_insns_constant_wide (HOST_WIDE_INT);
00607 static void validate_condition_mode (enum rtx_code, enum machine_mode);
00608 static rtx rs6000_generate_compare (enum rtx_code);
00609 static void rs6000_maybe_dead (rtx);
00610 static void rs6000_emit_stack_tie (void);
00611 static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx);
00612 static rtx spe_synthesize_frame_save (rtx);
00613 static bool spe_func_has_64bit_regs_p (void);
00614 static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int,
00615 int, HOST_WIDE_INT);
00616 static rtx gen_frame_mem_offset (enum machine_mode, rtx, int);
00617 static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int);
00618 static unsigned rs6000_hash_constant (rtx);
00619 static unsigned toc_hash_function (const void *);
00620 static int toc_hash_eq (const void *, const void *);
00621 static int constant_pool_expr_1 (rtx, int *, int *);
00622 static bool constant_pool_expr_p (rtx);
00623 static bool toc_relative_expr_p (rtx);
00624 static bool legitimate_indexed_address_p (rtx, int);
00625 static bool legitimate_indirect_address_p (rtx, int);
00626 static bool macho_lo_sum_memory_operand (rtx x, enum machine_mode mode);
00627 static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
00628 static struct machine_function * rs6000_init_machine_status (void);
00629 static bool rs6000_assemble_integer (rtx, unsigned int, int);
00630 #ifdef HAVE_GAS_HIDDEN
00631 static void rs6000_assemble_visibility (tree, int);
00632 #endif
00633 static int rs6000_ra_ever_killed (void);
00634 static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
00635 static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
00636 static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
00637 static const char *rs6000_mangle_fundamental_type (tree);
00638 extern const struct attribute_spec rs6000_attribute_table[];
00639 static void rs6000_set_default_type_attributes (tree);
00640 static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT);
00641 static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT);
00642 static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
00643 tree);
00644 static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
00645 static bool rs6000_return_in_memory (tree, tree);
00646 static void rs6000_file_start (void);
00647 #if TARGET_ELF
00648 static unsigned int rs6000_elf_section_type_flags (tree, const char *, int);
00649 static void rs6000_elf_asm_out_constructor (rtx, int);
00650 static void rs6000_elf_asm_out_destructor (rtx, int);
00651 static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED;
00652 static void rs6000_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
00653 static void rs6000_elf_unique_section (tree, int);
00654 static void rs6000_elf_select_rtx_section (enum machine_mode, rtx,
00655 unsigned HOST_WIDE_INT);
00656 static void rs6000_elf_encode_section_info (tree, rtx, int)
00657 ATTRIBUTE_UNUSED;
00658 static bool rs6000_elf_in_small_data_p (tree);
00659 #endif
00660 #if TARGET_XCOFF
00661 static void rs6000_xcoff_asm_globalize_label (FILE *, const char *);
00662 static void rs6000_xcoff_asm_named_section (const char *, unsigned int, tree);
00663 static void rs6000_xcoff_select_section (tree, int, unsigned HOST_WIDE_INT);
00664 static void rs6000_xcoff_unique_section (tree, int);
00665 static void rs6000_xcoff_select_rtx_section (enum machine_mode, rtx,
00666 unsigned HOST_WIDE_INT);
00667 static const char * rs6000_xcoff_strip_name_encoding (const char *);
00668 static unsigned int rs6000_xcoff_section_type_flags (tree, const char *, int);
00669 static void rs6000_xcoff_file_start (void);
00670 static void rs6000_xcoff_file_end (void);
00671 #endif
00672 #if TARGET_MACHO
00673 static bool rs6000_binds_local_p (tree);
00674 #endif
00675 static int rs6000_variable_issue (FILE *, int, rtx, int);
00676 static bool rs6000_rtx_costs (rtx, int, int, int *);
00677 static int rs6000_adjust_cost (rtx, rtx, rtx, int);
00678 static bool is_microcoded_insn (rtx);
00679 static int is_dispatch_slot_restricted (rtx);
00680 static bool is_cracked_insn (rtx);
00681 static bool is_branch_slot_insn (rtx);
00682 static int rs6000_adjust_priority (rtx, int);
00683 static int rs6000_issue_rate (void);
00684 static bool rs6000_is_costly_dependence (rtx, rtx, rtx, int, int);
00685 static rtx get_next_active_insn (rtx, rtx);
00686 static bool insn_terminates_group_p (rtx , enum group_termination);
00687 static bool is_costly_group (rtx *, rtx);
00688 static int force_new_group (int, FILE *, rtx *, rtx, bool *, int, int *);
00689 static int redefine_groups (FILE *, int, rtx, rtx);
00690 static int pad_groups (FILE *, int, rtx, rtx);
00691 static void rs6000_sched_finish (FILE *, int);
00692 static int rs6000_use_sched_lookahead (void);
00693 static tree rs6000_builtin_mask_for_load (void);
00694
00695 static void rs6000_init_builtins (void);
00696 static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx);
00697 static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx);
00698 static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx);
00699 static rtx rs6000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00700 static void altivec_init_builtins (void);
00701 static void rs6000_common_init_builtins (void);
00702 static void rs6000_init_libfuncs (void);
00703
00704 static void enable_mask_for_builtins (struct builtin_description *, int,
00705 enum rs6000_builtins,
00706 enum rs6000_builtins);
00707 static tree build_opaque_vector_type (tree, int);
00708 static void spe_init_builtins (void);
00709 static rtx spe_expand_builtin (tree, rtx, bool *);
00710 static rtx spe_expand_stv_builtin (enum insn_code, tree);
00711 static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
00712 static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
00713 static bool invalid_e500_subreg (rtx, enum machine_mode);
00714 static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
00715 static rs6000_stack_t *rs6000_stack_info (void);
00716 static void debug_stack_info (rs6000_stack_t *);
00717
00718 static rtx altivec_expand_builtin (tree, rtx, bool *);
00719 static rtx altivec_expand_ld_builtin (tree, rtx, bool *);
00720 static rtx altivec_expand_st_builtin (tree, rtx, bool *);
00721 static rtx altivec_expand_dst_builtin (tree, rtx, bool *);
00722 static rtx altivec_expand_abs_builtin (enum insn_code, tree, rtx);
00723 static rtx altivec_expand_predicate_builtin (enum insn_code,
00724 const char *, tree, rtx);
00725 static rtx altivec_expand_lv_builtin (enum insn_code, tree, rtx);
00726 static rtx altivec_expand_stv_builtin (enum insn_code, tree);
00727 static void rs6000_parse_abi_options (void);
00728 static void rs6000_parse_alignment_option (void);
00729 static void rs6000_parse_tls_size_option (void);
00730 static void rs6000_parse_yes_no_option (const char *, const char *, int *);
00731 static void rs6000_parse_float_gprs_option (void);
00732 static int first_altivec_reg_to_save (void);
00733 static unsigned int compute_vrsave_mask (void);
00734 static void compute_save_world_info(rs6000_stack_t *info_ptr);
00735 static void is_altivec_return_reg (rtx, void *);
00736 static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
00737 int easy_vector_constant (rtx, enum machine_mode);
00738 static int easy_vector_same (rtx, enum machine_mode);
00739 static int easy_vector_splat_const (int, enum machine_mode);
00740 static bool is_ev64_opaque_type (tree);
00741 static rtx rs6000_dwarf_register_span (rtx);
00742 static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
00743 static rtx rs6000_tls_get_addr (void);
00744 static rtx rs6000_got_sym (void);
00745 static inline int rs6000_tls_symbol_ref_1 (rtx *, void *);
00746 static const char *rs6000_get_some_local_dynamic_name (void);
00747 static int rs6000_get_some_local_dynamic_name_1 (rtx *, void *);
00748 static rtx rs6000_complex_function_value (enum machine_mode);
00749 static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
00750 enum machine_mode, tree);
00751 static void rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *,
00752 HOST_WIDE_INT);
00753 static void rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *,
00754 tree, HOST_WIDE_INT);
00755 static void rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *,
00756 HOST_WIDE_INT,
00757 rtx[], int *);
00758 static void rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *,
00759 tree, HOST_WIDE_INT,
00760 rtx[], int *);
00761 static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, tree, int, bool);
00762 static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int);
00763 static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
00764 static void setup_incoming_varargs (CUMULATIVE_ARGS *,
00765 enum machine_mode, tree,
00766 int *, int);
00767 static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00768 tree, bool);
00769 static int rs6000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00770 tree, bool);
00771 #if TARGET_MACHO
00772 static void macho_branch_islands (void);
00773 static void add_compiler_branch_island (tree, tree, int);
00774 static int no_previous_def (tree function_name);
00775 static tree get_prev_label (tree function_name);
00776 static void rs6000_darwin_file_start (void);
00777 #endif
00778
00779 static tree rs6000_build_builtin_va_list (void);
00780 static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *);
00781 static bool rs6000_must_pass_in_stack (enum machine_mode, tree);
00782 static bool rs6000_vector_mode_supported_p (enum machine_mode);
00783 static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
00784 enum machine_mode);
00785 static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
00786 enum machine_mode);
00787 static int get_vsel_insn (enum machine_mode);
00788 static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
00789
00790
00791 const int INSN_NOT_AVAILABLE = -1;
00792 static enum machine_mode rs6000_eh_return_filter_mode (void);
00793
00794
00795
00796 struct toc_hash_struct GTY(())
00797 {
00798
00799
00800 rtx key;
00801 enum machine_mode key_mode;
00802 int labelno;
00803 };
00804
00805 static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
00806
00807
00808 char rs6000_reg_names[][8] =
00809 {
00810 "0", "1", "2", "3", "4", "5", "6", "7",
00811 "8", "9", "10", "11", "12", "13", "14", "15",
00812 "16", "17", "18", "19", "20", "21", "22", "23",
00813 "24", "25", "26", "27", "28", "29", "30", "31",
00814 "0", "1", "2", "3", "4", "5", "6", "7",
00815 "8", "9", "10", "11", "12", "13", "14", "15",
00816 "16", "17", "18", "19", "20", "21", "22", "23",
00817 "24", "25", "26", "27", "28", "29", "30", "31",
00818 "mq", "lr", "ctr","ap",
00819 "0", "1", "2", "3", "4", "5", "6", "7",
00820 "xer",
00821
00822 "0", "1", "2", "3", "4", "5", "6", "7",
00823 "8", "9", "10", "11", "12", "13", "14", "15",
00824 "16", "17", "18", "19", "20", "21", "22", "23",
00825 "24", "25", "26", "27", "28", "29", "30", "31",
00826 "vrsave", "vscr",
00827
00828 "spe_acc", "spefscr"
00829 };
00830
00831 #ifdef TARGET_REGNAMES
00832 static const char alt_reg_names[][8] =
00833 {
00834 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
00835 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
00836 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
00837 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
00838 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
00839 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
00840 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
00841 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
00842 "mq", "lr", "ctr", "ap",
00843 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
00844 "xer",
00845
00846 "%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
00847 "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
00848 "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
00849 "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
00850 "vrsave", "vscr",
00851
00852 "spe_acc", "spefscr"
00853 };
00854 #endif
00855
00856 #ifndef MASK_STRICT_ALIGN
00857 #define MASK_STRICT_ALIGN 0
00858 #endif
00859 #ifndef TARGET_PROFILE_KERNEL
00860 #define TARGET_PROFILE_KERNEL 0
00861 #endif
00862
00863
00864 #define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
00865
00866
00867 #define RS6000_SYMBOL_REF_TLS_P(RTX) \
00868 (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
00869
00870
00871 #undef TARGET_ATTRIBUTE_TABLE
00872 #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
00873 #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
00874 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes
00875
00876 #undef TARGET_ASM_ALIGNED_DI_OP
00877 #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP
00878
00879
00880
00881 #ifndef OBJECT_FORMAT_ELF
00882 #if TARGET_XCOFF
00883
00884
00885 #undef TARGET_ASM_UNALIGNED_HI_OP
00886 #define TARGET_ASM_UNALIGNED_HI_OP "\t.vbyte\t2,"
00887 #undef TARGET_ASM_UNALIGNED_SI_OP
00888 #define TARGET_ASM_UNALIGNED_SI_OP "\t.vbyte\t4,"
00889 #undef TARGET_ASM_UNALIGNED_DI_OP
00890 #define TARGET_ASM_UNALIGNED_DI_OP "\t.vbyte\t8,"
00891 #else
00892
00893 #undef TARGET_ASM_UNALIGNED_HI_OP
00894 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
00895 #undef TARGET_ASM_UNALIGNED_SI_OP
00896 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
00897 #undef TARGET_ASM_UNALIGNED_DI_OP
00898 #define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t"
00899 #undef TARGET_ASM_ALIGNED_DI_OP
00900 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00901 #endif
00902 #endif
00903
00904
00905
00906 #undef TARGET_ASM_INTEGER
00907 #define TARGET_ASM_INTEGER rs6000_assemble_integer
00908
00909 #ifdef HAVE_GAS_HIDDEN
00910 #undef TARGET_ASM_ASSEMBLE_VISIBILITY
00911 #define TARGET_ASM_ASSEMBLE_VISIBILITY rs6000_assemble_visibility
00912 #endif
00913
00914 #undef TARGET_HAVE_TLS
00915 #define TARGET_HAVE_TLS HAVE_AS_TLS
00916
00917 #undef TARGET_CANNOT_FORCE_CONST_MEM
00918 #define TARGET_CANNOT_FORCE_CONST_MEM rs6000_tls_referenced_p
00919
00920 #undef TARGET_ASM_FUNCTION_PROLOGUE
00921 #define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
00922 #undef TARGET_ASM_FUNCTION_EPILOGUE
00923 #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
00924
00925 #undef TARGET_SCHED_VARIABLE_ISSUE
00926 #define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
00927
00928 #undef TARGET_SCHED_ISSUE_RATE
00929 #define TARGET_SCHED_ISSUE_RATE rs6000_issue_rate
00930 #undef TARGET_SCHED_ADJUST_COST
00931 #define TARGET_SCHED_ADJUST_COST rs6000_adjust_cost
00932 #undef TARGET_SCHED_ADJUST_PRIORITY
00933 #define TARGET_SCHED_ADJUST_PRIORITY rs6000_adjust_priority
00934 #undef TARGET_SCHED_IS_COSTLY_DEPENDENCE
00935 #define TARGET_SCHED_IS_COSTLY_DEPENDENCE rs6000_is_costly_dependence
00936 #undef TARGET_SCHED_FINISH
00937 #define TARGET_SCHED_FINISH rs6000_sched_finish
00938
00939 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
00940 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD rs6000_use_sched_lookahead
00941
00942 #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
00943 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD rs6000_builtin_mask_for_load
00944
00945 #undef TARGET_INIT_BUILTINS
00946 #define TARGET_INIT_BUILTINS rs6000_init_builtins
00947
00948 #undef TARGET_EXPAND_BUILTIN
00949 #define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
00950
00951 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
00952 #define TARGET_MANGLE_FUNDAMENTAL_TYPE rs6000_mangle_fundamental_type
00953
00954 #undef TARGET_INIT_LIBFUNCS
00955 #define TARGET_INIT_LIBFUNCS rs6000_init_libfuncs
00956
00957 #if TARGET_MACHO
00958 #undef TARGET_BINDS_LOCAL_P
00959 #define TARGET_BINDS_LOCAL_P rs6000_binds_local_p
00960 #endif
00961
00962 #undef TARGET_ASM_OUTPUT_MI_THUNK
00963 #define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
00964
00965 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00966 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00967
00968 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00969 #define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
00970
00971 #undef TARGET_RTX_COSTS
00972 #define TARGET_RTX_COSTS rs6000_rtx_costs
00973 #undef TARGET_ADDRESS_COST
00974 #define TARGET_ADDRESS_COST hook_int_rtx_0
00975
00976 #undef TARGET_VECTOR_OPAQUE_P
00977 #define TARGET_VECTOR_OPAQUE_P is_ev64_opaque_type
00978
00979 #undef TARGET_DWARF_REGISTER_SPAN
00980 #define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
00981
00982
00983
00984 #undef TARGET_PROMOTE_FUNCTION_ARGS
00985 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00986 #undef TARGET_PROMOTE_FUNCTION_RETURN
00987 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00988
00989 #undef TARGET_RETURN_IN_MEMORY
00990 #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
00991
00992 #undef TARGET_SETUP_INCOMING_VARARGS
00993 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
00994
00995
00996 #undef TARGET_STRICT_ARGUMENT_NAMING
00997 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
00998 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
00999 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
01000 #undef TARGET_SPLIT_COMPLEX_ARG
01001 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
01002 #undef TARGET_MUST_PASS_IN_STACK
01003 #define TARGET_MUST_PASS_IN_STACK rs6000_must_pass_in_stack
01004 #undef TARGET_PASS_BY_REFERENCE
01005 #define TARGET_PASS_BY_REFERENCE rs6000_pass_by_reference
01006 #undef TARGET_ARG_PARTIAL_BYTES
01007 #define TARGET_ARG_PARTIAL_BYTES rs6000_arg_partial_bytes
01008
01009 #undef TARGET_BUILD_BUILTIN_VA_LIST
01010 #define TARGET_BUILD_BUILTIN_VA_LIST rs6000_build_builtin_va_list
01011
01012 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
01013 #define TARGET_GIMPLIFY_VA_ARG_EXPR rs6000_gimplify_va_arg
01014
01015 #undef TARGET_EH_RETURN_FILTER_MODE
01016 #define TARGET_EH_RETURN_FILTER_MODE rs6000_eh_return_filter_mode
01017
01018 #undef TARGET_VECTOR_MODE_SUPPORTED_P
01019 #define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 #undef TARGET_RELAXED_ORDERING
01030 #define TARGET_RELAXED_ORDERING true
01031
01032 struct gcc_target targetm = TARGET_INITIALIZER;
01033
01034
01035
01036
01037 static int
01038 rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
01039 {
01040
01041
01042 if (INT_REGNO_P (regno))
01043 return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
01044
01045
01046 if (FP_REGNO_P (regno))
01047 return
01048 (GET_MODE_CLASS (mode) == MODE_FLOAT
01049 && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
01050 || (GET_MODE_CLASS (mode) == MODE_INT
01051 && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD);
01052
01053
01054 if (CR_REGNO_P (regno))
01055 return GET_MODE_CLASS (mode) == MODE_CC;
01056
01057 if (XER_REGNO_P (regno))
01058 return mode == PSImode;
01059
01060
01061 if (ALTIVEC_REGNO_P (regno))
01062 return ALTIVEC_VECTOR_MODE (mode);
01063
01064
01065 if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
01066 return 1;
01067
01068
01069
01070
01071 return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
01072 }
01073
01074
01075 static void
01076 rs6000_init_hard_regno_mode_ok (void)
01077 {
01078 int r, m;
01079
01080 for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
01081 for (m = 0; m < NUM_MACHINE_MODES; ++m)
01082 if (rs6000_hard_regno_mode_ok (r, m))
01083 rs6000_hard_regno_mode_ok_p[m][r] = true;
01084 }
01085
01086
01087
01088
01089 #ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE
01090 #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
01091 #endif
01092
01093
01094
01095
01096 void
01097 rs6000_override_options (const char *default_cpu)
01098 {
01099 size_t i, j;
01100 struct rs6000_cpu_select *ptr;
01101 int set_masks;
01102
01103
01104
01105 enum {
01106 POWERPC_BASE_MASK = MASK_POWERPC | MASK_NEW_MNEMONICS,
01107 POWERPC_7400_MASK = POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_ALTIVEC
01108 };
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 static struct ptt
01119 {
01120 const char *const name;
01121 const enum processor_type processor;
01122 const int target_enable;
01123 } const processor_target_table[]
01124 = {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01125 {"403", PROCESSOR_PPC403,
01126 POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
01127 {"405", PROCESSOR_PPC405, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01128 {"405fp", PROCESSOR_PPC405, POWERPC_BASE_MASK},
01129 {"440", PROCESSOR_PPC440, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01130 {"440fp", PROCESSOR_PPC440, POWERPC_BASE_MASK},
01131 {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
01132 {"601", PROCESSOR_PPC601,
01133 MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
01134 {"602", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01135 {"603", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01136 {"603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01137 {"604", PROCESSOR_PPC604, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01138 {"604e", PROCESSOR_PPC604e, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01139 {"620", PROCESSOR_PPC620,
01140 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01141 {"630", PROCESSOR_PPC630,
01142 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01143 {"740", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01144 {"7400", PROCESSOR_PPC7400, POWERPC_7400_MASK},
01145 {"7450", PROCESSOR_PPC7450, POWERPC_7400_MASK},
01146 {"750", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01147 {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01148 {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01149 {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01150 {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01151
01152 {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01153 {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01154 {"970", PROCESSOR_POWER4,
01155 POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
01156 {"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS},
01157 {"ec603e", PROCESSOR_PPC603, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
01158 {"G3", PROCESSOR_PPC750, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
01159 {"G4", PROCESSOR_PPC7450, POWERPC_7400_MASK},
01160 {"G5", PROCESSOR_POWER4,
01161 POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
01162 {"power", PROCESSOR_POWER, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01163 {"power2", PROCESSOR_POWER,
01164 MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
01165 {"power3", PROCESSOR_PPC630,
01166 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
01167 {"power4", PROCESSOR_POWER4,
01168 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POWERPC64},
01169 {"power5", PROCESSOR_POWER5,
01170 POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POWERPC64},
01171 {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
01172 {"powerpc64", PROCESSOR_POWERPC64,
01173 POWERPC_BASE_MASK | MASK_POWERPC64},
01174 {"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01175 {"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01176 {"rios2", PROCESSOR_RIOS2,
01177 MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
01178 {"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01179 {"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
01180 {"rs64a", PROCESSOR_RS64A, POWERPC_BASE_MASK | MASK_POWERPC64},
01181 };
01182
01183 const size_t ptt_size = ARRAY_SIZE (processor_target_table);
01184
01185
01186
01187
01188
01189
01190
01191 enum {
01192 POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
01193 POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT
01194 | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
01195 | MASK_MFCRF)
01196 };
01197
01198 rs6000_init_hard_regno_mode_ok ();
01199
01200 set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
01201 #ifdef OS_MISSING_POWERPC64
01202 if (OS_MISSING_POWERPC64)
01203 set_masks &= ~MASK_POWERPC64;
01204 #endif
01205 #ifdef OS_MISSING_ALTIVEC
01206 if (OS_MISSING_ALTIVEC)
01207 set_masks &= ~MASK_ALTIVEC;
01208 #endif
01209
01210
01211 set_masks &= ~target_flags_explicit;
01212
01213
01214 rs6000_select[0].string = default_cpu;
01215 rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
01216
01217 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
01218 {
01219 ptr = &rs6000_select[i];
01220 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
01221 {
01222 for (j = 0; j < ptt_size; j++)
01223 if (! strcmp (ptr->string, processor_target_table[j].name))
01224 {
01225 if (ptr->set_tune_p)
01226 rs6000_cpu = processor_target_table[j].processor;
01227
01228 if (ptr->set_arch_p)
01229 {
01230 target_flags &= ~set_masks;
01231 target_flags |= (processor_target_table[j].target_enable
01232 & set_masks);
01233 }
01234 break;
01235 }
01236
01237 if (j == ptt_size)
01238 error ("bad value (%s) for %s switch", ptr->string, ptr->name);
01239 }
01240 }
01241
01242 if (TARGET_E500)
01243 rs6000_isel = 1;
01244
01245
01246
01247 if (BYTES_BIG_ENDIAN && optimize_size)
01248 target_flags |= ~target_flags_explicit & (MASK_MULTIPLE | MASK_STRING);
01249
01250
01251
01252
01253
01254
01255
01256 if (!BYTES_BIG_ENDIAN && rs6000_cpu != PROCESSOR_PPC750)
01257 {
01258 if (TARGET_MULTIPLE)
01259 {
01260 target_flags &= ~MASK_MULTIPLE;
01261 if ((target_flags_explicit & MASK_MULTIPLE) != 0)
01262 warning ("-mmultiple is not supported on little endian systems");
01263 }
01264
01265 if (TARGET_STRING)
01266 {
01267 target_flags &= ~MASK_STRING;
01268 if ((target_flags_explicit & MASK_STRING) != 0)
01269 warning ("-mstring is not supported on little endian systems");
01270 }
01271 }
01272
01273
01274 if (rs6000_debug_name)
01275 {
01276 if (! strcmp (rs6000_debug_name, "all"))
01277 rs6000_debug_stack = rs6000_debug_arg = 1;
01278 else if (! strcmp (rs6000_debug_name, "stack"))
01279 rs6000_debug_stack = 1;
01280 else if (! strcmp (rs6000_debug_name, "arg"))
01281 rs6000_debug_arg = 1;
01282 else
01283 error ("unknown -mdebug-%s switch", rs6000_debug_name);
01284 }
01285
01286 if (rs6000_traceback_name)
01287 {
01288 if (! strncmp (rs6000_traceback_name, "full", 4))
01289 rs6000_traceback = traceback_full;
01290 else if (! strncmp (rs6000_traceback_name, "part", 4))
01291 rs6000_traceback = traceback_part;
01292 else if (! strncmp (rs6000_traceback_name, "no", 2))
01293 rs6000_traceback = traceback_none;
01294 else
01295 error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
01296 rs6000_traceback_name);
01297 }
01298
01299
01300 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01301 if (rs6000_long_double_size_string)
01302 {
01303 char *tail;
01304 int size = strtol (rs6000_long_double_size_string, &tail, 10);
01305 if (*tail != '\0' || (size != 64 && size != 128))
01306 error ("Unknown switch -mlong-double-%s",
01307 rs6000_long_double_size_string);
01308 else
01309 rs6000_long_double_type_size = size;
01310 }
01311
01312
01313 if (TARGET_ELF && TARGET_64BIT)
01314 {
01315 rs6000_altivec_abi = 1;
01316 rs6000_altivec_vrsave = 1;
01317 }
01318
01319
01320 if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
01321 {
01322 rs6000_darwin64_abi = 1;
01323
01324 #if TARGET_MACHO
01325 darwin_one_byte_bool = "";
01326 #endif
01327
01328 rs6000_alignment_flags = MASK_ALIGN_NATURAL;
01329 }
01330
01331
01332 rs6000_parse_abi_options ();
01333
01334
01335 rs6000_parse_alignment_option ();
01336
01337 rs6000_parse_float_gprs_option ();
01338
01339
01340 rs6000_parse_yes_no_option ("vrsave", rs6000_altivec_vrsave_string,
01341 &rs6000_altivec_vrsave);
01342 rs6000_parse_yes_no_option ("isel", rs6000_isel_string,
01343 &rs6000_isel);
01344 rs6000_parse_yes_no_option ("spe", rs6000_spe_string, &rs6000_spe);
01345
01346
01347 rs6000_parse_tls_size_option ();
01348
01349 #ifdef SUBTARGET_OVERRIDE_OPTIONS
01350 SUBTARGET_OVERRIDE_OPTIONS;
01351 #endif
01352 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
01353 SUBSUBTARGET_OVERRIDE_OPTIONS;
01354 #endif
01355 #ifdef SUB3TARGET_OVERRIDE_OPTIONS
01356 SUB3TARGET_OVERRIDE_OPTIONS;
01357 #endif
01358
01359 if (TARGET_E500)
01360 {
01361 if (TARGET_ALTIVEC)
01362 error ("AltiVec and E500 instructions cannot coexist");
01363
01364
01365
01366 if ((target_flags & MASK_STRING) != 0)
01367 target_flags = target_flags & ~MASK_STRING;
01368
01369
01370 if (rs6000_spe_string != 0
01371 && !strcmp (rs6000_spe_string, "no"))
01372 rs6000_long_double_type_size = 64;
01373 }
01374 else if (rs6000_select[1].string != NULL)
01375 {
01376
01377
01378
01379 if (rs6000_abi_string == 0)
01380 rs6000_spe_abi = 0;
01381 if (rs6000_spe_string == 0)
01382 rs6000_spe = 0;
01383 if (rs6000_float_gprs_string == 0)
01384 rs6000_float_gprs = 0;
01385 if (rs6000_isel_string == 0)
01386 rs6000_isel = 0;
01387 if (rs6000_long_double_size_string == 0)
01388 rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
01389 }
01390
01391 rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
01392 && rs6000_cpu != PROCESSOR_POWER5);
01393 rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
01394 || rs6000_cpu == PROCESSOR_POWER5);
01395
01396
01397
01398
01399
01400
01401
01402 if (rs6000_longcall_switch)
01403 {
01404 const char *base = rs6000_longcall_switch;
01405 while (base[-1] != 'm') base--;
01406
01407 if (*rs6000_longcall_switch != '\0')
01408 error ("invalid option %qs", base);
01409 rs6000_default_long_calls = (base[0] != 'n');
01410 }
01411
01412
01413 if (rs6000_warn_altivec_long_switch)
01414 {
01415 const char *base = rs6000_warn_altivec_long_switch;
01416 while (base[-1] != 'm') base--;
01417
01418 if (*rs6000_warn_altivec_long_switch != '\0')
01419 error ("invalid option %qs", base);
01420 rs6000_warn_altivec_long = (base[0] != 'n');
01421 }
01422
01423
01424 rs6000_sched_restricted_insns_priority
01425 = (rs6000_sched_groups ? 1 : 0);
01426 if (rs6000_sched_restricted_insns_priority_str)
01427 rs6000_sched_restricted_insns_priority =
01428 atoi (rs6000_sched_restricted_insns_priority_str);
01429
01430
01431 rs6000_sched_costly_dep
01432 = (rs6000_sched_groups ? store_to_load_dep_costly : no_dep_costly);
01433 if (rs6000_sched_costly_dep_str)
01434 {
01435 if (! strcmp (rs6000_sched_costly_dep_str, "no"))
01436 rs6000_sched_costly_dep = no_dep_costly;
01437 else if (! strcmp (rs6000_sched_costly_dep_str, "all"))
01438 rs6000_sched_costly_dep = all_deps_costly;
01439 else if (! strcmp (rs6000_sched_costly_dep_str, "true_store_to_load"))
01440 rs6000_sched_costly_dep = true_store_to_load_dep_costly;
01441 else if (! strcmp (rs6000_sched_costly_dep_str, "store_to_load"))
01442 rs6000_sched_costly_dep = store_to_load_dep_costly;
01443 else
01444 rs6000_sched_costly_dep = atoi (rs6000_sched_costly_dep_str);
01445 }
01446
01447
01448 rs6000_sched_insert_nops
01449 = (rs6000_sched_groups ? sched_finish_regroup_exact : sched_finish_none);
01450 if (rs6000_sched_insert_nops_str)
01451 {
01452 if (! strcmp (rs6000_sched_insert_nops_str, "no"))
01453 rs6000_sched_insert_nops = sched_finish_none;
01454 else if (! strcmp (rs6000_sched_insert_nops_str, "pad"))
01455 rs6000_sched_insert_nops = sched_finish_pad_groups;
01456 else if (! strcmp (rs6000_sched_insert_nops_str, "regroup_exact"))
01457 rs6000_sched_insert_nops = sched_finish_regroup_exact;
01458 else
01459 rs6000_sched_insert_nops = atoi (rs6000_sched_insert_nops_str);
01460 }
01461
01462 #ifdef TARGET_REGNAMES
01463
01464
01465 if (TARGET_REGNAMES)
01466 memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
01467 #endif
01468
01469
01470
01471
01472 if ((target_flags_explicit & MASK_AIX_STRUCT_RET) == 0)
01473 {
01474 if (DEFAULT_ABI == ABI_V4 && !DRAFT_V4_STRUCT_RET)
01475 target_flags = (target_flags & ~MASK_AIX_STRUCT_RET);
01476 else
01477 target_flags |= MASK_AIX_STRUCT_RET;
01478 }
01479
01480 if (TARGET_LONG_DOUBLE_128
01481 && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN))
01482 REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
01483
01484
01485 rs6000_sr_alias_set = new_alias_set ();
01486
01487 if (TARGET_TOC)
01488 ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
01489
01490
01491
01492 if (!TARGET_64BIT)
01493 {
01494 targetm.asm_out.aligned_op.di = NULL;
01495 targetm.asm_out.unaligned_op.di = NULL;
01496 }
01497
01498
01499 if (!optimize_size)
01500 {
01501 if (rs6000_sched_groups)
01502 {
01503 if (align_functions <= 0)
01504 align_functions = 16;
01505 if (align_jumps <= 0)
01506 align_jumps = 16;
01507 if (align_loops <= 0)
01508 align_loops = 16;
01509 }
01510 if (align_jumps_max_skip <= 0)
01511 align_jumps_max_skip = 15;
01512 if (align_loops_max_skip <= 0)
01513 align_loops_max_skip = 15;
01514 }
01515
01516
01517 init_machine_status = rs6000_init_machine_status;
01518
01519
01520
01521 if (DEFAULT_ABI != ABI_AIX)
01522 targetm.calls.split_complex_arg = NULL;
01523
01524
01525 if (optimize_size)
01526 rs6000_cost = TARGET_POWERPC64 ? &size64_cost : &size32_cost;
01527 else
01528 switch (rs6000_cpu)
01529 {
01530 case PROCESSOR_RIOS1:
01531 rs6000_cost = &rios1_cost;
01532 break;
01533
01534 case PROCESSOR_RIOS2:
01535 rs6000_cost = &rios2_cost;
01536 break;
01537
01538 case PROCESSOR_RS64A:
01539 rs6000_cost = &rs64a_cost;
01540 break;
01541
01542 case PROCESSOR_MPCCORE:
01543 rs6000_cost = &mpccore_cost;
01544 break;
01545
01546 case PROCESSOR_PPC403:
01547 rs6000_cost = &ppc403_cost;
01548 break;
01549
01550 case PROCESSOR_PPC405:
01551 rs6000_cost = &ppc405_cost;
01552 break;
01553
01554 case PROCESSOR_PPC440:
01555 rs6000_cost = &ppc440_cost;
01556 break;
01557
01558 case PROCESSOR_PPC601:
01559 rs6000_cost = &ppc601_cost;
01560 break;
01561
01562 case PROCESSOR_PPC603:
01563 rs6000_cost = &ppc603_cost;
01564 break;
01565
01566 case PROCESSOR_PPC604:
01567 rs6000_cost = &ppc604_cost;
01568 break;
01569
01570 case PROCESSOR_PPC604e:
01571 rs6000_cost = &ppc604e_cost;
01572 break;
01573
01574 case PROCESSOR_PPC620:
01575 rs6000_cost = &ppc620_cost;
01576 break;
01577
01578 case PROCESSOR_PPC630:
01579 rs6000_cost = &ppc630_cost;
01580 break;
01581
01582 case PROCESSOR_PPC750:
01583 case PROCESSOR_PPC7400:
01584 rs6000_cost = &ppc750_cost;
01585 break;
01586
01587 case PROCESSOR_PPC7450:
01588 rs6000_cost = &ppc7450_cost;
01589 break;
01590
01591 case PROCESSOR_PPC8540:
01592 rs6000_cost = &ppc8540_cost;
01593 break;
01594
01595 case PROCESSOR_POWER4:
01596 case PROCESSOR_POWER5:
01597 rs6000_cost = &power4_cost;
01598 break;
01599
01600 default:
01601 abort ();
01602 }
01603 }
01604
01605
01606 static tree
01607 rs6000_builtin_mask_for_load (void)
01608 {
01609 if (TARGET_ALTIVEC)
01610 return altivec_builtin_mask_for_load;
01611 else
01612 return 0;
01613 }
01614
01615
01616
01617
01618
01619
01620 static void
01621 rs6000_parse_yes_no_option (const char *name, const char *value, int *flag)
01622 {
01623 if (value == 0)
01624 return;
01625 else if (!strcmp (value, "yes"))
01626 *flag = 1;
01627 else if (!strcmp (value, "no"))
01628 *flag = 0;
01629 else
01630 error ("unknown -m%s= option specified: '%s'", name, value);
01631 }
01632
01633
01634 static void
01635 rs6000_parse_abi_options (void)
01636 {
01637 if (rs6000_abi_string == 0)
01638 return;
01639 else if (! strcmp (rs6000_abi_string, "altivec"))
01640 {
01641 rs6000_altivec_abi = 1;
01642 rs6000_spe_abi = 0;
01643 }
01644 else if (! strcmp (rs6000_abi_string, "no-altivec"))
01645 rs6000_altivec_abi = 0;
01646 else if (! strcmp (rs6000_abi_string, "spe"))
01647 {
01648 rs6000_spe_abi = 1;
01649 rs6000_altivec_abi = 0;
01650 if (!TARGET_SPE_ABI)
01651 error ("not configured for ABI: '%s'", rs6000_abi_string);
01652 }
01653
01654
01655
01656 else if (! strcmp (rs6000_abi_string, "d64"))
01657 {
01658 rs6000_darwin64_abi = 1;
01659 warning ("Using darwin64 ABI");
01660 }
01661 else if (! strcmp (rs6000_abi_string, "d32"))
01662 {
01663 rs6000_darwin64_abi = 0;
01664 warning ("Using old darwin ABI");
01665 }
01666
01667 else if (! strcmp (rs6000_abi_string, "no-spe"))
01668 rs6000_spe_abi = 0;
01669 else
01670 error ("unknown ABI specified: '%s'", rs6000_abi_string);
01671 }
01672
01673
01674 static void
01675 rs6000_parse_float_gprs_option (void)
01676 {
01677 if (rs6000_float_gprs_string == 0)
01678 return;
01679 else if (! strcmp (rs6000_float_gprs_string, "yes")
01680 || ! strcmp (rs6000_float_gprs_string, "single"))
01681 rs6000_float_gprs = 1;
01682 else if (! strcmp (rs6000_float_gprs_string, "double"))
01683 rs6000_float_gprs = 2;
01684 else if (! strcmp (rs6000_float_gprs_string, "no"))
01685 rs6000_float_gprs = 0;
01686 else
01687 error ("invalid option for -mfloat-gprs");
01688 }
01689
01690
01691 static void
01692 rs6000_parse_alignment_option (void)
01693 {
01694 if (rs6000_alignment_string == 0)
01695 return;
01696 else if (! strcmp (rs6000_alignment_string, "power"))
01697 {
01698
01699
01700
01701
01702 if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
01703 warning ("-malign-power is not supported for 64-bit Darwin;"
01704 " it is incompatible with the installed C and C++ libraries");
01705 rs6000_alignment_flags = MASK_ALIGN_POWER;
01706 }
01707 else if (! strcmp (rs6000_alignment_string, "natural"))
01708 rs6000_alignment_flags = MASK_ALIGN_NATURAL;
01709 else
01710 error ("unknown -malign-XXXXX option specified: '%s'",
01711 rs6000_alignment_string);
01712 }
01713
01714
01715
01716 static void
01717 rs6000_parse_tls_size_option (void)
01718 {
01719 if (rs6000_tls_size_string == 0)
01720 return;
01721 else if (strcmp (rs6000_tls_size_string, "16") == 0)
01722 rs6000_tls_size = 16;
01723 else if (strcmp (rs6000_tls_size_string, "32") == 0)
01724 rs6000_tls_size = 32;
01725 else if (strcmp (rs6000_tls_size_string, "64") == 0)
01726 rs6000_tls_size = 64;
01727 else
01728 error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
01729 }
01730
01731 void
01732 optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
01733 {
01734 }
01735
01736
01737
01738 static void
01739 rs6000_file_start (void)
01740 {
01741 size_t i;
01742 char buffer[80];
01743 const char *start = buffer;
01744 struct rs6000_cpu_select *ptr;
01745 const char *default_cpu = TARGET_CPU_DEFAULT;
01746 FILE *file = asm_out_file;
01747
01748 default_file_start ();
01749
01750 #ifdef TARGET_BI_ARCH
01751 if ((TARGET_DEFAULT ^ target_flags) & MASK_64BIT)
01752 default_cpu = 0;
01753 #endif
01754
01755 if (flag_verbose_asm)
01756 {
01757 sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);
01758 rs6000_select[0].string = default_cpu;
01759
01760 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
01761 {
01762 ptr = &rs6000_select[i];
01763 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
01764 {
01765 fprintf (file, "%s %s%s", start, ptr->name, ptr->string);
01766 start = "";
01767 }
01768 }
01769
01770 #ifdef USING_ELFOS_H
01771 switch (rs6000_sdata)
01772 {
01773 case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
01774 case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
01775 case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;
01776 case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
01777 }
01778
01779 if (rs6000_sdata && g_switch_value)
01780 {
01781 fprintf (file, "%s -G " HOST_WIDE_INT_PRINT_UNSIGNED, start,
01782 g_switch_value);
01783 start = "";
01784 }
01785 #endif
01786
01787 if (*start == '\0')
01788 putc ('\n', file);
01789 }
01790
01791 if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
01792 {
01793 toc_section ();
01794 text_section ();
01795 }
01796 }
01797
01798
01799
01800
01801 int
01802 direct_return (void)
01803 {
01804 if (reload_completed)
01805 {
01806 rs6000_stack_t *info = rs6000_stack_info ();
01807
01808 if (info->first_gp_reg_save == 32
01809 && info->first_fp_reg_save == 64
01810 && info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
01811 && ! info->lr_save_p
01812 && ! info->cr_save_p
01813 && info->vrsave_mask == 0
01814 && ! info->push_p)
01815 return 1;
01816 }
01817
01818 return 0;
01819 }
01820
01821
01822
01823 int
01824 any_operand (rtx op ATTRIBUTE_UNUSED,
01825 enum machine_mode mode ATTRIBUTE_UNUSED)
01826 {
01827 return 1;
01828 }
01829
01830
01831
01832 int
01833 any_parallel_operand (rtx op ATTRIBUTE_UNUSED,
01834 enum machine_mode mode ATTRIBUTE_UNUSED)
01835 {
01836 return 1;
01837 }
01838
01839
01840
01841 int
01842 count_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01843 {
01844 if (GET_CODE (op) != REG)
01845 return 0;
01846
01847 if (REGNO (op) == COUNT_REGISTER_REGNUM)
01848 return 1;
01849
01850 if (REGNO (op) > FIRST_PSEUDO_REGISTER)
01851 return 1;
01852
01853 return 0;
01854 }
01855
01856
01857
01858 int
01859 altivec_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01860 {
01861 return (register_operand (op, mode)
01862 && (GET_CODE (op) != REG
01863 || REGNO (op) > FIRST_PSEUDO_REGISTER
01864 || ALTIVEC_REGNO_P (REGNO (op))));
01865 }
01866
01867 int
01868 xer_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01869 {
01870 if (GET_CODE (op) != REG)
01871 return 0;
01872
01873 if (XER_REGNO_P (REGNO (op)))
01874 return 1;
01875
01876 return 0;
01877 }
01878
01879
01880
01881
01882 int
01883 s8bit_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01884 {
01885 return (GET_CODE (op) == CONST_INT
01886 && (INTVAL (op) >= -128 && INTVAL (op) <= 127));
01887 }
01888
01889
01890
01891 int
01892 short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01893 {
01894 return (GET_CODE (op) == CONST_INT
01895 && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
01896 }
01897
01898
01899
01900 int
01901 u_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01902 {
01903 return (GET_CODE (op) == CONST_INT
01904 && CONST_OK_FOR_LETTER_P (INTVAL (op) & GET_MODE_MASK (mode), 'K'));
01905 }
01906
01907
01908
01909 int
01910 non_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01911 {
01912 return (GET_CODE (op) == CONST_INT
01913 && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
01914 }
01915
01916
01917
01918
01919 int
01920 exact_log2_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01921 {
01922 return (GET_CODE (op) == CONST_INT
01923 && INTVAL (op) > 0
01924 && exact_log2 (INTVAL (op)) >= 0);
01925 }
01926
01927
01928
01929
01930 int
01931 gpc_reg_operand (rtx op, enum machine_mode mode)
01932 {
01933 return (register_operand (op, mode)
01934 && (GET_CODE (op) != REG
01935 || (REGNO (op) >= ARG_POINTER_REGNUM
01936 && !XER_REGNO_P (REGNO (op)))
01937 || REGNO (op) < MQ_REGNO));
01938 }
01939
01940
01941
01942
01943 int
01944 cc_reg_operand (rtx op, enum machine_mode mode)
01945 {
01946 return (register_operand (op, mode)
01947 && (GET_CODE (op) != REG
01948 || REGNO (op) >= FIRST_PSEUDO_REGISTER
01949 || CR_REGNO_P (REGNO (op))));
01950 }
01951
01952
01953
01954
01955 int
01956 cc_reg_not_cr0_operand (rtx op, enum machine_mode mode)
01957 {
01958 return (register_operand (op, mode)
01959 && (GET_CODE (op) != REG
01960 || REGNO (op) >= FIRST_PSEUDO_REGISTER
01961 || CR_REGNO_NOT_CR0_P (REGNO (op))));
01962 }
01963
01964
01965
01966
01967
01968 int
01969 reg_or_short_operand (rtx op, enum machine_mode mode)
01970 {
01971 return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
01972 }
01973
01974
01975
01976
01977
01978
01979
01980 int
01981 reg_or_neg_short_operand (rtx op, enum machine_mode mode)
01982 {
01983 if (GET_CODE (op) == CONST_INT)
01984 return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P') && INTVAL (op) != 0;
01985
01986 return gpc_reg_operand (op, mode);
01987 }
01988
01989
01990
01991
01992
01993 int
01994 reg_or_aligned_short_operand (rtx op, enum machine_mode mode)
01995 {
01996 if (gpc_reg_operand (op, mode))
01997 return 1;
01998 else if (short_cint_operand (op, mode) && !(INTVAL (op) & 3))
01999 return 1;
02000
02001 return 0;
02002 }
02003
02004
02005
02006
02007
02008 int
02009 reg_or_u_short_operand (rtx op, enum machine_mode mode)
02010 {
02011 return u_short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
02012 }
02013
02014
02015
02016
02017 int
02018 reg_or_cint_operand (rtx op, enum machine_mode mode)
02019 {
02020 return (GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode));
02021 }
02022
02023
02024
02025
02026 int
02027 reg_or_arith_cint_operand (rtx op, enum machine_mode mode)
02028 {
02029 return (gpc_reg_operand (op, mode)
02030 || (GET_CODE (op) == CONST_INT
02031 #if HOST_BITS_PER_WIDE_INT != 32
02032 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
02033 < (unsigned HOST_WIDE_INT) 0x100000000ll)
02034 #endif
02035 ));
02036 }
02037
02038
02039
02040
02041 int
02042 reg_or_add_cint64_operand (rtx op, enum machine_mode mode)
02043 {
02044 return (gpc_reg_operand (op, mode)
02045 || (GET_CODE (op) == CONST_INT
02046 #if HOST_BITS_PER_WIDE_INT == 32
02047 && INTVAL (op) < 0x7fff8000
02048 #else
02049 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
02050 < 0x100000000ll)
02051 #endif
02052 ));
02053 }
02054
02055
02056
02057
02058 int
02059 reg_or_sub_cint64_operand (rtx op, enum machine_mode mode)
02060 {
02061 return (gpc_reg_operand (op, mode)
02062 || (GET_CODE (op) == CONST_INT
02063 #if HOST_BITS_PER_WIDE_INT == 32
02064 && (- INTVAL (op)) < 0x7fff8000
02065 #else
02066 && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
02067 < 0x100000000ll)
02068 #endif
02069 ));
02070 }
02071
02072
02073
02074
02075 int
02076 reg_or_logical_cint_operand (rtx op, enum machine_mode mode)
02077 {
02078 if (GET_CODE (op) == CONST_INT)
02079 {
02080 if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
02081 {
02082 if (GET_MODE_BITSIZE (mode) <= 32)
02083 abort ();
02084
02085 if (INTVAL (op) < 0)
02086 return 0;
02087 }
02088
02089 return ((INTVAL (op) & GET_MODE_MASK (mode)
02090 & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0);
02091 }
02092 else if (GET_CODE (op) == CONST_DOUBLE)
02093 {
02094 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
02095 || mode != DImode)
02096 abort ();
02097
02098 return CONST_DOUBLE_HIGH (op) == 0;
02099 }
02100 else
02101 return gpc_reg_operand (op, mode);
02102 }
02103
02104
02105
02106 int
02107 got_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02108 {
02109 return (GET_CODE (op) == SYMBOL_REF
02110 || GET_CODE (op) == CONST
02111 || GET_CODE (op) == LABEL_REF);
02112 }
02113
02114
02115
02116
02117 int
02118 got_no_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02119 {
02120 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
02121 }
02122
02123
02124
02125
02126 static int
02127 num_insns_constant_wide (HOST_WIDE_INT value)
02128 {
02129
02130 if (CONST_OK_FOR_LETTER_P (value, 'I'))
02131 return 1;
02132
02133
02134 else if (CONST_OK_FOR_LETTER_P (value, 'L'))
02135 return 1;
02136
02137 #if HOST_BITS_PER_WIDE_INT == 64
02138 else if (TARGET_POWERPC64)
02139 {
02140 HOST_WIDE_INT low = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
02141 HOST_WIDE_INT high = value >> 31;
02142
02143 if (high == 0 || high == -1)
02144 return 2;
02145
02146 high >>= 1;
02147
02148 if (low == 0)
02149 return num_insns_constant_wide (high) + 1;
02150 else
02151 return (num_insns_constant_wide (high)
02152 + num_insns_constant_wide (low) + 1);
02153 }
02154 #endif
02155
02156 else
02157 return 2;
02158 }
02159
02160 int
02161 num_insns_constant (rtx op, enum machine_mode mode)
02162 {
02163 if (GET_CODE (op) == CONST_INT)
02164 {
02165 #if HOST_BITS_PER_WIDE_INT == 64
02166 if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
02167 && mask64_operand (op, mode))
02168 return 2;
02169 else
02170 #endif
02171 return num_insns_constant_wide (INTVAL (op));
02172 }
02173
02174 else if (GET_CODE (op) == CONST_DOUBLE && mode == SFmode)
02175 {
02176 long l;
02177 REAL_VALUE_TYPE rv;
02178
02179 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02180 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
02181 return num_insns_constant_wide ((HOST_WIDE_INT) l);
02182 }
02183
02184 else if (GET_CODE (op) == CONST_DOUBLE)
02185 {
02186 HOST_WIDE_INT low;
02187 HOST_WIDE_INT high;
02188 long l[2];
02189 REAL_VALUE_TYPE rv;
02190 int endian = (WORDS_BIG_ENDIAN == 0);
02191
02192 if (mode == VOIDmode || mode == DImode)
02193 {
02194 high = CONST_DOUBLE_HIGH (op);
02195 low = CONST_DOUBLE_LOW (op);
02196 }
02197 else
02198 {
02199 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02200 REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
02201 high = l[endian];
02202 low = l[1 - endian];
02203 }
02204
02205 if (TARGET_32BIT)
02206 return (num_insns_constant_wide (low)
02207 + num_insns_constant_wide (high));
02208
02209 else
02210 {
02211 if (high == 0 && low >= 0)
02212 return num_insns_constant_wide (low);
02213
02214 else if (high == -1 && low < 0)
02215 return num_insns_constant_wide (low);
02216
02217 else if (mask64_operand (op, mode))
02218 return 2;
02219
02220 else if (low == 0)
02221 return num_insns_constant_wide (high) + 1;
02222
02223 else
02224 return (num_insns_constant_wide (high)
02225 + num_insns_constant_wide (low) + 1);
02226 }
02227 }
02228
02229 else
02230 abort ();
02231 }
02232
02233
02234
02235
02236
02237 int
02238 easy_fp_constant (rtx op, enum machine_mode mode)
02239 {
02240 if (GET_CODE (op) != CONST_DOUBLE
02241 || GET_MODE (op) != mode
02242 || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
02243 return 0;
02244
02245
02246 if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
02247 && mode != DImode)
02248 return 1;
02249
02250
02251 if (flag_pic && DEFAULT_ABI == ABI_V4)
02252 return 0;
02253
02254 #ifdef TARGET_RELOCATABLE
02255
02256
02257 if (TARGET_RELOCATABLE)
02258 return 0;
02259 #endif
02260
02261 if (mode == TFmode)
02262 {
02263 long k[4];
02264 REAL_VALUE_TYPE rv;
02265
02266 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02267 REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
02268
02269 return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
02270 && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
02271 && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
02272 && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
02273 }
02274
02275 else if (mode == DFmode)
02276 {
02277 long k[2];
02278 REAL_VALUE_TYPE rv;
02279
02280 if (TARGET_E500_DOUBLE)
02281 return 0;
02282
02283 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02284 REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
02285
02286 return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
02287 && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
02288 }
02289
02290 else if (mode == SFmode)
02291 {
02292 long l;
02293 REAL_VALUE_TYPE rv;
02294
02295 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
02296 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
02297
02298 return num_insns_constant_wide (l) == 1;
02299 }
02300
02301 else if (mode == DImode)
02302 return ((TARGET_POWERPC64
02303 && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
02304 || (num_insns_constant (op, DImode) <= 2));
02305
02306 else if (mode == SImode)
02307 return 1;
02308 else
02309 abort ();
02310 }
02311
02312
02313
02314 static int
02315 easy_vector_splat_const (int cst, enum machine_mode mode)
02316 {
02317 switch (mode)
02318 {
02319 case V4SImode:
02320 if (EASY_VECTOR_15 (cst)
02321 || EASY_VECTOR_15_ADD_SELF (cst))
02322 return cst;
02323 if ((cst & 0xffff) != ((cst >> 16) & 0xffff))
02324 break;
02325 cst = cst >> 16;
02326
02327
02328 case V8HImode:
02329 if (EASY_VECTOR_15 (cst)
02330 || EASY_VECTOR_15_ADD_SELF (cst))
02331 return cst;
02332 if ((cst & 0xff) != ((cst >> 8) & 0xff))
02333 break;
02334 cst = cst >> 8;
02335
02336
02337 case V16QImode:
02338 if (EASY_VECTOR_15 (cst)
02339 || EASY_VECTOR_15_ADD_SELF (cst))
02340 return cst;
02341 default:
02342 break;
02343 }
02344 return 0;
02345 }
02346
02347
02348
02349
02350 static int
02351 easy_vector_same (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02352 {
02353 int units, i, cst;
02354
02355 units = CONST_VECTOR_NUNITS (op);
02356
02357 cst = INTVAL (CONST_VECTOR_ELT (op, 0));
02358 for (i = 1; i < units; ++i)
02359 if (INTVAL (CONST_VECTOR_ELT (op, i)) != cst)
02360 break;
02361 if (i == units && easy_vector_splat_const (cst, mode))
02362 return 1;
02363 return 0;
02364 }
02365
02366
02367
02368
02369 int
02370 easy_vector_constant (rtx op, enum machine_mode mode)
02371 {
02372 int cst, cst2;
02373
02374 if (GET_CODE (op) != CONST_VECTOR
02375 || (!TARGET_ALTIVEC
02376 && !TARGET_SPE))
02377 return 0;
02378
02379 if (zero_constant (op, mode)
02380 && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
02381 || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
02382 return 1;
02383
02384 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
02385 return 0;
02386
02387 if (TARGET_SPE && mode == V1DImode)
02388 return 0;
02389
02390 cst = INTVAL (CONST_VECTOR_ELT (op, 0));
02391 cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402 if (TARGET_SPE && mode == V2SImode
02403 && cst >= -0x7fff && cst <= 0x7fff
02404 && cst2 >= -0x7fff && cst2 <= 0x7fff)
02405 return 1;
02406
02407 if (TARGET_ALTIVEC
02408 && easy_vector_same (op, mode))
02409 {
02410 cst = easy_vector_splat_const (cst, mode);
02411 if (EASY_VECTOR_15_ADD_SELF (cst)
02412 || EASY_VECTOR_15 (cst))
02413 return 1;
02414 }
02415 return 0;
02416 }
02417
02418
02419
02420 int
02421 easy_vector_constant_add_self (rtx op, enum machine_mode mode)
02422 {
02423 int cst;
02424 if (TARGET_ALTIVEC
02425 && GET_CODE (op) == CONST_VECTOR
02426 && easy_vector_same (op, mode))
02427 {
02428 cst = easy_vector_splat_const (INTVAL (CONST_VECTOR_ELT (op, 0)), mode);
02429 if (EASY_VECTOR_15_ADD_SELF (cst))
02430 return 1;
02431 }
02432 return 0;
02433 }
02434
02435
02436
02437 rtx
02438 gen_easy_vector_constant_add_self (rtx op)
02439 {
02440 int i, units;
02441 rtvec v;
02442 units = GET_MODE_NUNITS (GET_MODE (op));
02443 v = rtvec_alloc (units);
02444
02445 for (i = 0; i < units; i++)
02446 RTVEC_ELT (v, i) =
02447 GEN_INT (INTVAL (CONST_VECTOR_ELT (op, i)) >> 1);
02448 return gen_rtx_raw_CONST_VECTOR (GET_MODE (op), v);
02449 }
02450
02451 const char *
02452 output_vec_const_move (rtx *operands)
02453 {
02454 int cst, cst2;
02455 enum machine_mode mode;
02456 rtx dest, vec;
02457
02458 dest = operands[0];
02459 vec = operands[1];
02460
02461 cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
02462 cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
02463 mode = GET_MODE (dest);
02464
02465 if (TARGET_ALTIVEC)
02466 {
02467 if (zero_constant (vec, mode))
02468 return "vxor %0,%0,%0";
02469 else if (easy_vector_constant (vec, mode))
02470 {
02471 operands[1] = GEN_INT (cst);
02472 switch (mode)
02473 {
02474 case V4SImode:
02475 if (EASY_VECTOR_15 (cst))
02476 {
02477 operands[1] = GEN_INT (cst);
02478 return "vspltisw %0,%1";
02479 }
02480 else if (EASY_VECTOR_15_ADD_SELF (cst))
02481 return "#";
02482 cst = cst >> 16;
02483
02484
02485 case V8HImode:
02486 if (EASY_VECTOR_15 (cst))
02487 {
02488 operands[1] = GEN_INT (cst);
02489 return "vspltish %0,%1";
02490 }
02491 else if (EASY_VECTOR_15_ADD_SELF (cst))
02492 return "#";
02493 cst = cst >> 8;
02494
02495
02496 case V16QImode:
02497 if (EASY_VECTOR_15 (cst))
02498 {
02499 operands[1] = GEN_INT (cst);
02500 return "vspltisb %0,%1";
02501 }
02502 else if (EASY_VECTOR_15_ADD_SELF (cst))
02503 return "#";
02504
02505 default:
02506 abort ();
02507 }
02508 }
02509 else
02510 abort ();
02511 }
02512
02513 if (TARGET_SPE)
02514 {
02515
02516
02517
02518
02519
02520 operands[1] = GEN_INT (cst);
02521 operands[2] = GEN_INT (cst2);
02522 if (cst == cst2)
02523 return "li %0,%1\n\tevmergelo %0,%0,%0";
02524 else
02525 return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
02526 }
02527
02528 abort ();
02529 }
02530
02531
02532
02533 int
02534 zero_constant (rtx op, enum machine_mode mode)
02535 {
02536 return op == CONST0_RTX (mode);
02537 }
02538
02539
02540 int
02541 zero_fp_constant (rtx op, enum machine_mode mode)
02542 {
02543 return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
02544 }
02545
02546
02547
02548
02549
02550
02551 int
02552 volatile_mem_operand (rtx op, enum machine_mode mode)
02553 {
02554 if (GET_CODE (op) != MEM)
02555 return 0;
02556
02557 if (!MEM_VOLATILE_P (op))
02558 return 0;
02559
02560 if (mode != GET_MODE (op))
02561 return 0;
02562
02563 if (reload_completed)
02564 return memory_operand (op, mode);
02565
02566 if (reload_in_progress)
02567 return strict_memory_address_p (mode, XEXP (op, 0));
02568
02569 return memory_address_p (mode, XEXP (op, 0));
02570 }
02571
02572
02573
02574 int
02575 offsettable_mem_operand (rtx op, enum machine_mode mode)
02576 {
02577 return ((GET_CODE (op) == MEM)
02578 && offsettable_address_p (reload_completed || reload_in_progress,
02579 mode, XEXP (op, 0)));
02580 }
02581
02582
02583
02584
02585 int
02586 mem_or_easy_const_operand (rtx op, enum machine_mode mode)
02587 {
02588 return memory_operand (op, mode) || easy_fp_constant (op, mode);
02589 }
02590
02591
02592
02593
02594 int
02595 add_operand (rtx op, enum machine_mode mode)
02596 {
02597 if (GET_CODE (op) == CONST_INT)
02598 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
02599 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
02600
02601 return gpc_reg_operand (op, mode);
02602 }
02603
02604
02605
02606 int
02607 non_add_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02608 {
02609 return (GET_CODE (op) == CONST_INT
02610 && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
02611 && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
02612 }
02613
02614
02615
02616
02617 int
02618 logical_operand (rtx op, enum machine_mode mode)
02619 {
02620 HOST_WIDE_INT opl, oph;
02621
02622 if (gpc_reg_operand (op, mode))
02623 return 1;
02624
02625 if (GET_CODE (op) == CONST_INT)
02626 {
02627 opl = INTVAL (op) & GET_MODE_MASK (mode);
02628
02629 #if HOST_BITS_PER_WIDE_INT <= 32
02630 if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
02631 return 0;
02632 #endif
02633 }
02634 else if (GET_CODE (op) == CONST_DOUBLE)
02635 {
02636 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
02637 abort ();
02638
02639 opl = CONST_DOUBLE_LOW (op);
02640 oph = CONST_DOUBLE_HIGH (op);
02641 if (oph != 0)
02642 return 0;
02643 }
02644 else
02645 return 0;
02646
02647 return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
02648 || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
02649 }
02650
02651
02652
02653
02654 int
02655 non_logical_cint_operand (rtx op, enum machine_mode mode)
02656 {
02657 return ((GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
02658 && ! logical_operand (op, mode)
02659 && reg_or_logical_cint_operand (op, mode));
02660 }
02661
02662
02663
02664
02665
02666
02667 int
02668 mask_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02669 {
02670 HOST_WIDE_INT c, lsb;
02671
02672 if (GET_CODE (op) != CONST_INT)
02673 return 0;
02674
02675 c = INTVAL (op);
02676
02677
02678
02679 if (TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
02680 return 0;
02681
02682
02683
02684 if (c & 1)
02685 c = ~c;
02686
02687
02688 if (c == 0)
02689 return 0;
02690
02691
02692 lsb = c & -c;
02693
02694
02695 c = ~c;
02696
02697
02698 c &= -lsb;
02699
02700
02701 lsb = c & -c;
02702
02703
02704 return c == -lsb;
02705 }
02706
02707
02708
02709 int
02710 mask_operand_wrap (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02711 {
02712 HOST_WIDE_INT c, lsb;
02713
02714 if (GET_CODE (op) != CONST_INT)
02715 return 0;
02716
02717 c = INTVAL (op);
02718
02719 if ((c & 0x80000001) != 0x80000001)
02720 return 0;
02721
02722 c = ~c;
02723 if (c == 0)
02724 return 0;
02725
02726 lsb = c & -c;
02727 c = ~c;
02728 c &= -lsb;
02729 lsb = c & -c;
02730 return c == -lsb;
02731 }
02732
02733
02734
02735
02736
02737
02738 int
02739 mask64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02740 {
02741 if (GET_CODE (op) == CONST_INT)
02742 {
02743 HOST_WIDE_INT c, lsb;
02744
02745 c = INTVAL (op);
02746
02747
02748 if (c == 0)
02749 return 0;
02750
02751
02752
02753 if (c & 1)
02754 c = ~c;
02755
02756
02757 lsb = c & -c;
02758
02759
02760 return c == -lsb;
02761 }
02762 return 0;
02763 }
02764
02765 static int
02766 mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED,
02767 bool allow_one)
02768 {
02769 if (GET_CODE (op) == CONST_INT)
02770 {
02771 HOST_WIDE_INT c, lsb;
02772 bool one_ok;
02773
02774 c = INTVAL (op);
02775
02776
02777 if (c == 0)
02778 return 0;
02779
02780
02781
02782
02783 one_ok = !(c & ~(HOST_WIDE_INT)0xffffffff);
02784
02785
02786
02787 if (c & 1)
02788 c = ~c;
02789
02790
02791 lsb = c & -c;
02792
02793
02794 c = ~c;
02795
02796
02797 c &= -lsb;
02798
02799
02800 lsb = c & -c;
02801
02802
02803 c = ~c;
02804
02805
02806 c &= -lsb;
02807
02808 if (one_ok && !(allow_one || c))
02809 return 0;
02810
02811
02812 lsb = c & -c;
02813
02814
02815 return c == -lsb;
02816 }
02817 return 0;
02818 }
02819
02820
02821
02822
02823 int mask64_2_operand (rtx op, enum machine_mode mode)
02824 {
02825 return mask64_1or2_operand (op, mode, false);
02826 }
02827
02828
02829
02830 void
02831 build_mask64_2_operands (rtx in, rtx *out)
02832 {
02833 #if HOST_BITS_PER_WIDE_INT >= 64
02834 unsigned HOST_WIDE_INT c, lsb, m1, m2;
02835 int shift;
02836
02837 if (GET_CODE (in) != CONST_INT)
02838 abort ();
02839
02840 c = INTVAL (in);
02841 if (c & 1)
02842 {
02843
02844
02845
02846
02847
02848 c = ~c;
02849 lsb = c & -c;
02850 m1 = -lsb;
02851 c = ~c;
02852 c &= -lsb;
02853 lsb = c & -c;
02854 c = ~c;
02855 c &= -lsb;
02856 shift = 0;
02857 while ((lsb >>= 1) != 0)
02858 shift++;
02859 m1 <<= 64 - shift;
02860 m1 = ~m1;
02861 m2 = ~c;
02862 }
02863 else
02864 {
02865
02866
02867
02868
02869
02870 lsb = c & -c;
02871 m2 = -lsb;
02872 c = ~c;
02873 c &= -lsb;
02874 lsb = c & -c;
02875 c = ~c;
02876 c &= -lsb;
02877 shift = 0;
02878 while ((lsb >>= 1) != 0)
02879 shift++;
02880 m1 = ~c;
02881 m1 >>= shift;
02882 m1 = ~m1;
02883 }
02884
02885
02886
02887 out[0] = GEN_INT (64 - shift);
02888 out[1] = GEN_INT (m1);
02889 out[2] = GEN_INT (shift);
02890 out[3] = GEN_INT (m2);
02891 #else
02892 (void)in;
02893 (void)out;
02894 abort ();
02895 #endif
02896 }
02897
02898
02899
02900
02901 int
02902 and64_operand (rtx op, enum machine_mode mode)
02903 {
02904 if (fixed_regs[CR0_REGNO])
02905 return (gpc_reg_operand (op, mode) || mask64_operand (op, mode));
02906
02907 return (logical_operand (op, mode) || mask64_operand (op, mode));
02908 }
02909
02910
02911
02912
02913 int
02914 and64_2_operand (rtx op, enum machine_mode mode)
02915 {
02916 if (fixed_regs[CR0_REGNO])
02917 return gpc_reg_operand (op, mode) || mask64_1or2_operand (op, mode, true);
02918
02919 return logical_operand (op, mode) || mask64_1or2_operand (op, mode, true);
02920 }
02921
02922
02923
02924
02925 int
02926 and_operand (rtx op, enum machine_mode mode)
02927 {
02928 if (fixed_regs[CR0_REGNO])
02929 return (gpc_reg_operand (op, mode) || mask_operand (op, mode));
02930
02931 return (logical_operand (op, mode) || mask_operand (op, mode));
02932 }
02933
02934
02935
02936 int
02937 reg_or_mem_operand (rtx op, enum machine_mode mode)
02938 {
02939 return (gpc_reg_operand (op, mode)
02940 || memory_operand (op, mode)
02941 || macho_lo_sum_memory_operand (op, mode)
02942 || volatile_mem_operand (op, mode));
02943 }
02944
02945
02946
02947
02948
02949 int
02950 lwa_operand (rtx op, enum machine_mode mode)
02951 {
02952 rtx inner = op;
02953
02954 if (reload_completed && GET_CODE (inner) == SUBREG)
02955 inner = SUBREG_REG (inner);
02956
02957 return gpc_reg_operand (inner, mode)
02958 || (memory_operand (inner, mode)
02959 && GET_CODE (XEXP (inner, 0)) != PRE_INC
02960 && GET_CODE (XEXP (inner, 0)) != PRE_DEC
02961 && (GET_CODE (XEXP (inner, 0)) != PLUS
02962 || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
02963 || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
02964 }
02965
02966
02967
02968 int
02969 symbol_ref_operand (rtx op, enum machine_mode mode)
02970 {
02971 if (mode != VOIDmode && GET_MODE (op) != mode)
02972 return 0;
02973
02974 return (GET_CODE (op) == SYMBOL_REF
02975 && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op)));
02976 }
02977
02978
02979
02980
02981 int
02982 call_operand (rtx op, enum machine_mode mode)
02983 {
02984 if (mode != VOIDmode && GET_MODE (op) != mode)
02985 return 0;
02986
02987 return (GET_CODE (op) == SYMBOL_REF
02988 || (GET_CODE (op) == REG
02989 && (REGNO (op) == LINK_REGISTER_REGNUM
02990 || REGNO (op) == COUNT_REGISTER_REGNUM
02991 || REGNO (op) >= FIRST_PSEUDO_REGISTER)));
02992 }
02993
02994
02995
02996
02997 int
02998 current_file_function_operand (rtx op,
02999 enum machine_mode mode ATTRIBUTE_UNUSED)
03000 {
03001 return (GET_CODE (op) == SYMBOL_REF
03002 && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
03003 && (SYMBOL_REF_LOCAL_P (op)
03004 || (DECL_RTL_SET_P (current_function_decl)
03005 && op == XEXP (DECL_RTL (current_function_decl), 0))));
03006 }
03007
03008
03009
03010 int
03011 input_operand (rtx op, enum machine_mode mode)
03012 {
03013
03014 if (memory_operand (op, mode))
03015 return 1;
03016
03017
03018 if (GET_MODE_CLASS (mode) == MODE_FLOAT
03019 && CONSTANT_P (op)
03020 && easy_fp_constant (op, mode))
03021 return 1;
03022
03023
03024 if (GET_MODE_CLASS (mode) == MODE_INT
03025 && (GET_CODE (op) == CONST_INT
03026 || GET_CODE (op) == CONST_DOUBLE))
03027 return 1;
03028
03029
03030 if (GET_CODE (op) == CONST_VECTOR
03031 && easy_vector_constant (op, mode))
03032 return 1;
03033
03034
03035
03036 if (GET_MODE_CLASS (mode) == MODE_FLOAT
03037 || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
03038 return register_operand (op, mode);
03039
03040
03041
03042
03043 if (register_operand (op, mode))
03044 return 1;
03045
03046
03047 if (legitimate_constant_pool_address_p (op))
03048 return 1;
03049
03050
03051 if (toc_relative_expr_p (op))
03052 return 1;
03053
03054
03055
03056 if (DEFAULT_ABI == ABI_V4
03057 && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
03058 && small_data_operand (op, Pmode))
03059 return 1;
03060
03061 return 0;
03062 }
03063
03064
03065 static bool
03066 invalid_e500_subreg (rtx op, enum machine_mode mode)
03067 {
03068
03069 if (GET_CODE (op) == SUBREG
03070 && mode == SImode
03071 && REG_P (SUBREG_REG (op))
03072 && GET_MODE (SUBREG_REG (op)) == DFmode)
03073 return true;
03074
03075
03076 if (GET_CODE (op) == SUBREG
03077 && mode == DFmode
03078 && REG_P (SUBREG_REG (op))
03079 && GET_MODE (SUBREG_REG (op)) == DImode)
03080 return true;
03081
03082 return false;
03083 }
03084
03085
03086
03087 int
03088 rs6000_nonimmediate_operand (rtx op, enum machine_mode mode)
03089 {
03090 if (TARGET_E500_DOUBLE
03091 && GET_CODE (op) == SUBREG
03092 && invalid_e500_subreg (op, mode))
03093 return 0;
03094
03095 return nonimmediate_operand (op, mode);
03096 }
03097
03098
03099
03100
03101 unsigned int
03102 rs6000_special_round_type_align (tree type, int computed, int specified)
03103 {
03104 tree field = TYPE_FIELDS (type);
03105
03106
03107 while (field != NULL && TREE_CODE (field) != FIELD_DECL)
03108 field = TREE_CHAIN (field);
03109
03110 if (field == NULL || field == type || DECL_MODE (field) != DFmode)
03111 return MAX (computed, specified);
03112
03113 return MAX (MAX (computed, specified), 64);
03114 }
03115
03116
03117
03118 int
03119 small_data_operand (rtx op ATTRIBUTE_UNUSED,
03120 enum machine_mode mode ATTRIBUTE_UNUSED)
03121 {
03122 #if TARGET_ELF
03123 rtx sym_ref;
03124
03125 if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
03126 return 0;
03127
03128 if (DEFAULT_ABI != ABI_V4)
03129 return 0;
03130
03131 if (GET_CODE (op) == SYMBOL_REF)
03132 sym_ref = op;
03133
03134 else if (GET_CODE (op) != CONST
03135 || GET_CODE (XEXP (op, 0)) != PLUS
03136 || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF
03137 || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT)
03138 return 0;
03139
03140 else
03141 {
03142 rtx sum = XEXP (op, 0);
03143 HOST_WIDE_INT summand;
03144
03145
03146
03147 summand = INTVAL (XEXP (sum, 1));
03148 if (summand < 0 || (unsigned HOST_WIDE_INT) summand > g_switch_value)
03149 return 0;
03150
03151 sym_ref = XEXP (sum, 0);
03152 }
03153
03154 return SYMBOL_REF_SMALL_P (sym_ref);
03155 #else
03156 return 0;
03157 #endif
03158 }
03159
03160
03161
03162
03163 int
03164 word_offset_memref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03165 {
03166 rtx addr;
03167 int off = 0;
03168
03169 if (!memory_operand (op, mode))
03170 return 0;
03171
03172 addr = XEXP (op, 0);
03173 if (GET_CODE (addr) == PLUS
03174 && GET_CODE (XEXP (addr, 0)) == REG
03175 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
03176 off = INTVAL (XEXP (addr, 1));
03177
03178 return (off % 4) == 0;
03179 }
03180
03181
03182
03183 bool
03184 gpr_or_gpr_p (rtx op0, rtx op1)
03185 {
03186 return ((REG_P (op0) && INT_REGNO_P (REGNO (op0)))
03187 || (REG_P (op1) && INT_REGNO_P (REGNO (op1))));
03188 }
03189
03190
03191
03192
03193 static int
03194 constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc)
03195 {
03196 switch (GET_CODE(op))
03197 {
03198 case SYMBOL_REF:
03199 if (RS6000_SYMBOL_REF_TLS_P (op))
03200 return 0;
03201 else if (CONSTANT_POOL_ADDRESS_P (op))
03202 {
03203 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
03204 {
03205 *have_sym = 1;
03206 return 1;
03207 }
03208 else
03209 return 0;
03210 }
03211 else if (! strcmp (XSTR (op, 0), toc_label_name))
03212 {
03213 *have_toc = 1;
03214 return 1;
03215 }
03216 else
03217 return 0;
03218 case PLUS:
03219 case MINUS:
03220 return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc)
03221 && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc));
03222 case CONST:
03223 return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc);
03224 case CONST_INT:
03225 return 1;
03226 default:
03227 return 0;
03228 }
03229 }
03230
03231 static bool
03232 constant_pool_expr_p (rtx op)
03233 {
03234 int have_sym = 0;
03235 int have_toc = 0;
03236 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
03237 }
03238
03239 static bool
03240 toc_relative_expr_p (rtx op)
03241 {
03242 int have_sym = 0;
03243 int have_toc = 0;
03244 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
03245 }
03246
03247 bool
03248 legitimate_constant_pool_address_p (rtx x)
03249 {
03250 return (TARGET_TOC
03251 && GET_CODE (x) == PLUS
03252 && GET_CODE (XEXP (x, 0)) == REG
03253 && (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER)
03254 && constant_pool_expr_p (XEXP (x, 1)));
03255 }
03256
03257 bool
03258 rs6000_legitimate_small_data_p (enum machine_mode mode, rtx x)
03259 {
03260 return (DEFAULT_ABI == ABI_V4
03261 && !flag_pic && !TARGET_TOC
03262 && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)
03263 && small_data_operand (x, mode));
03264 }
03265
03266
03267 #define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
03268
03269 bool
03270 rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
03271 {
03272 unsigned HOST_WIDE_INT offset, extra;
03273
03274 if (GET_CODE (x) != PLUS)
03275 return false;
03276 if (GET_CODE (XEXP (x, 0)) != REG)
03277 return false;
03278 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
03279 return false;
03280 if (legitimate_constant_pool_address_p (x))
03281 return true;
03282 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
03283 return false;
03284
03285 offset = INTVAL (XEXP (x, 1));
03286 extra = 0;
03287 switch (mode)
03288 {
03289 case V16QImode:
03290 case V8HImode:
03291 case V4SFmode:
03292 case V4SImode:
03293
03294
03295
03296 return false;
03297
03298 case V4HImode:
03299 case V2SImode:
03300 case V1DImode:
03301 case V2SFmode:
03302
03303 return SPE_CONST_OFFSET_OK (offset);
03304
03305 case DFmode:
03306 if (TARGET_E500_DOUBLE)
03307 return SPE_CONST_OFFSET_OK (offset);
03308
03309 case DImode:
03310
03311
03312
03313
03314
03315 if (TARGET_E500_DOUBLE)
03316 return SPE_CONST_OFFSET_OK (offset);
03317
03318 if (mode == DFmode || !TARGET_POWERPC64)
03319 extra = 4;
03320 else if (offset & 3)
03321 return false;
03322 break;
03323
03324 case TFmode:
03325 case TImode:
03326 if (mode == TFmode || !TARGET_POWERPC64)
03327 extra = 12;
03328 else if (offset & 3)
03329 return false;
03330 else
03331 extra = 8;
03332 break;
03333
03334 default:
03335 break;
03336 }
03337
03338 offset += 0x8000;
03339 return (offset < 0x10000) && (offset + extra < 0x10000);
03340 }
03341
03342 static bool
03343 legitimate_indexed_address_p (rtx x, int strict)
03344 {
03345 rtx op0, op1;
03346
03347 if (GET_CODE (x) != PLUS)
03348 return false;
03349
03350 op0 = XEXP (x, 0);
03351 op1 = XEXP (x, 1);
03352
03353 if (!REG_P (op0) || !REG_P (op1))
03354 return false;
03355
03356 return ((INT_REG_OK_FOR_BASE_P (op0, strict)
03357 && INT_REG_OK_FOR_INDEX_P (op1, strict))
03358 || (INT_REG_OK_FOR_BASE_P (op1, strict)
03359 && INT_REG_OK_FOR_INDEX_P (op0, strict)));
03360 }
03361
03362 static inline bool
03363 legitimate_indirect_address_p (rtx x, int strict)
03364 {
03365 return GET_CODE (x) == REG && INT_REG_OK_FOR_BASE_P (x, strict);
03366 }
03367
03368 static bool
03369 macho_lo_sum_memory_operand (rtx x, enum machine_mode mode)
03370 {
03371 if (!TARGET_MACHO || !flag_pic
03372 || mode != SImode || GET_CODE(x) != MEM)
03373 return false;
03374 x = XEXP (x, 0);
03375
03376 if (GET_CODE (x) != LO_SUM)
03377 return false;
03378 if (GET_CODE (XEXP (x, 0)) != REG)
03379 return false;
03380 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), 0))
03381 return false;
03382 x = XEXP (x, 1);
03383
03384 return CONSTANT_P (x);
03385 }
03386
03387 static bool
03388 legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
03389 {
03390 if (GET_CODE (x) != LO_SUM)
03391 return false;
03392 if (GET_CODE (XEXP (x, 0)) != REG)
03393 return false;
03394 if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
03395 return false;
03396
03397 if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
03398 return false;
03399 x = XEXP (x, 1);
03400
03401 if (TARGET_ELF || TARGET_MACHO)
03402 {
03403 if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
03404 return false;
03405 if (TARGET_TOC)
03406 return false;
03407 if (GET_MODE_NUNITS (mode) != 1)
03408 return false;
03409 if (GET_MODE_BITSIZE (mode) > 64
03410 || (GET_MODE_BITSIZE (mode) > 32 && !TARGET_POWERPC64
03411 && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode)))
03412 return false;
03413
03414 return CONSTANT_P (x);
03415 }
03416
03417 return false;
03418 }
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444 rtx
03445 rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
03446 enum machine_mode mode)
03447 {
03448 if (GET_CODE (x) == SYMBOL_REF)
03449 {
03450 enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
03451 if (model != 0)
03452 return rs6000_legitimize_tls_address (x, model);
03453 }
03454
03455 if (GET_CODE (x) == PLUS
03456 && GET_CODE (XEXP (x, 0)) == REG
03457 && GET_CODE (XEXP (x, 1)) == CONST_INT
03458 && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000)
03459 {
03460 HOST_WIDE_INT high_int, low_int;
03461 rtx sum;
03462 low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;
03463 high_int = INTVAL (XEXP (x, 1)) - low_int;
03464 sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
03465 GEN_INT (high_int)), 0);
03466 return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
03467 }
03468 else if (GET_CODE (x) == PLUS
03469 && GET_CODE (XEXP (x, 0)) == REG
03470 && GET_CODE (XEXP (x, 1)) != CONST_INT
03471 && GET_MODE_NUNITS (mode) == 1
03472 && ((TARGET_HARD_FLOAT && TARGET_FPRS)
03473 || TARGET_POWERPC64
03474 || (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE)
03475 && mode != TFmode))
03476 && (TARGET_POWERPC64 || mode != DImode)
03477 && mode != TImode)
03478 {
03479 return gen_rtx_PLUS (Pmode, XEXP (x, 0),
03480 force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
03481 }
03482 else if (ALTIVEC_VECTOR_MODE (mode))
03483 {
03484 rtx reg;
03485
03486
03487 if (GET_CODE (x) == PLUS)
03488 return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
03489 force_reg (Pmode, XEXP (x, 1)));
03490
03491 reg = force_reg (Pmode, x);
03492 return reg;
03493 }
03494 else if (SPE_VECTOR_MODE (mode)
03495 || (TARGET_E500_DOUBLE && (mode == DFmode
03496 || mode == DImode)))
03497 {
03498 if (mode == DImode)
03499 return NULL_RTX;
03500
03501
03502 if (GET_CODE (x) == PLUS)
03503 {
03504 rtx op1 = XEXP (x, 0);
03505 rtx op2 = XEXP (x, 1);
03506
03507 op1 = force_reg (Pmode, op1);
03508
03509 if (GET_CODE (op2) != REG
03510 && (GET_CODE (op2) != CONST_INT
03511 || !SPE_CONST_OFFSET_OK (INTVAL (op2))))
03512 op2 = force_reg (Pmode, op2);
03513
03514 return gen_rtx_PLUS (Pmode, op1, op2);
03515 }
03516
03517 return force_reg (Pmode, x);
03518 }
03519 else if (TARGET_ELF
03520 && TARGET_32BIT
03521 && TARGET_NO_TOC
03522 && ! flag_pic
03523 && GET_CODE (x) != CONST_INT
03524 && GET_CODE (x) != CONST_DOUBLE
03525 && CONSTANT_P (x)
03526 && GET_MODE_NUNITS (mode) == 1
03527 && (GET_MODE_BITSIZE (mode) <= 32
03528 || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode)))
03529 {
03530 rtx reg = gen_reg_rtx (Pmode);
03531 emit_insn (gen_elf_high (reg, x));
03532 return gen_rtx_LO_SUM (Pmode, reg, x);
03533 }
03534 else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
03535 && ! flag_pic
03536 #if TARGET_MACHO
03537 && ! MACHO_DYNAMIC_NO_PIC_P
03538 #endif
03539 && GET_CODE (x) != CONST_INT
03540 && GET_CODE (x) != CONST_DOUBLE
03541 && CONSTANT_P (x)
03542 && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
03543 && mode != DImode
03544 && mode != TImode)
03545 {
03546 rtx reg = gen_reg_rtx (Pmode);
03547 emit_insn (gen_macho_high (reg, x));
03548 return gen_rtx_LO_SUM (Pmode, reg, x);
03549 }
03550 else if (TARGET_TOC
03551 && constant_pool_expr_p (x)
03552 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
03553 {
03554 return create_TOC_reference (x);
03555 }
03556 else
03557 return NULL_RTX;
03558 }
03559
03560
03561
03562
03563 void
03564 rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
03565 {
03566 switch (size)
03567 {
03568 case 4:
03569 fputs ("\t.long\t", file);
03570 break;
03571 case 8:
03572 fputs (DOUBLE_INT_ASM_OP, file);
03573 break;
03574 default:
03575 abort ();
03576 }
03577 output_addr_const (file, x);
03578 fputs ("@dtprel+0x8000", file);
03579 }
03580
03581
03582
03583 static GTY(()) rtx rs6000_tls_symbol;
03584 static rtx
03585 rs6000_tls_get_addr (void)
03586 {
03587 if (!rs6000_tls_symbol)
03588 rs6000_tls_symbol = init_one_libfunc ("__tls_get_addr");
03589
03590 return rs6000_tls_symbol;
03591 }
03592
03593
03594
03595 static GTY(()) rtx rs6000_got_symbol;
03596 static rtx
03597 rs6000_got_sym (void)
03598 {
03599 if (!rs6000_got_symbol)
03600 {
03601 rs6000_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
03602 SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_LOCAL;
03603 SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_EXTERNAL;
03604 }
03605
03606 return rs6000_got_symbol;
03607 }
03608
03609
03610
03611
03612 static rtx
03613 rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
03614 {
03615 rtx dest, insn;
03616
03617 dest = gen_reg_rtx (Pmode);
03618 if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
03619 {
03620 rtx tlsreg;
03621
03622 if (TARGET_64BIT)
03623 {
03624 tlsreg = gen_rtx_REG (Pmode, 13);
03625 insn = gen_tls_tprel_64 (dest, tlsreg, addr);
03626 }
03627 else
03628 {
03629 tlsreg = gen_rtx_REG (Pmode, 2);
03630 insn = gen_tls_tprel_32 (dest, tlsreg, addr);
03631 }
03632 emit_insn (insn);
03633 }
03634 else if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 32)
03635 {
03636 rtx tlsreg, tmp;
03637
03638 tmp = gen_reg_rtx (Pmode);
03639 if (TARGET_64BIT)
03640 {
03641 tlsreg = gen_rtx_REG (Pmode, 13);
03642 insn = gen_tls_tprel_ha_64 (tmp, tlsreg, addr);
03643 }
03644 else
03645 {
03646 tlsreg = gen_rtx_REG (Pmode, 2);
03647 insn = gen_tls_tprel_ha_32 (tmp, tlsreg, addr);
03648 }
03649 emit_insn (insn);
03650 if (TARGET_64BIT)
03651 insn = gen_tls_tprel_lo_64 (dest, tmp, addr);
03652 else
03653 insn = gen_tls_tprel_lo_32 (dest, tmp, addr);
03654 emit_insn (insn);
03655 }
03656 else
03657 {
03658 rtx r3, got, tga, tmp1, tmp2, eqv;
03659
03660 if (TARGET_64BIT)
03661 got = gen_rtx_REG (Pmode, TOC_REGISTER);
03662 else
03663 {
03664 if (flag_pic == 1)
03665 got = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
03666 else
03667 {
03668 rtx gsym = rs6000_got_sym ();
03669 got = gen_reg_rtx (Pmode);
03670 if (flag_pic == 0)
03671 rs6000_emit_move (got, gsym, Pmode);
03672 else
03673 {
03674 rtx tempLR, tmp3, mem;
03675 rtx first, last;
03676
03677 tempLR = gen_reg_rtx (Pmode);
03678 tmp1 = gen_reg_rtx (Pmode);
03679 tmp2 = gen_reg_rtx (Pmode);
03680 tmp3 = gen_reg_rtx (Pmode);
03681 mem = gen_const_mem (Pmode, tmp1);
03682
03683 first = emit_insn (gen_load_toc_v4_PIC_1b (tempLR, gsym));
03684 emit_move_insn (tmp1, tempLR);
03685 emit_move_insn (tmp2, mem);
03686 emit_insn (gen_addsi3 (tmp3, tmp1, tmp2));
03687 last = emit_move_insn (got, tmp3);
03688 REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, gsym,
03689 REG_NOTES (last));
03690 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
03691 REG_NOTES (first));
03692 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
03693 REG_NOTES (last));
03694 }
03695 }
03696 }
03697
03698 if (model == TLS_MODEL_GLOBAL_DYNAMIC)
03699 {
03700 r3 = gen_rtx_REG (Pmode, 3);
03701 if (TARGET_64BIT)
03702 insn = gen_tls_gd_64 (r3, got, addr);
03703 else
03704 insn = gen_tls_gd_32 (r3, got, addr);
03705 start_sequence ();
03706 emit_insn (insn);
03707 tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
03708 insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
03709 insn = emit_call_insn (insn);
03710 CONST_OR_PURE_CALL_P (insn) = 1;
03711 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
03712 insn = get_insns ();
03713 end_sequence ();
03714 emit_libcall_block (insn, dest, r3, addr);
03715 }
03716 else if (model == TLS_MODEL_LOCAL_DYNAMIC)
03717 {
03718 r3 = gen_rtx_REG (Pmode, 3);
03719 if (TARGET_64BIT)
03720 insn = gen_tls_ld_64 (r3, got);
03721 else
03722 insn = gen_tls_ld_32 (r3, got);
03723 start_sequence ();
03724 emit_insn (insn);
03725 tga = gen_rtx_MEM (Pmode, rs6000_tls_get_addr ());
03726 insn = gen_call_value (r3, tga, const0_rtx, const0_rtx);
03727 insn = emit_call_insn (insn);
03728 CONST_OR_PURE_CALL_P (insn) = 1;
03729 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r3);
03730 insn = get_insns ();
03731 end_sequence ();
03732 tmp1 = gen_reg_rtx (Pmode);
03733 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
03734 UNSPEC_TLSLD);
03735 emit_libcall_block (insn, tmp1, r3, eqv);
03736 if (rs6000_tls_size == 16)
03737 {
03738 if (TARGET_64BIT)
03739 insn = gen_tls_dtprel_64 (dest, tmp1, addr);
03740 else
03741 insn = gen_tls_dtprel_32 (dest, tmp1, addr);
03742 }
03743 else if (rs6000_tls_size == 32)
03744 {
03745 tmp2 = gen_reg_rtx (Pmode);
03746 if (TARGET_64BIT)
03747 insn = gen_tls_dtprel_ha_64 (tmp2, tmp1, addr);
03748 else
03749 insn = gen_tls_dtprel_ha_32 (tmp2, tmp1, addr);
03750 emit_insn (insn);
03751 if (TARGET_64BIT)
03752 insn = gen_tls_dtprel_lo_64 (dest, tmp2, addr);
03753 else
03754 insn = gen_tls_dtprel_lo_32 (dest, tmp2, addr);
03755 }
03756 else
03757 {
03758 tmp2 = gen_reg_rtx (Pmode);
03759 if (TARGET_64BIT)
03760 insn = gen_tls_got_dtprel_64 (tmp2, got, addr);
03761 else
03762 insn = gen_tls_got_dtprel_32 (tmp2, got, addr);
03763 emit_insn (insn);
03764 insn = gen_rtx_SET (Pmode, dest,
03765 gen_rtx_PLUS (Pmode, tmp2, tmp1));
03766 }
03767 emit_insn (insn);
03768 }
03769 else
03770 {
03771
03772 tmp2 = gen_reg_rtx (Pmode);
03773 if (TARGET_64BIT)
03774 insn = gen_tls_got_tprel_64 (tmp2, got, addr);
03775 else
03776 insn = gen_tls_got_tprel_32 (tmp2, got, addr);
03777 emit_insn (insn);
03778 if (TARGET_64BIT)
03779 insn = gen_tls_tls_64 (dest, tmp2, addr);
03780 else
03781 insn = gen_tls_tls_32 (dest, tmp2, addr);
03782 emit_insn (insn);
03783 }
03784 }
03785
03786 return dest;
03787 }
03788
03789
03790
03791
03792 int
03793 rs6000_tls_symbol_ref (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
03794 {
03795 return RS6000_SYMBOL_REF_TLS_P (x);
03796 }
03797
03798
03799
03800 bool
03801 rs6000_tls_referenced_p (rtx x)
03802 {
03803 if (! TARGET_HAVE_TLS)
03804 return false;
03805
03806 return for_each_rtx (&x, &rs6000_tls_symbol_ref_1, 0);
03807 }
03808
03809
03810
03811
03812 static inline int
03813 rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
03814 {
03815 return RS6000_SYMBOL_REF_TLS_P (*x);
03816 }
03817
03818
03819
03820
03821 #ifndef REG_MODE_OK_FOR_BASE_P
03822 #define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
03823 #endif
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838 rtx
03839 rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
03840 int opnum, int type,
03841 int ind_levels ATTRIBUTE_UNUSED, int *win)
03842 {
03843
03844 if (GET_CODE (x) == PLUS
03845 && GET_CODE (XEXP (x, 0)) == PLUS
03846 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
03847 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
03848 && GET_CODE (XEXP (x, 1)) == CONST_INT)
03849 {
03850 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03851 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03852 opnum, (enum reload_type)type);
03853 *win = 1;
03854 return x;
03855 }
03856
03857 #if TARGET_MACHO
03858 if (DEFAULT_ABI == ABI_DARWIN && flag_pic
03859 && GET_CODE (x) == LO_SUM
03860 && GET_CODE (XEXP (x, 0)) == PLUS
03861 && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
03862 && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
03863 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST
03864 && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
03865 && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS
03866 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF
03867 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF)
03868 {
03869
03870
03871 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03872 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
03873 opnum, (enum reload_type)type);
03874 *win = 1;
03875 return x;
03876 }
03877 #endif
03878
03879
03880
03881 if (GET_CODE (x) == PLUS
03882 && GET_CODE (XEXP (x, 0)) == REG
03883 && REGNO (XEXP (x, 0)) < 32
03884 && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
03885 && GET_CODE (XEXP (x, 1)) == CONST_INT
03886 && (INTVAL (XEXP (x, 1)) & 3) != 0
03887 && !ALTIVEC_VECTOR_MODE (mode)
03888 && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
03889 && TARGET_POWERPC64)
03890 {
03891 x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
03892 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03893 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03894 opnum, (enum reload_type) type);
03895 *win = 1;
03896 return x;
03897 }
03898
03899 if (GET_CODE (x) == PLUS
03900 && GET_CODE (XEXP (x, 0)) == REG
03901 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
03902 && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
03903 && GET_CODE (XEXP (x, 1)) == CONST_INT
03904 && !SPE_VECTOR_MODE (mode)
03905 && !(TARGET_E500_DOUBLE && (mode == DFmode
03906 || mode == DImode))
03907 && !ALTIVEC_VECTOR_MODE (mode))
03908 {
03909 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
03910 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
03911 HOST_WIDE_INT high
03912 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
03913
03914
03915 if (high + low != val)
03916 {
03917 *win = 0;
03918 return x;
03919 }
03920
03921
03922
03923
03924 x = gen_rtx_PLUS (GET_MODE (x),
03925 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
03926 GEN_INT (high)),
03927 GEN_INT (low));
03928
03929 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03930 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
03931 opnum, (enum reload_type)type);
03932 *win = 1;
03933 return x;
03934 }
03935
03936 #if TARGET_MACHO
03937 if (GET_CODE (x) == SYMBOL_REF
03938 && DEFAULT_ABI == ABI_DARWIN
03939 && !ALTIVEC_VECTOR_MODE (mode)
03940 && (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
03941
03942
03943 && mode != TFmode
03944 && (mode != DImode || TARGET_POWERPC64))
03945 {
03946 if (flag_pic)
03947 {
03948 rtx offset = gen_rtx_CONST (Pmode,
03949 gen_rtx_MINUS (Pmode, x,
03950 machopic_function_base_sym ()));
03951 x = gen_rtx_LO_SUM (GET_MODE (x),
03952 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
03953 gen_rtx_HIGH (Pmode, offset)), offset);
03954 }
03955 else
03956 x = gen_rtx_LO_SUM (GET_MODE (x),
03957 gen_rtx_HIGH (Pmode, x), x);
03958
03959 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
03960 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
03961 opnum, (enum reload_type)type);
03962 *win = 1;
03963 return x;
03964 }
03965 #endif
03966
03967 if (TARGET_TOC
03968 && constant_pool_expr_p (x)
03969 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
03970 {
03971 (x) = create_TOC_reference (x);
03972 *win = 1;
03973 return x;
03974 }
03975 *win = 0;
03976 return x;
03977 }
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996 int
03997 rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
03998 {
03999
04000 if (TARGET_ALTIVEC
04001 && ALTIVEC_VECTOR_MODE (mode)
04002 && GET_CODE (x) == AND
04003 && GET_CODE (XEXP (x, 1)) == CONST_INT
04004 && INTVAL (XEXP (x, 1)) == -16)
04005 x = XEXP (x, 0);
04006
04007 if (RS6000_SYMBOL_REF_TLS_P (x))
04008 return 0;
04009 if (legitimate_indirect_address_p (x, reg_ok_strict))
04010 return 1;
04011 if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
04012 && !ALTIVEC_VECTOR_MODE (mode)
04013 && !SPE_VECTOR_MODE (mode)
04014
04015 && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
04016 && TARGET_UPDATE
04017 && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
04018 return 1;
04019 if (rs6000_legitimate_small_data_p (mode, x))
04020 return 1;
04021 if (legitimate_constant_pool_address_p (x))
04022 return 1;
04023
04024 if (! reg_ok_strict
04025 && GET_CODE (x) == PLUS
04026 && GET_CODE (XEXP (x, 0)) == REG
04027 && (XEXP (x, 0) == virtual_stack_vars_rtx
04028 || XEXP (x, 0) == arg_pointer_rtx)
04029 && GET_CODE (XEXP (x, 1)) == CONST_INT)
04030 return 1;
04031 if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
04032 return 1;
04033 if (mode != TImode
04034 && mode != TFmode
04035 && ((TARGET_HARD_FLOAT && TARGET_FPRS)
04036 || TARGET_POWERPC64
04037 || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
04038 && (TARGET_POWERPC64 || mode != DImode)
04039 && legitimate_indexed_address_p (x, reg_ok_strict))
04040 return 1;
04041 if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
04042 return 1;
04043 return 0;
04044 }
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057 bool
04058 rs6000_mode_dependent_address (rtx addr)
04059 {
04060 switch (GET_CODE (addr))
04061 {
04062 case PLUS:
04063 if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
04064 {
04065 unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
04066 return val + 12 + 0x8000 >= 0x10000;
04067 }
04068 break;
04069
04070 case LO_SUM:
04071 return true;
04072
04073 case PRE_INC:
04074 case PRE_DEC:
04075 return TARGET_UPDATE;
04076
04077 default:
04078 break;
04079 }
04080
04081 return false;
04082 }
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095
04096 int
04097 rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
04098 {
04099 if (FP_REGNO_P (regno))
04100 return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
04101
04102 if (TARGET_E500_DOUBLE && mode == DFmode)
04103 return 1;
04104
04105 if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
04106 return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
04107
04108 if (ALTIVEC_REGNO_P (regno))
04109 return
04110 (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
04111
04112 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
04113 }
04114
04115
04116 void
04117 rs6000_conditional_register_usage (void)
04118 {
04119 int i;
04120
04121
04122
04123
04124 if (! TARGET_POWER)
04125 fixed_regs[64] = 1;
04126
04127
04128 if (TARGET_64BIT)
04129 fixed_regs[13] = call_used_regs[13]
04130 = call_really_used_regs[13] = 1;
04131
04132
04133 if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
04134 for (i = 32; i < 64; i++)
04135 fixed_regs[i] = call_used_regs[i]
04136 = call_really_used_regs[i] = 1;
04137
04138 if (DEFAULT_ABI == ABI_V4
04139 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
04140 && flag_pic == 2)
04141 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
04142
04143 if (DEFAULT_ABI == ABI_V4
04144 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
04145 && flag_pic == 1)
04146 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04147 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04148 = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
04149
04150 if (DEFAULT_ABI == ABI_DARWIN
04151 && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
04152 global_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04153 = fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04154 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04155 = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
04156
04157 if (TARGET_TOC && TARGET_MINIMAL_TOC)
04158 fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
04159 = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
04160
04161 if (TARGET_ALTIVEC)
04162 global_regs[VSCR_REGNO] = 1;
04163
04164 if (TARGET_SPE)
04165 {
04166 global_regs[SPEFSCR_REGNO] = 1;
04167 fixed_regs[FIXED_SCRATCH]
04168 = call_used_regs[FIXED_SCRATCH]
04169 = call_really_used_regs[FIXED_SCRATCH] = 1;
04170 }
04171
04172 if (! TARGET_ALTIVEC)
04173 {
04174 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
04175 fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
04176 call_really_used_regs[VRSAVE_REGNO] = 1;
04177 }
04178
04179 if (TARGET_ALTIVEC_ABI)
04180 for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i)
04181 call_used_regs[i] = call_really_used_regs[i] = 1;
04182 }
04183
04184
04185
04186
04187
04188
04189
04190 rtx
04191 rs6000_emit_set_const (rtx dest, enum machine_mode mode,
04192 rtx source, int n ATTRIBUTE_UNUSED)
04193 {
04194 rtx result, insn, set;
04195 HOST_WIDE_INT c0, c1;
04196
04197 if (mode == QImode || mode == HImode)
04198 {
04199 if (dest == NULL)
04200 dest = gen_reg_rtx (mode);
04201 emit_insn (gen_rtx_SET (VOIDmode, dest, source));
04202 return dest;
04203 }
04204 else if (mode == SImode)
04205 {
04206 result = no_new_pseudos ? dest : gen_reg_rtx (SImode);
04207
04208 emit_insn (gen_rtx_SET (VOIDmode, result,
04209 GEN_INT (INTVAL (source)
04210 & (~ (HOST_WIDE_INT) 0xffff))));
04211 emit_insn (gen_rtx_SET (VOIDmode, dest,
04212 gen_rtx_IOR (SImode, result,
04213 GEN_INT (INTVAL (source) & 0xffff))));
04214 result = dest;
04215 }
04216 else if (mode == DImode)
04217 {
04218 if (GET_CODE (source) == CONST_INT)
04219 {
04220 c0 = INTVAL (source);
04221 c1 = -(c0 < 0);
04222 }
04223 else if (GET_CODE (source) == CONST_DOUBLE)
04224 {
04225 #if HOST_BITS_PER_WIDE_INT >= 64
04226 c0 = CONST_DOUBLE_LOW (source);
04227 c1 = -(c0 < 0);
04228 #else
04229 c0 = CONST_DOUBLE_LOW (source);
04230 c1 = CONST_DOUBLE_HIGH (source);
04231 #endif
04232 }
04233 else
04234 abort ();
04235
04236 result = rs6000_emit_set_long_const (dest, c0, c1);
04237 }
04238 else
04239 abort ();
04240
04241 insn = get_last_insn ();
04242 set = single_set (insn);
04243 if (! CONSTANT_P (SET_SRC (set)))
04244 set_unique_reg_note (insn, REG_EQUAL, source);
04245
04246 return result;
04247 }
04248
04249
04250
04251
04252
04253 static rtx
04254 rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
04255 {
04256 if (!TARGET_POWERPC64)
04257 {
04258 rtx operand1, operand2;
04259
04260 operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
04261 DImode);
04262 operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
04263 DImode);
04264 emit_move_insn (operand1, GEN_INT (c1));
04265 emit_move_insn (operand2, GEN_INT (c2));
04266 }
04267 else
04268 {
04269 HOST_WIDE_INT ud1, ud2, ud3, ud4;
04270
04271 ud1 = c1 & 0xffff;
04272 ud2 = (c1 & 0xffff0000) >> 16;
04273 #if HOST_BITS_PER_WIDE_INT >= 64
04274 c2 = c1 >> 32;
04275 #endif
04276 ud3 = c2 & 0xffff;
04277 ud4 = (c2 & 0xffff0000) >> 16;
04278
04279 if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
04280 || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
04281 {
04282 if (ud1 & 0x8000)
04283 emit_move_insn (dest, GEN_INT (((ud1 ^ 0x8000) - 0x8000)));
04284 else
04285 emit_move_insn (dest, GEN_INT (ud1));
04286 }
04287
04288 else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
04289 || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
04290 {
04291 if (ud2 & 0x8000)
04292 emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
04293 - 0x80000000));
04294 else
04295 emit_move_insn (dest, GEN_INT (ud2 << 16));
04296 if (ud1 != 0)
04297 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
04298 }
04299 else if ((ud4 == 0xffff && (ud3 & 0x8000))
04300 || (ud4 == 0 && ! (ud3 & 0x8000)))
04301 {
04302 if (ud3 & 0x8000)
04303 emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
04304 - 0x80000000));
04305 else
04306 emit_move_insn (dest, GEN_INT (ud3 << 16));
04307
04308 if (ud2 != 0)
04309 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud2)));
04310 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (16)));
04311 if (ud1 != 0)
04312 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
04313 }
04314 else
04315 {
04316 if (ud4 & 0x8000)
04317 emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
04318 - 0x80000000));
04319 else
04320 emit_move_insn (dest, GEN_INT (ud4 << 16));
04321
04322 if (ud3 != 0)
04323 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud3)));
04324
04325 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
04326 if (ud2 != 0)
04327 emit_move_insn (dest, gen_rtx_IOR (DImode, dest,
04328 GEN_INT (ud2 << 16)));
04329 if (ud1 != 0)
04330 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
04331 }
04332 }
04333 return dest;
04334 }
04335
04336
04337
04338
04339 static void
04340 rs6000_eliminate_indexed_memrefs (rtx operands[2])
04341 {
04342 if (GET_CODE (operands[0]) == MEM
04343 && GET_CODE (XEXP (operands[0], 0)) != REG
04344 && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0))
04345 && ! reload_in_progress)
04346 operands[0]
04347 = replace_equiv_address (operands[0],
04348 copy_addr_to_reg (XEXP (operands[0], 0)));
04349
04350 if (GET_CODE (operands[1]) == MEM
04351 && GET_CODE (XEXP (operands[1], 0)) != REG
04352 && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0))
04353 && ! reload_in_progress)
04354 operands[1]
04355 = replace_equiv_address (operands[1],
04356 copy_addr_to_reg (XEXP (operands[1], 0)));
04357 }
04358
04359
04360 void
04361 rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
04362 {
04363 rtx operands[2];
04364 operands[0] = dest;
04365 operands[1] = source;
04366
04367
04368 if (GET_CODE (operands[1]) == CONST_DOUBLE
04369 && ! FLOAT_MODE_P (mode)
04370 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
04371 {
04372
04373
04374
04375 operands[1] = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), mode);
04376 }
04377 if (GET_CODE (operands[1]) == CONST_DOUBLE
04378 && ! FLOAT_MODE_P (mode)
04379 && ((CONST_DOUBLE_HIGH (operands[1]) == 0
04380 && CONST_DOUBLE_LOW (operands[1]) >= 0)
04381 || (CONST_DOUBLE_HIGH (operands[1]) == -1
04382 && CONST_DOUBLE_LOW (operands[1]) < 0)))
04383 abort ();
04384
04385
04386
04387 if (GET_CODE (operands[0]) == MEM
04388 && GET_CODE (operands[1]) == MEM
04389 && mode == DImode
04390 && (SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[0]))
04391 || SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[1])))
04392 && ! (SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[0]) > 32
04393 ? 32 : MEM_ALIGN (operands[0])))
04394 || SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[1]) > 32
04395 ? 32
04396 : MEM_ALIGN (operands[1]))))
04397 && ! MEM_VOLATILE_P (operands [0])
04398 && ! MEM_VOLATILE_P (operands [1]))
04399 {
04400 emit_move_insn (adjust_address (operands[0], SImode, 0),
04401 adjust_address (operands[1], SImode, 0));
04402 emit_move_insn (adjust_address (operands[0], SImode, 4),
04403 adjust_address (operands[1], SImode, 4));
04404 return;
04405 }
04406
04407 if (!no_new_pseudos && GET_CODE (operands[0]) == MEM
04408 && !gpc_reg_operand (operands[1], mode))
04409 operands[1] = force_reg (mode, operands[1]);
04410
04411 if (mode == SFmode && ! TARGET_POWERPC
04412 && TARGET_HARD_FLOAT && TARGET_FPRS
04413 && GET_CODE (operands[0]) == MEM)
04414 {
04415 int regnum;
04416
04417 if (reload_in_progress || reload_completed)
04418 regnum = true_regnum (operands[1]);
04419 else if (GET_CODE (operands[1]) == REG)
04420 regnum = REGNO (operands[1]);
04421 else
04422 regnum = -1;
04423
04424
04425
04426
04427 if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
04428 {
04429 rtx newreg;
04430 newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
04431 emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
04432 operands[1] = newreg;
04433 }
04434 }
04435
04436
04437
04438 if (rs6000_tls_referenced_p (operands[1]))
04439 {
04440 enum tls_model model;
04441 rtx tmp = operands[1];
04442 rtx addend = NULL;
04443
04444 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
04445 {
04446 addend = XEXP (XEXP (tmp, 0), 1);
04447 tmp = XEXP (XEXP (tmp, 0), 0);
04448 }
04449
04450 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
04451 model = SYMBOL_REF_TLS_MODEL (tmp);
04452 gcc_assert (model != 0);
04453
04454 tmp = rs6000_legitimize_tls_address (tmp, model);
04455 if (addend)
04456 {
04457 tmp = gen_rtx_PLUS (mode, tmp, addend);
04458 tmp = force_operand (tmp, operands[0]);
04459 }
04460 operands[1] = tmp;
04461 }
04462
04463
04464 if (reload_in_progress && mode == Pmode
04465 && (! general_operand (operands[1], mode)
04466 || ! nonimmediate_operand (operands[0], mode)))
04467 goto emit_set;
04468
04469
04470
04471 if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
04472 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
04473 && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
04474 {
04475
04476
04477 rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode, 0),
04478 simplify_gen_subreg (DImode, operands[1], mode, 0),
04479 DImode);
04480 rs6000_emit_move (simplify_gen_subreg (DImode, operands[0], mode,
04481 GET_MODE_SIZE (DImode)),
04482 simplify_gen_subreg (DImode, operands[1], mode,
04483 GET_MODE_SIZE (DImode)),
04484 DImode);
04485 return;
04486 }
04487
04488
04489
04490
04491 switch (mode)
04492 {
04493 case HImode:
04494 case QImode:
04495 if (CONSTANT_P (operands[1])
04496 && GET_CODE (operands[1]) != CONST_INT)
04497 operands[1] = force_const_mem (mode, operands[1]);
04498 break;
04499
04500 case TFmode:
04501 rs6000_eliminate_indexed_memrefs (operands);
04502
04503
04504 case DFmode:
04505 case SFmode:
04506 if (CONSTANT_P (operands[1])
04507 && ! easy_fp_constant (operands[1], mode))
04508 operands[1] = force_const_mem (mode, operands[1]);
04509 break;
04510
04511 case V16QImode:
04512 case V8HImode:
04513 case V4SFmode:
04514 case V4SImode:
04515 case V4HImode:
04516 case V2SFmode:
04517 case V2SImode:
04518 case V1DImode:
04519 if (CONSTANT_P (operands[1])
04520 && !easy_vector_constant (operands[1], mode))
04521 operands[1] = force_const_mem (mode, operands[1]);
04522 break;
04523
04524 case SImode:
04525 case DImode:
04526
04527 if (TARGET_ELF
04528 && mode == Pmode
04529 && DEFAULT_ABI == ABI_V4
04530 && (GET_CODE (operands[1]) == SYMBOL_REF
04531 || GET_CODE (operands[1]) == CONST)
04532 && small_data_operand (operands[1], mode))
04533 {
04534 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04535 return;
04536 }
04537
04538 if (DEFAULT_ABI == ABI_V4
04539 && mode == Pmode && mode == SImode
04540 && flag_pic == 1 && got_operand (operands[1], mode))
04541 {
04542 emit_insn (gen_movsi_got (operands[0], operands[1]));
04543 return;
04544 }
04545
04546 if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
04547 && TARGET_NO_TOC
04548 && ! flag_pic
04549 && mode == Pmode
04550 && CONSTANT_P (operands[1])
04551 && GET_CODE (operands[1]) != HIGH
04552 && GET_CODE (operands[1]) != CONST_INT)
04553 {
04554 rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode));
04555
04556
04557
04558 if (DEFAULT_ABI == ABI_AIX
04559 && GET_CODE (operands[1]) == SYMBOL_REF
04560 && XSTR (operands[1], 0)[0] == '.')
04561 {
04562 const char *name = XSTR (operands[1], 0);
04563 rtx new_ref;
04564 while (*name == '.')
04565 name++;
04566 new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
04567 CONSTANT_POOL_ADDRESS_P (new_ref)
04568 = CONSTANT_POOL_ADDRESS_P (operands[1]);
04569 SYMBOL_REF_FLAGS (new_ref) = SYMBOL_REF_FLAGS (operands[1]);
04570 SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
04571 SYMBOL_REF_DECL (new_ref) = SYMBOL_REF_DECL (operands[1]);
04572 operands[1] = new_ref;
04573 }
04574
04575 if (DEFAULT_ABI == ABI_DARWIN)
04576 {
04577 #if TARGET_MACHO
04578 if (MACHO_DYNAMIC_NO_PIC_P)
04579 {
04580
04581 operands[1] = rs6000_machopic_legitimize_pic_address (
04582 operands[1], mode, operands[0]);
04583 if (operands[0] != operands[1])
04584 emit_insn (gen_rtx_SET (VOIDmode,
04585 operands[0], operands[1]));
04586 return;
04587 }
04588 #endif
04589 emit_insn (gen_macho_high (target, operands[1]));
04590 emit_insn (gen_macho_low (operands[0], target, operands[1]));
04591 return;
04592 }
04593
04594 emit_insn (gen_elf_high (target, operands[1]));
04595 emit_insn (gen_elf_low (operands[0], target, operands[1]));
04596 return;
04597 }
04598
04599
04600
04601
04602 if (TARGET_TOC
04603 && GET_CODE (operands[1]) == SYMBOL_REF
04604 && constant_pool_expr_p (operands[1])
04605 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
04606 get_pool_mode (operands[1])))
04607 {
04608 operands[1] = create_TOC_reference (operands[1]);
04609 }
04610 else if (mode == Pmode
04611 && CONSTANT_P (operands[1])
04612 && ((GET_CODE (operands[1]) != CONST_INT
04613 && ! easy_fp_constant (operands[1], mode))
04614 || (GET_CODE (operands[1]) == CONST_INT
04615 && num_insns_constant (operands[1], mode) > 2)
04616 || (GET_CODE (operands[0]) == REG
04617 && FP_REGNO_P (REGNO (operands[0]))))
04618 && GET_CODE (operands[1]) != HIGH
04619 && ! legitimate_constant_pool_address_p (operands[1])
04620 && ! toc_relative_expr_p (operands[1]))
04621 {
04622
04623
04624
04625
04626
04627
04628 if (GET_CODE (operands[1]) != LABEL_REF)
04629 emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
04630
04631 #if TARGET_MACHO
04632
04633 if (DEFAULT_ABI == ABI_DARWIN && MACHOPIC_INDIRECT)
04634 {
04635 operands[1] =
04636 rs6000_machopic_legitimize_pic_address (operands[1], mode,
04637 operands[0]);
04638 if (operands[0] != operands[1])
04639 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04640 return;
04641 }
04642 #endif
04643
04644
04645
04646
04647
04648 if (GET_CODE (operands[1]) == CONST
04649 && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
04650 && GET_CODE (XEXP (operands[1], 0)) == PLUS
04651 && add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
04652 && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
04653 || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
04654 && ! side_effects_p (operands[0]))
04655 {
04656 rtx sym =
04657 force_const_mem (mode, XEXP (XEXP (operands[1], 0), 0));
04658 rtx other = XEXP (XEXP (operands[1], 0), 1);
04659
04660 sym = force_reg (mode, sym);
04661 if (mode == SImode)
04662 emit_insn (gen_addsi3 (operands[0], sym, other));
04663 else
04664 emit_insn (gen_adddi3 (operands[0], sym, other));
04665 return;
04666 }
04667
04668 operands[1] = force_const_mem (mode, operands[1]);
04669
04670 if (TARGET_TOC
04671 && constant_pool_expr_p (XEXP (operands[1], 0))
04672 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (
04673 get_pool_constant (XEXP (operands[1], 0)),
04674 get_pool_mode (XEXP (operands[1], 0))))
04675 {
04676 operands[1]
04677 = gen_const_mem (mode,
04678 create_TOC_reference (XEXP (operands[1], 0)));
04679 set_mem_alias_set (operands[1], get_TOC_alias_set ());
04680 }
04681 }
04682 break;
04683
04684 case TImode:
04685 rs6000_eliminate_indexed_memrefs (operands);
04686
04687 if (TARGET_POWER)
04688 {
04689 emit_insn (gen_rtx_PARALLEL (VOIDmode,
04690 gen_rtvec (2,
04691 gen_rtx_SET (VOIDmode,
04692 operands[0], operands[1]),
04693 gen_rtx_CLOBBER (VOIDmode,
04694 gen_rtx_SCRATCH (SImode)))));
04695 return;
04696 }
04697 break;
04698
04699 default:
04700 abort ();
04701 }
04702
04703
04704
04705
04706 if (GET_CODE (operands[1]) == MEM && ! reload_in_progress)
04707 operands[1] = validize_mem (operands[1]);
04708
04709 emit_set:
04710 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
04711 }
04712
04713
04714 #define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
04715 (GET_MODE_CLASS (MODE) == MODE_FLOAT \
04716 && (CUM)->fregno <= FP_ARG_MAX_REG \
04717 && TARGET_HARD_FLOAT && TARGET_FPRS)
04718
04719
04720 #define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
04721 (ALTIVEC_VECTOR_MODE (MODE) \
04722 && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
04723 && TARGET_ALTIVEC_ABI \
04724 && (NAMED))
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747 static bool
04748 rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
04749 {
04750
04751
04752 if (rs6000_darwin64_abi
04753 && TREE_CODE (type) == RECORD_TYPE
04754 && int_size_in_bytes (type) > 0)
04755 {
04756 CUMULATIVE_ARGS valcum;
04757 rtx valret;
04758
04759 valcum.words = 0;
04760 valcum.fregno = FP_ARG_MIN_REG;
04761 valcum.vregno = ALTIVEC_ARG_MIN_REG;
04762
04763
04764 valret = rs6000_darwin64_record_arg (&valcum, type, 1, true);
04765 if (valret)
04766 return false;
04767
04768 }
04769
04770 if (AGGREGATE_TYPE_P (type)
04771 && (TARGET_AIX_STRUCT_RET
04772 || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
04773 return true;
04774
04775
04776
04777 if (TARGET_32BIT && !TARGET_ALTIVEC_ABI
04778 && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
04779 return false;
04780
04781
04782 if (TREE_CODE (type) == VECTOR_TYPE
04783 && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
04784 {
04785 static bool warned_for_return_big_vectors = false;
04786 if (!warned_for_return_big_vectors)
04787 {
04788 warning ("GCC vector returned by reference: "
04789 "non-standard ABI extension with no compatibility guarantee");
04790 warned_for_return_big_vectors = true;
04791 }
04792 return true;
04793 }
04794
04795 if (DEFAULT_ABI == ABI_V4 && TYPE_MODE (type) == TFmode)
04796 return true;
04797
04798 return false;
04799 }
04800
04801
04802
04803
04804
04805
04806
04807
04808 void
04809 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
04810 rtx libname ATTRIBUTE_UNUSED, int incoming,
04811 int libcall, int n_named_args)
04812 {
04813 static CUMULATIVE_ARGS zero_cumulative;
04814
04815 *cum = zero_cumulative;
04816 cum->words = 0;
04817 cum->fregno = FP_ARG_MIN_REG;
04818 cum->vregno = ALTIVEC_ARG_MIN_REG;
04819 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
04820 cum->call_cookie = ((DEFAULT_ABI == ABI_V4 && libcall)
04821 ? CALL_LIBCALL : CALL_NORMAL);
04822 cum->sysv_gregno = GP_ARG_MIN_REG;
04823 cum->stdarg = fntype
04824 && (TYPE_ARG_TYPES (fntype) != 0
04825 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04826 != void_type_node));
04827
04828 cum->nargs_prototype = 0;
04829 if (incoming || cum->prototype)
04830 cum->nargs_prototype = n_named_args;
04831
04832
04833 if ((!fntype && rs6000_default_long_calls)
04834 || (fntype
04835 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
04836 && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))))
04837 cum->call_cookie |= CALL_LONG;
04838
04839 if (TARGET_DEBUG_ARG)
04840 {
04841 fprintf (stderr, "\ninit_cumulative_args:");
04842 if (fntype)
04843 {
04844 tree ret_type = TREE_TYPE (fntype);
04845 fprintf (stderr, " ret code = %s,",
04846 tree_code_name[ (int)TREE_CODE (ret_type) ]);
04847 }
04848
04849 if (cum->call_cookie & CALL_LONG)
04850 fprintf (stderr, " longcall,");
04851
04852 fprintf (stderr, " proto = %d, nargs = %d\n",
04853 cum->prototype, cum->nargs_prototype);
04854 }
04855
04856 if (fntype
04857 && !TARGET_ALTIVEC
04858 && TARGET_ALTIVEC_ABI
04859 && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
04860 {
04861 error ("Cannot return value in vector register because"
04862 " altivec instructions are disabled, use -maltivec"
04863 " to enable them.");
04864 }
04865 }
04866
04867
04868
04869 static bool
04870 rs6000_must_pass_in_stack (enum machine_mode mode, tree type)
04871 {
04872 if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT)
04873 return must_pass_in_stack_var_size (mode, type);
04874 else
04875 return must_pass_in_stack_var_size_or_pad (mode, type);
04876 }
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887 enum direction
04888 function_arg_padding (enum machine_mode mode, tree type)
04889 {
04890 #ifndef AGGREGATE_PADDING_FIXED
04891 #define AGGREGATE_PADDING_FIXED 0
04892 #endif
04893 #ifndef AGGREGATES_PAD_UPWARD_ALWAYS
04894 #define AGGREGATES_PAD_UPWARD_ALWAYS 0
04895 #endif
04896
04897 if (!AGGREGATE_PADDING_FIXED)
04898 {
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908 if (BYTES_BIG_ENDIAN)
04909 {
04910 HOST_WIDE_INT size = 0;
04911
04912 if (mode == BLKmode)
04913 {
04914 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
04915 size = int_size_in_bytes (type);
04916 }
04917 else
04918 size = GET_MODE_SIZE (mode);
04919
04920 if (size == 1 || size == 2 || size == 4)
04921 return downward;
04922 }
04923 return upward;
04924 }
04925
04926 if (AGGREGATES_PAD_UPWARD_ALWAYS)
04927 {
04928 if (type != 0 && AGGREGATE_TYPE_P (type))
04929 return upward;
04930 }
04931
04932
04933 return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945 int
04946 function_arg_boundary (enum machine_mode mode, tree type)
04947 {
04948 if (DEFAULT_ABI == ABI_V4 && GET_MODE_SIZE (mode) == 8)
04949 return 64;
04950 else if (SPE_VECTOR_MODE (mode)
04951 || (type && TREE_CODE (type) == VECTOR_TYPE
04952 && int_size_in_bytes (type) >= 8
04953 && int_size_in_bytes (type) < 16))
04954 return 64;
04955 else if (ALTIVEC_VECTOR_MODE (mode)
04956 || (type && TREE_CODE (type) == VECTOR_TYPE
04957 && int_size_in_bytes (type) >= 16))
04958 return 128;
04959 else if (rs6000_darwin64_abi && mode == BLKmode
04960 && type && TYPE_ALIGN (type) > 64)
04961 return 128;
04962 else
04963 return PARM_BOUNDARY;
04964 }
04965
04966
04967
04968 static unsigned long
04969 rs6000_arg_size (enum machine_mode mode, tree type)
04970 {
04971 unsigned long size;
04972
04973 if (mode != BLKmode)
04974 size = GET_MODE_SIZE (mode);
04975 else
04976 size = int_size_in_bytes (type);
04977
04978 if (TARGET_32BIT)
04979 return (size + 3) >> 2;
04980 else
04981 return (size + 7) >> 3;
04982 }
04983
04984
04985
04986 static void
04987 rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum,
04988 HOST_WIDE_INT bitpos)
04989 {
04990 unsigned int startbit, endbit;
04991 int intregs, intoffset;
04992 enum machine_mode mode;
04993
04994 if (cum->intoffset == -1)
04995 return;
04996
04997 intoffset = cum->intoffset;
04998 cum->intoffset = -1;
04999
05000 if (intoffset % BITS_PER_WORD != 0)
05001 {
05002 mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
05003 MODE_INT, 0);
05004 if (mode == BLKmode)
05005 {
05006
05007
05008
05009
05010 intoffset = intoffset & -BITS_PER_WORD;
05011 }
05012 }
05013
05014 startbit = intoffset & -BITS_PER_WORD;
05015 endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
05016 intregs = (endbit - startbit) / BITS_PER_WORD;
05017 cum->words += intregs;
05018 }
05019
05020
05021
05022
05023
05024
05025 static void
05026 rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum,
05027 tree type,
05028 HOST_WIDE_INT startbitpos)
05029 {
05030 tree f;
05031
05032 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
05033 if (TREE_CODE (f) == FIELD_DECL)
05034 {
05035 HOST_WIDE_INT bitpos = startbitpos;
05036 tree ftype = TREE_TYPE (f);
05037 enum machine_mode mode = TYPE_MODE (ftype);
05038
05039 if (DECL_SIZE (f) != 0
05040 && host_integerp (bit_position (f), 1))
05041 bitpos += int_bit_position (f);
05042
05043
05044
05045 if (TREE_CODE (ftype) == RECORD_TYPE)
05046 rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos);
05047 else if (USE_FP_FOR_ARG_P (cum, mode, ftype))
05048 {
05049 rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
05050 cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
05051 cum->words += (GET_MODE_SIZE (mode) + 7) >> 3;
05052 }
05053 else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, 1))
05054 {
05055 rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
05056 cum->vregno++;
05057 cum->words += 2;
05058 }
05059 else if (cum->intoffset == -1)
05060 cum->intoffset = bitpos;
05061 }
05062 }
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072 void
05073 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05074 tree type, int named, int depth)
05075 {
05076 int size;
05077
05078
05079 if (depth == 0)
05080 cum->nargs_prototype--;
05081
05082 if (TARGET_ALTIVEC_ABI
05083 && (ALTIVEC_VECTOR_MODE (mode)
05084 || (type && TREE_CODE (type) == VECTOR_TYPE
05085 && int_size_in_bytes (type) == 16)))
05086 {
05087 bool stack = false;
05088
05089 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
05090 {
05091 cum->vregno++;
05092 if (!TARGET_ALTIVEC)
05093 error ("Cannot pass argument in vector register because"
05094 " altivec instructions are disabled, use -maltivec"
05095 " to enable them.");
05096
05097
05098
05099
05100 if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
05101 || (cum->stdarg && DEFAULT_ABI != ABI_V4))
05102 stack = true;
05103 }
05104 else
05105 stack = true;
05106
05107 if (stack)
05108 {
05109 int align;
05110
05111
05112
05113
05114
05115
05116
05117
05118 if (TARGET_32BIT)
05119 align = (2 - cum->words) & 3;
05120 else
05121 align = cum->words & 1;
05122 cum->words += align + rs6000_arg_size (mode, type);
05123
05124 if (TARGET_DEBUG_ARG)
05125 {
05126 fprintf (stderr, "function_adv: words = %2d, align=%d, ",
05127 cum->words, align);
05128 fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
05129 cum->nargs_prototype, cum->prototype,
05130 GET_MODE_NAME (mode));
05131 }
05132 }
05133 }
05134 else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode)
05135 && !cum->stdarg
05136 && cum->sysv_gregno <= GP_ARG_MAX_REG)
05137 cum->sysv_gregno++;
05138
05139 else if (rs6000_darwin64_abi
05140 && mode == BLKmode
05141 && TREE_CODE (type) == RECORD_TYPE
05142 && (size = int_size_in_bytes (type)) > 0)
05143 {
05144
05145
05146
05147 if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
05148 && (cum->words % 2) != 0)
05149 cum->words++;
05150
05151 if (!named)
05152 cum->words += (size + 7) / 8;
05153 else
05154 {
05155
05156
05157
05158
05159 cum->intoffset = 0;
05160 rs6000_darwin64_record_arg_advance_recurse (cum, type, 0);
05161 rs6000_darwin64_record_arg_advance_flush (cum,
05162 size * BITS_PER_UNIT);
05163 }
05164 }
05165 else if (DEFAULT_ABI == ABI_V4)
05166 {
05167 if (TARGET_HARD_FLOAT && TARGET_FPRS
05168 && (mode == SFmode || mode == DFmode))
05169 {
05170 if (cum->fregno <= FP_ARG_V4_MAX_REG)
05171 cum->fregno++;
05172 else
05173 {
05174 if (mode == DFmode)
05175 cum->words += cum->words & 1;
05176 cum->words += rs6000_arg_size (mode, type);
05177 }
05178 }
05179 else
05180 {
05181 int n_words = rs6000_arg_size (mode, type);
05182 int gregno = cum->sysv_gregno;
05183
05184
05185
05186
05187 if (n_words == 2)
05188 gregno += (1 - gregno) & 1;
05189
05190
05191 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
05192 {
05193
05194
05195
05196 if (n_words == 2)
05197 cum->words += cum->words & 1;
05198 cum->words += n_words;
05199 }
05200
05201
05202
05203
05204 cum->sysv_gregno = gregno + n_words;
05205 }
05206
05207 if (TARGET_DEBUG_ARG)
05208 {
05209 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
05210 cum->words, cum->fregno);
05211 fprintf (stderr, "gregno = %2d, nargs = %4d, proto = %d, ",
05212 cum->sysv_gregno, cum->nargs_prototype, cum->prototype);
05213 fprintf (stderr, "mode = %4s, named = %d\n",
05214 GET_MODE_NAME (mode), named);
05215 }
05216 }
05217 else
05218 {
05219 int n_words = rs6000_arg_size (mode, type);
05220 int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
05221
05222
05223
05224
05225
05226
05227 align &= cum->words;
05228 cum->words += align + n_words;
05229
05230 if (GET_MODE_CLASS (mode) == MODE_FLOAT
05231 && TARGET_HARD_FLOAT && TARGET_FPRS)
05232 cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
05233
05234 if (TARGET_DEBUG_ARG)
05235 {
05236 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
05237 cum->words, cum->fregno);
05238 fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ",
05239 cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
05240 fprintf (stderr, "named = %d, align = %d, depth = %d\n",
05241 named, align, depth);
05242 }
05243 }
05244 }
05245
05246 static rtx
05247 spe_build_register_parallel (enum machine_mode mode, int gregno)
05248 {
05249 rtx r1, r3;
05250
05251 if (mode == DFmode)
05252 {
05253 r1 = gen_rtx_REG (DImode, gregno);
05254 r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
05255 return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
05256 }
05257 else if (mode == DCmode)
05258 {
05259 r1 = gen_rtx_REG (DImode, gregno);
05260 r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
05261 r3 = gen_rtx_REG (DImode, gregno + 2);
05262 r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
05263 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
05264 }
05265 abort();
05266 return NULL_RTX;
05267 }
05268
05269
05270 static rtx
05271 rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05272 tree type)
05273 {
05274 int gregno = cum->sysv_gregno;
05275
05276
05277
05278 if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode))
05279 {
05280 int n_words = rs6000_arg_size (mode, type);
05281
05282
05283 if (mode == DFmode)
05284 gregno += (1 - gregno) & 1;
05285
05286
05287 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
05288 return NULL_RTX;
05289
05290 return spe_build_register_parallel (mode, gregno);
05291 }
05292 if (cum->stdarg)
05293 {
05294 int n_words = rs6000_arg_size (mode, type);
05295
05296
05297 if (n_words == 2 && (gregno & 1) == 0)
05298 gregno += 1;
05299
05300 if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
05301 {
05302 rtx r1, r2;
05303 enum machine_mode m = SImode;
05304
05305 r1 = gen_rtx_REG (m, gregno);
05306 r1 = gen_rtx_EXPR_LIST (m, r1, const0_rtx);
05307 r2 = gen_rtx_REG (m, gregno + 1);
05308 r2 = gen_rtx_EXPR_LIST (m, r2, GEN_INT (4));
05309 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
05310 }
05311 else
05312 return NULL_RTX;
05313 }
05314 else
05315 {
05316 if (gregno <= GP_ARG_MAX_REG)
05317 return gen_rtx_REG (mode, gregno);
05318 else
05319 return NULL_RTX;
05320 }
05321 }
05322
05323
05324
05325
05326 static void
05327 rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum,
05328 HOST_WIDE_INT bitpos, rtx rvec[], int *k)
05329 {
05330 enum machine_mode mode;
05331 unsigned int regno;
05332 unsigned int startbit, endbit;
05333 int this_regno, intregs, intoffset;
05334 rtx reg;
05335
05336 if (cum->intoffset == -1)
05337 return;
05338
05339 intoffset = cum->intoffset;
05340 cum->intoffset = -1;
05341
05342
05343
05344
05345
05346
05347 if (intoffset % BITS_PER_WORD != 0)
05348 {
05349 mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
05350 MODE_INT, 0);
05351 if (mode == BLKmode)
05352 {
05353
05354
05355
05356
05357 intoffset = intoffset & -BITS_PER_WORD;
05358 mode = word_mode;
05359 }
05360 }
05361 else
05362 mode = word_mode;
05363
05364 startbit = intoffset & -BITS_PER_WORD;
05365 endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
05366 intregs = (endbit - startbit) / BITS_PER_WORD;
05367 this_regno = cum->words + intoffset / BITS_PER_WORD;
05368
05369 if (intregs > 0 && intregs > GP_ARG_NUM_REG - this_regno)
05370 cum->use_stack = 1;
05371
05372 intregs = MIN (intregs, GP_ARG_NUM_REG - this_regno);
05373 if (intregs <= 0)
05374 return;
05375
05376 intoffset /= BITS_PER_UNIT;
05377 do
05378 {
05379 regno = GP_ARG_MIN_REG + this_regno;
05380 reg = gen_rtx_REG (mode, regno);
05381 rvec[(*k)++] =
05382 gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
05383
05384 this_regno += 1;
05385 intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
05386 mode = word_mode;
05387 intregs -= 1;
05388 }
05389 while (intregs > 0);
05390 }
05391
05392
05393
05394 static void
05395 rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, tree type,
05396 HOST_WIDE_INT startbitpos, rtx rvec[],
05397 int *k)
05398 {
05399 tree f;
05400
05401 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
05402 if (TREE_CODE (f) == FIELD_DECL)
05403 {
05404 HOST_WIDE_INT bitpos = startbitpos;
05405 tree ftype = TREE_TYPE (f);
05406 enum machine_mode mode = TYPE_MODE (ftype);
05407
05408 if (DECL_SIZE (f) != 0
05409 && host_integerp (bit_position (f), 1))
05410 bitpos += int_bit_position (f);
05411
05412
05413
05414 if (TREE_CODE (ftype) == RECORD_TYPE)
05415 rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k);
05416 else if (cum->named && USE_FP_FOR_ARG_P (cum, mode, ftype))
05417 {
05418 #if 0
05419 switch (mode)
05420 {
05421 case SCmode: mode = SFmode; break;
05422 case DCmode: mode = DFmode; break;
05423 case TCmode: mode = TFmode; break;
05424 default: break;
05425 }
05426 #endif
05427 rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
05428 rvec[(*k)++]
05429 = gen_rtx_EXPR_LIST (VOIDmode,
05430 gen_rtx_REG (mode, cum->fregno++),
05431 GEN_INT (bitpos / BITS_PER_UNIT));
05432 if (mode == TFmode)
05433 cum->fregno++;
05434 }
05435 else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, ftype, 1))
05436 {
05437 rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
05438 rvec[(*k)++]
05439 = gen_rtx_EXPR_LIST (VOIDmode,
05440 gen_rtx_REG (mode, cum->vregno++),
05441 GEN_INT (bitpos / BITS_PER_UNIT));
05442 }
05443 else if (cum->intoffset == -1)
05444 cum->intoffset = bitpos;
05445 }
05446 }
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461 static rtx
05462 rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, tree type,
05463 int named, bool retval)
05464 {
05465 rtx rvec[FIRST_PSEUDO_REGISTER];
05466 int k = 1, kbase = 1;
05467 HOST_WIDE_INT typesize = int_size_in_bytes (type);
05468
05469 CUMULATIVE_ARGS copy_cum = *orig_cum;
05470 CUMULATIVE_ARGS *cum = ©_cum;
05471
05472
05473 if (!retval && TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
05474 && (cum->words % 2) != 0)
05475 cum->words++;
05476
05477 cum->intoffset = 0;
05478 cum->use_stack = 0;
05479 cum->named = named;
05480
05481
05482
05483
05484
05485 rs6000_darwin64_record_arg_recurse (cum, type, 0, rvec, &k);
05486 rs6000_darwin64_record_arg_flush (cum, typesize * BITS_PER_UNIT, rvec, &k);
05487
05488
05489
05490
05491
05492 if (cum->use_stack)
05493 {
05494 if (retval)
05495 return NULL_RTX;
05496 kbase = 0;
05497 rvec[0] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05498 }
05499 if (k > 1 || cum->use_stack)
05500 return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (k - kbase, &rvec[kbase]));
05501 else
05502 return NULL_RTX;
05503 }
05504
05505
05506
05507 static rtx
05508 rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
05509 {
05510 int n_units;
05511 int i, k;
05512 rtx rvec[GP_ARG_NUM_REG + 1];
05513
05514 if (align_words >= GP_ARG_NUM_REG)
05515 return NULL_RTX;
05516
05517 n_units = rs6000_arg_size (mode, type);
05518
05519
05520
05521
05522 if (n_units == 0
05523 || (n_units == 1 && mode != BLKmode))
05524 return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05525
05526 k = 0;
05527 if (align_words + n_units > GP_ARG_NUM_REG)
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05542
05543 i = 0;
05544 do
05545 {
05546 rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words);
05547 rtx off = GEN_INT (i++ * 4);
05548 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
05549 }
05550 while (++align_words < GP_ARG_NUM_REG && --n_units != 0);
05551
05552 return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
05553 }
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583 struct rtx_def *
05584 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05585 tree type, int named)
05586 {
05587 enum rs6000_abi abi = DEFAULT_ABI;
05588
05589
05590
05591
05592
05593 if (mode == VOIDmode)
05594 {
05595 if (abi == ABI_V4
05596 && (cum->call_cookie & CALL_LIBCALL) == 0
05597 && (cum->stdarg
05598 || (cum->nargs_prototype < 0
05599 && (cum->prototype || TARGET_NO_PROTOTYPE))))
05600 {
05601
05602 if (TARGET_SPE_ABI)
05603 return GEN_INT (cum->call_cookie | CALL_V4_SET_FP_ARGS);
05604 else if (TARGET_HARD_FLOAT && TARGET_FPRS)
05605 return GEN_INT (cum->call_cookie
05606 | ((cum->fregno == FP_ARG_MIN_REG)
05607 ? CALL_V4_SET_FP_ARGS
05608 : CALL_V4_CLEAR_FP_ARGS));
05609 }
05610
05611 return GEN_INT (cum->call_cookie);
05612 }
05613
05614 if (rs6000_darwin64_abi && mode == BLKmode
05615 && TREE_CODE (type) == RECORD_TYPE)
05616 {
05617 rtx rslt = rs6000_darwin64_record_arg (cum, type, named, false);
05618 if (rslt != NULL_RTX)
05619 return rslt;
05620
05621 }
05622
05623 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
05624 if (TARGET_64BIT && ! cum->prototype)
05625 {
05626
05627
05628 int align_words;
05629 rtx slot;
05630 align_words = (cum->words + 1) & ~1;
05631
05632 if (align_words >= GP_ARG_NUM_REG)
05633 {
05634 slot = NULL_RTX;
05635 }
05636 else
05637 {
05638 slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05639 }
05640 return gen_rtx_PARALLEL (mode,
05641 gen_rtvec (2,
05642 gen_rtx_EXPR_LIST (VOIDmode,
05643 slot, const0_rtx),
05644 gen_rtx_EXPR_LIST (VOIDmode,
05645 gen_rtx_REG (mode, cum->vregno),
05646 const0_rtx)));
05647 }
05648 else
05649 return gen_rtx_REG (mode, cum->vregno);
05650 else if (TARGET_ALTIVEC_ABI
05651 && (ALTIVEC_VECTOR_MODE (mode)
05652 || (type && TREE_CODE (type) == VECTOR_TYPE
05653 && int_size_in_bytes (type) == 16)))
05654 {
05655 if (named || abi == ABI_V4)
05656 return NULL_RTX;
05657 else
05658 {
05659
05660
05661 int align, align_words, n_words;
05662 enum machine_mode part_mode;
05663
05664
05665
05666
05667
05668
05669 if (TARGET_32BIT)
05670 align = (2 - cum->words) & 3;
05671 else
05672 align = cum->words & 1;
05673 align_words = cum->words + align;
05674
05675
05676 if (align_words >= GP_ARG_NUM_REG)
05677 return NULL_RTX;
05678
05679 if (TARGET_32BIT && TARGET_POWERPC64)
05680 return rs6000_mixed_function_arg (mode, type, align_words);
05681
05682
05683
05684 part_mode = mode;
05685 n_words = rs6000_arg_size (mode, type);
05686 if (align_words + n_words > GP_ARG_NUM_REG)
05687
05688
05689 part_mode = DImode;
05690
05691 return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
05692 }
05693 }
05694 else if (TARGET_SPE_ABI && TARGET_SPE
05695 && (SPE_VECTOR_MODE (mode)
05696 || (TARGET_E500_DOUBLE && (mode == DFmode
05697 || mode == DCmode))))
05698 return rs6000_spe_function_arg (cum, mode, type);
05699
05700 else if (abi == ABI_V4)
05701 {
05702 if (TARGET_HARD_FLOAT && TARGET_FPRS
05703 && (mode == SFmode || mode == DFmode))
05704 {
05705 if (cum->fregno <= FP_ARG_V4_MAX_REG)
05706 return gen_rtx_REG (mode, cum->fregno);
05707 else
05708 return NULL_RTX;
05709 }
05710 else
05711 {
05712 int n_words = rs6000_arg_size (mode, type);
05713 int gregno = cum->sysv_gregno;
05714
05715
05716
05717
05718 if (n_words == 2)
05719 gregno += (1 - gregno) & 1;
05720
05721
05722 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
05723 return NULL_RTX;
05724
05725 if (TARGET_32BIT && TARGET_POWERPC64)
05726 return rs6000_mixed_function_arg (mode, type,
05727 gregno - GP_ARG_MIN_REG);
05728 return gen_rtx_REG (mode, gregno);
05729 }
05730 }
05731 else
05732 {
05733 int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
05734 int align_words = cum->words + (cum->words & align);
05735
05736 if (USE_FP_FOR_ARG_P (cum, mode, type))
05737 {
05738 rtx rvec[GP_ARG_NUM_REG + 1];
05739 rtx r;
05740 int k;
05741 bool needs_psave;
05742 enum machine_mode fmode = mode;
05743 unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
05744
05745 if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
05746 {
05747
05748
05749 if (cum->fregno != FP_ARG_MAX_REG || fmode != TFmode)
05750 abort ();
05751
05752
05753 fmode = DFmode;
05754 }
05755
05756
05757
05758 needs_psave = (type
05759 && (cum->nargs_prototype <= 0
05760 || (DEFAULT_ABI == ABI_AIX
05761 && TARGET_XL_COMPAT
05762 && align_words >= GP_ARG_NUM_REG)));
05763
05764 if (!needs_psave && mode == fmode)
05765 return gen_rtx_REG (fmode, cum->fregno);
05766
05767 k = 0;
05768 if (needs_psave)
05769 {
05770
05771
05772 if (align_words < GP_ARG_NUM_REG)
05773 {
05774 unsigned long n_words = rs6000_arg_size (mode, type);
05775
05776 if (align_words + n_words > GP_ARG_NUM_REG
05777 || (TARGET_32BIT && TARGET_POWERPC64))
05778 {
05779
05780
05781 enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
05782 rtx off;
05783 int i=0;
05784 if (align_words + n_words > GP_ARG_NUM_REG
05785 && (TARGET_32BIT && TARGET_POWERPC64))
05786
05787
05788
05789
05790
05791
05792 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX,
05793 const0_rtx);
05794 do
05795 {
05796 r = gen_rtx_REG (rmode,
05797 GP_ARG_MIN_REG + align_words);
05798 off = GEN_INT (i++ * GET_MODE_SIZE (rmode));
05799 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
05800 }
05801 while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
05802 }
05803 else
05804 {
05805
05806 r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05807 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
05808 }
05809 }
05810 else
05811
05812 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
05813 }
05814
05815
05816 r = gen_rtx_REG (fmode, cum->fregno);
05817 rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
05818
05819 return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
05820 }
05821 else if (align_words < GP_ARG_NUM_REG)
05822 {
05823 if (TARGET_32BIT && TARGET_POWERPC64)
05824 return rs6000_mixed_function_arg (mode, type, align_words);
05825
05826 if (mode == BLKmode)
05827 mode = Pmode;
05828
05829 return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
05830 }
05831 else
05832 return NULL_RTX;
05833 }
05834 }
05835
05836
05837
05838
05839
05840
05841
05842 static int
05843 rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
05844 tree type, bool named)
05845 {
05846 int ret = 0;
05847 int align;
05848 int parm_offset;
05849 int align_words;
05850
05851 if (DEFAULT_ABI == ABI_V4)
05852 return 0;
05853
05854 if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named)
05855 && cum->nargs_prototype >= 0)
05856 return 0;
05857
05858
05859 if (rs6000_darwin64_abi && mode == BLKmode
05860 && TREE_CODE (type) == RECORD_TYPE
05861 && int_size_in_bytes (type) > 0)
05862 return 0;
05863
05864 align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
05865 parm_offset = TARGET_32BIT ? 2 : 0;
05866 align_words = cum->words + ((parm_offset - cum->words) & align);
05867
05868 if (USE_FP_FOR_ARG_P (cum, mode, type)
05869
05870
05871
05872 && !(type
05873 && (cum->nargs_prototype <= 0
05874 || (DEFAULT_ABI == ABI_AIX
05875 && TARGET_XL_COMPAT
05876 && align_words >= GP_ARG_NUM_REG))))
05877 {
05878 if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
05879 ret = FP_ARG_MAX_REG + 1 - cum->fregno;
05880 else if (cum->nargs_prototype >= 0)
05881 return 0;
05882 }
05883
05884 if (align_words < GP_ARG_NUM_REG
05885 && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
05886 ret = GP_ARG_NUM_REG - align_words;
05887
05888 ret *= (TARGET_32BIT ? 4 : 8);
05889
05890 if (ret != 0 && TARGET_DEBUG_ARG)
05891 fprintf (stderr, "rs6000_arg_partial_bytes: %d\n", ret);
05892
05893 return ret;
05894 }
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910 static bool
05911 rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
05912 enum machine_mode mode, tree type,
05913 bool named ATTRIBUTE_UNUSED)
05914 {
05915 if (DEFAULT_ABI == ABI_V4 && mode == TFmode)
05916 {
05917 if (TARGET_DEBUG_ARG)
05918 fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
05919 return 1;
05920 }
05921
05922 if (!type)
05923 return 0;
05924
05925 if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type))
05926 {
05927 if (TARGET_DEBUG_ARG)
05928 fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n");
05929 return 1;
05930 }
05931
05932 if (int_size_in_bytes (type) < 0)
05933 {
05934 if (TARGET_DEBUG_ARG)
05935 fprintf (stderr, "function_arg_pass_by_reference: variable size\n");
05936 return 1;
05937 }
05938
05939
05940
05941 if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
05942 {
05943 if (TARGET_DEBUG_ARG)
05944 fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n");
05945 return 1;
05946 }
05947
05948
05949 if (TREE_CODE (type) == VECTOR_TYPE
05950 && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
05951 {
05952 static bool warned_for_pass_big_vectors = false;
05953 if (TARGET_DEBUG_ARG)
05954 fprintf (stderr, "function_arg_pass_by_reference: synthetic vector\n");
05955 if (!warned_for_pass_big_vectors)
05956 {
05957 warning ("GCC vector passed by reference: "
05958 "non-standard ABI extension with no compatibility guarantee");
05959 warned_for_pass_big_vectors = true;
05960 }
05961 return 1;
05962 }
05963
05964 return 0;
05965 }
05966
05967 static void
05968 rs6000_move_block_from_reg (int regno, rtx x, int nregs)
05969 {
05970 int i;
05971 enum machine_mode reg_mode = TARGET_32BIT ? SImode : DImode;
05972
05973 if (nregs == 0)
05974 return;
05975
05976 for (i = 0; i < nregs; i++)
05977 {
05978 rtx tem = adjust_address_nv (x, reg_mode, i*GET_MODE_SIZE(reg_mode));
05979 if (reload_completed)
05980 {
05981 if (! strict_memory_address_p (reg_mode, XEXP (tem, 0)))
05982 tem = NULL_RTX;
05983 else
05984 tem = simplify_gen_subreg (reg_mode, x, BLKmode,
05985 i * GET_MODE_SIZE(reg_mode));
05986 }
05987 else
05988 tem = replace_equiv_address (tem, XEXP (tem, 0));
05989
05990 if (tem == NULL_RTX)
05991 abort ();
05992
05993 emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i));
05994 }
05995 }
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011 static void
06012 setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
06013 tree type, int *pretend_size ATTRIBUTE_UNUSED,
06014 int no_rtl)
06015 {
06016 CUMULATIVE_ARGS next_cum;
06017 int reg_size = TARGET_32BIT ? 4 : 8;
06018 rtx save_area = NULL_RTX, mem;
06019 int first_reg_offset, set;
06020
06021
06022 next_cum = *cum;
06023 function_arg_advance (&next_cum, mode, type, 1, 0);
06024
06025 if (DEFAULT_ABI == ABI_V4)
06026 {
06027 if (! no_rtl)
06028 save_area = plus_constant (virtual_stack_vars_rtx,
06029 - RS6000_VARARGS_SIZE);
06030
06031 first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
06032 }
06033 else
06034 {
06035 first_reg_offset = next_cum.words;
06036 save_area = virtual_incoming_args_rtx;
06037
06038 if (targetm.calls.must_pass_in_stack (mode, type))
06039 first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type);
06040 }
06041
06042 set = get_varargs_alias_set ();
06043 if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG)
06044 {
06045 mem = gen_rtx_MEM (BLKmode,
06046 plus_constant (save_area,
06047 first_reg_offset * reg_size)),
06048 set_mem_alias_set (mem, set);
06049 set_mem_align (mem, BITS_PER_WORD);
06050
06051 rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
06052 GP_ARG_NUM_REG - first_reg_offset);
06053 }
06054
06055
06056 if (DEFAULT_ABI == ABI_V4
06057 && TARGET_HARD_FLOAT && TARGET_FPRS
06058 && ! no_rtl
06059 && next_cum.fregno <= FP_ARG_V4_MAX_REG)
06060 {
06061 int fregno = next_cum.fregno;
06062 rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO);
06063 rtx lab = gen_label_rtx ();
06064 int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG) * 8);
06065
06066 emit_jump_insn
06067 (gen_rtx_SET (VOIDmode,
06068 pc_rtx,
06069 gen_rtx_IF_THEN_ELSE (VOIDmode,
06070 gen_rtx_NE (VOIDmode, cr1,
06071 const0_rtx),
06072 gen_rtx_LABEL_REF (VOIDmode, lab),
06073 pc_rtx)));
06074
06075 while (fregno <= FP_ARG_V4_MAX_REG)
06076 {
06077 mem = gen_rtx_MEM (DFmode, plus_constant (save_area, off));
06078 set_mem_alias_set (mem, set);
06079 set_mem_align (mem, GET_MODE_ALIGNMENT (DFmode));
06080 emit_move_insn (mem, gen_rtx_REG (DFmode, fregno));
06081 fregno++;
06082 off += 8;
06083 }
06084
06085 emit_label (lab);
06086 }
06087 }
06088
06089
06090
06091 static tree
06092 rs6000_build_builtin_va_list (void)
06093 {
06094 tree f_gpr, f_fpr, f_res, f_ovf, f_sav, record, type_decl;
06095
06096
06097
06098 if (DEFAULT_ABI != ABI_V4)
06099 return build_pointer_type (char_type_node);
06100
06101 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
06102 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
06103
06104 f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
06105 unsigned_char_type_node);
06106 f_fpr = build_decl (FIELD_DECL, get_identifier ("fpr"),
06107 unsigned_char_type_node);
06108
06109
06110 f_res = build_decl (FIELD_DECL, get_identifier ("reserved"),
06111 short_unsigned_type_node);
06112 f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
06113 ptr_type_node);
06114 f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
06115 ptr_type_node);
06116
06117 DECL_FIELD_CONTEXT (f_gpr) = record;
06118 DECL_FIELD_CONTEXT (f_fpr) = record;
06119 DECL_FIELD_CONTEXT (f_res) = record;
06120 DECL_FIELD_CONTEXT (f_ovf) = record;
06121 DECL_FIELD_CONTEXT (f_sav) = record;
06122
06123 TREE_CHAIN (record) = type_decl;
06124 TYPE_NAME (record) = type_decl;
06125 TYPE_FIELDS (record) = f_gpr;
06126 TREE_CHAIN (f_gpr) = f_fpr;
06127 TREE_CHAIN (f_fpr) = f_res;
06128 TREE_CHAIN (f_res) = f_ovf;
06129 TREE_CHAIN (f_ovf) = f_sav;
06130
06131 layout_type (record);
06132
06133
06134 return build_array_type (record, build_index_type (size_zero_node));
06135 }
06136
06137
06138
06139 void
06140 rs6000_va_start (tree valist, rtx nextarg)
06141 {
06142 HOST_WIDE_INT words, n_gpr, n_fpr;
06143 tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
06144 tree gpr, fpr, ovf, sav, t;
06145
06146
06147 if (DEFAULT_ABI != ABI_V4)
06148 {
06149 std_expand_builtin_va_start (valist, nextarg);
06150 return;
06151 }
06152
06153 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
06154 f_fpr = TREE_CHAIN (f_gpr);
06155 f_res = TREE_CHAIN (f_fpr);
06156 f_ovf = TREE_CHAIN (f_res);
06157 f_sav = TREE_CHAIN (f_ovf);
06158
06159 valist = build_va_arg_indirect_ref (valist);
06160 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
06161 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
06162 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
06163 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
06164
06165
06166 words = current_function_args_info.words;
06167 n_gpr = MIN (current_function_args_info.sysv_gregno - GP_ARG_MIN_REG,
06168 GP_ARG_NUM_REG);
06169 n_fpr = MIN (current_function_args_info.fregno - FP_ARG_MIN_REG,
06170 FP_ARG_NUM_REG);
06171
06172 if (TARGET_DEBUG_ARG)
06173 fprintf (stderr, "va_start: words = "HOST_WIDE_INT_PRINT_DEC", n_gpr = "
06174 HOST_WIDE_INT_PRINT_DEC", n_fpr = "HOST_WIDE_INT_PRINT_DEC"\n",
06175 words, n_gpr, n_fpr);
06176
06177 t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
06178 build_int_cst (NULL_TREE, n_gpr));
06179 TREE_SIDE_EFFECTS (t) = 1;
06180 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06181
06182 t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
06183 build_int_cst (NULL_TREE, n_fpr));
06184 TREE_SIDE_EFFECTS (t) = 1;
06185 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06186
06187
06188 t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
06189 if (words != 0)
06190 t = build (PLUS_EXPR, TREE_TYPE (ovf), t,
06191 build_int_cst (NULL_TREE, words * UNITS_PER_WORD));
06192 t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
06193 TREE_SIDE_EFFECTS (t) = 1;
06194 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06195
06196
06197 t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
06198 t = build (PLUS_EXPR, TREE_TYPE (sav), t,
06199 build_int_cst (NULL_TREE, -RS6000_VARARGS_SIZE));
06200 t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
06201 TREE_SIDE_EFFECTS (t) = 1;
06202 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06203 }
06204
06205
06206
06207 tree
06208 rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
06209 {
06210 tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
06211 tree gpr, fpr, ovf, sav, reg, t, u;
06212 int size, rsize, n_reg, sav_ofs, sav_scale;
06213 tree lab_false, lab_over, addr;
06214 int align;
06215 tree ptrtype = build_pointer_type (type);
06216
06217 if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
06218 {
06219 t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
06220 return build_va_arg_indirect_ref (t);
06221 }
06222
06223 if (DEFAULT_ABI != ABI_V4)
06224 {
06225 if (targetm.calls.split_complex_arg && TREE_CODE (type) == COMPLEX_TYPE)
06226 {
06227 tree elem_type = TREE_TYPE (type);
06228 enum machine_mode elem_mode = TYPE_MODE (elem_type);
06229 int elem_size = GET_MODE_SIZE (elem_mode);
06230
06231 if (elem_size < UNITS_PER_WORD)
06232 {
06233 tree real_part, imag_part;
06234 tree post = NULL_TREE;
06235
06236 real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
06237 &post);
06238
06239
06240 real_part = get_initialized_tmp_var (real_part, pre_p, &post);
06241 append_to_statement_list (post, pre_p);
06242
06243 imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
06244 post_p);
06245
06246 return build (COMPLEX_EXPR, type, real_part, imag_part);
06247 }
06248 }
06249
06250 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
06251 }
06252
06253 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
06254 f_fpr = TREE_CHAIN (f_gpr);
06255 f_res = TREE_CHAIN (f_fpr);
06256 f_ovf = TREE_CHAIN (f_res);
06257 f_sav = TREE_CHAIN (f_ovf);
06258
06259 valist = build_va_arg_indirect_ref (valist);
06260 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
06261 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
06262 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
06263 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
06264
06265 size = int_size_in_bytes (type);
06266 rsize = (size + 3) / 4;
06267 align = 1;
06268
06269 if (TARGET_HARD_FLOAT && TARGET_FPRS
06270 && (TYPE_MODE (type) == SFmode || TYPE_MODE (type) == DFmode))
06271 {
06272
06273 reg = fpr;
06274 n_reg = 1;
06275 sav_ofs = 8*4;
06276 sav_scale = 8;
06277 if (TYPE_MODE (type) == DFmode)
06278 align = 8;
06279 }
06280 else
06281 {
06282
06283 reg = gpr;
06284 n_reg = rsize;
06285 sav_ofs = 0;
06286 sav_scale = 4;
06287 if (n_reg == 2)
06288 align = 8;
06289 }
06290
06291
06292
06293 lab_over = NULL;
06294 addr = create_tmp_var (ptr_type_node, "addr");
06295 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
06296
06297
06298 if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
06299 align = 16;
06300 else
06301 {
06302 lab_false = create_artificial_label ();
06303 lab_over = create_artificial_label ();
06304
06305
06306
06307
06308 u = reg;
06309 if (n_reg == 2)
06310 {
06311 u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), reg,
06312 size_int (n_reg - 1));
06313 u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u);
06314 }
06315
06316 t = fold_convert (TREE_TYPE (reg), size_int (8 - n_reg + 1));
06317 t = build2 (GE_EXPR, boolean_type_node, u, t);
06318 u = build1 (GOTO_EXPR, void_type_node, lab_false);
06319 t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
06320 gimplify_and_add (t, pre_p);
06321
06322 t = sav;
06323 if (sav_ofs)
06324 t = build2 (PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
06325
06326 u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg));
06327 u = build1 (CONVERT_EXPR, integer_type_node, u);
06328 u = build2 (MULT_EXPR, integer_type_node, u, size_int (sav_scale));
06329 t = build2 (PLUS_EXPR, ptr_type_node, t, u);
06330
06331 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
06332 gimplify_and_add (t, pre_p);
06333
06334 t = build1 (GOTO_EXPR, void_type_node, lab_over);
06335 gimplify_and_add (t, pre_p);
06336
06337 t = build1 (LABEL_EXPR, void_type_node, lab_false);
06338 append_to_statement_list (t, pre_p);
06339
06340 if (n_reg > 2)
06341 {
06342
06343
06344 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, size_int (8));
06345 gimplify_and_add (t, pre_p);
06346 }
06347 }
06348
06349
06350
06351
06352 t = ovf;
06353 if (align != 1)
06354 {
06355 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
06356 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
06357 build_int_cst (NULL_TREE, -align));
06358 }
06359 gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
06360
06361 u = build2 (MODIFY_EXPR, void_type_node, addr, t);
06362 gimplify_and_add (u, pre_p);
06363
06364 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
06365 t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
06366 gimplify_and_add (t, pre_p);
06367
06368 if (lab_over)
06369 {
06370 t = build1 (LABEL_EXPR, void_type_node, lab_over);
06371 append_to_statement_list (t, pre_p);
06372 }
06373
06374 addr = fold_convert (ptrtype, addr);
06375 return build_va_arg_indirect_ref (addr);
06376 }
06377
06378
06379
06380 #define def_builtin(MASK, NAME, TYPE, CODE) \
06381 do { \
06382 if ((MASK) & target_flags) \
06383 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
06384 NULL, NULL_TREE); \
06385 } while (0)
06386
06387
06388
06389 static const struct builtin_description bdesc_3arg[] =
06390 {
06391 { MASK_ALTIVEC, CODE_FOR_altivec_vmaddfp, "__builtin_altivec_vmaddfp", ALTIVEC_BUILTIN_VMADDFP },
06392 { MASK_ALTIVEC, CODE_FOR_altivec_vmhaddshs, "__builtin_altivec_vmhaddshs", ALTIVEC_BUILTIN_VMHADDSHS },
06393 { MASK_ALTIVEC, CODE_FOR_altivec_vmhraddshs, "__builtin_altivec_vmhraddshs", ALTIVEC_BUILTIN_VMHRADDSHS },
06394 { MASK_ALTIVEC, CODE_FOR_altivec_vmladduhm, "__builtin_altivec_vmladduhm", ALTIVEC_BUILTIN_VMLADDUHM},
06395 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumubm, "__builtin_altivec_vmsumubm", ALTIVEC_BUILTIN_VMSUMUBM },
06396 { MASK_ALTIVEC, CODE_FOR_altivec_vmsummbm, "__builtin_altivec_vmsummbm", ALTIVEC_BUILTIN_VMSUMMBM },
06397 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhm, "__builtin_altivec_vmsumuhm", ALTIVEC_BUILTIN_VMSUMUHM },
06398 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshm, "__builtin_altivec_vmsumshm", ALTIVEC_BUILTIN_VMSUMSHM },
06399 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
06400 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
06401 { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
06402 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
06403 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
06404 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
06405 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
06406 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
06407 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
06408 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
06409 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
06410 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
06411 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
06412 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
06413 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
06414 };
06415
06416
06417
06418 static const struct builtin_description bdesc_dst[] =
06419 {
06420 { MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
06421 { MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
06422 { MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
06423 { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT }
06424 };
06425
06426
06427
06428 static struct builtin_description bdesc_2arg[] =
06429 {
06430 { MASK_ALTIVEC, CODE_FOR_addv16qi3, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
06431 { MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
06432 { MASK_ALTIVEC, CODE_FOR_addv4si3, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
06433 { MASK_ALTIVEC, CODE_FOR_addv4sf3, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
06434 { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
06435 { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
06436 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
06437 { MASK_ALTIVEC, CODE_FOR_altivec_vadduhs, "__builtin_altivec_vadduhs", ALTIVEC_BUILTIN_VADDUHS },
06438 { MASK_ALTIVEC, CODE_FOR_altivec_vaddshs, "__builtin_altivec_vaddshs", ALTIVEC_BUILTIN_VADDSHS },
06439 { MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
06440 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
06441 { MASK_ALTIVEC, CODE_FOR_andv4si3, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
06442 { MASK_ALTIVEC, CODE_FOR_andcv4si3, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
06443 { MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
06444 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
06445 { MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
06446 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsh, "__builtin_altivec_vavgsh", ALTIVEC_BUILTIN_VAVGSH },
06447 { MASK_ALTIVEC, CODE_FOR_altivec_vavguw, "__builtin_altivec_vavguw", ALTIVEC_BUILTIN_VAVGUW },
06448 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsw, "__builtin_altivec_vavgsw", ALTIVEC_BUILTIN_VAVGSW },
06449 { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
06450 { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
06451 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
06452 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
06453 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
06454 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
06455 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
06456 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
06457 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
06458 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
06459 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
06460 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
06461 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
06462 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
06463 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
06464 { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
06465 { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
06466 { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
06467 { MASK_ALTIVEC, CODE_FOR_smaxv16qi3, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
06468 { MASK_ALTIVEC, CODE_FOR_umaxv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
06469 { MASK_ALTIVEC, CODE_FOR_smaxv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
06470 { MASK_ALTIVEC, CODE_FOR_umaxv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
06471 { MASK_ALTIVEC, CODE_FOR_smaxv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
06472 { MASK_ALTIVEC, CODE_FOR_smaxv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
06473 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
06474 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
06475 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
06476 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, "__builtin_altivec_vmrglb", ALTIVEC_BUILTIN_VMRGLB },
06477 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, "__builtin_altivec_vmrglh", ALTIVEC_BUILTIN_VMRGLH },
06478 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, "__builtin_altivec_vmrglw", ALTIVEC_BUILTIN_VMRGLW },
06479 { MASK_ALTIVEC, CODE_FOR_uminv16qi3, "__builtin_altivec_vminub", ALTIVEC_BUILTIN_VMINUB },
06480 { MASK_ALTIVEC, CODE_FOR_sminv16qi3, "__builtin_altivec_vminsb", ALTIVEC_BUILTIN_VMINSB },
06481 { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vminuh", ALTIVEC_BUILTIN_VMINUH },
06482 { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vminsh", ALTIVEC_BUILTIN_VMINSH },
06483 { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vminuw", ALTIVEC_BUILTIN_VMINUW },
06484 { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
06485 { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
06486 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
06487 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
06488 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
06489 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
06490 { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
06491 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
06492 { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
06493 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
06494 { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
06495 { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
06496 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
06497 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
06498 { MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
06499 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhss, "__builtin_altivec_vpkuhss", ALTIVEC_BUILTIN_VPKUHSS },
06500 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
06501 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwss, "__builtin_altivec_vpkuwss", ALTIVEC_BUILTIN_VPKUWSS },
06502 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
06503 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
06504 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
06505 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
06506 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
06507 { MASK_ALTIVEC, CODE_FOR_altivec_vrlb, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
06508 { MASK_ALTIVEC, CODE_FOR_altivec_vrlh, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
06509 { MASK_ALTIVEC, CODE_FOR_altivec_vrlw, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
06510 { MASK_ALTIVEC, CODE_FOR_altivec_vslb, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
06511 { MASK_ALTIVEC, CODE_FOR_altivec_vslh, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
06512 { MASK_ALTIVEC, CODE_FOR_altivec_vslw, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
06513 { MASK_ALTIVEC, CODE_FOR_altivec_vsl, "__builtin_altivec_vsl", ALTIVEC_BUILTIN_VSL },
06514 { MASK_ALTIVEC, CODE_FOR_altivec_vslo, "__builtin_altivec_vslo", ALTIVEC_BUILTIN_VSLO },
06515 { MASK_ALTIVEC, CODE_FOR_altivec_vspltb, "__builtin_altivec_vspltb", ALTIVEC_BUILTIN_VSPLTB },
06516 { MASK_ALTIVEC, CODE_FOR_altivec_vsplth, "__builtin_altivec_vsplth", ALTIVEC_BUILTIN_VSPLTH },
06517 { MASK_ALTIVEC, CODE_FOR_altivec_vspltw, "__builtin_altivec_vspltw", ALTIVEC_BUILTIN_VSPLTW },
06518 { MASK_ALTIVEC, CODE_FOR_altivec_vsrb, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
06519 { MASK_ALTIVEC, CODE_FOR_altivec_vsrh, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
06520 { MASK_ALTIVEC, CODE_FOR_altivec_vsrw, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
06521 { MASK_ALTIVEC, CODE_FOR_altivec_vsrab, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
06522 { MASK_ALTIVEC, CODE_FOR_altivec_vsrah, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
06523 { MASK_ALTIVEC, CODE_FOR_altivec_vsraw, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
06524 { MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
06525 { MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
06526 { MASK_ALTIVEC, CODE_FOR_subv16qi3, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
06527 { MASK_ALTIVEC, CODE_FOR_subv8hi3, "__builtin_altivec_vsubuhm", ALTIVEC_BUILTIN_VSUBUHM },
06528 { MASK_ALTIVEC, CODE_FOR_subv4si3, "__builtin_altivec_vsubuwm", ALTIVEC_BUILTIN_VSUBUWM },
06529 { MASK_ALTIVEC, CODE_FOR_subv4sf3, "__builtin_altivec_vsubfp", ALTIVEC_BUILTIN_VSUBFP },
06530 { MASK_ALTIVEC, CODE_FOR_altivec_vsubcuw, "__builtin_altivec_vsubcuw", ALTIVEC_BUILTIN_VSUBCUW },
06531 { MASK_ALTIVEC, CODE_FOR_altivec_vsububs, "__builtin_altivec_vsububs", ALTIVEC_BUILTIN_VSUBUBS },
06532 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsbs, "__builtin_altivec_vsubsbs", ALTIVEC_BUILTIN_VSUBSBS },
06533 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhs, "__builtin_altivec_vsubuhs", ALTIVEC_BUILTIN_VSUBUHS },
06534 { MASK_ALTIVEC, CODE_FOR_altivec_vsubshs, "__builtin_altivec_vsubshs", ALTIVEC_BUILTIN_VSUBSHS },
06535 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuws, "__builtin_altivec_vsubuws", ALTIVEC_BUILTIN_VSUBUWS },
06536 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsws, "__builtin_altivec_vsubsws", ALTIVEC_BUILTIN_VSUBSWS },
06537 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4ubs, "__builtin_altivec_vsum4ubs", ALTIVEC_BUILTIN_VSUM4UBS },
06538 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4sbs, "__builtin_altivec_vsum4sbs", ALTIVEC_BUILTIN_VSUM4SBS },
06539 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4shs, "__builtin_altivec_vsum4shs", ALTIVEC_BUILTIN_VSUM4SHS },
06540 { MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
06541 { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
06542 { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
06543
06544
06545 { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
06546 { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
06547 { 0, CODE_FOR_spe_evandc, "__builtin_spe_evandc", SPE_BUILTIN_EVANDC },
06548 { 0, CODE_FOR_spe_evdivws, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
06549 { 0, CODE_FOR_spe_evdivwu, "__builtin_spe_evdivwu", SPE_BUILTIN_EVDIVWU },
06550 { 0, CODE_FOR_spe_eveqv, "__builtin_spe_eveqv", SPE_BUILTIN_EVEQV },
06551 { 0, CODE_FOR_spe_evfsadd, "__builtin_spe_evfsadd", SPE_BUILTIN_EVFSADD },
06552 { 0, CODE_FOR_spe_evfsdiv, "__builtin_spe_evfsdiv", SPE_BUILTIN_EVFSDIV },
06553 { 0, CODE_FOR_spe_evfsmul, "__builtin_spe_evfsmul", SPE_BUILTIN_EVFSMUL },
06554 { 0, CODE_FOR_spe_evfssub, "__builtin_spe_evfssub", SPE_BUILTIN_EVFSSUB },
06555 { 0, CODE_FOR_spe_evmergehi, "__builtin_spe_evmergehi", SPE_BUILTIN_EVMERGEHI },
06556 { 0, CODE_FOR_spe_evmergehilo, "__builtin_spe_evmergehilo", SPE_BUILTIN_EVMERGEHILO },
06557 { 0, CODE_FOR_spe_evmergelo, "__builtin_spe_evmergelo", SPE_BUILTIN_EVMERGELO },
06558 { 0, CODE_FOR_spe_evmergelohi, "__builtin_spe_evmergelohi", SPE_BUILTIN_EVMERGELOHI },
06559 { 0, CODE_FOR_spe_evmhegsmfaa, "__builtin_spe_evmhegsmfaa", SPE_BUILTIN_EVMHEGSMFAA },
06560 { 0, CODE_FOR_spe_evmhegsmfan, "__builtin_spe_evmhegsmfan", SPE_BUILTIN_EVMHEGSMFAN },
06561 { 0, CODE_FOR_spe_evmhegsmiaa, "__builtin_spe_evmhegsmiaa", SPE_BUILTIN_EVMHEGSMIAA },
06562 { 0, CODE_FOR_spe_evmhegsmian, "__builtin_spe_evmhegsmian", SPE_BUILTIN_EVMHEGSMIAN },
06563 { 0, CODE_FOR_spe_evmhegumiaa, "__builtin_spe_evmhegumiaa", SPE_BUILTIN_EVMHEGUMIAA },
06564 { 0, CODE_FOR_spe_evmhegumian, "__builtin_spe_evmhegumian", SPE_BUILTIN_EVMHEGUMIAN },
06565 { 0, CODE_FOR_spe_evmhesmf, "__builtin_spe_evmhesmf", SPE_BUILTIN_EVMHESMF },
06566 { 0, CODE_FOR_spe_evmhesmfa, "__builtin_spe_evmhesmfa", SPE_BUILTIN_EVMHESMFA },
06567 { 0, CODE_FOR_spe_evmhesmfaaw, "__builtin_spe_evmhesmfaaw", SPE_BUILTIN_EVMHESMFAAW },
06568 { 0, CODE_FOR_spe_evmhesmfanw, "__builtin_spe_evmhesmfanw", SPE_BUILTIN_EVMHESMFANW },
06569 { 0, CODE_FOR_spe_evmhesmi, "__builtin_spe_evmhesmi", SPE_BUILTIN_EVMHESMI },
06570 { 0, CODE_FOR_spe_evmhesmia, "__builtin_spe_evmhesmia", SPE_BUILTIN_EVMHESMIA },
06571 { 0, CODE_FOR_spe_evmhesmiaaw, "__builtin_spe_evmhesmiaaw", SPE_BUILTIN_EVMHESMIAAW },
06572 { 0, CODE_FOR_spe_evmhesmianw, "__builtin_spe_evmhesmianw", SPE_BUILTIN_EVMHESMIANW },
06573 { 0, CODE_FOR_spe_evmhessf, "__builtin_spe_evmhessf", SPE_BUILTIN_EVMHESSF },
06574 { 0, CODE_FOR_spe_evmhessfa, "__builtin_spe_evmhessfa", SPE_BUILTIN_EVMHESSFA },
06575 { 0, CODE_FOR_spe_evmhessfaaw, "__builtin_spe_evmhessfaaw", SPE_BUILTIN_EVMHESSFAAW },
06576 { 0, CODE_FOR_spe_evmhessfanw, "__builtin_spe_evmhessfanw", SPE_BUILTIN_EVMHESSFANW },
06577 { 0, CODE_FOR_spe_evmhessiaaw, "__builtin_spe_evmhessiaaw", SPE_BUILTIN_EVMHESSIAAW },
06578 { 0, CODE_FOR_spe_evmhessianw, "__builtin_spe_evmhessianw", SPE_BUILTIN_EVMHESSIANW },
06579 { 0, CODE_FOR_spe_evmheumi, "__builtin_spe_evmheumi", SPE_BUILTIN_EVMHEUMI },
06580 { 0, CODE_FOR_spe_evmheumia, "__builtin_spe_evmheumia", SPE_BUILTIN_EVMHEUMIA },
06581 { 0, CODE_FOR_spe_evmheumiaaw, "__builtin_spe_evmheumiaaw", SPE_BUILTIN_EVMHEUMIAAW },
06582 { 0, CODE_FOR_spe_evmheumianw, "__builtin_spe_evmheumianw", SPE_BUILTIN_EVMHEUMIANW },
06583 { 0, CODE_FOR_spe_evmheusiaaw, "__builtin_spe_evmheusiaaw", SPE_BUILTIN_EVMHEUSIAAW },
06584 { 0, CODE_FOR_spe_evmheusianw, "__builtin_spe_evmheusianw", SPE_BUILTIN_EVMHEUSIANW },
06585 { 0, CODE_FOR_spe_evmhogsmfaa, "__builtin_spe_evmhogsmfaa", SPE_BUILTIN_EVMHOGSMFAA },
06586 { 0, CODE_FOR_spe_evmhogsmfan, "__builtin_spe_evmhogsmfan", SPE_BUILTIN_EVMHOGSMFAN },
06587 { 0, CODE_FOR_spe_evmhogsmiaa, "__builtin_spe_evmhogsmiaa", SPE_BUILTIN_EVMHOGSMIAA },
06588 { 0, CODE_FOR_spe_evmhogsmian, "__builtin_spe_evmhogsmian", SPE_BUILTIN_EVMHOGSMIAN },
06589 { 0, CODE_FOR_spe_evmhogumiaa, "__builtin_spe_evmhogumiaa", SPE_BUILTIN_EVMHOGUMIAA },
06590 { 0, CODE_FOR_spe_evmhogumian, "__builtin_spe_evmhogumian", SPE_BUILTIN_EVMHOGUMIAN },
06591 { 0, CODE_FOR_spe_evmhosmf, "__builtin_spe_evmhosmf", SPE_BUILTIN_EVMHOSMF },
06592 { 0, CODE_FOR_spe_evmhosmfa, "__builtin_spe_evmhosmfa", SPE_BUILTIN_EVMHOSMFA },
06593 { 0, CODE_FOR_spe_evmhosmfaaw, "__builtin_spe_evmhosmfaaw", SPE_BUILTIN_EVMHOSMFAAW },
06594 { 0, CODE_FOR_spe_evmhosmfanw, "__builtin_spe_evmhosmfanw", SPE_BUILTIN_EVMHOSMFANW },
06595 { 0, CODE_FOR_spe_evmhosmi, "__builtin_spe_evmhosmi", SPE_BUILTIN_EVMHOSMI },
06596 { 0, CODE_FOR_spe_evmhosmia, "__builtin_spe_evmhosmia", SPE_BUILTIN_EVMHOSMIA },
06597 { 0, CODE_FOR_spe_evmhosmiaaw, "__builtin_spe_evmhosmiaaw", SPE_BUILTIN_EVMHOSMIAAW },
06598 { 0, CODE_FOR_spe_evmhosmianw, "__builtin_spe_evmhosmianw", SPE_BUILTIN_EVMHOSMIANW },
06599 { 0, CODE_FOR_spe_evmhossf, "__builtin_spe_evmhossf", SPE_BUILTIN_EVMHOSSF },
06600 { 0, CODE_FOR_spe_evmhossfa, "__builtin_spe_evmhossfa", SPE_BUILTIN_EVMHOSSFA },
06601 { 0, CODE_FOR_spe_evmhossfaaw, "__builtin_spe_evmhossfaaw", SPE_BUILTIN_EVMHOSSFAAW },
06602 { 0, CODE_FOR_spe_evmhossfanw, "__builtin_spe_evmhossfanw", SPE_BUILTIN_EVMHOSSFANW },
06603 { 0, CODE_FOR_spe_evmhossiaaw, "__builtin_spe_evmhossiaaw", SPE_BUILTIN_EVMHOSSIAAW },
06604 { 0, CODE_FOR_spe_evmhossianw, "__builtin_spe_evmhossianw", SPE_BUILTIN_EVMHOSSIANW },
06605 { 0, CODE_FOR_spe_evmhoumi, "__builtin_spe_evmhoumi", SPE_BUILTIN_EVMHOUMI },
06606 { 0, CODE_FOR_spe_evmhoumia, "__builtin_spe_evmhoumia", SPE_BUILTIN_EVMHOUMIA },
06607 { 0, CODE_FOR_spe_evmhoumiaaw, "__builtin_spe_evmhoumiaaw", SPE_BUILTIN_EVMHOUMIAAW },
06608 { 0, CODE_FOR_spe_evmhoumianw, "__builtin_spe_evmhoumianw", SPE_BUILTIN_EVMHOUMIANW },
06609 { 0, CODE_FOR_spe_evmhousiaaw, "__builtin_spe_evmhousiaaw", SPE_BUILTIN_EVMHOUSIAAW },
06610 { 0, CODE_FOR_spe_evmhousianw, "__builtin_spe_evmhousianw", SPE_BUILTIN_EVMHOUSIANW },
06611 { 0, CODE_FOR_spe_evmwhsmf, "__builtin_spe_evmwhsmf", SPE_BUILTIN_EVMWHSMF },
06612 { 0, CODE_FOR_spe_evmwhsmfa, "__builtin_spe_evmwhsmfa", SPE_BUILTIN_EVMWHSMFA },
06613 { 0, CODE_FOR_spe_evmwhsmi, "__builtin_spe_evmwhsmi", SPE_BUILTIN_EVMWHSMI },
06614 { 0, CODE_FOR_spe_evmwhsmia, "__builtin_spe_evmwhsmia", SPE_BUILTIN_EVMWHSMIA },
06615 { 0, CODE_FOR_spe_evmwhssf, "__builtin_spe_evmwhssf", SPE_BUILTIN_EVMWHSSF },
06616 { 0, CODE_FOR_spe_evmwhssfa, "__builtin_spe_evmwhssfa", SPE_BUILTIN_EVMWHSSFA },
06617 { 0, CODE_FOR_spe_evmwhumi, "__builtin_spe_evmwhumi", SPE_BUILTIN_EVMWHUMI },
06618 { 0, CODE_FOR_spe_evmwhumia, "__builtin_spe_evmwhumia", SPE_BUILTIN_EVMWHUMIA },
06619 { 0, CODE_FOR_spe_evmwlsmiaaw, "__builtin_spe_evmwlsmiaaw", SPE_BUILTIN_EVMWLSMIAAW },
06620 { 0, CODE_FOR_spe_evmwlsmianw, "__builtin_spe_evmwlsmianw", SPE_BUILTIN_EVMWLSMIANW },
06621 { 0, CODE_FOR_spe_evmwlssiaaw, "__builtin_spe_evmwlssiaaw", SPE_BUILTIN_EVMWLSSIAAW },
06622 { 0, CODE_FOR_spe_evmwlssianw, "__builtin_spe_evmwlssianw", SPE_BUILTIN_EVMWLSSIANW },
06623 { 0, CODE_FOR_spe_evmwlumi, "__builtin_spe_evmwlumi", SPE_BUILTIN_EVMWLUMI },
06624 { 0, CODE_FOR_spe_evmwlumia, "__builtin_spe_evmwlumia", SPE_BUILTIN_EVMWLUMIA },
06625 { 0, CODE_FOR_spe_evmwlumiaaw, "__builtin_spe_evmwlumiaaw", SPE_BUILTIN_EVMWLUMIAAW },
06626 { 0, CODE_FOR_spe_evmwlumianw, "__builtin_spe_evmwlumianw", SPE_BUILTIN_EVMWLUMIANW },
06627 { 0, CODE_FOR_spe_evmwlusiaaw, "__builtin_spe_evmwlusiaaw", SPE_BUILTIN_EVMWLUSIAAW },
06628 { 0, CODE_FOR_spe_evmwlusianw, "__builtin_spe_evmwlusianw", SPE_BUILTIN_EVMWLUSIANW },
06629 { 0, CODE_FOR_spe_evmwsmf, "__builtin_spe_evmwsmf", SPE_BUILTIN_EVMWSMF },
06630 { 0, CODE_FOR_spe_evmwsmfa, "__builtin_spe_evmwsmfa", SPE_BUILTIN_EVMWSMFA },
06631 { 0, CODE_FOR_spe_evmwsmfaa, "__builtin_spe_evmwsmfaa", SPE_BUILTIN_EVMWSMFAA },
06632 { 0, CODE_FOR_spe_evmwsmfan, "__builtin_spe_evmwsmfan", SPE_BUILTIN_EVMWSMFAN },
06633 { 0, CODE_FOR_spe_evmwsmi, "__builtin_spe_evmwsmi", SPE_BUILTIN_EVMWSMI },
06634 { 0, CODE_FOR_spe_evmwsmia, "__builtin_spe_evmwsmia", SPE_BUILTIN_EVMWSMIA },
06635 { 0, CODE_FOR_spe_evmwsmiaa, "__builtin_spe_evmwsmiaa", SPE_BUILTIN_EVMWSMIAA },
06636 { 0, CODE_FOR_spe_evmwsmian, "__builtin_spe_evmwsmian", SPE_BUILTIN_EVMWSMIAN },
06637 { 0, CODE_FOR_spe_evmwssf, "__builtin_spe_evmwssf", SPE_BUILTIN_EVMWSSF },
06638 { 0, CODE_FOR_spe_evmwssfa, "__builtin_spe_evmwssfa", SPE_BUILTIN_EVMWSSFA },
06639 { 0, CODE_FOR_spe_evmwssfaa, "__builtin_spe_evmwssfaa", SPE_BUILTIN_EVMWSSFAA },
06640 { 0, CODE_FOR_spe_evmwssfan, "__builtin_spe_evmwssfan", SPE_BUILTIN_EVMWSSFAN },
06641 { 0, CODE_FOR_spe_evmwumi, "__builtin_spe_evmwumi", SPE_BUILTIN_EVMWUMI },
06642 { 0, CODE_FOR_spe_evmwumia, "__builtin_spe_evmwumia", SPE_BUILTIN_EVMWUMIA },
06643 { 0, CODE_FOR_spe_evmwumiaa, "__builtin_spe_evmwumiaa", SPE_BUILTIN_EVMWUMIAA },
06644 { 0, CODE_FOR_spe_evmwumian, "__builtin_spe_evmwumian", SPE_BUILTIN_EVMWUMIAN },
06645 { 0, CODE_FOR_spe_evnand, "__builtin_spe_evnand", SPE_BUILTIN_EVNAND },
06646 { 0, CODE_FOR_spe_evnor, "__builtin_spe_evnor", SPE_BUILTIN_EVNOR },
06647 { 0, CODE_FOR_spe_evor, "__builtin_spe_evor", SPE_BUILTIN_EVOR },
06648 { 0, CODE_FOR_spe_evorc, "__builtin_spe_evorc", SPE_BUILTIN_EVORC },
06649 { 0, CODE_FOR_spe_evrlw, "__builtin_spe_evrlw", SPE_BUILTIN_EVRLW },
06650 { 0, CODE_FOR_spe_evslw, "__builtin_spe_evslw", SPE_BUILTIN_EVSLW },
06651 { 0, CODE_FOR_spe_evsrws, "__builtin_spe_evsrws", SPE_BUILTIN_EVSRWS },
06652 { 0, CODE_FOR_spe_evsrwu, "__builtin_spe_evsrwu", SPE_BUILTIN_EVSRWU },
06653 { 0, CODE_FOR_spe_evsubfw, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
06654
06655
06656 { 0, CODE_FOR_spe_evaddiw, "__builtin_spe_evaddiw", SPE_BUILTIN_EVADDIW },
06657
06658 { 0, CODE_FOR_spe_evrlwi, "__builtin_spe_evrlwi", SPE_BUILTIN_EVRLWI },
06659 { 0, CODE_FOR_spe_evslwi, "__builtin_spe_evslwi", SPE_BUILTIN_EVSLWI },
06660 { 0, CODE_FOR_spe_evsrwis, "__builtin_spe_evsrwis", SPE_BUILTIN_EVSRWIS },
06661 { 0, CODE_FOR_spe_evsrwiu, "__builtin_spe_evsrwiu", SPE_BUILTIN_EVSRWIU },
06662 { 0, CODE_FOR_spe_evsubifw, "__builtin_spe_evsubifw", SPE_BUILTIN_EVSUBIFW },
06663 { 0, CODE_FOR_spe_evmwhssfaa, "__builtin_spe_evmwhssfaa", SPE_BUILTIN_EVMWHSSFAA },
06664 { 0, CODE_FOR_spe_evmwhssmaa, "__builtin_spe_evmwhssmaa", SPE_BUILTIN_EVMWHSSMAA },
06665 { 0, CODE_FOR_spe_evmwhsmfaa, "__builtin_spe_evmwhsmfaa", SPE_BUILTIN_EVMWHSMFAA },
06666 { 0, CODE_FOR_spe_evmwhsmiaa, "__builtin_spe_evmwhsmiaa", SPE_BUILTIN_EVMWHSMIAA },
06667 { 0, CODE_FOR_spe_evmwhusiaa, "__builtin_spe_evmwhusiaa", SPE_BUILTIN_EVMWHUSIAA },
06668 { 0, CODE_FOR_spe_evmwhumiaa, "__builtin_spe_evmwhumiaa", SPE_BUILTIN_EVMWHUMIAA },
06669 { 0, CODE_FOR_spe_evmwhssfan, "__builtin_spe_evmwhssfan", SPE_BUILTIN_EVMWHSSFAN },
06670 { 0, CODE_FOR_spe_evmwhssian, "__builtin_spe_evmwhssian", SPE_BUILTIN_EVMWHSSIAN },
06671 { 0, CODE_FOR_spe_evmwhsmfan, "__builtin_spe_evmwhsmfan", SPE_BUILTIN_EVMWHSMFAN },
06672 { 0, CODE_FOR_spe_evmwhsmian, "__builtin_spe_evmwhsmian", SPE_BUILTIN_EVMWHSMIAN },
06673 { 0, CODE_FOR_spe_evmwhusian, "__builtin_spe_evmwhusian", SPE_BUILTIN_EVMWHUSIAN },
06674 { 0, CODE_FOR_spe_evmwhumian, "__builtin_spe_evmwhumian", SPE_BUILTIN_EVMWHUMIAN },
06675 { 0, CODE_FOR_spe_evmwhgssfaa, "__builtin_spe_evmwhgssfaa", SPE_BUILTIN_EVMWHGSSFAA },
06676 { 0, CODE_FOR_spe_evmwhgsmfaa, "__builtin_spe_evmwhgsmfaa", SPE_BUILTIN_EVMWHGSMFAA },
06677 { 0, CODE_FOR_spe_evmwhgsmiaa, "__builtin_spe_evmwhgsmiaa", SPE_BUILTIN_EVMWHGSMIAA },
06678 { 0, CODE_FOR_spe_evmwhgumiaa, "__builtin_spe_evmwhgumiaa", SPE_BUILTIN_EVMWHGUMIAA },
06679 { 0, CODE_FOR_spe_evmwhgssfan, "__builtin_spe_evmwhgssfan", SPE_BUILTIN_EVMWHGSSFAN },
06680 { 0, CODE_FOR_spe_evmwhgsmfan, "__builtin_spe_evmwhgsmfan", SPE_BUILTIN_EVMWHGSMFAN },
06681 { 0, CODE_FOR_spe_evmwhgsmian, "__builtin_spe_evmwhgsmian", SPE_BUILTIN_EVMWHGSMIAN },
06682 { 0, CODE_FOR_spe_evmwhgumian, "__builtin_spe_evmwhgumian", SPE_BUILTIN_EVMWHGUMIAN },
06683 { 0, CODE_FOR_spe_brinc, "__builtin_spe_brinc", SPE_BUILTIN_BRINC },
06684
06685
06686 { 0, CODE_FOR_xorv2si3, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR },
06687 };
06688
06689
06690
06691 struct builtin_description_predicates
06692 {
06693 const unsigned int mask;
06694 const enum insn_code icode;
06695 const char *opcode;
06696 const char *const name;
06697 const enum rs6000_builtins code;
06698 };
06699
06700 static const struct builtin_description_predicates bdesc_altivec_preds[] =
06701 {
06702 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpbfp.", "__builtin_altivec_vcmpbfp_p", ALTIVEC_BUILTIN_VCMPBFP_P },
06703 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpeqfp.", "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
06704 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgefp.", "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
06705 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgtfp.", "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
06706 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpequw.", "__builtin_altivec_vcmpequw_p", ALTIVEC_BUILTIN_VCMPEQUW_P },
06707 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtsw.", "__builtin_altivec_vcmpgtsw_p", ALTIVEC_BUILTIN_VCMPGTSW_P },
06708 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtuw.", "__builtin_altivec_vcmpgtuw_p", ALTIVEC_BUILTIN_VCMPGTUW_P },
06709 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtuh.", "__builtin_altivec_vcmpgtuh_p", ALTIVEC_BUILTIN_VCMPGTUH_P },
06710 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtsh.", "__builtin_altivec_vcmpgtsh_p", ALTIVEC_BUILTIN_VCMPGTSH_P },
06711 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpequh.", "__builtin_altivec_vcmpequh_p", ALTIVEC_BUILTIN_VCMPEQUH_P },
06712 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpequb.", "__builtin_altivec_vcmpequb_p", ALTIVEC_BUILTIN_VCMPEQUB_P },
06713 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtsb.", "__builtin_altivec_vcmpgtsb_p", ALTIVEC_BUILTIN_VCMPGTSB_P },
06714 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P }
06715 };
06716
06717
06718 static struct builtin_description bdesc_spe_predicates[] =
06719 {
06720
06721 { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evcmpeq", SPE_BUILTIN_EVCMPEQ },
06722 { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evcmpgts", SPE_BUILTIN_EVCMPGTS },
06723 { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evcmpgtu", SPE_BUILTIN_EVCMPGTU },
06724 { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evcmplts", SPE_BUILTIN_EVCMPLTS },
06725 { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evcmpltu", SPE_BUILTIN_EVCMPLTU },
06726 { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evfscmpeq", SPE_BUILTIN_EVFSCMPEQ },
06727 { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evfscmpgt", SPE_BUILTIN_EVFSCMPGT },
06728 { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evfscmplt", SPE_BUILTIN_EVFSCMPLT },
06729 { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evfststeq", SPE_BUILTIN_EVFSTSTEQ },
06730 { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evfststgt", SPE_BUILTIN_EVFSTSTGT },
06731
06732 { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evfststlt", SPE_BUILTIN_EVFSTSTLT },
06733 };
06734
06735
06736 static struct builtin_description bdesc_spe_evsel[] =
06737 {
06738
06739 { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evsel_gts", SPE_BUILTIN_EVSEL_CMPGTS },
06740 { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evsel_gtu", SPE_BUILTIN_EVSEL_CMPGTU },
06741 { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evsel_lts", SPE_BUILTIN_EVSEL_CMPLTS },
06742 { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evsel_ltu", SPE_BUILTIN_EVSEL_CMPLTU },
06743 { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evsel_eq", SPE_BUILTIN_EVSEL_CMPEQ },
06744 { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evsel_fsgt", SPE_BUILTIN_EVSEL_FSCMPGT },
06745 { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evsel_fslt", SPE_BUILTIN_EVSEL_FSCMPLT },
06746 { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evsel_fseq", SPE_BUILTIN_EVSEL_FSCMPEQ },
06747 { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evsel_fststgt", SPE_BUILTIN_EVSEL_FSTSTGT },
06748 { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evsel_fststlt", SPE_BUILTIN_EVSEL_FSTSTLT },
06749
06750 { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ },
06751 };
06752
06753
06754
06755 static const struct builtin_description bdesc_abs[] =
06756 {
06757 { MASK_ALTIVEC, CODE_FOR_absv4si2, "__builtin_altivec_abs_v4si", ALTIVEC_BUILTIN_ABS_V4SI },
06758 { MASK_ALTIVEC, CODE_FOR_absv8hi2, "__builtin_altivec_abs_v8hi", ALTIVEC_BUILTIN_ABS_V8HI },
06759 { MASK_ALTIVEC, CODE_FOR_absv4sf2, "__builtin_altivec_abs_v4sf", ALTIVEC_BUILTIN_ABS_V4SF },
06760 { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
06761 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
06762 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
06763 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
06764 };
06765
06766
06767
06768
06769 static struct builtin_description bdesc_1arg[] =
06770 {
06771 { MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
06772 { MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
06773 { MASK_ALTIVEC, CODE_FOR_altivec_vrefp, "__builtin_altivec_vrefp", ALTIVEC_BUILTIN_VREFP },
06774 { MASK_ALTIVEC, CODE_FOR_altivec_vrfim, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
06775 { MASK_ALTIVEC, CODE_FOR_altivec_vrfin, "__builtin_altivec_vrfin", ALTIVEC_BUILTIN_VRFIN },
06776 { MASK_ALTIVEC, CODE_FOR_altivec_vrfip, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
06777 { MASK_ALTIVEC, CODE_FOR_ftruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
06778 { MASK_ALTIVEC, CODE_FOR_altivec_vrsqrtefp, "__builtin_altivec_vrsqrtefp", ALTIVEC_BUILTIN_VRSQRTEFP },
06779 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisb, "__builtin_altivec_vspltisb", ALTIVEC_BUILTIN_VSPLTISB },
06780 { MASK_ALTIVEC, CODE_FOR_altivec_vspltish, "__builtin_altivec_vspltish", ALTIVEC_BUILTIN_VSPLTISH },
06781 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisw, "__builtin_altivec_vspltisw", ALTIVEC_BUILTIN_VSPLTISW },
06782 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsb, "__builtin_altivec_vupkhsb", ALTIVEC_BUILTIN_VUPKHSB },
06783 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhpx, "__builtin_altivec_vupkhpx", ALTIVEC_BUILTIN_VUPKHPX },
06784 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsh, "__builtin_altivec_vupkhsh", ALTIVEC_BUILTIN_VUPKHSH },
06785 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsb, "__builtin_altivec_vupklsb", ALTIVEC_BUILTIN_VUPKLSB },
06786 { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
06787 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
06788
06789
06790
06791 { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
06792 { 0, CODE_FOR_spe_evaddsmiaaw, "__builtin_spe_evaddsmiaaw", SPE_BUILTIN_EVADDSMIAAW },
06793 { 0, CODE_FOR_spe_evaddssiaaw, "__builtin_spe_evaddssiaaw", SPE_BUILTIN_EVADDSSIAAW },
06794 { 0, CODE_FOR_spe_evaddumiaaw, "__builtin_spe_evaddumiaaw", SPE_BUILTIN_EVADDUMIAAW },
06795 { 0, CODE_FOR_spe_evaddusiaaw, "__builtin_spe_evaddusiaaw", SPE_BUILTIN_EVADDUSIAAW },
06796 { 0, CODE_FOR_spe_evcntlsw, "__builtin_spe_evcntlsw", SPE_BUILTIN_EVCNTLSW },
06797 { 0, CODE_FOR_spe_evcntlzw, "__builtin_spe_evcntlzw", SPE_BUILTIN_EVCNTLZW },
06798 { 0, CODE_FOR_spe_evextsb, "__builtin_spe_evextsb", SPE_BUILTIN_EVEXTSB },
06799 { 0, CODE_FOR_spe_evextsh, "__builtin_spe_evextsh", SPE_BUILTIN_EVEXTSH },
06800 { 0, CODE_FOR_spe_evfsabs, "__builtin_spe_evfsabs", SPE_BUILTIN_EVFSABS },
06801 { 0, CODE_FOR_spe_evfscfsf, "__builtin_spe_evfscfsf", SPE_BUILTIN_EVFSCFSF },
06802 { 0, CODE_FOR_spe_evfscfsi, "__builtin_spe_evfscfsi", SPE_BUILTIN_EVFSCFSI },
06803 { 0, CODE_FOR_spe_evfscfuf, "__builtin_spe_evfscfuf", SPE_BUILTIN_EVFSCFUF },
06804 { 0, CODE_FOR_spe_evfscfui, "__builtin_spe_evfscfui", SPE_BUILTIN_EVFSCFUI },
06805 { 0, CODE_FOR_spe_evfsctsf, "__builtin_spe_evfsctsf", SPE_BUILTIN_EVFSCTSF },
06806 { 0, CODE_FOR_spe_evfsctsi, "__builtin_spe_evfsctsi", SPE_BUILTIN_EVFSCTSI },
06807 { 0, CODE_FOR_spe_evfsctsiz, "__builtin_spe_evfsctsiz", SPE_BUILTIN_EVFSCTSIZ },
06808 { 0, CODE_FOR_spe_evfsctuf, "__builtin_spe_evfsctuf", SPE_BUILTIN_EVFSCTUF },
06809 { 0, CODE_FOR_spe_evfsctui, "__builtin_spe_evfsctui", SPE_BUILTIN_EVFSCTUI },
06810 { 0, CODE_FOR_spe_evfsctuiz, "__builtin_spe_evfsctuiz", SPE_BUILTIN_EVFSCTUIZ },
06811 { 0, CODE_FOR_spe_evfsnabs, "__builtin_spe_evfsnabs", SPE_BUILTIN_EVFSNABS },
06812 { 0, CODE_FOR_spe_evfsneg, "__builtin_spe_evfsneg", SPE_BUILTIN_EVFSNEG },
06813 { 0, CODE_FOR_spe_evmra, "__builtin_spe_evmra", SPE_BUILTIN_EVMRA },
06814 { 0, CODE_FOR_negv2si2, "__builtin_spe_evneg", SPE_BUILTIN_EVNEG },
06815 { 0, CODE_FOR_spe_evrndw, "__builtin_spe_evrndw", SPE_BUILTIN_EVRNDW },
06816 { 0, CODE_FOR_spe_evsubfsmiaaw, "__builtin_spe_evsubfsmiaaw", SPE_BUILTIN_EVSUBFSMIAAW },
06817 { 0, CODE_FOR_spe_evsubfssiaaw, "__builtin_spe_evsubfssiaaw", SPE_BUILTIN_EVSUBFSSIAAW },
06818 { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
06819
06820
06821 { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
06822 };
06823
06824 static rtx
06825 rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target)
06826 {
06827 rtx pat;
06828 tree arg0 = TREE_VALUE (arglist);
06829 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
06830 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06831 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06832
06833 if (icode == CODE_FOR_nothing)
06834
06835 return 0;
06836
06837
06838 if (arg0 == error_mark_node)
06839 return const0_rtx;
06840
06841 if (icode == CODE_FOR_altivec_vspltisb
06842 || icode == CODE_FOR_altivec_vspltish
06843 || icode == CODE_FOR_altivec_vspltisw
06844 || icode == CODE_FOR_spe_evsplatfi
06845 || icode == CODE_FOR_spe_evsplati)
06846 {
06847
06848 if (GET_CODE (op0) != CONST_INT
06849 || INTVAL (op0) > 0x1f
06850 || INTVAL (op0) < -0x1f)
06851 {
06852 error ("argument 1 must be a 5-bit signed literal");
06853 return const0_rtx;
06854 }
06855 }
06856
06857 if (target == 0
06858 || GET_MODE (target) != tmode
06859 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06860 target = gen_reg_rtx (tmode);
06861
06862 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06863 op0 = copy_to_mode_reg (mode0, op0);
06864
06865 pat = GEN_FCN (icode) (target, op0);
06866 if (! pat)
06867 return 0;
06868 emit_insn (pat);
06869
06870 return target;
06871 }
06872
06873 static rtx
06874 altivec_expand_abs_builtin (enum insn_code icode, tree arglist, rtx target)
06875 {
06876 rtx pat, scratch1, scratch2;
06877 tree arg0 = TREE_VALUE (arglist);
06878 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
06879 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06880 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06881
06882
06883 if (arg0 == error_mark_node)
06884 return const0_rtx;
06885
06886 if (target == 0
06887 || GET_MODE (target) != tmode
06888 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06889 target = gen_reg_rtx (tmode);
06890
06891 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06892 op0 = copy_to_mode_reg (mode0, op0);
06893
06894 scratch1 = gen_reg_rtx (mode0);
06895 scratch2 = gen_reg_rtx (mode0);
06896
06897 pat = GEN_FCN (icode) (target, op0, scratch1, scratch2);
06898 if (! pat)
06899 return 0;
06900 emit_insn (pat);
06901
06902 return target;
06903 }
06904
06905 static rtx
06906 rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
06907 {
06908 rtx pat;
06909 tree arg0 = TREE_VALUE (arglist);
06910 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
06911 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
06912 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
06913 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06914 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06915 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
06916
06917 if (icode == CODE_FOR_nothing)
06918
06919 return 0;
06920
06921
06922 if (arg0 == error_mark_node || arg1 == error_mark_node)
06923 return const0_rtx;
06924
06925 if (icode == CODE_FOR_altivec_vcfux
06926 || icode == CODE_FOR_altivec_vcfsx
06927 || icode == CODE_FOR_altivec_vctsxs
06928 || icode == CODE_FOR_altivec_vctuxs
06929 || icode == CODE_FOR_altivec_vspltb
06930 || icode == CODE_FOR_altivec_vsplth
06931 || icode == CODE_FOR_altivec_vspltw
06932 || icode == CODE_FOR_spe_evaddiw
06933 || icode == CODE_FOR_spe_evldd
06934 || icode == CODE_FOR_spe_evldh
06935 || icode == CODE_FOR_spe_evldw
06936 || icode == CODE_FOR_spe_evlhhesplat
06937 || icode == CODE_FOR_spe_evlhhossplat
06938 || icode == CODE_FOR_spe_evlhhousplat
06939 || icode == CODE_FOR_spe_evlwhe
06940 || icode == CODE_FOR_spe_evlwhos
06941 || icode == CODE_FOR_spe_evlwhou
06942 || icode == CODE_FOR_spe_evlwhsplat
06943 || icode == CODE_FOR_spe_evlwwsplat
06944 || icode == CODE_FOR_spe_evrlwi
06945 || icode == CODE_FOR_spe_evslwi
06946 || icode == CODE_FOR_spe_evsrwis
06947 || icode == CODE_FOR_spe_evsubifw
06948 || icode == CODE_FOR_spe_evsrwiu)
06949 {
06950
06951 STRIP_NOPS (arg1);
06952 if (TREE_CODE (arg1) != INTEGER_CST
06953 || TREE_INT_CST_LOW (arg1) & ~0x1f)
06954 {
06955 error ("argument 2 must be a 5-bit unsigned literal");
06956 return const0_rtx;
06957 }
06958 }
06959
06960 if (target == 0
06961 || GET_MODE (target) != tmode
06962 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
06963 target = gen_reg_rtx (tmode);
06964
06965 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
06966 op0 = copy_to_mode_reg (mode0, op0);
06967 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
06968 op1 = copy_to_mode_reg (mode1, op1);
06969
06970 pat = GEN_FCN (icode) (target, op0, op1);
06971 if (! pat)
06972 return 0;
06973 emit_insn (pat);
06974
06975 return target;
06976 }
06977
06978 static rtx
06979 altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
06980 tree arglist, rtx target)
06981 {
06982 rtx pat, scratch;
06983 tree cr6_form = TREE_VALUE (arglist);
06984 tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
06985 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
06986 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
06987 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
06988 enum machine_mode tmode = SImode;
06989 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
06990 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
06991 int cr6_form_int;
06992
06993 if (TREE_CODE (cr6_form) != INTEGER_CST)
06994 {
06995 error ("argument 1 of __builtin_altivec_predicate must be a constant");
06996 return const0_rtx;
06997 }
06998 else
06999 cr6_form_int = TREE_INT_CST_LOW (cr6_form);
07000
07001 if (mode0 != mode1)
07002 abort ();
07003
07004
07005 if (arg0 == error_mark_node || arg1 == error_mark_node)
07006 return const0_rtx;
07007
07008 if (target == 0
07009 || GET_MODE (target) != tmode
07010 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07011 target = gen_reg_rtx (tmode);
07012
07013 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07014 op0 = copy_to_mode_reg (mode0, op0);
07015 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
07016 op1 = copy_to_mode_reg (mode1, op1);
07017
07018 scratch = gen_reg_rtx (mode0);
07019
07020 pat = GEN_FCN (icode) (scratch, op0, op1,
07021 gen_rtx_SYMBOL_REF (Pmode, opcode));
07022 if (! pat)
07023 return 0;
07024 emit_insn (pat);
07025
07026
07027
07028
07029
07030
07031
07032
07033
07034 switch (cr6_form_int)
07035 {
07036 case 0:
07037 emit_insn (gen_cr6_test_for_zero (target));
07038 break;
07039 case 1:
07040 emit_insn (gen_cr6_test_for_zero_reverse (target));
07041 break;
07042 case 2:
07043 emit_insn (gen_cr6_test_for_lt (target));
07044 break;
07045 case 3:
07046 emit_insn (gen_cr6_test_for_lt_reverse (target));
07047 break;
07048 default:
07049 error ("argument 1 of __builtin_altivec_predicate is out of range");
07050 break;
07051 }
07052
07053 return target;
07054 }
07055
07056 static rtx
07057 altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target)
07058 {
07059 rtx pat, addr;
07060 tree arg0 = TREE_VALUE (arglist);
07061 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07062 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07063 enum machine_mode mode0 = Pmode;
07064 enum machine_mode mode1 = Pmode;
07065 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07066 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07067
07068 if (icode == CODE_FOR_nothing)
07069
07070 return 0;
07071
07072
07073 if (arg0 == error_mark_node || arg1 == error_mark_node)
07074 return const0_rtx;
07075
07076 if (target == 0
07077 || GET_MODE (target) != tmode
07078 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07079 target = gen_reg_rtx (tmode);
07080
07081 op1 = copy_to_mode_reg (mode1, op1);
07082
07083 if (op0 == const0_rtx)
07084 {
07085 addr = gen_rtx_MEM (tmode, op1);
07086 }
07087 else
07088 {
07089 op0 = copy_to_mode_reg (mode0, op0);
07090 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1));
07091 }
07092
07093 pat = GEN_FCN (icode) (target, addr);
07094
07095 if (! pat)
07096 return 0;
07097 emit_insn (pat);
07098
07099 return target;
07100 }
07101
07102 static rtx
07103 spe_expand_stv_builtin (enum insn_code icode, tree arglist)
07104 {
07105 tree arg0 = TREE_VALUE (arglist);
07106 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07107 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07108 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07109 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07110 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
07111 rtx pat;
07112 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
07113 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
07114 enum machine_mode mode2 = insn_data[icode].operand[2].mode;
07115
07116
07117 if (arg0 == error_mark_node
07118 || arg1 == error_mark_node
07119 || arg2 == error_mark_node)
07120 return const0_rtx;
07121
07122 if (! (*insn_data[icode].operand[2].predicate) (op0, mode2))
07123 op0 = copy_to_mode_reg (mode2, op0);
07124 if (! (*insn_data[icode].operand[0].predicate) (op1, mode0))
07125 op1 = copy_to_mode_reg (mode0, op1);
07126 if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
07127 op2 = copy_to_mode_reg (mode1, op2);
07128
07129 pat = GEN_FCN (icode) (op1, op2, op0);
07130 if (pat)
07131 emit_insn (pat);
07132 return NULL_RTX;
07133 }
07134
07135 static rtx
07136 altivec_expand_stv_builtin (enum insn_code icode, tree arglist)
07137 {
07138 tree arg0 = TREE_VALUE (arglist);
07139 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07140 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07141 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07142 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07143 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
07144 rtx pat, addr;
07145 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07146 enum machine_mode mode1 = Pmode;
07147 enum machine_mode mode2 = Pmode;
07148
07149
07150 if (arg0 == error_mark_node
07151 || arg1 == error_mark_node
07152 || arg2 == error_mark_node)
07153 return const0_rtx;
07154
07155 if (! (*insn_data[icode].operand[1].predicate) (op0, tmode))
07156 op0 = copy_to_mode_reg (tmode, op0);
07157
07158 op2 = copy_to_mode_reg (mode2, op2);
07159
07160 if (op1 == const0_rtx)
07161 {
07162 addr = gen_rtx_MEM (tmode, op2);
07163 }
07164 else
07165 {
07166 op1 = copy_to_mode_reg (mode1, op1);
07167 addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
07168 }
07169
07170 pat = GEN_FCN (icode) (addr, op0);
07171 if (pat)
07172 emit_insn (pat);
07173 return NULL_RTX;
07174 }
07175
07176 static rtx
07177 rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target)
07178 {
07179 rtx pat;
07180 tree arg0 = TREE_VALUE (arglist);
07181 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07182 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07183 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07184 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07185 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
07186 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07187 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07188 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07189 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
07190
07191 if (icode == CODE_FOR_nothing)
07192
07193 return 0;
07194
07195
07196 if (arg0 == error_mark_node
07197 || arg1 == error_mark_node
07198 || arg2 == error_mark_node)
07199 return const0_rtx;
07200
07201 if (icode == CODE_FOR_altivec_vsldoi_v4sf
07202 || icode == CODE_FOR_altivec_vsldoi_v4si
07203 || icode == CODE_FOR_altivec_vsldoi_v8hi
07204 || icode == CODE_FOR_altivec_vsldoi_v16qi)
07205 {
07206
07207 STRIP_NOPS (arg2);
07208 if (TREE_CODE (arg2) != INTEGER_CST
07209 || TREE_INT_CST_LOW (arg2) & ~0xf)
07210 {
07211 error ("argument 3 must be a 4-bit unsigned literal");
07212 return const0_rtx;
07213 }
07214 }
07215
07216 if (target == 0
07217 || GET_MODE (target) != tmode
07218 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07219 target = gen_reg_rtx (tmode);
07220
07221 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07222 op0 = copy_to_mode_reg (mode0, op0);
07223 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
07224 op1 = copy_to_mode_reg (mode1, op1);
07225 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
07226 op2 = copy_to_mode_reg (mode2, op2);
07227
07228 pat = GEN_FCN (icode) (target, op0, op1, op2);
07229 if (! pat)
07230 return 0;
07231 emit_insn (pat);
07232
07233 return target;
07234 }
07235
07236
07237 static rtx
07238 altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
07239 {
07240 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07241 tree arglist = TREE_OPERAND (exp, 1);
07242 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07243 tree arg0;
07244 enum machine_mode tmode, mode0;
07245 rtx pat, op0;
07246 enum insn_code icode;
07247
07248 switch (fcode)
07249 {
07250 case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
07251 icode = CODE_FOR_altivec_lvx_v16qi;
07252 break;
07253 case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
07254 icode = CODE_FOR_altivec_lvx_v8hi;
07255 break;
07256 case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
07257 icode = CODE_FOR_altivec_lvx_v4si;
07258 break;
07259 case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
07260 icode = CODE_FOR_altivec_lvx_v4sf;
07261 break;
07262 default:
07263 *expandedp = false;
07264 return NULL_RTX;
07265 }
07266
07267 *expandedp = true;
07268
07269 arg0 = TREE_VALUE (arglist);
07270 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07271 tmode = insn_data[icode].operand[0].mode;
07272 mode0 = insn_data[icode].operand[1].mode;
07273
07274 if (target == 0
07275 || GET_MODE (target) != tmode
07276 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07277 target = gen_reg_rtx (tmode);
07278
07279 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07280 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
07281
07282 pat = GEN_FCN (icode) (target, op0);
07283 if (! pat)
07284 return 0;
07285 emit_insn (pat);
07286 return target;
07287 }
07288
07289
07290 static rtx
07291 altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
07292 bool *expandedp)
07293 {
07294 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07295 tree arglist = TREE_OPERAND (exp, 1);
07296 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07297 tree arg0, arg1;
07298 enum machine_mode mode0, mode1;
07299 rtx pat, op0, op1;
07300 enum insn_code icode;
07301
07302 switch (fcode)
07303 {
07304 case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
07305 icode = CODE_FOR_altivec_stvx_v16qi;
07306 break;
07307 case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
07308 icode = CODE_FOR_altivec_stvx_v8hi;
07309 break;
07310 case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
07311 icode = CODE_FOR_altivec_stvx_v4si;
07312 break;
07313 case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
07314 icode = CODE_FOR_altivec_stvx_v4sf;
07315 break;
07316 default:
07317 *expandedp = false;
07318 return NULL_RTX;
07319 }
07320
07321 arg0 = TREE_VALUE (arglist);
07322 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07323 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07324 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07325 mode0 = insn_data[icode].operand[0].mode;
07326 mode1 = insn_data[icode].operand[1].mode;
07327
07328 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07329 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
07330 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
07331 op1 = copy_to_mode_reg (mode1, op1);
07332
07333 pat = GEN_FCN (icode) (op0, op1);
07334 if (pat)
07335 emit_insn (pat);
07336
07337 *expandedp = true;
07338 return NULL_RTX;
07339 }
07340
07341
07342 static rtx
07343 altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
07344 bool *expandedp)
07345 {
07346 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07347 tree arglist = TREE_OPERAND (exp, 1);
07348 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07349 tree arg0, arg1, arg2;
07350 enum machine_mode mode0, mode1, mode2;
07351 rtx pat, op0, op1, op2;
07352 struct builtin_description *d;
07353 size_t i;
07354
07355 *expandedp = false;
07356
07357
07358 d = (struct builtin_description *) bdesc_dst;
07359 for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
07360 if (d->code == fcode)
07361 {
07362 arg0 = TREE_VALUE (arglist);
07363 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07364 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07365 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07366 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07367 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
07368 mode0 = insn_data[d->icode].operand[0].mode;
07369 mode1 = insn_data[d->icode].operand[1].mode;
07370 mode2 = insn_data[d->icode].operand[2].mode;
07371
07372
07373 if (arg0 == error_mark_node
07374 || arg1 == error_mark_node
07375 || arg2 == error_mark_node)
07376 return const0_rtx;
07377
07378 *expandedp = true;
07379 STRIP_NOPS (arg2);
07380 if (TREE_CODE (arg2) != INTEGER_CST
07381 || TREE_INT_CST_LOW (arg2) & ~0x3)
07382 {
07383 error ("argument to %qs must be a 2-bit unsigned literal", d->name);
07384 return const0_rtx;
07385 }
07386
07387 if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
07388 op0 = copy_to_mode_reg (Pmode, op0);
07389 if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
07390 op1 = copy_to_mode_reg (mode1, op1);
07391
07392 pat = GEN_FCN (d->icode) (op0, op1, op2);
07393 if (pat != 0)
07394 emit_insn (pat);
07395
07396 return NULL_RTX;
07397 }
07398
07399 return NULL_RTX;
07400 }
07401
07402
07403
07404 static rtx
07405 altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
07406 {
07407 struct builtin_description *d;
07408 struct builtin_description_predicates *dp;
07409 size_t i;
07410 enum insn_code icode;
07411 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07412 tree arglist = TREE_OPERAND (exp, 1);
07413 tree arg0;
07414 rtx op0, pat;
07415 enum machine_mode tmode, mode0;
07416 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07417
07418 target = altivec_expand_ld_builtin (exp, target, expandedp);
07419 if (*expandedp)
07420 return target;
07421
07422 target = altivec_expand_st_builtin (exp, target, expandedp);
07423 if (*expandedp)
07424 return target;
07425
07426 target = altivec_expand_dst_builtin (exp, target, expandedp);
07427 if (*expandedp)
07428 return target;
07429
07430 *expandedp = true;
07431
07432 switch (fcode)
07433 {
07434 case ALTIVEC_BUILTIN_STVX:
07435 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist);
07436 case ALTIVEC_BUILTIN_STVEBX:
07437 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, arglist);
07438 case ALTIVEC_BUILTIN_STVEHX:
07439 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, arglist);
07440 case ALTIVEC_BUILTIN_STVEWX:
07441 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist);
07442 case ALTIVEC_BUILTIN_STVXL:
07443 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist);
07444
07445 case ALTIVEC_BUILTIN_MFVSCR:
07446 icode = CODE_FOR_altivec_mfvscr;
07447 tmode = insn_data[icode].operand[0].mode;
07448
07449 if (target == 0
07450 || GET_MODE (target) != tmode
07451 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07452 target = gen_reg_rtx (tmode);
07453
07454 pat = GEN_FCN (icode) (target);
07455 if (! pat)
07456 return 0;
07457 emit_insn (pat);
07458 return target;
07459
07460 case ALTIVEC_BUILTIN_MTVSCR:
07461 icode = CODE_FOR_altivec_mtvscr;
07462 arg0 = TREE_VALUE (arglist);
07463 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07464 mode0 = insn_data[icode].operand[0].mode;
07465
07466
07467 if (arg0 == error_mark_node)
07468 return const0_rtx;
07469
07470 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07471 op0 = copy_to_mode_reg (mode0, op0);
07472
07473 pat = GEN_FCN (icode) (op0);
07474 if (pat)
07475 emit_insn (pat);
07476 return NULL_RTX;
07477
07478 case ALTIVEC_BUILTIN_DSSALL:
07479 emit_insn (gen_altivec_dssall ());
07480 return NULL_RTX;
07481
07482 case ALTIVEC_BUILTIN_DSS:
07483 icode = CODE_FOR_altivec_dss;
07484 arg0 = TREE_VALUE (arglist);
07485 STRIP_NOPS (arg0);
07486 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07487 mode0 = insn_data[icode].operand[0].mode;
07488
07489
07490 if (arg0 == error_mark_node)
07491 return const0_rtx;
07492
07493 if (TREE_CODE (arg0) != INTEGER_CST
07494 || TREE_INT_CST_LOW (arg0) & ~0x3)
07495 {
07496 error ("argument to dss must be a 2-bit unsigned literal");
07497 return const0_rtx;
07498 }
07499
07500 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07501 op0 = copy_to_mode_reg (mode0, op0);
07502
07503 emit_insn (gen_altivec_dss (op0));
07504 return NULL_RTX;
07505
07506 case ALTIVEC_BUILTIN_COMPILETIME_ERROR:
07507 arg0 = TREE_VALUE (arglist);
07508 while (TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == ADDR_EXPR
07509 || TREE_CODE (arg0) == ARRAY_REF)
07510 arg0 = TREE_OPERAND (arg0, 0);
07511 error ("invalid parameter combination for %qs AltiVec intrinsic",
07512 TREE_STRING_POINTER (arg0));
07513
07514 return const0_rtx;
07515 }
07516
07517
07518 d = (struct builtin_description *) bdesc_abs;
07519 for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
07520 if (d->code == fcode)
07521 return altivec_expand_abs_builtin (d->icode, arglist, target);
07522
07523
07524 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
07525 for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
07526 if (dp->code == fcode)
07527 return altivec_expand_predicate_builtin (dp->icode, dp->opcode,
07528 arglist, target);
07529
07530
07531 switch (fcode)
07532 {
07533 case ALTIVEC_BUILTIN_LVSL:
07534 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl,
07535 arglist, target);
07536 case ALTIVEC_BUILTIN_LVSR:
07537 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr,
07538 arglist, target);
07539 case ALTIVEC_BUILTIN_LVEBX:
07540 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx,
07541 arglist, target);
07542 case ALTIVEC_BUILTIN_LVEHX:
07543 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx,
07544 arglist, target);
07545 case ALTIVEC_BUILTIN_LVEWX:
07546 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx,
07547 arglist, target);
07548 case ALTIVEC_BUILTIN_LVXL:
07549 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl,
07550 arglist, target);
07551 case ALTIVEC_BUILTIN_LVX:
07552 return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx,
07553 arglist, target);
07554 default:
07555 break;
07556
07557 }
07558
07559 *expandedp = false;
07560 return NULL_RTX;
07561 }
07562
07563
07564
07565 static struct builtin_description bdesc_2arg_spe[] =
07566 {
07567 { 0, CODE_FOR_spe_evlddx, "__builtin_spe_evlddx", SPE_BUILTIN_EVLDDX },
07568 { 0, CODE_FOR_spe_evldwx, "__builtin_spe_evldwx", SPE_BUILTIN_EVLDWX },
07569 { 0, CODE_FOR_spe_evldhx, "__builtin_spe_evldhx", SPE_BUILTIN_EVLDHX },
07570 { 0, CODE_FOR_spe_evlwhex, "__builtin_spe_evlwhex", SPE_BUILTIN_EVLWHEX },
07571 { 0, CODE_FOR_spe_evlwhoux, "__builtin_spe_evlwhoux", SPE_BUILTIN_EVLWHOUX },
07572 { 0, CODE_FOR_spe_evlwhosx, "__builtin_spe_evlwhosx", SPE_BUILTIN_EVLWHOSX },
07573 { 0, CODE_FOR_spe_evlwwsplatx, "__builtin_spe_evlwwsplatx", SPE_BUILTIN_EVLWWSPLATX },
07574 { 0, CODE_FOR_spe_evlwhsplatx, "__builtin_spe_evlwhsplatx", SPE_BUILTIN_EVLWHSPLATX },
07575 { 0, CODE_FOR_spe_evlhhesplatx, "__builtin_spe_evlhhesplatx", SPE_BUILTIN_EVLHHESPLATX },
07576 { 0, CODE_FOR_spe_evlhhousplatx, "__builtin_spe_evlhhousplatx", SPE_BUILTIN_EVLHHOUSPLATX },
07577 { 0, CODE_FOR_spe_evlhhossplatx, "__builtin_spe_evlhhossplatx", SPE_BUILTIN_EVLHHOSSPLATX },
07578 { 0, CODE_FOR_spe_evldd, "__builtin_spe_evldd", SPE_BUILTIN_EVLDD },
07579 { 0, CODE_FOR_spe_evldw, "__builtin_spe_evldw", SPE_BUILTIN_EVLDW },
07580 { 0, CODE_FOR_spe_evldh, "__builtin_spe_evldh", SPE_BUILTIN_EVLDH },
07581 { 0, CODE_FOR_spe_evlwhe, "__builtin_spe_evlwhe", SPE_BUILTIN_EVLWHE },
07582 { 0, CODE_FOR_spe_evlwhou, "__builtin_spe_evlwhou", SPE_BUILTIN_EVLWHOU },
07583 { 0, CODE_FOR_spe_evlwhos, "__builtin_spe_evlwhos", SPE_BUILTIN_EVLWHOS },
07584 { 0, CODE_FOR_spe_evlwwsplat, "__builtin_spe_evlwwsplat", SPE_BUILTIN_EVLWWSPLAT },
07585 { 0, CODE_FOR_spe_evlwhsplat, "__builtin_spe_evlwhsplat", SPE_BUILTIN_EVLWHSPLAT },
07586 { 0, CODE_FOR_spe_evlhhesplat, "__builtin_spe_evlhhesplat", SPE_BUILTIN_EVLHHESPLAT },
07587 { 0, CODE_FOR_spe_evlhhousplat, "__builtin_spe_evlhhousplat", SPE_BUILTIN_EVLHHOUSPLAT },
07588 { 0, CODE_FOR_spe_evlhhossplat, "__builtin_spe_evlhhossplat", SPE_BUILTIN_EVLHHOSSPLAT }
07589 };
07590
07591
07592
07593
07594
07595
07596 static rtx
07597 spe_expand_builtin (tree exp, rtx target, bool *expandedp)
07598 {
07599 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07600 tree arglist = TREE_OPERAND (exp, 1);
07601 tree arg1, arg0;
07602 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07603 enum insn_code icode;
07604 enum machine_mode tmode, mode0;
07605 rtx pat, op0;
07606 struct builtin_description *d;
07607 size_t i;
07608
07609 *expandedp = true;
07610
07611
07612 switch (fcode)
07613 {
07614 case SPE_BUILTIN_EVSTDD:
07615 case SPE_BUILTIN_EVSTDH:
07616 case SPE_BUILTIN_EVSTDW:
07617 case SPE_BUILTIN_EVSTWHE:
07618 case SPE_BUILTIN_EVSTWHO:
07619 case SPE_BUILTIN_EVSTWWE:
07620 case SPE_BUILTIN_EVSTWWO:
07621 arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07622 if (TREE_CODE (arg1) != INTEGER_CST
07623 || TREE_INT_CST_LOW (arg1) & ~0x1f)
07624 {
07625 error ("argument 2 must be a 5-bit unsigned literal");
07626 return const0_rtx;
07627 }
07628 break;
07629 default:
07630 break;
07631 }
07632
07633
07634 switch (fcode)
07635 {
07636 case SPE_BUILTIN_EVSPLATFI:
07637 return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplatfi,
07638 arglist, target);
07639 case SPE_BUILTIN_EVSPLATI:
07640 return rs6000_expand_unop_builtin (CODE_FOR_spe_evsplati,
07641 arglist, target);
07642 default:
07643 break;
07644 }
07645
07646 d = (struct builtin_description *) bdesc_2arg_spe;
07647 for (i = 0; i < ARRAY_SIZE (bdesc_2arg_spe); ++i, ++d)
07648 if (d->code == fcode)
07649 return rs6000_expand_binop_builtin (d->icode, arglist, target);
07650
07651 d = (struct builtin_description *) bdesc_spe_predicates;
07652 for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, ++d)
07653 if (d->code == fcode)
07654 return spe_expand_predicate_builtin (d->icode, arglist, target);
07655
07656 d = (struct builtin_description *) bdesc_spe_evsel;
07657 for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, ++d)
07658 if (d->code == fcode)
07659 return spe_expand_evsel_builtin (d->icode, arglist, target);
07660
07661 switch (fcode)
07662 {
07663 case SPE_BUILTIN_EVSTDDX:
07664 return spe_expand_stv_builtin (CODE_FOR_spe_evstddx, arglist);
07665 case SPE_BUILTIN_EVSTDHX:
07666 return spe_expand_stv_builtin (CODE_FOR_spe_evstdhx, arglist);
07667 case SPE_BUILTIN_EVSTDWX:
07668 return spe_expand_stv_builtin (CODE_FOR_spe_evstdwx, arglist);
07669 case SPE_BUILTIN_EVSTWHEX:
07670 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhex, arglist);
07671 case SPE_BUILTIN_EVSTWHOX:
07672 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhox, arglist);
07673 case SPE_BUILTIN_EVSTWWEX:
07674 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwex, arglist);
07675 case SPE_BUILTIN_EVSTWWOX:
07676 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwox, arglist);
07677 case SPE_BUILTIN_EVSTDD:
07678 return spe_expand_stv_builtin (CODE_FOR_spe_evstdd, arglist);
07679 case SPE_BUILTIN_EVSTDH:
07680 return spe_expand_stv_builtin (CODE_FOR_spe_evstdh, arglist);
07681 case SPE_BUILTIN_EVSTDW:
07682 return spe_expand_stv_builtin (CODE_FOR_spe_evstdw, arglist);
07683 case SPE_BUILTIN_EVSTWHE:
07684 return spe_expand_stv_builtin (CODE_FOR_spe_evstwhe, arglist);
07685 case SPE_BUILTIN_EVSTWHO:
07686 return spe_expand_stv_builtin (CODE_FOR_spe_evstwho, arglist);
07687 case SPE_BUILTIN_EVSTWWE:
07688 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwe, arglist);
07689 case SPE_BUILTIN_EVSTWWO:
07690 return spe_expand_stv_builtin (CODE_FOR_spe_evstwwo, arglist);
07691 case SPE_BUILTIN_MFSPEFSCR:
07692 icode = CODE_FOR_spe_mfspefscr;
07693 tmode = insn_data[icode].operand[0].mode;
07694
07695 if (target == 0
07696 || GET_MODE (target) != tmode
07697 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
07698 target = gen_reg_rtx (tmode);
07699
07700 pat = GEN_FCN (icode) (target);
07701 if (! pat)
07702 return 0;
07703 emit_insn (pat);
07704 return target;
07705 case SPE_BUILTIN_MTSPEFSCR:
07706 icode = CODE_FOR_spe_mtspefscr;
07707 arg0 = TREE_VALUE (arglist);
07708 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07709 mode0 = insn_data[icode].operand[0].mode;
07710
07711 if (arg0 == error_mark_node)
07712 return const0_rtx;
07713
07714 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
07715 op0 = copy_to_mode_reg (mode0, op0);
07716
07717 pat = GEN_FCN (icode) (op0);
07718 if (pat)
07719 emit_insn (pat);
07720 return NULL_RTX;
07721 default:
07722 break;
07723 }
07724
07725 *expandedp = false;
07726 return NULL_RTX;
07727 }
07728
07729 static rtx
07730 spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target)
07731 {
07732 rtx pat, scratch, tmp;
07733 tree form = TREE_VALUE (arglist);
07734 tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
07735 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07736 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07737 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07738 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07739 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07740 int form_int;
07741 enum rtx_code code;
07742
07743 if (TREE_CODE (form) != INTEGER_CST)
07744 {
07745 error ("argument 1 of __builtin_spe_predicate must be a constant");
07746 return const0_rtx;
07747 }
07748 else
07749 form_int = TREE_INT_CST_LOW (form);
07750
07751 if (mode0 != mode1)
07752 abort ();
07753
07754 if (arg0 == error_mark_node || arg1 == error_mark_node)
07755 return const0_rtx;
07756
07757 if (target == 0
07758 || GET_MODE (target) != SImode
07759 || ! (*insn_data[icode].operand[0].predicate) (target, SImode))
07760 target = gen_reg_rtx (SImode);
07761
07762 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07763 op0 = copy_to_mode_reg (mode0, op0);
07764 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
07765 op1 = copy_to_mode_reg (mode1, op1);
07766
07767 scratch = gen_reg_rtx (CCmode);
07768
07769 pat = GEN_FCN (icode) (scratch, op0, op1);
07770 if (! pat)
07771 return const0_rtx;
07772 emit_insn (pat);
07773
07774
07775
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788
07789
07790
07791
07792
07793
07794
07795 switch (form_int)
07796 {
07797
07798 case 0:
07799
07800
07801
07802
07803 emit_insn (gen_move_from_CR_ov_bit (target, scratch));
07804 return target;
07805
07806 case 1:
07807 code = EQ;
07808 break;
07809
07810 case 2:
07811 code = LT;
07812 break;
07813
07814 case 3:
07815 code = GT;
07816 break;
07817 default:
07818 error ("argument 1 of __builtin_spe_predicate is out of range");
07819 return const0_rtx;
07820 }
07821
07822 tmp = gen_rtx_fmt_ee (code, SImode, scratch, const0_rtx);
07823 emit_move_insn (target, tmp);
07824
07825 return target;
07826 }
07827
07828
07829
07830
07831
07832
07833
07834
07835
07836
07837
07838 static rtx
07839 spe_expand_evsel_builtin (enum insn_code icode, tree arglist, rtx target)
07840 {
07841 rtx pat, scratch;
07842 tree arg0 = TREE_VALUE (arglist);
07843 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07844 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07845 tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
07846 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
07847 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
07848 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
07849 rtx op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
07850 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
07851 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
07852
07853 if (mode0 != mode1)
07854 abort ();
07855
07856 if (arg0 == error_mark_node || arg1 == error_mark_node
07857 || arg2 == error_mark_node || arg3 == error_mark_node)
07858 return const0_rtx;
07859
07860 if (target == 0
07861 || GET_MODE (target) != mode0
07862 || ! (*insn_data[icode].operand[0].predicate) (target, mode0))
07863 target = gen_reg_rtx (mode0);
07864
07865 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
07866 op0 = copy_to_mode_reg (mode0, op0);
07867 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
07868 op1 = copy_to_mode_reg (mode0, op1);
07869 if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
07870 op2 = copy_to_mode_reg (mode0, op2);
07871 if (! (*insn_data[icode].operand[1].predicate) (op3, mode1))
07872 op3 = copy_to_mode_reg (mode0, op3);
07873
07874
07875 scratch = gen_reg_rtx (CCmode);
07876 pat = GEN_FCN (icode) (scratch, op0, op1);
07877 if (! pat)
07878 return const0_rtx;
07879 emit_insn (pat);
07880
07881 if (mode0 == V2SImode)
07882 emit_insn (gen_spe_evsel (target, op2, op3, scratch));
07883 else
07884 emit_insn (gen_spe_evsel_fs (target, op2, op3, scratch));
07885
07886 return target;
07887 }
07888
07889
07890
07891
07892
07893
07894
07895 static rtx
07896 rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
07897 enum machine_mode mode ATTRIBUTE_UNUSED,
07898 int ignore ATTRIBUTE_UNUSED)
07899 {
07900 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
07901 tree arglist = TREE_OPERAND (exp, 1);
07902 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
07903 struct builtin_description *d;
07904 size_t i;
07905 rtx ret;
07906 bool success;
07907
07908 if (fcode == ALTIVEC_BUILTIN_MASK_FOR_LOAD
07909 || fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
07910 {
07911 int icode = (int) CODE_FOR_altivec_lvsr;
07912 enum machine_mode tmode = insn_data[icode].operand[0].mode;
07913 enum machine_mode mode = insn_data[icode].operand[1].mode;
07914 tree arg;
07915 rtx op, addr, pat;
07916
07917 if (!TARGET_ALTIVEC)
07918 abort ();
07919
07920 arg = TREE_VALUE (arglist);
07921 if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
07922 abort ();
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 if (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
07986 abort ();
07987 return NULL_RTX;
07988 }
07989
07990 static tree
07991 build_opaque_vector_type (tree node, int nunits)
07992 {
07993 node = copy_node (node);
07994 TYPE_MAIN_VARIANT (node) = node;
07995 return build_vector_type (node, nunits);
07996 }
07997
07998 static void
07999 rs6000_init_builtins (void)
08000 {
08001 V2SI_type_node = build_vector_type (intSI_type_node, 2);
08002 V2SF_type_node = build_vector_type (float_type_node, 2);
08003 V4HI_type_node = build_vector_type (intHI_type_node, 4);
08004 V4SI_type_node = build_vector_type (intSI_type_node, 4);
08005 V4SF_type_node = build_vector_type (float_type_node, 4);
08006 V8HI_type_node = build_vector_type (intHI_type_node, 8);
08007 V16QI_type_node = build_vector_type (intQI_type_node, 16);
08008
08009 unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
08010 unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
08011 unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
08012
08013 opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2);
08014 opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2);
08015 opaque_p_V2SI_type_node = build_pointer_type (opaque_V2SI_type_node);
08016
08017
08018
08019
08020
08021 bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
08022 bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
08023 bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
08024 pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
08025
08026 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08027 get_identifier ("__bool char"),
08028 bool_char_type_node));
08029 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08030 get_identifier ("__bool short"),
08031 bool_short_type_node));
08032 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08033 get_identifier ("__bool int"),
08034 bool_int_type_node));
08035 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08036 get_identifier ("__pixel"),
08037 pixel_type_node));
08038
08039 bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16);
08040 bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8);
08041 bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
08042 pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
08043
08044 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08045 get_identifier ("__vector unsigned char"),
08046 unsigned_V16QI_type_node));
08047 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08048 get_identifier ("__vector signed char"),
08049 V16QI_type_node));
08050 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08051 get_identifier ("__vector __bool char"),
08052 bool_V16QI_type_node));
08053
08054 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08055 get_identifier ("__vector unsigned short"),
08056 unsigned_V8HI_type_node));
08057 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08058 get_identifier ("__vector signed short"),
08059 V8HI_type_node));
08060 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08061 get_identifier ("__vector __bool short"),
08062 bool_V8HI_type_node));
08063
08064 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08065 get_identifier ("__vector unsigned int"),
08066 unsigned_V4SI_type_node));
08067 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08068 get_identifier ("__vector signed int"),
08069 V4SI_type_node));
08070 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08071 get_identifier ("__vector __bool int"),
08072 bool_V4SI_type_node));
08073
08074 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08075 get_identifier ("__vector float"),
08076 V4SF_type_node));
08077 (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
08078 get_identifier ("__vector __pixel"),
08079 pixel_V8HI_type_node));
08080
08081 if (TARGET_SPE)
08082 spe_init_builtins ();
08083 if (TARGET_ALTIVEC)
08084 altivec_init_builtins ();
08085 if (TARGET_ALTIVEC || TARGET_SPE)
08086 rs6000_common_init_builtins ();
08087 }
08088
08089
08090
08091
08092
08093
08094 static void
08095 enable_mask_for_builtins (struct builtin_description *desc, int size,
08096 enum rs6000_builtins start,
08097 enum rs6000_builtins end)
08098 {
08099 int i;
08100
08101 for (i = 0; i < size; ++i)
08102 if (desc[i].code == start)
08103 break;
08104
08105 if (i == size)
08106 return;
08107
08108 for (; i < size; ++i)
08109 {
08110
08111 desc[i].mask = target_flags;
08112 if (desc[i].code == end)
08113 break;
08114 }
08115 }
08116
08117 static void
08118 spe_init_builtins (void)
08119 {
08120 tree endlink = void_list_node;
08121 tree puint_type_node = build_pointer_type (unsigned_type_node);
08122 tree pushort_type_node = build_pointer_type (short_unsigned_type_node);
08123 struct builtin_description *d;
08124 size_t i;
08125
08126 tree v2si_ftype_4_v2si
08127 = build_function_type
08128 (opaque_V2SI_type_node,
08129 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08130 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08131 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08132 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08133 endlink)))));
08134
08135 tree v2sf_ftype_4_v2sf
08136 = build_function_type
08137 (opaque_V2SF_type_node,
08138 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08139 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08140 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08141 tree_cons (NULL_TREE, opaque_V2SF_type_node,
08142 endlink)))));
08143
08144 tree int_ftype_int_v2si_v2si
08145 = build_function_type
08146 (integer_type_node,
08147 tree_cons (NULL_TREE, integer_type_node,
08148 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08149 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08150 endlink))));
08151
08152 tree int_ftype_int_v2sf_v2sf
08153 = build_function_type
08154 (integer_type_node,
08155 tree_cons (NULL_TREE, integer_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 void_ftype_v2si_puint_int
08161 = build_function_type (void_type_node,
08162 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08163 tree_cons (NULL_TREE, puint_type_node,
08164 tree_cons (NULL_TREE,
08165 integer_type_node,
08166 endlink))));
08167
08168 tree void_ftype_v2si_puint_char
08169 = build_function_type (void_type_node,
08170 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08171 tree_cons (NULL_TREE, puint_type_node,
08172 tree_cons (NULL_TREE,
08173 char_type_node,
08174 endlink))));
08175
08176 tree void_ftype_v2si_pv2si_int
08177 = build_function_type (void_type_node,
08178 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08179 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08180 tree_cons (NULL_TREE,
08181 integer_type_node,
08182 endlink))));
08183
08184 tree void_ftype_v2si_pv2si_char
08185 = build_function_type (void_type_node,
08186 tree_cons (NULL_TREE, opaque_V2SI_type_node,
08187 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08188 tree_cons (NULL_TREE,
08189 char_type_node,
08190 endlink))));
08191
08192 tree void_ftype_int
08193 = build_function_type (void_type_node,
08194 tree_cons (NULL_TREE, integer_type_node, endlink));
08195
08196 tree int_ftype_void
08197 = build_function_type (integer_type_node, endlink);
08198
08199 tree v2si_ftype_pv2si_int
08200 = build_function_type (opaque_V2SI_type_node,
08201 tree_cons (NULL_TREE, opaque_p_V2SI_type_node,
08202 tree_cons (NULL_TREE, integer_type_node,
08203 endlink)));
08204
08205 tree v2si_ftype_puint_int
08206 = build_function_type (opaque_V2SI_type_node,
08207 tree_cons (NULL_TREE, puint_type_node,
08208 tree_cons (NULL_TREE, integer_type_node,
08209 endlink)));
08210
08211 tree v2si_ftype_pushort_int
08212 = build_function_type (opaque_V2SI_type_node,
08213 tree_cons (NULL_TREE, pushort_type_node,
08214 tree_cons (NULL_TREE, integer_type_node,
08215 endlink)));
08216
08217 tree v2si_ftype_signed_char
08218 = build_function_type (opaque_V2SI_type_node,
08219 tree_cons (NULL_TREE, signed_char_type_node,
08220 endlink));
08221
08222
08223
08224
08225
08226
08227 enable_mask_for_builtins ((struct builtin_description *) bdesc_2arg,
08228 ARRAY_SIZE (bdesc_2arg),
08229 SPE_BUILTIN_EVADDW,
08230 SPE_BUILTIN_EVXOR);
08231 enable_mask_for_builtins ((struct builtin_description *) bdesc_1arg,
08232 ARRAY_SIZE (bdesc_1arg),
08233 SPE_BUILTIN_EVABS,
08234 SPE_BUILTIN_EVSUBFUSIAAW);
08235 enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_predicates,
08236 ARRAY_SIZE (bdesc_spe_predicates),
08237 SPE_BUILTIN_EVCMPEQ,
08238 SPE_BUILTIN_EVFSTSTLT);
08239 enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_evsel,
08240 ARRAY_SIZE (bdesc_spe_evsel),
08241 SPE_BUILTIN_EVSEL_CMPGTS,
08242 SPE_BUILTIN_EVSEL_FSTSTEQ);
08243
08244 (*lang_hooks.decls.pushdecl)
08245 (build_decl (TYPE_DECL, get_identifier ("__ev64_opaque__"),
08246 opaque_V2SI_type_node));
08247
08248
08249
08250 def_builtin (target_flags, "__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
08251 def_builtin (target_flags, "__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
08252 def_builtin (target_flags, "__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
08253 def_builtin (target_flags, "__builtin_spe_evstdhx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDHX);
08254 def_builtin (target_flags, "__builtin_spe_evstdwx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDWX);
08255 def_builtin (target_flags, "__builtin_spe_evstwhex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHEX);
08256 def_builtin (target_flags, "__builtin_spe_evstwhox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHOX);
08257 def_builtin (target_flags, "__builtin_spe_evstwwex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWEX);
08258 def_builtin (target_flags, "__builtin_spe_evstwwox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWOX);
08259 def_builtin (target_flags, "__builtin_spe_evstdd", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDD);
08260 def_builtin (target_flags, "__builtin_spe_evstdh", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDH);
08261 def_builtin (target_flags, "__builtin_spe_evstdw", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDW);
08262 def_builtin (target_flags, "__builtin_spe_evstwhe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHE);
08263 def_builtin (target_flags, "__builtin_spe_evstwho", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHO);
08264 def_builtin (target_flags, "__builtin_spe_evstwwe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWE);
08265 def_builtin (target_flags, "__builtin_spe_evstwwo", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWO);
08266 def_builtin (target_flags, "__builtin_spe_evsplatfi", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATFI);
08267 def_builtin (target_flags, "__builtin_spe_evsplati", v2si_ftype_signed_char, SPE_BUILTIN_EVSPLATI);
08268
08269
08270 def_builtin (target_flags, "__builtin_spe_evlddx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDDX);
08271 def_builtin (target_flags, "__builtin_spe_evldwx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDWX);
08272 def_builtin (target_flags, "__builtin_spe_evldhx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDHX);
08273 def_builtin (target_flags, "__builtin_spe_evlwhex", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHEX);
08274 def_builtin (target_flags, "__builtin_spe_evlwhoux", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOUX);
08275 def_builtin (target_flags, "__builtin_spe_evlwhosx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOSX);
08276 def_builtin (target_flags, "__builtin_spe_evlwwsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLATX);
08277 def_builtin (target_flags, "__builtin_spe_evlwhsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLATX);
08278 def_builtin (target_flags, "__builtin_spe_evlhhesplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLATX);
08279 def_builtin (target_flags, "__builtin_spe_evlhhousplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLATX);
08280 def_builtin (target_flags, "__builtin_spe_evlhhossplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLATX);
08281 def_builtin (target_flags, "__builtin_spe_evldd", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDD);
08282 def_builtin (target_flags, "__builtin_spe_evldw", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDW);
08283 def_builtin (target_flags, "__builtin_spe_evldh", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDH);
08284 def_builtin (target_flags, "__builtin_spe_evlhhesplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLAT);
08285 def_builtin (target_flags, "__builtin_spe_evlhhossplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLAT);
08286 def_builtin (target_flags, "__builtin_spe_evlhhousplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLAT);
08287 def_builtin (target_flags, "__builtin_spe_evlwhe", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHE);
08288 def_builtin (target_flags, "__builtin_spe_evlwhos", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOS);
08289 def_builtin (target_flags, "__builtin_spe_evlwhou", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOU);
08290 def_builtin (target_flags, "__builtin_spe_evlwhsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLAT);
08291 def_builtin (target_flags, "__builtin_spe_evlwwsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLAT);
08292
08293
08294 d = (struct builtin_description *) bdesc_spe_predicates;
08295 for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, d++)
08296 {
08297 tree type;
08298
08299 switch (insn_data[d->icode].operand[1].mode)
08300 {
08301 case V2SImode:
08302 type = int_ftype_int_v2si_v2si;
08303 break;
08304 case V2SFmode:
08305 type = int_ftype_int_v2sf_v2sf;
08306 break;
08307 default:
08308 abort ();
08309 }
08310
08311 def_builtin (d->mask, d->name, type, d->code);
08312 }
08313
08314
08315 d = (struct builtin_description *) bdesc_spe_evsel;
08316 for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, d++)
08317 {
08318 tree type;
08319
08320 switch (insn_data[d->icode].operand[1].mode)
08321 {
08322 case V2SImode:
08323 type = v2si_ftype_4_v2si;
08324 break;
08325 case V2SFmode:
08326 type = v2sf_ftype_4_v2sf;
08327 break;
08328 default:
08329 abort ();
08330 }
08331
08332 def_builtin (d->mask, d->name, type, d->code);
08333 }
08334 }
08335
08336 static void
08337 altivec_init_builtins (void)
08338 {
08339 struct builtin_description *d;
08340 struct builtin_description_predicates *dp;
08341 size_t i;
08342 tree pfloat_type_node = build_pointer_type (float_type_node);
08343 tree pint_type_node = build_pointer_type (integer_type_node);
08344 tree pshort_type_node = build_pointer_type (short_integer_type_node);
08345 tree pchar_type_node = build_pointer_type (char_type_node);
08346
08347 tree pvoid_type_node = build_pointer_type (void_type_node);
08348
08349 tree pcfloat_type_node = build_pointer_type (build_qualified_type (float_type_node, TYPE_QUAL_CONST));
08350 tree pcint_type_node = build_pointer_type (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
08351 tree pcshort_type_node = build_pointer_type (build_qualified_type (short_integer_type_node, TYPE_QUAL_CONST));
08352 tree pcchar_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
08353
08354 tree pcvoid_type_node = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
08355
08356 tree int_ftype_int_v4si_v4si
08357 = build_function_type_list (integer_type_node,
08358 integer_type_node, V4SI_type_node,
08359 V4SI_type_node, NULL_TREE);
08360 tree v4sf_ftype_pcfloat
08361 = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
08362 tree void_ftype_pfloat_v4sf
08363 = build_function_type_list (void_type_node,
08364 pfloat_type_node, V4SF_type_node, NULL_TREE);
08365 tree v4si_ftype_pcint
08366 = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
08367 tree void_ftype_pint_v4si
08368 = build_function_type_list (void_type_node,
08369 pint_type_node, V4SI_type_node, NULL_TREE);
08370 tree v8hi_ftype_pcshort
08371 = build_function_type_list (V8HI_type_node, pcshort_type_node, NULL_TREE);
08372 tree void_ftype_pshort_v8hi
08373 = build_function_type_list (void_type_node,
08374 pshort_type_node, V8HI_type_node, NULL_TREE);
08375 tree v16qi_ftype_pcchar
08376 = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
08377 tree void_ftype_pchar_v16qi
08378 = build_function_type_list (void_type_node,
08379 pchar_type_node, V16QI_type_node, NULL_TREE);
08380 tree void_ftype_v4si
08381 = build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE);
08382 tree v8hi_ftype_void
08383 = build_function_type (V8HI_type_node, void_list_node);
08384 tree void_ftype_void
08385 = build_function_type (void_type_node, void_list_node);
08386 tree void_ftype_int
08387 = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
08388
08389 tree v16qi_ftype_long_pcvoid
08390 = build_function_type_list (V16QI_type_node,
08391 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08392 tree v8hi_ftype_long_pcvoid
08393 = build_function_type_list (V8HI_type_node,
08394 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08395 tree v4si_ftype_long_pcvoid
08396 = build_function_type_list (V4SI_type_node,
08397 long_integer_type_node, pcvoid_type_node, NULL_TREE);
08398
08399 tree void_ftype_v4si_long_pvoid
08400 = build_function_type_list (void_type_node,
08401 V4SI_type_node, long_integer_type_node,
08402 pvoid_type_node, NULL_TREE);
08403 tree void_ftype_v16qi_long_pvoid
08404 = build_function_type_list (void_type_node,
08405 V16QI_type_node, long_integer_type_node,
08406 pvoid_type_node, NULL_TREE);
08407 tree void_ftype_v8hi_long_pvoid
08408 = build_function_type_list (void_type_node,
08409 V8HI_type_node, long_integer_type_node,
08410 pvoid_type_node, NULL_TREE);
08411 tree int_ftype_int_v8hi_v8hi
08412 = build_function_type_list (integer_type_node,
08413 integer_type_node, V8HI_type_node,
08414 V8HI_type_node, NULL_TREE);
08415 tree int_ftype_int_v16qi_v16qi
08416 = build_function_type_list (integer_type_node,
08417 integer_type_node, V16QI_type_node,
08418 V16QI_type_node, NULL_TREE);
08419 tree int_ftype_int_v4sf_v4sf
08420 = build_function_type_list (integer_type_node,
08421 integer_type_node, V4SF_type_node,
08422 V4SF_type_node, NULL_TREE);
08423 tree v4si_ftype_v4si
08424 = build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE);
08425 tree v8hi_ftype_v8hi
08426 = build_function_type_list (V8HI_type_node, V8HI_type_node, NULL_TREE);
08427 tree v16qi_ftype_v16qi
08428 = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
08429 tree v4sf_ftype_v4sf
08430 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
08431 tree void_ftype_pcvoid_int_int
08432 = build_function_type_list (void_type_node,
08433 pcvoid_type_node, integer_type_node,
08434 integer_type_node, NULL_TREE);
08435 tree int_ftype_pcchar
08436 = build_function_type_list (integer_type_node,
08437 pcchar_type_node, NULL_TREE);
08438
08439 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pcfloat,
08440 ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
08441 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf,
08442 ALTIVEC_BUILTIN_ST_INTERNAL_4sf);
08443 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4si", v4si_ftype_pcint,
08444 ALTIVEC_BUILTIN_LD_INTERNAL_4si);
08445 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4si", void_ftype_pint_v4si,
08446 ALTIVEC_BUILTIN_ST_INTERNAL_4si);
08447 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_8hi", v8hi_ftype_pcshort,
08448 ALTIVEC_BUILTIN_LD_INTERNAL_8hi);
08449 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi,
08450 ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
08451 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pcchar,
08452 ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
08453 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi,
08454 ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
08455 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
08456 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
08457 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
08458 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS);
08459 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL);
08460 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR);
08461 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX);
08462 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX);
08463 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX);
08464 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL);
08465 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX);
08466 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX);
08467 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX);
08468 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
08469 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
08470 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
08471
08472
08473 def_builtin (MASK_ALTIVEC, "__builtin_altivec_compiletime_error", int_ftype_pcchar,
08474 ALTIVEC_BUILTIN_COMPILETIME_ERROR);
08475
08476
08477 d = (struct builtin_description *) bdesc_dst;
08478 for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
08479 def_builtin (d->mask, d->name, void_ftype_pcvoid_int_int, d->code);
08480
08481
08482 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
08483 for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
08484 {
08485 enum machine_mode mode1;
08486 tree type;
08487
08488 mode1 = insn_data[dp->icode].operand[1].mode;
08489
08490 switch (mode1)
08491 {
08492 case V4SImode:
08493 type = int_ftype_int_v4si_v4si;
08494 break;
08495 case V8HImode:
08496 type = int_ftype_int_v8hi_v8hi;
08497 break;
08498 case V16QImode:
08499 type = int_ftype_int_v16qi_v16qi;
08500 break;
08501 case V4SFmode:
08502 type = int_ftype_int_v4sf_v4sf;
08503 break;
08504 default:
08505 abort ();
08506 }
08507
08508 def_builtin (dp->mask, dp->name, type, dp->code);
08509 }
08510
08511
08512 d = (struct builtin_description *) bdesc_abs;
08513 for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
08514 {
08515 enum machine_mode mode0;
08516 tree type;
08517
08518 mode0 = insn_data[d->icode].operand[0].mode;
08519
08520 switch (mode0)
08521 {
08522 case V4SImode:
08523 type = v4si_ftype_v4si;
08524 break;
08525 case V8HImode:
08526 type = v8hi_ftype_v8hi;
08527 break;
08528 case V16QImode:
08529 type = v16qi_ftype_v16qi;
08530 break;
08531 case V4SFmode:
08532 type = v4sf_ftype_v4sf;
08533 break;
08534 default:
08535 abort ();
08536 }
08537
08538 def_builtin (d->mask, d->name, type, d->code);
08539 }
08540
08541 if (TARGET_ALTIVEC)
08542 {
08543 tree decl;
08544
08545
08546
08547
08548 decl = lang_hooks.builtin_function ("__builtin_altivec_mask_for_load",
08549 v16qi_ftype_long_pcvoid,
08550 ALTIVEC_BUILTIN_MASK_FOR_LOAD,
08551 BUILT_IN_MD, NULL, NULL_TREE);
08552
08553 altivec_builtin_mask_for_load = decl;
08554 }
08555 }
08556
08557 static void
08558 rs6000_common_init_builtins (void)
08559 {
08560 struct builtin_description *d;
08561 size_t i;
08562
08563 tree v4sf_ftype_v4sf_v4sf_v16qi
08564 = build_function_type_list (V4SF_type_node,
08565 V4SF_type_node, V4SF_type_node,
08566 V16QI_type_node, NULL_TREE);
08567 tree v4si_ftype_v4si_v4si_v16qi
08568 = build_function_type_list (V4SI_type_node,
08569 V4SI_type_node, V4SI_type_node,
08570 V16QI_type_node, NULL_TREE);
08571 tree v8hi_ftype_v8hi_v8hi_v16qi
08572 = build_function_type_list (V8HI_type_node,
08573 V8HI_type_node, V8HI_type_node,
08574 V16QI_type_node, NULL_TREE);
08575 tree v16qi_ftype_v16qi_v16qi_v16qi
08576 = build_function_type_list (V16QI_type_node,
08577 V16QI_type_node, V16QI_type_node,
08578 V16QI_type_node, NULL_TREE);
08579 tree v4si_ftype_int
08580 = build_function_type_list (V4SI_type_node, integer_type_node, NULL_TREE);
08581 tree v8hi_ftype_int
08582 = build_function_type_list (V8HI_type_node, integer_type_node, NULL_TREE);
08583 tree v16qi_ftype_int
08584 = build_function_type_list (V16QI_type_node, integer_type_node, NULL_TREE);
08585 tree v8hi_ftype_v16qi
08586 = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE);
08587 tree v4sf_ftype_v4sf
08588 = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
08589
08590 tree v2si_ftype_v2si_v2si
08591 = build_function_type_list (opaque_V2SI_type_node,
08592 opaque_V2SI_type_node,
08593 opaque_V2SI_type_node, NULL_TREE);
08594
08595 tree v2sf_ftype_v2sf_v2sf
08596 = build_function_type_list (opaque_V2SF_type_node,
08597 opaque_V2SF_type_node,
08598 opaque_V2SF_type_node, NULL_TREE);
08599
08600 tree v2si_ftype_int_int
08601 = build_function_type_list (opaque_V2SI_type_node,
08602 integer_type_node, integer_type_node,
08603 NULL_TREE);
08604
08605 tree v2si_ftype_v2si
08606 = build_function_type_list (opaque_V2SI_type_node,
08607 opaque_V2SI_type_node, NULL_TREE);
08608
08609 tree v2sf_ftype_v2sf
08610 = build_function_type_list (opaque_V2SF_type_node,
08611 opaque_V2SF_type_node, NULL_TREE);
08612
08613 tree v2sf_ftype_v2si
08614 = build_function_type_list (opaque_V2SF_type_node,
08615 opaque_V2SI_type_node, NULL_TREE);
08616
08617 tree v2si_ftype_v2sf
08618 = build_function_type_list (opaque_V2SI_type_node,
08619 opaque_V2SF_type_node, NULL_TREE);
08620
08621 tree v2si_ftype_v2si_char
08622 = build_function_type_list (opaque_V2SI_type_node,
08623 opaque_V2SI_type_node,
08624 char_type_node, NULL_TREE);
08625
08626 tree v2si_ftype_int_char
08627 = build_function_type_list (opaque_V2SI_type_node,
08628 integer_type_node, char_type_node, NULL_TREE);
08629
08630 tree v2si_ftype_char
08631 = build_function_type_list (opaque_V2SI_type_node,
08632 char_type_node, NULL_TREE);
08633
08634 tree int_ftype_int_int
08635 = build_function_type_list (integer_type_node,
08636 integer_type_node, integer_type_node,
08637 NULL_TREE);
08638
08639 tree v4si_ftype_v4si_v4si
08640 = build_function_type_list (V4SI_type_node,
08641 V4SI_type_node, V4SI_type_node, NULL_TREE);
08642 tree v4sf_ftype_v4si_int
08643 = build_function_type_list (V4SF_type_node,
08644 V4SI_type_node, integer_type_node, NULL_TREE);
08645 tree v4si_ftype_v4sf_int
08646 = build_function_type_list (V4SI_type_node,
08647 V4SF_type_node, integer_type_node, NULL_TREE);
08648 tree v4si_ftype_v4si_int
08649 = build_function_type_list (V4SI_type_node,
08650 V4SI_type_node, integer_type_node, NULL_TREE);
08651 tree v8hi_ftype_v8hi_int
08652 = build_function_type_list (V8HI_type_node,
08653 V8HI_type_node, integer_type_node, NULL_TREE);
08654 tree v16qi_ftype_v16qi_int
08655 = build_function_type_list (V16QI_type_node,
08656 V16QI_type_node, integer_type_node, NULL_TREE);
08657 tree v16qi_ftype_v16qi_v16qi_int
08658 = build_function_type_list (V16QI_type_node,
08659 V16QI_type_node, V16QI_type_node,
08660 integer_type_node, NULL_TREE);
08661 tree v8hi_ftype_v8hi_v8hi_int
08662 = build_function_type_list (V8HI_type_node,
08663 V8HI_type_node, V8HI_type_node,
08664 integer_type_node, NULL_TREE);
08665 tree v4si_ftype_v4si_v4si_int
08666 = build_function_type_list (V4SI_type_node,
08667 V4SI_type_node, V4SI_type_node,
08668 integer_type_node, NULL_TREE);
08669 tree v4sf_ftype_v4sf_v4sf_int
08670 = build_function_type_list (V4SF_type_node,
08671 V4SF_type_node, V4SF_type_node,
08672 integer_type_node, NULL_TREE);
08673 tree v4sf_ftype_v4sf_v4sf
08674 = build_function_type_list (V4SF_type_node,
08675 V4SF_type_node, V4SF_type_node, NULL_TREE);
08676 tree v4sf_ftype_v4sf_v4sf_v4si
08677 = build_function_type_list (V4SF_type_node,
08678 V4SF_type_node, V4SF_type_node,
08679 V4SI_type_node, NULL_TREE);
08680 tree v4sf_ftype_v4sf_v4sf_v4sf
08681 = build_function_type_list (V4SF_type_node,
08682 V4SF_type_node, V4SF_type_node,
08683 V4SF_type_node, NULL_TREE);
08684 tree v4si_ftype_v4si_v4si_v4si
08685 = build_function_type_list (V4SI_type_node,
08686 V4SI_type_node, V4SI_type_node,
08687 V4SI_type_node, NULL_TREE);
08688 tree v8hi_ftype_v8hi_v8hi
08689 = build_function_type_list (V8HI_type_node,
08690 V8HI_type_node, V8HI_type_node, NULL_TREE);
08691 tree v8hi_ftype_v8hi_v8hi_v8hi
08692 = build_function_type_list (V8HI_type_node,
08693 V8HI_type_node, V8HI_type_node,
08694 V8HI_type_node, NULL_TREE);
08695 tree v4si_ftype_v8hi_v8hi_v4si
08696 = build_function_type_list (V4SI_type_node,
08697 V8HI_type_node, V8HI_type_node,
08698 V4SI_type_node, NULL_TREE);
08699 tree v4si_ftype_v16qi_v16qi_v4si
08700 = build_function_type_list (V4SI_type_node,
08701 V16QI_type_node, V16QI_type_node,
08702 V4SI_type_node, NULL_TREE);
08703 tree v16qi_ftype_v16qi_v16qi
08704 = build_function_type_list (V16QI_type_node,
08705 V16QI_type_node, V16QI_type_node, NULL_TREE);
08706 tree v4si_ftype_v4sf_v4sf
08707 = build_function_type_list (V4SI_type_node,
08708 V4SF_type_node, V4SF_type_node, NULL_TREE);
08709 tree v8hi_ftype_v16qi_v16qi
08710 = build_function_type_list (V8HI_type_node,
08711 V16QI_type_node, V16QI_type_node, NULL_TREE);
08712 tree v4si_ftype_v8hi_v8hi
08713 = build_function_type_list (V4SI_type_node,
08714 V8HI_type_node, V8HI_type_node, NULL_TREE);
08715 tree v8hi_ftype_v4si_v4si
08716 = build_function_type_list (V8HI_type_node,
08717 V4SI_type_node, V4SI_type_node, NULL_TREE);
08718 tree v16qi_ftype_v8hi_v8hi
08719 = build_function_type_list (V16QI_type_node,
08720 V8HI_type_node, V8HI_type_node, NULL_TREE);
08721 tree v4si_ftype_v16qi_v4si
08722 = build_function_type_list (V4SI_type_node,
08723 V16QI_type_node, V4SI_type_node, NULL_TREE);
08724 tree v4si_ftype_v16qi_v16qi
08725 = build_function_type_list (V4SI_type_node,
08726 V16QI_type_node, V16QI_type_node, NULL_TREE);
08727 tree v4si_ftype_v8hi_v4si
08728 = build_function_type_list (V4SI_type_node,
08729 V8HI_type_node, V4SI_type_node, NULL_TREE);
08730 tree v4si_ftype_v8hi
08731 = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE);
08732 tree int_ftype_v4si_v4si
08733 = build_function_type_list (integer_type_node,
08734 V4SI_type_node, V4SI_type_node, NULL_TREE);
08735 tree int_ftype_v4sf_v4sf
08736 = build_function_type_list (integer_type_node,
08737 V4SF_type_node, V4SF_type_node, NULL_TREE);
08738 tree int_ftype_v16qi_v16qi
08739 = build_function_type_list (integer_type_node,
08740 V16QI_type_node, V16QI_type_node, NULL_TREE);
08741 tree int_ftype_v8hi_v8hi
08742 = build_function_type_list (integer_type_node,
08743 V8HI_type_node, V8HI_type_node, NULL_TREE);
08744
08745
08746 d = (struct builtin_description *) bdesc_3arg;
08747 for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
08748 {
08749
08750 enum machine_mode mode0, mode1, mode2, mode3;
08751 tree type;
08752
08753 if (d->name == 0 || d->icode == CODE_FOR_nothing)
08754 continue;
08755
08756 mode0 = insn_data[d->icode].operand[0].mode;
08757 mode1 = insn_data[d->icode].operand[1].mode;
08758 mode2 = insn_data[d->icode].operand[2].mode;
08759 mode3 = insn_data[d->icode].operand[3].mode;
08760
08761
08762 if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
08763 {
08764 switch (mode0)
08765 {
08766 case V4SImode:
08767 type = v4si_ftype_v4si_v4si_v4si;
08768 break;
08769 case V4SFmode:
08770 type = v4sf_ftype_v4sf_v4sf_v4sf;
08771 break;
08772 case V8HImode:
08773 type = v8hi_ftype_v8hi_v8hi_v8hi;
08774 break;
08775 case V16QImode:
08776 type = v16qi_ftype_v16qi_v16qi_v16qi;
08777 break;
08778 default:
08779 abort();
08780 }
08781 }
08782 else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
08783 {
08784 switch (mode0)
08785 {
08786 case V4SImode:
08787 type = v4si_ftype_v4si_v4si_v16qi;
08788 break;
08789 case V4SFmode:
08790 type = v4sf_ftype_v4sf_v4sf_v16qi;
08791 break;
08792 case V8HImode:
08793 type = v8hi_ftype_v8hi_v8hi_v16qi;
08794 break;
08795 case V16QImode:
08796 type = v16qi_ftype_v16qi_v16qi_v16qi;
08797 break;
08798 default:
08799 abort();
08800 }
08801 }
08802 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
08803 && mode3 == V4SImode)
08804 type = v4si_ftype_v16qi_v16qi_v4si;
08805 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
08806 && mode3 == V4SImode)
08807 type = v4si_ftype_v8hi_v8hi_v4si;
08808 else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
08809 && mode3 == V4SImode)
08810 type = v4sf_ftype_v4sf_v4sf_v4si;
08811
08812
08813 else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0
08814 && mode3 == QImode)
08815 type = v16qi_ftype_v16qi_v16qi_int;
08816
08817
08818 else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0
08819 && mode3 == QImode)
08820 type = v8hi_ftype_v8hi_v8hi_int;
08821
08822
08823 else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0
08824 && mode3 == QImode)
08825 type = v4si_ftype_v4si_v4si_int;
08826
08827
08828 else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0
08829 && mode3 == QImode)
08830 type = v4sf_ftype_v4sf_v4sf_int;
08831
08832 else
08833 abort ();
08834
08835 def_builtin (d->mask, d->name, type, d->code);
08836 }
08837
08838
08839 d = (struct builtin_description *) bdesc_2arg;
08840 for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
08841 {
08842 enum machine_mode mode0, mode1, mode2;
08843 tree type;
08844
08845 if (d->name == 0 || d->icode == CODE_FOR_nothing)
08846 continue;
08847
08848 mode0 = insn_data[d->icode].operand[0].mode;
08849 mode1 = insn_data[d->icode].operand[1].mode;
08850 mode2 = insn_data[d->icode].operand[2].mode;
08851
08852
08853 if (mode0 == mode1 && mode1 == mode2)
08854 {
08855 switch (mode0)
08856 {
08857 case V4SFmode:
08858 type = v4sf_ftype_v4sf_v4sf;
08859 break;
08860 case V4SImode:
08861 type = v4si_ftype_v4si_v4si;
08862 break;
08863 case V16QImode:
08864 type = v16qi_ftype_v16qi_v16qi;
08865 break;
08866 case V8HImode:
08867 type = v8hi_ftype_v8hi_v8hi;
08868 break;
08869 case V2SImode:
08870 type = v2si_ftype_v2si_v2si;
08871 break;
08872 case V2SFmode:
08873 type = v2sf_ftype_v2sf_v2sf;
08874 break;
08875 case SImode:
08876 type = int_ftype_int_int;
08877 break;
08878 default:
08879 abort ();
08880 }
08881 }
08882
08883
08884
08885
08886 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
08887 type = v4si_ftype_v4sf_v4sf;
08888
08889
08890 else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
08891 type = v8hi_ftype_v16qi_v16qi;
08892
08893
08894 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
08895 type = v4si_ftype_v8hi_v8hi;
08896
08897
08898 else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
08899 type = v8hi_ftype_v4si_v4si;
08900
08901
08902 else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
08903 type = v16qi_ftype_v8hi_v8hi;
08904
08905
08906 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
08907 type = v4si_ftype_v16qi_v4si;
08908
08909
08910 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode)
08911 type = v4si_ftype_v16qi_v16qi;
08912
08913
08914 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
08915 type = v4si_ftype_v8hi_v4si;
08916
08917
08918 else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
08919 type = v4si_ftype_v4si_int;
08920
08921
08922 else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
08923 type = v8hi_ftype_v8hi_int;
08924
08925
08926 else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
08927 type = v16qi_ftype_v16qi_int;
08928
08929
08930 else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
08931 type = v4sf_ftype_v4si_int;
08932
08933
08934 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
08935 type = v4si_ftype_v4sf_int;
08936
08937 else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode)
08938 type = v2si_ftype_int_int;
08939
08940 else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
08941 type = v2si_ftype_v2si_char;
08942
08943 else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
08944 type = v2si_ftype_int_char;
08945
08946
08947 else if (mode0 == SImode)
08948 {
08949 switch (mode1)
08950 {
08951 case V4SImode:
08952 type = int_ftype_v4si_v4si;
08953 break;
08954 case V4SFmode:
08955 type = int_ftype_v4sf_v4sf;
08956 break;
08957 case V16QImode:
08958 type = int_ftype_v16qi_v16qi;
08959 break;
08960 case V8HImode:
08961 type = int_ftype_v8hi_v8hi;
08962 break;
08963 default:
08964 abort ();
08965 }
08966 }
08967
08968 else
08969 abort ();
08970
08971 def_builtin (d->mask, d->name, type, d->code);
08972 }
08973
08974
08975 d = (struct builtin_description *) bdesc_1arg;
08976 for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
08977 {
08978 enum machine_mode mode0, mode1;
08979 tree type;
08980
08981 if (d->name == 0 || d->icode == CODE_FOR_nothing)
08982 continue;
08983
08984 mode0 = insn_data[d->icode].operand[0].mode;
08985 mode1 = insn_data[d->icode].operand[1].mode;
08986
08987 if (mode0 == V4SImode && mode1 == QImode)
08988 type = v4si_ftype_int;
08989 else if (mode0 == V8HImode && mode1 == QImode)
08990 type = v8hi_ftype_int;
08991 else if (mode0 == V16QImode && mode1 == QImode)
08992 type = v16qi_ftype_int;
08993 else if (mode0 == V4SFmode && mode1 == V4SFmode)
08994 type = v4sf_ftype_v4sf;
08995 else if (mode0 == V8HImode && mode1 == V16QImode)
08996 type = v8hi_ftype_v16qi;
08997 else if (mode0 == V4SImode && mode1 == V8HImode)
08998 type = v4si_ftype_v8hi;
08999 else if (mode0 == V2SImode && mode1 == V2SImode)
09000 type = v2si_ftype_v2si;
09001 else if (mode0 == V2SFmode && mode1 == V2SFmode)
09002 type = v2sf_ftype_v2sf;
09003 else if (mode0 == V2SFmode && mode1 == V2SImode)
09004 type = v2sf_ftype_v2si;
09005 else if (mode0 == V2SImode && mode1 == V2SFmode)
09006 type = v2si_ftype_v2sf;
09007 else if (mode0 == V2SImode && mode1 == QImode)
09008 type = v2si_ftype_char;
09009 else
09010 abort ();
09011
09012 def_builtin (d->mask, d->name, type, d->code);
09013 }
09014 }
09015
09016 static void
09017 rs6000_init_libfuncs (void)
09018 {
09019 if (!TARGET_HARD_FLOAT)
09020 return;
09021
09022 if (DEFAULT_ABI != ABI_V4)
09023 {
09024 if (TARGET_XCOFF && ! TARGET_POWER2 && ! TARGET_POWERPC)
09025 {
09026
09027 set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc");
09028 set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc");
09029 set_conv_libfunc (sfix_optab, SImode, TFmode, "_qitrunc");
09030 set_conv_libfunc (ufix_optab, SImode, TFmode, "_quitrunc");
09031 }
09032
09033
09034 if (!TARGET_XL_COMPAT)
09035 {
09036 set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
09037 set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
09038 set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
09039 set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
09040 }
09041 else
09042 {
09043 set_optab_libfunc (add_optab, TFmode, "_xlqadd");
09044 set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
09045 set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
09046 set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
09047 }
09048 }
09049 else
09050 {
09051
09052
09053 set_optab_libfunc (add_optab, TFmode, "_q_add");
09054 set_optab_libfunc (sub_optab, TFmode, "_q_sub");
09055 set_optab_libfunc (neg_optab, TFmode, "_q_neg");
09056 set_optab_libfunc (smul_optab, TFmode, "_q_mul");
09057 set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
09058 if (TARGET_PPC_GPOPT || TARGET_POWER2)
09059 set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
09060
09061 set_optab_libfunc (eq_optab, TFmode, "_q_feq");
09062 set_optab_libfunc (ne_optab, TFmode, "_q_fne");
09063 set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
09064 set_optab_libfunc (ge_optab, TFmode, "_q_fge");
09065 set_optab_libfunc (lt_optab, TFmode, "_q_flt");
09066 set_optab_libfunc (le_optab, TFmode, "_q_fle");
09067
09068 set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
09069 set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
09070 set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
09071 set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
09072 set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
09073 set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
09074 set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
09075 }
09076 }
09077
09078
09079
09080
09081
09082
09083
09084
09085
09086 int
09087 expand_block_clear (rtx operands[])
09088 {
09089 rtx orig_dest = operands[0];
09090 rtx bytes_rtx = operands[1];
09091 rtx align_rtx = operands[2];
09092 bool constp = (GET_CODE (bytes_rtx) == CONST_INT);
09093 HOST_WIDE_INT align;
09094 HOST_WIDE_INT bytes;
09095 int offset;
09096 int clear_bytes;
09097 int clear_step;
09098
09099
09100 if (! constp)
09101 return 0;
09102
09103
09104 if (GET_CODE (align_rtx) != CONST_INT)
09105 abort ();
09106 align = INTVAL (align_rtx) * BITS_PER_UNIT;
09107
09108
09109 bytes = INTVAL (bytes_rtx);
09110 if (bytes <= 0)
09111 return 1;
09112
09113
09114
09115
09116
09117 if (TARGET_ALTIVEC && align >= 128)
09118 clear_step = 16;
09119 else if (TARGET_POWERPC64 && align >= 32)
09120 clear_step = 8;
09121 else
09122 clear_step = 4;
09123
09124 if (optimize_size && bytes > 3 * clear_step)
09125 return 0;
09126 if (! optimize_size && bytes > 8 * clear_step)
09127 return 0;
09128
09129 for (offset = 0; bytes > 0; offset += clear_bytes, bytes -= clear_bytes)
09130 {
09131 enum machine_mode mode = BLKmode;
09132 rtx dest;
09133
09134 if (bytes >= 16 && TARGET_ALTIVEC && align >= 128)
09135 {
09136 clear_bytes = 16;
09137 mode = V4SImode;
09138 }
09139 else if (bytes >= 8 && TARGET_POWERPC64
09140
09141
09142 && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
09143 {
09144 clear_bytes = 8;
09145 mode = DImode;
09146 }
09147 else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
09148 {
09149 clear_bytes = 4;
09150 mode = SImode;
09151 }
09152 else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
09153 {
09154 clear_bytes = 2;
09155 mode = HImode;
09156 }
09157 else
09158 {
09159 clear_bytes = 1;
09160 mode = QImode;
09161 }
09162
09163 dest = adjust_address (orig_dest, mode, offset);
09164
09165 emit_move_insn (dest, CONST0_RTX (mode));
09166 }
09167
09168 return 1;
09169 }
09170
09171
09172
09173
09174
09175
09176
09177
09178
09179
09180 #define MAX_MOVE_REG 4
09181
09182 int
09183 expand_block_move (rtx operands[])
09184 {
09185 rtx orig_dest = operands[0];
09186 rtx orig_src = operands[1];
09187 rtx bytes_rtx = operands[2];
09188 rtx align_rtx = operands[3];
09189 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
09190 int align;
09191 int bytes;
09192 int offset;
09193 int move_bytes;
09194 rtx stores[MAX_MOVE_REG];
09195 int num_reg = 0;
09196
09197
09198 if (! constp)
09199 return 0;
09200
09201
09202 if (GET_CODE (align_rtx) != CONST_INT)
09203 abort ();
09204 align = INTVAL (align_rtx) * BITS_PER_UNIT;
09205
09206
09207 bytes = INTVAL (bytes_rtx);
09208 if (bytes <= 0)
09209 return 1;
09210
09211
09212
09213 if (bytes > (TARGET_POWERPC64 ? 64 : 32))
09214 return 0;
09215
09216 for (offset = 0; bytes > 0; offset += move_bytes, bytes -= move_bytes)
09217 {
09218 union {
09219 rtx (*movmemsi) (rtx, rtx, rtx, rtx);
09220 rtx (*mov) (rtx, rtx);
09221 } gen_func;
09222 enum machine_mode mode = BLKmode;
09223 rtx src, dest;
09224
09225
09226
09227 if (TARGET_ALTIVEC && bytes >= 16 && align >= 128)
09228 {
09229 move_bytes = 16;
09230 mode = V4SImode;
09231 gen_func.mov = gen_movv4si;
09232 }
09233 else if (TARGET_STRING
09234 && bytes > 24
09235 && ! fixed_regs[5]
09236 && ! fixed_regs[6]
09237 && ! fixed_regs[7]
09238 && ! fixed_regs[8]
09239 && ! fixed_regs[9]
09240 && ! fixed_regs[10]
09241 && ! fixed_regs[11]
09242 && ! fixed_regs[12])
09243 {
09244 move_bytes = (bytes > 32) ? 32 : bytes;
09245 gen_func.movmemsi = gen_movmemsi_8reg;
09246 }
09247 else if (TARGET_STRING
09248 && bytes > 16
09249 && ! fixed_regs[5]
09250 && ! fixed_regs[6]
09251 && ! fixed_regs[7]
09252 && ! fixed_regs[8]
09253 && ! fixed_regs[9]
09254 && ! fixed_regs[10])
09255 {
09256 move_bytes = (bytes > 24) ? 24 : bytes;
09257 gen_func.movmemsi = gen_movmemsi_6reg;
09258 }
09259 else if (TARGET_STRING
09260 && bytes > 8
09261 && ! fixed_regs[5]
09262 && ! fixed_regs[6]
09263 && ! fixed_regs[7]
09264 && ! fixed_regs[8])
09265 {
09266 move_bytes = (bytes > 16) ? 16 : bytes;
09267 gen_func.movmemsi = gen_movmemsi_4reg;
09268 }
09269 else if (bytes >= 8 && TARGET_POWERPC64
09270
09271
09272 && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
09273 {
09274 move_bytes = 8;
09275 mode = DImode;
09276 gen_func.mov = gen_movdi;
09277 }
09278 else if (TARGET_STRING && bytes > 4 && !TARGET_POWERPC64)
09279 {
09280 move_bytes = (bytes > 8) ? 8 : bytes;
09281 gen_func.movmemsi = gen_movmemsi_2reg;
09282 }
09283 else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
09284 {
09285 move_bytes = 4;
09286 mode = SImode;
09287 gen_func.mov = gen_movsi;
09288 }
09289 else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
09290 {
09291 move_bytes = 2;
09292 mode = HImode;
09293 gen_func.mov = gen_movhi;
09294 }
09295 else if (TARGET_STRING && bytes > 1)
09296 {
09297 move_bytes = (bytes > 4) ? 4 : bytes;
09298 gen_func.movmemsi = gen_movmemsi_1reg;
09299 }
09300 else
09301 {
09302 move_bytes = 1;
09303 mode = QImode;
09304 gen_func.mov = gen_movqi;
09305 }
09306
09307 src = adjust_address (orig_src, mode, offset);
09308 dest = adjust_address (orig_dest, mode, offset);
09309
09310 if (mode != BLKmode)
09311 {
09312 rtx tmp_reg = gen_reg_rtx (mode);
09313
09314 emit_insn ((*gen_func.mov) (tmp_reg, src));
09315 stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
09316 }
09317
09318 if (mode == BLKmode || num_reg >= MAX_MOVE_REG || bytes == move_bytes)
09319 {
09320 int i;
09321 for (i = 0; i < num_reg; i++)
09322 emit_insn (stores[i]);
09323 num_reg = 0;
09324 }
09325
09326 if (mode == BLKmode)
09327 {
09328
09329
09330 if (!REG_P (XEXP (src, 0)))
09331 {
09332 rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
09333 src = replace_equiv_address (src, src_reg);
09334 }
09335 set_mem_size (src, GEN_INT (move_bytes));
09336
09337 if (!REG_P (XEXP (dest, 0)))
09338 {
09339 rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
09340 dest = replace_equiv_address (dest, dest_reg);
09341 }
09342 set_mem_size (dest, GEN_INT (move_bytes));
09343
09344 emit_insn ((*gen_func.movmemsi) (dest, src,
09345 GEN_INT (move_bytes & 31),
09346 align_rtx));
09347 }
09348 }
09349
09350 return 1;
09351 }
09352
09353
09354
09355
09356 int
09357 save_world_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09358 {
09359 int index;
09360 int i;
09361 rtx elt;
09362 int count = XVECLEN (op, 0);
09363
09364 if (count != 55)
09365 return 0;
09366
09367 index = 0;
09368 if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
09369 || GET_CODE (XVECEXP (op, 0, index++)) != USE)
09370 return 0;
09371
09372 for (i=1; i <= 18; i++)
09373 {
09374 elt = XVECEXP (op, 0, index++);
09375 if (GET_CODE (elt) != SET
09376 || GET_CODE (SET_DEST (elt)) != MEM
09377 || ! memory_operand (SET_DEST (elt), DFmode)
09378 || GET_CODE (SET_SRC (elt)) != REG
09379 || GET_MODE (SET_SRC (elt)) != DFmode)
09380 return 0;
09381 }
09382
09383 for (i=1; i <= 12; i++)
09384 {
09385 elt = XVECEXP (op, 0, index++);
09386 if (GET_CODE (elt) != SET
09387 || GET_CODE (SET_DEST (elt)) != MEM
09388 || GET_CODE (SET_SRC (elt)) != REG
09389 || GET_MODE (SET_SRC (elt)) != V4SImode)
09390 return 0;
09391 }
09392
09393 for (i=1; i <= 19; i++)
09394 {
09395 elt = XVECEXP (op, 0, index++);
09396 if (GET_CODE (elt) != SET
09397 || GET_CODE (SET_DEST (elt)) != MEM
09398 || ! memory_operand (SET_DEST (elt), Pmode)
09399 || GET_CODE (SET_SRC (elt)) != REG
09400 || GET_MODE (SET_SRC (elt)) != Pmode)
09401 return 0;
09402 }
09403
09404 elt = XVECEXP (op, 0, index++);
09405 if (GET_CODE (elt) != SET
09406 || GET_CODE (SET_DEST (elt)) != MEM
09407 || ! memory_operand (SET_DEST (elt), Pmode)
09408 || GET_CODE (SET_SRC (elt)) != REG
09409 || REGNO (SET_SRC (elt)) != CR2_REGNO
09410 || GET_MODE (SET_SRC (elt)) != Pmode)
09411 return 0;
09412
09413 if (GET_CODE (XVECEXP (op, 0, index++)) != USE
09414 || GET_CODE (XVECEXP (op, 0, index++)) != USE
09415 || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
09416 return 0;
09417 return 1;
09418 }
09419
09420
09421
09422 int
09423 restore_world_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09424 {
09425 int index;
09426 int i;
09427 rtx elt;
09428 int count = XVECLEN (op, 0);
09429
09430 if (count != 59)
09431 return 0;
09432
09433 index = 0;
09434 if (GET_CODE (XVECEXP (op, 0, index++)) != RETURN
09435 || GET_CODE (XVECEXP (op, 0, index++)) != USE
09436 || GET_CODE (XVECEXP (op, 0, index++)) != USE
09437 || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
09438 return 0;
09439
09440 elt = XVECEXP (op, 0, index++);
09441 if (GET_CODE (elt) != SET
09442 || GET_CODE (SET_SRC (elt)) != MEM
09443 || ! memory_operand (SET_SRC (elt), Pmode)
09444 || GET_CODE (SET_DEST (elt)) != REG
09445 || REGNO (SET_DEST (elt)) != CR2_REGNO
09446 || GET_MODE (SET_DEST (elt)) != Pmode)
09447 return 0;
09448
09449 for (i=1; i <= 19; i++)
09450 {
09451 elt = XVECEXP (op, 0, index++);
09452 if (GET_CODE (elt) != SET
09453 || GET_CODE (SET_SRC (elt)) != MEM
09454 || ! memory_operand (SET_SRC (elt), Pmode)
09455 || GET_CODE (SET_DEST (elt)) != REG
09456 || GET_MODE (SET_DEST (elt)) != Pmode)
09457 return 0;
09458 }
09459
09460 for (i=1; i <= 12; i++)
09461 {
09462 elt = XVECEXP (op, 0, index++);
09463 if (GET_CODE (elt) != SET
09464 || GET_CODE (SET_SRC (elt)) != MEM
09465 || GET_CODE (SET_DEST (elt)) != REG
09466 || GET_MODE (SET_DEST (elt)) != V4SImode)
09467 return 0;
09468 }
09469
09470 for (i=1; i <= 18; i++)
09471 {
09472 elt = XVECEXP (op, 0, index++);
09473 if (GET_CODE (elt) != SET
09474 || GET_CODE (SET_SRC (elt)) != MEM
09475 || ! memory_operand (SET_SRC (elt), DFmode)
09476 || GET_CODE (SET_DEST (elt)) != REG
09477 || GET_MODE (SET_DEST (elt)) != DFmode)
09478 return 0;
09479 }
09480
09481 if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
09482 || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
09483 || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
09484 || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
09485 || GET_CODE (XVECEXP (op, 0, index++)) != USE)
09486 return 0;
09487 return 1;
09488 }
09489
09490
09491
09492
09493
09494 int
09495 load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09496 {
09497 int count = XVECLEN (op, 0);
09498 unsigned int dest_regno;
09499 rtx src_addr;
09500 int i;
09501
09502
09503 if (count <= 1
09504 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09505 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
09506 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
09507 return 0;
09508
09509 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
09510 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
09511
09512 for (i = 1; i < count; i++)
09513 {
09514 rtx elt = XVECEXP (op, 0, i);
09515
09516 if (GET_CODE (elt) != SET
09517 || GET_CODE (SET_DEST (elt)) != REG
09518 || GET_MODE (SET_DEST (elt)) != SImode
09519 || REGNO (SET_DEST (elt)) != dest_regno + i
09520 || GET_CODE (SET_SRC (elt)) != MEM
09521 || GET_MODE (SET_SRC (elt)) != SImode
09522 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
09523 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
09524 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
09525 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
09526 return 0;
09527 }
09528
09529 return 1;
09530 }
09531
09532
09533
09534
09535 int
09536 store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09537 {
09538 int count = XVECLEN (op, 0) - 1;
09539 unsigned int src_regno;
09540 rtx dest_addr;
09541 int i;
09542
09543
09544 if (count <= 1
09545 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09546 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
09547 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
09548 return 0;
09549
09550 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
09551 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
09552
09553 for (i = 1; i < count; i++)
09554 {
09555 rtx elt = XVECEXP (op, 0, i + 1);
09556
09557 if (GET_CODE (elt) != SET
09558 || GET_CODE (SET_SRC (elt)) != REG
09559 || GET_MODE (SET_SRC (elt)) != SImode
09560 || REGNO (SET_SRC (elt)) != src_regno + i
09561 || GET_CODE (SET_DEST (elt)) != MEM
09562 || GET_MODE (SET_DEST (elt)) != SImode
09563 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
09564 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
09565 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
09566 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
09567 return 0;
09568 }
09569
09570 return 1;
09571 }
09572
09573
09574
09575
09576
09577
09578 const char *
09579 rs6000_output_load_multiple (rtx operands[3])
09580 {
09581
09582
09583 int i, j;
09584 int words = XVECLEN (operands[0], 0);
09585 rtx xop[10];
09586
09587 if (XVECLEN (operands[0], 0) == 1)
09588 return "{l|lwz} %2,0(%1)";
09589
09590 for (i = 0; i < words; i++)
09591 if (refers_to_regno_p (REGNO (operands[2]) + i,
09592 REGNO (operands[2]) + i + 1, operands[1], 0))
09593 {
09594 if (i == words-1)
09595 {
09596 xop[0] = GEN_INT (4 * (words-1));
09597 xop[1] = operands[1];
09598 xop[2] = operands[2];
09599 output_asm_insn ("{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,%0(%1)", xop);
09600 return "";
09601 }
09602 else if (i == 0)
09603 {
09604 xop[0] = GEN_INT (4 * (words-1));
09605 xop[1] = operands[1];
09606 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
09607 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);
09608 return "";
09609 }
09610 else
09611 {
09612 for (j = 0; j < words; j++)
09613 if (j != i)
09614 {
09615 xop[0] = GEN_INT (j * 4);
09616 xop[1] = operands[1];
09617 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + j);
09618 output_asm_insn ("{l|lwz} %2,%0(%1)", xop);
09619 }
09620 xop[0] = GEN_INT (i * 4);
09621 xop[1] = operands[1];
09622 output_asm_insn ("{l|lwz} %1,%0(%1)", xop);
09623 return "";
09624 }
09625 }
09626
09627 return "{lsi|lswi} %2,%1,%N0";
09628 }
09629
09630
09631
09632 int
09633 vrsave_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09634 {
09635 int count = XVECLEN (op, 0);
09636 unsigned int dest_regno, src_regno;
09637 int i;
09638
09639 if (count <= 1
09640 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09641 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
09642 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC_VOLATILE)
09643 return 0;
09644
09645 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
09646 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
09647
09648 if (dest_regno != VRSAVE_REGNO
09649 && src_regno != VRSAVE_REGNO)
09650 return 0;
09651
09652 for (i = 1; i < count; i++)
09653 {
09654 rtx elt = XVECEXP (op, 0, i);
09655
09656 if (GET_CODE (elt) != CLOBBER
09657 && GET_CODE (elt) != SET)
09658 return 0;
09659 }
09660
09661 return 1;
09662 }
09663
09664
09665
09666 int
09667 mfcr_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09668 {
09669 int count = XVECLEN (op, 0);
09670 int i;
09671
09672
09673 if (count < 1
09674 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09675 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
09676 || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
09677 return 0;
09678
09679 for (i = 0; i < count; i++)
09680 {
09681 rtx exp = XVECEXP (op, 0, i);
09682 rtx unspec;
09683 int maskval;
09684 rtx src_reg;
09685
09686 src_reg = XVECEXP (SET_SRC (exp), 0, 0);
09687
09688 if (GET_CODE (src_reg) != REG
09689 || GET_MODE (src_reg) != CCmode
09690 || ! CR_REGNO_P (REGNO (src_reg)))
09691 return 0;
09692
09693 if (GET_CODE (exp) != SET
09694 || GET_CODE (SET_DEST (exp)) != REG
09695 || GET_MODE (SET_DEST (exp)) != SImode
09696 || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
09697 return 0;
09698 unspec = SET_SRC (exp);
09699 maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
09700
09701 if (GET_CODE (unspec) != UNSPEC
09702 || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
09703 || XVECLEN (unspec, 0) != 2
09704 || XVECEXP (unspec, 0, 0) != src_reg
09705 || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
09706 || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
09707 return 0;
09708 }
09709 return 1;
09710 }
09711
09712
09713
09714 int
09715 mtcrf_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09716 {
09717 int count = XVECLEN (op, 0);
09718 int i;
09719 rtx src_reg;
09720
09721
09722 if (count < 1
09723 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09724 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
09725 || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
09726 return 0;
09727 src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
09728
09729 if (GET_CODE (src_reg) != REG
09730 || GET_MODE (src_reg) != SImode
09731 || ! INT_REGNO_P (REGNO (src_reg)))
09732 return 0;
09733
09734 for (i = 0; i < count; i++)
09735 {
09736 rtx exp = XVECEXP (op, 0, i);
09737 rtx unspec;
09738 int maskval;
09739
09740 if (GET_CODE (exp) != SET
09741 || GET_CODE (SET_DEST (exp)) != REG
09742 || GET_MODE (SET_DEST (exp)) != CCmode
09743 || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
09744 return 0;
09745 unspec = SET_SRC (exp);
09746 maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
09747
09748 if (GET_CODE (unspec) != UNSPEC
09749 || XINT (unspec, 1) != UNSPEC_MOVESI_TO_CR
09750 || XVECLEN (unspec, 0) != 2
09751 || XVECEXP (unspec, 0, 0) != src_reg
09752 || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
09753 || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
09754 return 0;
09755 }
09756 return 1;
09757 }
09758
09759
09760
09761 int
09762 lmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09763 {
09764 int count = XVECLEN (op, 0);
09765 unsigned int dest_regno;
09766 rtx src_addr;
09767 unsigned int base_regno;
09768 HOST_WIDE_INT offset;
09769 int i;
09770
09771
09772 if (count <= 1
09773 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09774 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
09775 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
09776 return 0;
09777
09778 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
09779 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
09780
09781 if (dest_regno > 31
09782 || count != 32 - (int) dest_regno)
09783 return 0;
09784
09785 if (legitimate_indirect_address_p (src_addr, 0))
09786 {
09787 offset = 0;
09788 base_regno = REGNO (src_addr);
09789 if (base_regno == 0)
09790 return 0;
09791 }
09792 else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
09793 {
09794 offset = INTVAL (XEXP (src_addr, 1));
09795 base_regno = REGNO (XEXP (src_addr, 0));
09796 }
09797 else
09798 return 0;
09799
09800 for (i = 0; i < count; i++)
09801 {
09802 rtx elt = XVECEXP (op, 0, i);
09803 rtx newaddr;
09804 rtx addr_reg;
09805 HOST_WIDE_INT newoffset;
09806
09807 if (GET_CODE (elt) != SET
09808 || GET_CODE (SET_DEST (elt)) != REG
09809 || GET_MODE (SET_DEST (elt)) != SImode
09810 || REGNO (SET_DEST (elt)) != dest_regno + i
09811 || GET_CODE (SET_SRC (elt)) != MEM
09812 || GET_MODE (SET_SRC (elt)) != SImode)
09813 return 0;
09814 newaddr = XEXP (SET_SRC (elt), 0);
09815 if (legitimate_indirect_address_p (newaddr, 0))
09816 {
09817 newoffset = 0;
09818 addr_reg = newaddr;
09819 }
09820 else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
09821 {
09822 addr_reg = XEXP (newaddr, 0);
09823 newoffset = INTVAL (XEXP (newaddr, 1));
09824 }
09825 else
09826 return 0;
09827 if (REGNO (addr_reg) != base_regno
09828 || newoffset != offset + 4 * i)
09829 return 0;
09830 }
09831
09832 return 1;
09833 }
09834
09835
09836
09837 int
09838 stmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09839 {
09840 int count = XVECLEN (op, 0);
09841 unsigned int src_regno;
09842 rtx dest_addr;
09843 unsigned int base_regno;
09844 HOST_WIDE_INT offset;
09845 int i;
09846
09847
09848 if (count <= 1
09849 || GET_CODE (XVECEXP (op, 0, 0)) != SET
09850 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
09851 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
09852 return 0;
09853
09854 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
09855 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
09856
09857 if (src_regno > 31
09858 || count != 32 - (int) src_regno)
09859 return 0;
09860
09861 if (legitimate_indirect_address_p (dest_addr, 0))
09862 {
09863 offset = 0;
09864 base_regno = REGNO (dest_addr);
09865 if (base_regno == 0)
09866 return 0;
09867 }
09868 else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
09869 {
09870 offset = INTVAL (XEXP (dest_addr, 1));
09871 base_regno = REGNO (XEXP (dest_addr, 0));
09872 }
09873 else
09874 return 0;
09875
09876 for (i = 0; i < count; i++)
09877 {
09878 rtx elt = XVECEXP (op, 0, i);
09879 rtx newaddr;
09880 rtx addr_reg;
09881 HOST_WIDE_INT newoffset;
09882
09883 if (GET_CODE (elt) != SET
09884 || GET_CODE (SET_SRC (elt)) != REG
09885 || GET_MODE (SET_SRC (elt)) != SImode
09886 || REGNO (SET_SRC (elt)) != src_regno + i
09887 || GET_CODE (SET_DEST (elt)) != MEM
09888 || GET_MODE (SET_DEST (elt)) != SImode)
09889 return 0;
09890 newaddr = XEXP (SET_DEST (elt), 0);
09891 if (legitimate_indirect_address_p (newaddr, 0))
09892 {
09893 newoffset = 0;
09894 addr_reg = newaddr;
09895 }
09896 else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
09897 {
09898 addr_reg = XEXP (newaddr, 0);
09899 newoffset = INTVAL (XEXP (newaddr, 1));
09900 }
09901 else
09902 return 0;
09903 if (REGNO (addr_reg) != base_regno
09904 || newoffset != offset + 4 * i)
09905 return 0;
09906 }
09907
09908 return 1;
09909 }
09910
09911
09912
09913
09914
09915 static void
09916 validate_condition_mode (enum rtx_code code, enum machine_mode mode)
09917 {
09918 if ((GET_RTX_CLASS (code) != RTX_COMPARE
09919 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
09920 || GET_MODE_CLASS (mode) != MODE_CC)
09921 abort ();
09922
09923
09924 if ((code == GT || code == LT || code == GE || code == LE)
09925 && mode == CCUNSmode)
09926 abort ();
09927
09928 if ((code == GTU || code == LTU || code == GEU || code == LEU)
09929 && mode != CCUNSmode)
09930 abort ();
09931
09932 if (mode != CCFPmode
09933 && (code == ORDERED || code == UNORDERED
09934 || code == UNEQ || code == LTGT
09935 || code == UNGT || code == UNLT
09936 || code == UNGE || code == UNLE))
09937 abort ();
09938
09939
09940
09941 if (mode == CCFPmode
09942 && ! flag_finite_math_only
09943 && (code == LE || code == GE
09944 || code == UNEQ || code == LTGT
09945 || code == UNGT || code == UNLT))
09946 abort ();
09947
09948
09949 if (mode == CCEQmode
09950 && code != EQ && code != NE)
09951 abort ();
09952 }
09953
09954
09955
09956
09957 int
09958 branch_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
09959 {
09960 enum rtx_code code = GET_CODE (op);
09961 enum machine_mode cc_mode;
09962
09963 if (!COMPARISON_P (op))
09964 return 0;
09965
09966 cc_mode = GET_MODE (XEXP (op, 0));
09967 if (GET_MODE_CLASS (cc_mode) != MODE_CC)
09968 return 0;
09969
09970 validate_condition_mode (code, cc_mode);
09971
09972 return 1;
09973 }
09974
09975
09976
09977
09978
09979 int
09980 branch_positive_comparison_operator (rtx op, enum machine_mode mode)
09981 {
09982 enum rtx_code code;
09983
09984 if (! branch_comparison_operator (op, mode))
09985 return 0;
09986
09987 code = GET_CODE (op);
09988 return (code == EQ || code == LT || code == GT
09989 || code == LTU || code == GTU
09990 || code == UNORDERED);
09991 }
09992
09993
09994
09995
09996 int
09997 scc_comparison_operator (rtx op, enum machine_mode mode)
09998 {
09999 return branch_positive_comparison_operator (op, mode);
10000 }
10001
10002 int
10003 trap_comparison_operator (rtx op, enum machine_mode mode)
10004 {
10005 if (mode != VOIDmode && mode != GET_MODE (op))
10006 return 0;
10007 return COMPARISON_P (op);
10008 }
10009
10010 int
10011 boolean_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
10012 {
10013 enum rtx_code code = GET_CODE (op);
10014 return (code == AND || code == IOR || code == XOR);
10015 }
10016
10017 int
10018 boolean_or_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
10019 {
10020 enum rtx_code code = GET_CODE (op);
10021 return (code == IOR || code == XOR);
10022 }
10023
10024 int
10025 min_max_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
10026 {
10027 enum rtx_code code = GET_CODE (op);
10028 return (code == SMIN || code == SMAX || code == UMIN || code == UMAX);
10029 }
10030
10031
10032
10033
10034
10035 int
10036 includes_lshift_p (rtx shiftop, rtx andop)
10037 {
10038 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
10039
10040 shift_mask <<= INTVAL (shiftop);
10041
10042 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
10043 }
10044
10045
10046
10047 int
10048 includes_rshift_p (rtx shiftop, rtx andop)
10049 {
10050 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
10051
10052 shift_mask >>= INTVAL (shiftop);
10053
10054 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
10055 }
10056
10057
10058
10059
10060
10061 int
10062 includes_rldic_lshift_p (rtx shiftop, rtx andop)
10063 {
10064 if (GET_CODE (andop) == CONST_INT)
10065 {
10066 HOST_WIDE_INT c, lsb, shift_mask;
10067
10068 c = INTVAL (andop);
10069 if (c == 0 || c == ~0)
10070 return 0;
10071
10072 shift_mask = ~0;
10073 shift_mask <<= INTVAL (shiftop);
10074
10075
10076 lsb = c & -c;
10077
10078
10079 if (-lsb != shift_mask)
10080 return 0;
10081
10082
10083 c = ~c;
10084
10085
10086 c &= -lsb;
10087
10088
10089 lsb = c & -c;
10090 return c == -lsb;
10091 }
10092 else if (GET_CODE (andop) == CONST_DOUBLE
10093 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
10094 {
10095 HOST_WIDE_INT low, high, lsb;
10096 HOST_WIDE_INT shift_mask_low, shift_mask_high;
10097
10098 low = CONST_DOUBLE_LOW (andop);
10099 if (HOST_BITS_PER_WIDE_INT < 64)
10100 high = CONST_DOUBLE_HIGH (andop);
10101
10102 if ((low == 0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == 0))
10103 || (low == ~0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0)))
10104 return 0;
10105
10106 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
10107 {
10108 shift_mask_high = ~0;
10109 if (INTVAL (shiftop) > 32)
10110 shift_mask_high <<= INTVAL (shiftop) - 32;
10111
10112 lsb = high & -high;
10113
10114 if (-lsb != shift_mask_high || INTVAL (shiftop) < 32)
10115 return 0;
10116
10117 high = ~high;
10118 high &= -lsb;
10119
10120 lsb = high & -high;
10121 return high == -lsb;
10122 }
10123
10124 shift_mask_low = ~0;
10125 shift_mask_low <<= INTVAL (shiftop);
10126
10127 lsb = low & -low;
10128
10129 if (-lsb != shift_mask_low)
10130 return 0;
10131
10132 if (HOST_BITS_PER_WIDE_INT < 64)
10133 high = ~high;
10134 low = ~low;
10135 low &= -lsb;
10136
10137 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
10138 {
10139 lsb = high & -high;
10140 return high == -lsb;
10141 }
10142
10143 lsb = low & -low;
10144 return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
10145 }
10146 else
10147 return 0;
10148 }
10149
10150
10151
10152
10153
10154 int
10155 includes_rldicr_lshift_p (rtx shiftop, rtx andop)
10156 {
10157 if (GET_CODE (andop) == CONST_INT)
10158 {
10159 HOST_WIDE_INT c, lsb, shift_mask;
10160
10161 shift_mask = ~0;
10162 shift_mask <<= INTVAL (shiftop);
10163 c = INTVAL (andop);
10164
10165
10166 lsb = c & -c;
10167
10168
10169
10170 if ((lsb & shift_mask) == 0)
10171 return 0;
10172
10173
10174 return c == -lsb && lsb != 1;
10175 }
10176 else if (GET_CODE (andop) == CONST_DOUBLE
10177 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
10178 {
10179 HOST_WIDE_INT low, lsb, shift_mask_low;
10180
10181 low = CONST_DOUBLE_LOW (andop);
10182
10183 if (HOST_BITS_PER_WIDE_INT < 64)
10184 {
10185 HOST_WIDE_INT high, shift_mask_high;
10186
10187 high = CONST_DOUBLE_HIGH (andop);
10188
10189 if (low == 0)
10190 {
10191 shift_mask_high = ~0;
10192 if (INTVAL (shiftop) > 32)
10193 shift_mask_high <<= INTVAL (shiftop) - 32;
10194
10195 lsb = high & -high;
10196
10197 if ((lsb & shift_mask_high) == 0)
10198 return 0;
10199
10200 return high == -lsb;
10201 }
10202 if (high != ~0)
10203 return 0;
10204 }
10205
10206 shift_mask_low = ~0;
10207 shift_mask_low <<= INTVAL (shiftop);
10208
10209 lsb = low & -low;
10210
10211 if ((lsb & shift_mask_low) == 0)
10212 return 0;
10213
10214 return low == -lsb && lsb != 1;
10215 }
10216 else
10217 return 0;
10218 }
10219
10220
10221
10222
10223
10224
10225 int
10226 insvdi_rshift_rlwimi_p (rtx sizeop, rtx startop, rtx shiftop)
10227 {
10228 if (INTVAL (startop) < 64
10229 && INTVAL (startop) > 32
10230 && (INTVAL (sizeop) + INTVAL (startop) < 64)
10231 && (INTVAL (sizeop) + INTVAL (startop) > 33)
10232 && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) < 96)
10233 && (INTVAL (sizeop) + INTVAL (startop) + INTVAL (shiftop) >= 64)
10234 && (64 - (INTVAL (shiftop) & 63)) >= INTVAL (sizeop))
10235 return 1;
10236
10237 return 0;
10238 }
10239
10240
10241
10242
10243 int
10244 registers_ok_for_quad_peep (rtx reg1, rtx reg2)
10245 {
10246
10247 if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
10248 return 0;
10249
10250
10251 if (!FP_REGNO_P (REGNO (reg1))
10252 || !FP_REGNO_P (REGNO (reg2)))
10253 return 0;
10254
10255 return (REGNO (reg1) == REGNO (reg2) - 1);
10256 }
10257
10258
10259
10260
10261
10262 int
10263 mems_ok_for_quad_peep (rtx mem1, rtx mem2)
10264 {
10265 rtx addr1, addr2;
10266 unsigned int reg1;
10267 int offset1;
10268
10269
10270 if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
10271 return 0;
10272
10273 addr1 = XEXP (mem1, 0);
10274 addr2 = XEXP (mem2, 0);
10275
10276
10277 if (GET_CODE (addr1) == PLUS)
10278 {
10279
10280 if (GET_CODE (XEXP (addr1, 0)) != REG)
10281 return 0;
10282 else
10283 {
10284 reg1 = REGNO (XEXP (addr1, 0));
10285
10286 if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
10287 return 0;
10288 offset1 = INTVAL (XEXP (addr1, 1));
10289 }
10290 }
10291 else if (GET_CODE (addr1) != REG)
10292 return 0;
10293 else
10294 {
10295 reg1 = REGNO (addr1);
10296
10297 offset1 = 0;
10298 }
10299
10300
10301
10302
10303 if (offset1 == -8 && GET_CODE (addr2) == REG && reg1 == REGNO (addr2))
10304 return 1;
10305 if (GET_CODE (addr2) != PLUS)
10306 return 0;
10307
10308 if (GET_CODE (XEXP (addr2, 0)) != REG
10309 || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
10310 return 0;
10311
10312 if (reg1 != REGNO (XEXP (addr2, 0)))
10313 return 0;
10314
10315
10316 if (INTVAL (XEXP (addr2, 1)) != offset1 + 8)
10317 return 0;
10318
10319
10320
10321 return 1;
10322 }
10323
10324
10325
10326
10327
10328 enum reg_class
10329 secondary_reload_class (enum reg_class class,
10330 enum machine_mode mode ATTRIBUTE_UNUSED,
10331 rtx in)
10332 {
10333 int regno;
10334
10335 if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN
10336 #if TARGET_MACHO
10337 && MACHOPIC_INDIRECT
10338 #endif
10339 ))
10340 {
10341
10342
10343
10344
10345
10346
10347
10348 if (class != BASE_REGS
10349 && (GET_CODE (in) == SYMBOL_REF
10350 || GET_CODE (in) == HIGH
10351 || GET_CODE (in) == LABEL_REF
10352 || GET_CODE (in) == CONST))
10353 return BASE_REGS;
10354 }
10355
10356 if (GET_CODE (in) == REG)
10357 {
10358 regno = REGNO (in);
10359 if (regno >= FIRST_PSEUDO_REGISTER)
10360 {
10361 regno = true_regnum (in);
10362 if (regno >= FIRST_PSEUDO_REGISTER)
10363 regno = -1;
10364 }
10365 }
10366 else if (GET_CODE (in) == SUBREG)
10367 {
10368 regno = true_regnum (in);
10369 if (regno >= FIRST_PSEUDO_REGISTER)
10370 regno = -1;
10371 }
10372 else
10373 regno = -1;
10374
10375
10376
10377 if (class == GENERAL_REGS || class == BASE_REGS
10378 || (regno >= 0 && INT_REGNO_P (regno)))
10379 return NO_REGS;
10380
10381
10382 if ((regno == -1 || FP_REGNO_P (regno))
10383 && (class == FLOAT_REGS || class == NON_SPECIAL_REGS))
10384 return NO_REGS;
10385
10386
10387 if ((regno == -1 || ALTIVEC_REGNO_P (regno))
10388 && class == ALTIVEC_REGS)
10389 return NO_REGS;
10390
10391
10392 if ((class == CR_REGS || class == CR0_REGS)
10393 && regno >= 0 && CR_REGNO_P (regno))
10394 return NO_REGS;
10395
10396
10397 return GENERAL_REGS;
10398 }
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408 int
10409 ccr_bit (rtx op, int scc_p)
10410 {
10411 enum rtx_code code = GET_CODE (op);
10412 enum machine_mode cc_mode;
10413 int cc_regnum;
10414 int base_bit;
10415 rtx reg;
10416
10417 if (!COMPARISON_P (op))
10418 return -1;
10419
10420 reg = XEXP (op, 0);
10421
10422 if (GET_CODE (reg) != REG
10423 || ! CR_REGNO_P (REGNO (reg)))
10424 abort ();
10425
10426 cc_mode = GET_MODE (reg);
10427 cc_regnum = REGNO (reg);
10428 base_bit = 4 * (cc_regnum - CR0_REGNO);
10429
10430 validate_condition_mode (code, cc_mode);
10431
10432
10433
10434 if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED
10435 && code != GTU && code != LTU)
10436 abort ();
10437
10438 switch (code)
10439 {
10440 case NE:
10441 return scc_p ? base_bit + 3 : base_bit + 2;
10442 case EQ:
10443 return base_bit + 2;
10444 case GT: case GTU: case UNLE:
10445 return base_bit + 1;
10446 case LT: case LTU: case UNGE:
10447 return base_bit;
10448 case ORDERED: case UNORDERED:
10449 return base_bit + 3;
10450
10451 case GE: case GEU:
10452
10453
10454
10455 return scc_p ? base_bit + 3 : base_bit;
10456
10457 case LE: case LEU:
10458 return scc_p ? base_bit + 3 : base_bit + 1;
10459
10460 default:
10461 abort ();
10462 }
10463 }
10464
10465
10466
10467 struct rtx_def *
10468 rs6000_got_register (rtx value ATTRIBUTE_UNUSED)
10469 {
10470
10471
10472
10473 if (no_new_pseudos && ! regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM])
10474 regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
10475
10476 current_function_uses_pic_offset_table = 1;
10477
10478 return pic_offset_table_rtx;
10479 }
10480
10481
10482
10483
10484
10485 static struct machine_function *
10486 rs6000_init_machine_status (void)
10487 {
10488 return ggc_alloc_cleared (sizeof (machine_function));
10489 }
10490
10491
10492 #define INT_P(X) \
10493 ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
10494 && GET_MODE (X) == VOIDmode)
10495
10496 #define INT_LOWPART(X) \
10497 (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
10498
10499 int
10500 extract_MB (rtx op)
10501 {
10502 int i;
10503 unsigned long val = INT_LOWPART (op);
10504
10505
10506
10507 if ((val & 0x80000000) == 0)
10508 {
10509 if ((val & 0xffffffff) == 0)
10510 abort ();
10511
10512 i = 1;
10513 while (((val <<= 1) & 0x80000000) == 0)
10514 ++i;
10515 return i;
10516 }
10517
10518
10519
10520 if ((val & 1) == 0 || (val & 0xffffffff) == 0xffffffff)
10521 return 0;
10522
10523
10524
10525 i = 31;
10526 while (((val >>= 1) & 1) != 0)
10527 --i;
10528
10529 return i;
10530 }
10531
10532 int
10533 extract_ME (rtx op)
10534 {
10535 int i;
10536 unsigned long val = INT_LOWPART (op);
10537
10538
10539
10540 if ((val & 1) == 0)
10541 {
10542 if ((val & 0xffffffff) == 0)
10543 abort ();
10544
10545 i = 30;
10546 while (((val >>= 1) & 1) == 0)
10547 --i;
10548
10549 return i;
10550 }
10551
10552
10553
10554 if ((val & 0x80000000) == 0 || (val & 0xffffffff) == 0xffffffff)
10555 return 31;
10556
10557
10558
10559 i = 0;
10560 while (((val <<= 1) & 0x80000000) != 0)
10561 ++i;
10562
10563 return i;
10564 }
10565
10566
10567
10568
10569 static const char *
10570 rs6000_get_some_local_dynamic_name (void)
10571 {
10572 rtx insn;
10573
10574 if (cfun->machine->some_ld_name)
10575 return cfun->machine->some_ld_name;
10576
10577 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
10578 if (INSN_P (insn)
10579 && for_each_rtx (&PATTERN (insn),
10580 rs6000_get_some_local_dynamic_name_1, 0))
10581 return cfun->machine->some_ld_name;
10582
10583 abort ();
10584 }
10585
10586
10587
10588 static int
10589 rs6000_get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
10590 {
10591 rtx x = *px;
10592
10593 if (GET_CODE (x) == SYMBOL_REF)
10594 {
10595 const char *str = XSTR (x, 0);
10596 if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
10597 {
10598 cfun->machine->some_ld_name = str;
10599 return 1;
10600 }
10601 }
10602
10603 return 0;
10604 }
10605
10606
10607
10608 void
10609 rs6000_output_function_entry (FILE *file, const char *fname)
10610 {
10611 if (fname[0] != '.')
10612 {
10613 switch (DEFAULT_ABI)
10614 {
10615 default:
10616 abort ();
10617
10618 case ABI_AIX:
10619 if (DOT_SYMBOLS)
10620 putc ('.', file);
10621 else
10622 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "L.");
10623 break;
10624
10625 case ABI_V4:
10626 case ABI_DARWIN:
10627 break;
10628 }
10629 }
10630 if (TARGET_AIX)
10631 RS6000_OUTPUT_BASENAME (file, fname);
10632 else
10633 assemble_name (file, fname);
10634 }
10635
10636
10637
10638 #if TARGET_ELF
10639 #define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
10640 #define SMALL_DATA_REG ((rs6000_sdata == SDATA_EABI) ? 0 : 13)
10641 #else
10642 #define SMALL_DATA_RELOC "sda21"
10643 #define SMALL_DATA_REG 0
10644 #endif
10645
10646 void
10647 print_operand (FILE *file, rtx x, int code)
10648 {
10649 int i;
10650 HOST_WIDE_INT val;
10651 unsigned HOST_WIDE_INT uval;
10652
10653 switch (code)
10654 {
10655 case '.':
10656
10657
10658 asm_fprintf (file, RS6000_CALL_GLUE);
10659 return;
10660
10661
10662
10663 case 'A':
10664
10665
10666
10667
10668 if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0)
10669 putc ('l', file);
10670 else
10671 putc ('r', file);
10672 return;
10673
10674 case 'b':
10675
10676
10677 if (INT_P (x))
10678 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 0xffff);
10679 else
10680 print_operand (file, x, 0);
10681 return;
10682
10683 case 'B':
10684
10685
10686 putc (((INT_LOWPART(x) & 1) == 0 ? 'r' : 'l'), file);
10687 return;
10688
10689
10690
10691
10692 case 'c':
10693
10694 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10695 output_operand_lossage ("invalid %%E value");
10696 else
10697 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
10698 return;
10699
10700 case 'D':
10701
10702 if (GET_CODE (x) != REG)
10703 abort ();
10704
10705
10706 i = 4 * (REGNO (x) - CR0_REGNO) + 2;
10707
10708 fprintf (file, "%d", i);
10709 return;
10710
10711 case 'E':
10712
10713 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10714 output_operand_lossage ("invalid %%E value");
10715 else
10716 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 2);
10717 return;
10718
10719 case 'f':
10720
10721
10722 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10723 output_operand_lossage ("invalid %%f value");
10724 else
10725 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO));
10726 return;
10727
10728 case 'F':
10729
10730
10731 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10732 output_operand_lossage ("invalid %%F value");
10733 else
10734 fprintf (file, "%d", 32 - 4 * (REGNO (x) - CR0_REGNO));
10735 return;
10736
10737 case 'G':
10738
10739
10740 if (GET_CODE (x) != CONST_INT)
10741 output_operand_lossage ("invalid %%G value");
10742 else if (INTVAL (x) >= 0)
10743 putc ('z', file);
10744 else
10745 putc ('m', file);
10746 return;
10747
10748 case 'h':
10749
10750
10751 if (INT_P (x))
10752 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 31);
10753 else
10754 print_operand (file, x, 0);
10755 return;
10756
10757 case 'H':
10758
10759
10760 if (INT_P (x))
10761 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 63);
10762 else
10763 print_operand (file, x, 0);
10764 return;
10765
10766 case 'I':
10767
10768 if (INT_P (x))
10769 putc ('i', file);
10770 return;
10771
10772 case 'j':
10773
10774 i = ccr_bit (x, 0);
10775 if (i == -1)
10776 output_operand_lossage ("invalid %%j code");
10777 else
10778 fprintf (file, "%d", i);
10779 return;
10780
10781 case 'J':
10782
10783
10784 i = ccr_bit (x, 1);
10785 if (i == -1)
10786 output_operand_lossage ("invalid %%J code");
10787 else
10788
10789 fprintf (file, "%d", i == 31 ? 0 : i + 1);
10790 return;
10791
10792 case 'k':
10793
10794
10795 if (! INT_P (x))
10796 output_operand_lossage ("invalid %%k value");
10797 else
10798 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INT_LOWPART (x));
10799 return;
10800
10801 case 'K':
10802
10803
10804
10805 if (GET_CODE (x) != CONST)
10806 {
10807 print_operand_address (file, x);
10808 fputs ("@l", file);
10809 }
10810 else
10811 {
10812 if (GET_CODE (XEXP (x, 0)) != PLUS
10813 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
10814 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
10815 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
10816 output_operand_lossage ("invalid %%K value");
10817 print_operand_address (file, XEXP (XEXP (x, 0), 0));
10818 fputs ("@l", file);
10819
10820
10821
10822 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
10823 fputs ("+", file);
10824 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
10825 }
10826 return;
10827
10828
10829
10830 case 'L':
10831
10832
10833 if (GET_CODE (x) == REG)
10834 fputs (reg_names[REGNO (x) + 1], file);
10835 else if (GET_CODE (x) == MEM)
10836 {
10837
10838
10839 if (GET_CODE (XEXP (x, 0)) == PRE_INC
10840 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
10841 output_address (plus_constant (XEXP (XEXP (x, 0), 0),
10842 UNITS_PER_WORD));
10843 else
10844 output_address (XEXP (adjust_address_nv (x, SImode,
10845 UNITS_PER_WORD),
10846 0));
10847
10848 if (small_data_operand (x, GET_MODE (x)))
10849 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
10850 reg_names[SMALL_DATA_REG]);
10851 }
10852 return;
10853
10854 case 'm':
10855
10856 if (! mask_operand (x, SImode))
10857 output_operand_lossage ("invalid %%m value");
10858
10859 fprintf (file, "%d", extract_MB (x));
10860 return;
10861
10862 case 'M':
10863
10864 if (! mask_operand (x, SImode))
10865 output_operand_lossage ("invalid %%M value");
10866
10867 fprintf (file, "%d", extract_ME (x));
10868 return;
10869
10870
10871
10872 case 'N':
10873
10874 if (GET_CODE (x) != PARALLEL)
10875 output_operand_lossage ("invalid %%N value");
10876 else
10877 fprintf (file, "%d", XVECLEN (x, 0) * 4);
10878 return;
10879
10880 case 'O':
10881
10882 if (GET_CODE (x) != PARALLEL)
10883 output_operand_lossage ("invalid %%O value");
10884 else
10885 fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4);
10886 return;
10887
10888 case 'p':
10889
10890 if (! INT_P (x)
10891 || INT_LOWPART (x) < 0
10892 || (i = exact_log2 (INT_LOWPART (x))) < 0)
10893 output_operand_lossage ("invalid %%p value");
10894 else
10895 fprintf (file, "%d", i);
10896 return;
10897
10898 case 'P':
10899
10900
10901 if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG
10902 || REGNO (XEXP (x, 0)) >= 32)
10903 output_operand_lossage ("invalid %%P value");
10904 else
10905 fputs (reg_names[REGNO (XEXP (x, 0))], file);
10906 return;
10907
10908 case 'q':
10909
10910
10911
10912
10913
10914 {
10915 const char *const *t = 0;
10916 const char *s;
10917 enum rtx_code code = GET_CODE (x);
10918 static const char * const tbl[3][3] = {
10919 { "and", "andc", "nor" },
10920 { "or", "orc", "nand" },
10921 { "xor", "eqv", "xor" } };
10922
10923 if (code == AND)
10924 t = tbl[0];
10925 else if (code == IOR)
10926 t = tbl[1];
10927 else if (code == XOR)
10928 t = tbl[2];
10929 else
10930 output_operand_lossage ("invalid %%q value");
10931
10932 if (GET_CODE (XEXP (x, 0)) != NOT)
10933 s = t[0];
10934 else
10935 {
10936 if (GET_CODE (XEXP (x, 1)) == NOT)
10937 s = t[2];
10938 else
10939 s = t[1];
10940 }
10941
10942 fputs (s, file);
10943 }
10944 return;
10945
10946 case 'Q':
10947 if (TARGET_MFCRF)
10948 fputc (',', file);
10949
10950 else
10951 return;
10952
10953 case 'R':
10954
10955 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
10956 output_operand_lossage ("invalid %%R value");
10957 else
10958 fprintf (file, "%d", 128 >> (REGNO (x) - CR0_REGNO));
10959 return;
10960
10961 case 's':
10962
10963 if (! INT_P (x))
10964 output_operand_lossage ("invalid %%s value");
10965 else
10966 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INT_LOWPART (x)) & 31);
10967 return;
10968
10969 case 'S':
10970
10971
10972
10973 if (! mask64_operand (x, DImode))
10974 output_operand_lossage ("invalid %%S value");
10975
10976 uval = INT_LOWPART (x);
10977
10978 if (uval & 1)
10979 {
10980 #if HOST_BITS_PER_WIDE_INT > 64
10981 uval &= ((unsigned HOST_WIDE_INT) 1 << 64) - 1;
10982 #endif
10983 i = 64;
10984 }
10985 else
10986 {
10987 uval = ~uval;
10988 #if HOST_BITS_PER_WIDE_INT > 64
10989 uval &= ((unsigned HOST_WIDE_INT) 1 << 64) - 1;
10990 #endif
10991 i = 63;
10992 }
10993 while (uval != 0)
10994 --i, uval >>= 1;
10995 if (i < 0)
10996 abort ();
10997 fprintf (file, "%d", i);
10998 return;
10999
11000 case 't':
11001
11002 if (GET_CODE (x) != REG || GET_MODE (x) != CCmode)
11003 abort ();
11004
11005
11006 i = 4 * (REGNO (x) - CR0_REGNO) + 3;
11007
11008
11009 fprintf (file, "%d", i == 31 ? 0 : i + 1);
11010 return;
11011
11012 case 'T':
11013
11014 if (GET_CODE (x) != REG || (REGNO (x) != LINK_REGISTER_REGNUM
11015 && REGNO (x) != COUNT_REGISTER_REGNUM))
11016 output_operand_lossage ("invalid %%T value");
11017 else if (REGNO (x) == LINK_REGISTER_REGNUM)
11018 fputs (TARGET_NEW_MNEMONICS ? "lr" : "r", file);
11019 else
11020 fputs ("ctr", file);
11021 return;
11022
11023 case 'u':
11024
11025 if (! INT_P (x))
11026 output_operand_lossage ("invalid %%u value");
11027 else
11028 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
11029 (INT_LOWPART (x) >> 16) & 0xffff);
11030 return;
11031
11032 case 'v':
11033
11034 if (! INT_P (x))
11035 output_operand_lossage ("invalid %%v value");
11036 else
11037 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
11038 (INT_LOWPART (x) >> 16) & 0xffff);
11039 return;
11040
11041 case 'U':
11042
11043 if (GET_CODE (x) == MEM
11044 && (GET_CODE (XEXP (x, 0)) == PRE_INC
11045 || GET_CODE (XEXP (x, 0)) == PRE_DEC))
11046 putc ('u', file);
11047 return;
11048
11049 case 'V':
11050
11051 switch (GET_CODE (x))
11052 {
11053 case EQ:
11054 fputs ("eq", file);
11055 break;
11056 case NE:
11057 fputs ("ne", file);
11058 break;
11059 case LT:
11060 fputs ("lt", file);
11061 break;
11062 case LE:
11063 fputs ("le", file);
11064 break;
11065 case GT:
11066 fputs ("gt", file);
11067 break;
11068 case GE:
11069 fputs ("ge", file);
11070 break;
11071 case LTU:
11072 fputs ("llt", file);
11073 break;
11074 case LEU:
11075 fputs ("lle", file);
11076 break;
11077 case GTU:
11078 fputs ("lgt", file);
11079 break;
11080 case GEU:
11081 fputs ("lge", file);
11082 break;
11083 default:
11084 abort ();
11085 }
11086 break;
11087
11088 case 'w':
11089
11090
11091 if (INT_P (x))
11092 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
11093 ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000);
11094 else
11095 print_operand (file, x, 0);
11096 return;
11097
11098 case 'W':
11099
11100 val = (GET_CODE (x) == CONST_INT
11101 ? INTVAL (x) : CONST_DOUBLE_HIGH (x));
11102
11103 if (val < 0)
11104 i = -1;
11105 else
11106 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
11107 if ((val <<= 1) < 0)
11108 break;
11109
11110 #if HOST_BITS_PER_WIDE_INT == 32
11111 if (GET_CODE (x) == CONST_INT && i >= 0)
11112 i += 32;
11113 else if (GET_CODE (x) == CONST_DOUBLE && i == 32)
11114 {
11115 val = CONST_DOUBLE_LOW (x);
11116
11117 if (val == 0)
11118 abort ();
11119 else if (val < 0)
11120 --i;
11121 else
11122 for ( ; i < 64; i++)
11123 if ((val <<= 1) < 0)
11124 break;
11125 }
11126 #endif
11127
11128 fprintf (file, "%d", i + 1);
11129 return;
11130
11131 case 'X':
11132 if (GET_CODE (x) == MEM
11133 && legitimate_indexed_address_p (XEXP (x, 0), 0))
11134 putc ('x', file);
11135 return;
11136
11137 case 'Y':
11138
11139 if (GET_CODE (x) == REG)
11140 fputs (reg_names[REGNO (x) + 2], file);
11141 else if (GET_CODE (x) == MEM)
11142 {
11143 if (GET_CODE (XEXP (x, 0)) == PRE_INC
11144 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
11145 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8));
11146 else
11147 output_address (XEXP (adjust_address_nv (x, SImode, 8), 0));
11148 if (small_data_operand (x, GET_MODE (x)))
11149 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
11150 reg_names[SMALL_DATA_REG]);
11151 }
11152 return;
11153
11154 case 'z':
11155
11156
11157
11158
11159
11160 if (GET_CODE (x) != SYMBOL_REF)
11161 abort ();
11162
11163
11164
11165 if (SYMBOL_REF_DECL (x))
11166 mark_decl_referenced (SYMBOL_REF_DECL (x));
11167
11168
11169 if (TARGET_MACHO)
11170 {
11171 const char *name = XSTR (x, 0);
11172 #if TARGET_MACHO
11173 if (MACHOPIC_INDIRECT
11174 && machopic_classify_symbol (x) == MACHOPIC_UNDEFINED_FUNCTION)
11175 name = machopic_indirection_name (x, true);
11176 #endif
11177 assemble_name (file, name);
11178 }
11179 else if (!DOT_SYMBOLS)
11180 assemble_name (file, XSTR (x, 0));
11181 else
11182 rs6000_output_function_entry (file, XSTR (x, 0));
11183 return;
11184
11185 case 'Z':
11186
11187 if (GET_CODE (x) == REG)
11188 fputs (reg_names[REGNO (x) + 3], file);
11189 else if (GET_CODE (x) == MEM)
11190 {
11191 if (GET_CODE (XEXP (x, 0)) == PRE_INC
11192 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
11193 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12));
11194 else
11195 output_address (XEXP (adjust_address_nv (x, SImode, 12), 0));
11196 if (small_data_operand (x, GET_MODE (x)))
11197 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
11198 reg_names[SMALL_DATA_REG]);
11199 }
11200 return;
11201
11202
11203 case 'y':
11204 {
11205 rtx tmp;
11206
11207 if (GET_CODE (x) != MEM)
11208 abort ();
11209
11210 tmp = XEXP (x, 0);
11211
11212 if (TARGET_E500)
11213 {
11214
11215 if (GET_CODE (tmp) == REG)
11216 {
11217 fprintf (file, "0(%s)", reg_names[REGNO (tmp)]);
11218 break;
11219 }
11220
11221 else if (GET_CODE (tmp) == PLUS &&
11222 GET_CODE (XEXP (tmp, 1)) == CONST_INT)
11223 {
11224 int x;
11225
11226 if (GET_CODE (XEXP (tmp, 0)) != REG)
11227 abort ();
11228
11229 x = INTVAL (XEXP (tmp, 1));
11230 fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
11231 break;
11232 }
11233
11234
11235 }
11236 if (TARGET_ALTIVEC
11237 && GET_CODE (tmp) == AND
11238 && GET_CODE (XEXP (tmp, 1)) == CONST_INT
11239 && INTVAL (XEXP (tmp, 1)) == -16)
11240 tmp = XEXP (tmp, 0);
11241 if (GET_CODE (tmp) == REG)
11242 fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
11243 else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
11244 {
11245 if (REGNO (XEXP (tmp, 0)) == 0)
11246 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
11247 reg_names[ REGNO (XEXP (tmp, 0)) ]);
11248 else
11249 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
11250 reg_names[ REGNO (XEXP (tmp, 1)) ]);
11251 }
11252 else
11253 abort ();
11254 break;
11255 }
11256
11257 case 0:
11258 if (GET_CODE (x) == REG)
11259 fprintf (file, "%s", reg_names[REGNO (x)]);
11260 else if (GET_CODE (x) == MEM)
11261 {
11262
11263
11264 if (GET_CODE (XEXP (x, 0)) == PRE_INC)
11265 fprintf (file, "%d(%s)", GET_MODE_SIZE (GET_MODE (x)),
11266 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
11267 else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
11268 fprintf (file, "%d(%s)", - GET_MODE_SIZE (GET_MODE (x)),
11269 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
11270 else
11271 output_address (XEXP (x, 0));
11272 }
11273 else
11274 output_addr_const (file, x);
11275 return;
11276
11277 case '&':
11278 assemble_name (file, rs6000_get_some_local_dynamic_name ());
11279 return;
11280
11281 default:
11282 output_operand_lossage ("invalid %%xn code");
11283 }
11284 }
11285
11286
11287
11288 void
11289 print_operand_address (FILE *file, rtx x)
11290 {
11291 if (GET_CODE (x) == REG)
11292 fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
11293 else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST
11294 || GET_CODE (x) == LABEL_REF)
11295 {
11296 output_addr_const (file, x);
11297 if (small_data_operand (x, GET_MODE (x)))
11298 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
11299 reg_names[SMALL_DATA_REG]);
11300 else if (TARGET_TOC)
11301 abort ();
11302 }
11303 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
11304 {
11305 if (REGNO (XEXP (x, 0)) == 0)
11306 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
11307 reg_names[ REGNO (XEXP (x, 0)) ]);
11308 else
11309 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
11310 reg_names[ REGNO (XEXP (x, 1)) ]);
11311 }
11312 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
11313 fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
11314 INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
11315 #if TARGET_ELF
11316 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
11317 && CONSTANT_P (XEXP (x, 1)))
11318 {
11319 output_addr_const (file, XEXP (x, 1));
11320 fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
11321 }
11322 #endif
11323 #if TARGET_MACHO
11324 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
11325 && CONSTANT_P (XEXP (x, 1)))
11326 {
11327 fprintf (file, "lo16(");
11328 output_addr_const (file, XEXP (x, 1));
11329 fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
11330 }
11331 #endif
11332 else if (legitimate_constant_pool_address_p (x))
11333 {
11334 if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
11335 {
11336 rtx contains_minus = XEXP (x, 1);
11337 rtx minus, symref;
11338 const char *name;
11339
11340
11341
11342 while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
11343 contains_minus = XEXP (contains_minus, 0);
11344
11345 minus = XEXP (contains_minus, 0);
11346 symref = XEXP (minus, 0);
11347 XEXP (contains_minus, 0) = symref;
11348 if (TARGET_ELF)
11349 {
11350 char *newname;
11351
11352 name = XSTR (symref, 0);
11353 newname = alloca (strlen (name) + sizeof ("@toc"));
11354 strcpy (newname, name);
11355 strcat (newname, "@toc");
11356 XSTR (symref, 0) = newname;
11357 }
11358 output_addr_const (file, XEXP (x, 1));
11359 if (TARGET_ELF)
11360 XSTR (symref, 0) = name;
11361 XEXP (contains_minus, 0) = minus;
11362 }
11363 else
11364 output_addr_const (file, XEXP (x, 1));
11365
11366 fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
11367 }
11368 else
11369 abort ();
11370 }
11371
11372
11373
11374
11375
11376
11377 static bool
11378 rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
11379 {
11380 #ifdef RELOCATABLE_NEEDS_FIXUP
11381
11382 if (RELOCATABLE_NEEDS_FIXUP && size == 4 && aligned_p)
11383 {
11384 extern int in_toc_section (void);
11385 static int recurse = 0;
11386
11387
11388
11389 if (TARGET_RELOCATABLE
11390 && !in_toc_section ()
11391 && !in_text_section ()
11392 && !in_unlikely_text_section ()
11393 && !recurse
11394 && GET_CODE (x) != CONST_INT
11395 && GET_CODE (x) != CONST_DOUBLE
11396 && CONSTANT_P (x))
11397 {
11398 char buf[256];
11399
11400 recurse = 1;
11401 ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno);
11402 fixuplabelno++;
11403 ASM_OUTPUT_LABEL (asm_out_file, buf);
11404 fprintf (asm_out_file, "\t.long\t(");
11405 output_addr_const (asm_out_file, x);
11406 fprintf (asm_out_file, ")@fixup\n");
11407 fprintf (asm_out_file, "\t.section\t\".fixup\",\"aw\"\n");
11408 ASM_OUTPUT_ALIGN (asm_out_file, 2);
11409 fprintf (asm_out_file, "\t.long\t");
11410 assemble_name (asm_out_file, buf);
11411 fprintf (asm_out_file, "\n\t.previous\n");
11412 recurse = 0;
11413 return true;
11414 }
11415
11416
11417
11418 else if (GET_CODE (x) == SYMBOL_REF
11419 && XSTR (x, 0)[0] == '.'
11420 && DEFAULT_ABI == ABI_AIX)
11421 {
11422 const char *name = XSTR (x, 0);
11423 while (*name == '.')
11424 name++;
11425
11426 fprintf (asm_out_file, "\t.long\t%s\n", name);
11427 return true;
11428 }
11429 }
11430 #endif
11431 return default_assemble_integer (x, size, aligned_p);
11432 }
11433
11434 #ifdef HAVE_GAS_HIDDEN
11435
11436
11437
11438 static void
11439 rs6000_assemble_visibility (tree decl, int vis)
11440 {
11441
11442
11443 if (DEFAULT_ABI == ABI_AIX
11444 && DOT_SYMBOLS
11445 && TREE_CODE (decl) == FUNCTION_DECL)
11446 {
11447 static const char * const visibility_types[] = {
11448 NULL, "internal", "hidden", "protected"
11449 };
11450
11451 const char *name, *type;
11452
11453 name = ((* targetm.strip_name_encoding)
11454 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
11455 type = visibility_types[vis];
11456
11457 fprintf (asm_out_file, "\t.%s\t%s\n", type, name);
11458 fprintf (asm_out_file, "\t.%s\t.%s\n", type, name);
11459 }
11460 else
11461 default_assemble_visibility (decl, vis);
11462 }
11463 #endif
11464
11465 enum rtx_code
11466 rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code)
11467 {
11468
11469
11470 if (mode == CCFPmode
11471 && (!flag_finite_math_only
11472 || code == UNLT || code == UNLE || code == UNGT || code == UNGE
11473 || code == UNEQ || code == LTGT))
11474 return reverse_condition_maybe_unordered (code);
11475 else
11476 return reverse_condition (code);
11477 }
11478
11479
11480
11481
11482 static rtx
11483 rs6000_generate_compare (enum rtx_code code)
11484 {
11485 enum machine_mode comp_mode;
11486 rtx compare_result;
11487
11488 if (rs6000_compare_fp_p)
11489 comp_mode = CCFPmode;
11490 else if (code == GTU || code == LTU
11491 || code == GEU || code == LEU)
11492 comp_mode = CCUNSmode;
11493 else if ((code == EQ || code == NE)
11494 && GET_CODE (rs6000_compare_op0) == SUBREG
11495 && GET_CODE (rs6000_compare_op1) == SUBREG
11496 && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0)
11497 && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1))
11498
11499
11500
11501
11502 comp_mode = CCUNSmode;
11503 else
11504 comp_mode = CCmode;
11505
11506
11507 compare_result = gen_reg_rtx (comp_mode);
11508
11509
11510 if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
11511 && rs6000_compare_fp_p)
11512 {
11513 rtx cmp, or_result, compare_result2;
11514 enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
11515
11516 if (op_mode == VOIDmode)
11517 op_mode = GET_MODE (rs6000_compare_op1);
11518
11519
11520
11521
11522 switch (code)
11523 {
11524 case EQ: case UNEQ: case NE: case LTGT:
11525 if (op_mode == SFmode)
11526 cmp = flag_unsafe_math_optimizations
11527 ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
11528 rs6000_compare_op1)
11529 : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
11530 rs6000_compare_op1);
11531 else if (op_mode == DFmode)
11532 cmp = flag_unsafe_math_optimizations
11533 ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
11534 rs6000_compare_op1)
11535 : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
11536 rs6000_compare_op1);
11537 else abort ();
11538 break;
11539 case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
11540 if (op_mode == SFmode)
11541 cmp = flag_unsafe_math_optimizations
11542 ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
11543 rs6000_compare_op1)
11544 : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
11545 rs6000_compare_op1);
11546 else if (op_mode == DFmode)
11547 cmp = flag_unsafe_math_optimizations
11548 ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
11549 rs6000_compare_op1)
11550 : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
11551 rs6000_compare_op1);
11552 else abort ();
11553 break;
11554 case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
11555 if (op_mode == SFmode)
11556 cmp = flag_unsafe_math_optimizations
11557 ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
11558 rs6000_compare_op1)
11559 : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
11560 rs6000_compare_op1);
11561 else if (op_mode == DFmode)
11562 cmp = flag_unsafe_math_optimizations
11563 ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
11564 rs6000_compare_op1)
11565 : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
11566 rs6000_compare_op1);
11567 else abort ();
11568 break;
11569 default:
11570 abort ();
11571 }
11572
11573
11574 if (code == LE || code == GE || code == LEU || code == GEU)
11575 {
11576 emit_insn (cmp);
11577
11578 switch (code)
11579 {
11580 case LE: code = LT; break;
11581 case GE: code = GT; break;
11582 case LEU: code = LT; break;
11583 case GEU: code = GT; break;
11584 default: abort ();
11585 }
11586
11587 compare_result2 = gen_reg_rtx (CCFPmode);
11588
11589
11590 if (op_mode == SFmode)
11591 cmp = flag_unsafe_math_optimizations
11592 ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
11593 rs6000_compare_op1)
11594 : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
11595 rs6000_compare_op1);
11596 else if (op_mode == DFmode)
11597 cmp = flag_unsafe_math_optimizations
11598 ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
11599 rs6000_compare_op1)
11600 : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
11601 rs6000_compare_op1);
11602 else abort ();
11603 emit_insn (cmp);
11604
11605
11606 or_result = gen_reg_rtx (CCFPmode);
11607 cmp = gen_e500_cr_ior_compare (or_result, compare_result,
11608 compare_result2);
11609 compare_result = or_result;
11610 code = EQ;
11611 }
11612 else
11613 {
11614 if (code == NE || code == LTGT)
11615 code = NE;
11616 else
11617 code = EQ;
11618 }
11619
11620 emit_insn (cmp);
11621 }
11622 else
11623 {
11624
11625
11626 if (comp_mode == CCFPmode && TARGET_XL_COMPAT
11627 && GET_MODE (rs6000_compare_op0) == TFmode
11628 && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
11629 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
11630 emit_insn (gen_rtx_PARALLEL (VOIDmode,
11631 gen_rtvec (9,
11632 gen_rtx_SET (VOIDmode,
11633 compare_result,
11634 gen_rtx_COMPARE (comp_mode,
11635 rs6000_compare_op0,
11636 rs6000_compare_op1)),
11637 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11638 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11639 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11640 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11641 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11642 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11643 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
11644 gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
11645 else
11646 emit_insn (gen_rtx_SET (VOIDmode, compare_result,
11647 gen_rtx_COMPARE (comp_mode,
11648 rs6000_compare_op0,
11649 rs6000_compare_op1)));
11650 }
11651
11652
11653
11654 if (rs6000_compare_fp_p
11655 && ! flag_unsafe_math_optimizations
11656 && ! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
11657 && (code == LE || code == GE
11658 || code == UNEQ || code == LTGT
11659 || code == UNGT || code == UNLT))
11660 {
11661 enum rtx_code or1, or2;
11662 rtx or1_rtx, or2_rtx, compare2_rtx;
11663 rtx or_result = gen_reg_rtx (CCEQmode);
11664
11665 switch (code)
11666 {
11667 case LE: or1 = LT; or2 = EQ; break;
11668 case GE: or1 = GT; or2 = EQ; break;
11669 case UNEQ: or1 = UNORDERED; or2 = EQ; break;
11670 case LTGT: or1 = LT; or2 = GT; break;
11671 case UNGT: or1 = UNORDERED; or2 = GT; break;
11672 case UNLT: or1 = UNORDERED; or2 = LT; break;
11673 default: abort ();
11674 }
11675 validate_condition_mode (or1, comp_mode);
11676 validate_condition_mode (or2, comp_mode);
11677 or1_rtx = gen_rtx_fmt_ee (or1, SImode, compare_result, const0_rtx);
11678 or2_rtx = gen_rtx_fmt_ee (or2, SImode, compare_result, const0_rtx);
11679 compare2_rtx = gen_rtx_COMPARE (CCEQmode,
11680 gen_rtx_IOR (SImode, or1_rtx, or2_rtx),
11681 const_true_rtx);
11682 emit_insn (gen_rtx_SET (VOIDmode, or_result, compare2_rtx));
11683
11684 compare_result = or_result;
11685 code = EQ;
11686 }
11687
11688 validate_condition_mode (code, GET_MODE (compare_result));
11689
11690 return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
11691 }
11692
11693
11694
11695
11696 void
11697 rs6000_emit_sCOND (enum rtx_code code, rtx result)
11698 {
11699 rtx condition_rtx;
11700 enum machine_mode op_mode;
11701 enum rtx_code cond_code;
11702
11703 condition_rtx = rs6000_generate_compare (code);
11704 cond_code = GET_CODE (condition_rtx);
11705
11706 if (TARGET_E500 && rs6000_compare_fp_p
11707 && !TARGET_FPRS && TARGET_HARD_FLOAT)
11708 {
11709 rtx t;
11710
11711 PUT_MODE (condition_rtx, SImode);
11712 t = XEXP (condition_rtx, 0);
11713
11714 if (cond_code != NE && cond_code != EQ)
11715 abort ();
11716
11717 if (cond_code == NE)
11718 emit_insn (gen_e500_flip_gt_bit (t, t));
11719
11720 emit_insn (gen_move_from_CR_gt_bit (result, t));
11721 return;
11722 }
11723
11724 if (cond_code == NE
11725 || cond_code == GE || cond_code == LE
11726 || cond_code == GEU || cond_code == LEU
11727 || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE)
11728 {
11729 rtx not_result = gen_reg_rtx (CCEQmode);
11730 rtx not_op, rev_cond_rtx;
11731 enum machine_mode cc_mode;
11732
11733 cc_mode = GET_MODE (XEXP (condition_rtx, 0));
11734
11735 rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, cond_code),
11736 SImode, XEXP (condition_rtx, 0), const0_rtx);
11737 not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
11738 emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
11739 condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
11740 }
11741
11742 op_mode = GET_MODE (rs6000_compare_op0);
11743 if (op_mode == VOIDmode)
11744 op_mode = GET_MODE (rs6000_compare_op1);
11745
11746 if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p))
11747 {
11748 PUT_MODE (condition_rtx, DImode);
11749 convert_move (result, condition_rtx, 0);
11750 }
11751 else
11752 {
11753 PUT_MODE (condition_rtx, SImode);
11754 emit_insn (gen_rtx_SET (VOIDmode, result, condition_rtx));
11755 }
11756 }
11757
11758
11759
11760 void
11761 rs6000_emit_cbranch (enum rtx_code code, rtx loc)
11762 {
11763 rtx condition_rtx, loc_ref;
11764
11765 condition_rtx = rs6000_generate_compare (code);
11766 loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
11767 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
11768 gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
11769 loc_ref, pc_rtx)));
11770 }
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784 char *
11785 output_cbranch (rtx op, const char *label, int reversed, rtx insn)
11786 {
11787 static char string[64];
11788 enum rtx_code code = GET_CODE (op);
11789 rtx cc_reg = XEXP (op, 0);
11790 enum machine_mode mode = GET_MODE (cc_reg);
11791 int cc_regno = REGNO (cc_reg) - CR0_REGNO;
11792 int need_longbranch = label != NULL && get_attr_length (insn) == 8;
11793 int really_reversed = reversed ^ need_longbranch;
11794 char *s = string;
11795 const char *ccode;
11796 const char *pred;
11797 rtx note;
11798
11799 validate_condition_mode (code, mode);
11800
11801
11802
11803
11804 if (really_reversed)
11805 {
11806
11807
11808 if (mode == CCFPmode)
11809 code = reverse_condition_maybe_unordered (code);
11810 else
11811 code = reverse_condition (code);
11812 }
11813
11814 if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT) && mode == CCFPmode)
11815 {
11816
11817
11818 if (code == EQ)
11819
11820 code = GT;
11821 else if (code == NE)
11822 code = UNLE;
11823 else
11824 abort ();
11825 }
11826
11827 switch (code)
11828 {
11829
11830
11831 case NE: case LTGT:
11832 ccode = "ne"; break;
11833 case EQ: case UNEQ:
11834 ccode = "eq"; break;
11835 case GE: case GEU:
11836 ccode = "ge"; break;
11837 case GT: case GTU: case UNGT:
11838 ccode = "gt"; break;
11839 case LE: case LEU:
11840 ccode = "le"; break;
11841 case LT: case LTU: case UNLT:
11842 ccode = "lt"; break;
11843 case UNORDERED: ccode = "un"; break;
11844 case ORDERED: ccode = "nu"; break;
11845 case UNGE: ccode = "nl"; break;
11846 case UNLE: ccode = "ng"; break;
11847 default:
11848 abort ();
11849 }
11850
11851
11852
11853 pred = "";
11854 note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
11855 if (note != NULL_RTX)
11856 {
11857
11858 int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
11859
11860
11861
11862
11863
11864
11865
11866 if (rs6000_always_hint
11867 || abs (prob) > REG_BR_PROB_BASE / 100 * 48)
11868 {
11869 if (abs (prob) > REG_BR_PROB_BASE / 20
11870 && ((prob > 0) ^ need_longbranch))
11871 pred = "+";
11872 else
11873 pred = "-";
11874 }
11875 }
11876
11877 if (label == NULL)
11878 s += sprintf (s, "{b%sr|b%slr%s} ", ccode, ccode, pred);
11879 else
11880 s += sprintf (s, "{b%s|b%s%s} ", ccode, ccode, pred);
11881
11882
11883
11884 if (reg_names[cc_regno + CR0_REGNO][0] == '%')
11885 *s++ = '%';
11886 s += sprintf (s, "%s", reg_names[cc_regno + CR0_REGNO]);
11887
11888 if (label != NULL)
11889 {
11890
11891
11892 if (need_longbranch)
11893 s += sprintf (s, ",$+8\n\tb %s", label);
11894 else
11895 s += sprintf (s, ",%s", label);
11896 }
11897
11898 return string;
11899 }
11900
11901
11902 char *
11903 output_e500_flip_gt_bit (rtx dst, rtx src)
11904 {
11905 static char string[64];
11906 int a, b;
11907
11908 if (GET_CODE (dst) != REG || ! CR_REGNO_P (REGNO (dst))
11909 || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
11910 abort ();
11911
11912
11913 a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
11914 b = 4 * (REGNO (src) - CR0_REGNO) + 1;
11915
11916 sprintf (string, "crnot %d,%d", a, b);
11917 return string;
11918 }
11919
11920
11921
11922
11923
11924 static int
11925 get_vec_cmp_insn (enum rtx_code code,
11926 enum machine_mode dest_mode,
11927 enum machine_mode op_mode)
11928 {
11929 if (!TARGET_ALTIVEC)
11930 return INSN_NOT_AVAILABLE;
11931
11932 switch (code)
11933 {
11934 case EQ:
11935 if (dest_mode == V16QImode && op_mode == V16QImode)
11936 return UNSPEC_VCMPEQUB;
11937 if (dest_mode == V8HImode && op_mode == V8HImode)
11938 return UNSPEC_VCMPEQUH;
11939 if (dest_mode == V4SImode && op_mode == V4SImode)
11940 return UNSPEC_VCMPEQUW;
11941 if (dest_mode == V4SImode && op_mode == V4SFmode)
11942 return UNSPEC_VCMPEQFP;
11943 break;
11944 case GE:
11945 if (dest_mode == V4SImode && op_mode == V4SFmode)
11946 return UNSPEC_VCMPGEFP;
11947 case GT:
11948 if (dest_mode == V16QImode && op_mode == V16QImode)
11949 return UNSPEC_VCMPGTSB;
11950 if (dest_mode == V8HImode && op_mode == V8HImode)
11951 return UNSPEC_VCMPGTSH;
11952 if (dest_mode == V4SImode && op_mode == V4SImode)
11953 return UNSPEC_VCMPGTSW;
11954 if (dest_mode == V4SImode && op_mode == V4SFmode)
11955 return UNSPEC_VCMPGTFP;
11956 break;
11957 case GTU:
11958 if (dest_mode == V16QImode && op_mode == V16QImode)
11959 return UNSPEC_VCMPGTUB;
11960 if (dest_mode == V8HImode && op_mode == V8HImode)
11961 return UNSPEC_VCMPGTUH;
11962 if (dest_mode == V4SImode && op_mode == V4SImode)
11963 return UNSPEC_VCMPGTUW;
11964 break;
11965 default:
11966 break;
11967 }
11968 return INSN_NOT_AVAILABLE;
11969 }
11970
11971
11972
11973
11974 static rtx
11975 rs6000_emit_vector_compare (enum rtx_code rcode,
11976 rtx op0, rtx op1,
11977 enum machine_mode dmode)
11978 {
11979 int vec_cmp_insn;
11980 rtx mask;
11981 enum machine_mode dest_mode;
11982 enum machine_mode op_mode = GET_MODE (op1);
11983
11984 #ifdef ENABLE_CHECKING
11985 if (!TARGET_ALTIVEC)
11986 abort ();
11987
11988 if (GET_MODE (op0) != GET_MODE (op1))
11989 abort ();
11990 #endif
11991
11992
11993
11994 if (dmode == V4SFmode)
11995 dest_mode = V4SImode;
11996 else
11997 dest_mode = dmode;
11998
11999 mask = gen_reg_rtx (dest_mode);
12000 vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
12001
12002 if (vec_cmp_insn == INSN_NOT_AVAILABLE)
12003 {
12004 bool swap_operands = false;
12005 bool try_again = false;
12006 switch (rcode)
12007 {
12008 case LT:
12009 rcode = GT;
12010 swap_operands = true;
12011 try_again = true;
12012 break;
12013 case LTU:
12014 rcode = GTU;
12015 swap_operands = true;
12016 try_again = true;
12017 break;
12018 case NE:
12019
12020 {
12021 enum insn_code nor_code;
12022 rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
12023 dest_mode);
12024
12025 nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code;
12026 if (nor_code == CODE_FOR_nothing)
12027 abort ();
12028 emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
12029
12030 if (dmode != dest_mode)
12031 {
12032 rtx temp = gen_reg_rtx (dest_mode);
12033 convert_move (temp, mask, 0);
12034 return temp;
12035 }
12036 return mask;
12037 }
12038 break;
12039 case GE:
12040 case GEU:
12041 case LE:
12042 case LEU:
12043
12044 {
12045 rtx c_rtx, eq_rtx;
12046 enum insn_code ior_code;
12047 enum rtx_code new_code;
12048
12049 if (rcode == GE)
12050 new_code = GT;
12051 else if (rcode == GEU)
12052 new_code = GTU;
12053 else if (rcode == LE)
12054 new_code = LT;
12055 else if (rcode == LEU)
12056 new_code = LTU;
12057 else
12058 abort ();
12059
12060 c_rtx = rs6000_emit_vector_compare (new_code,
12061 op0, op1, dest_mode);
12062 eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
12063 dest_mode);
12064
12065 ior_code = ior_optab->handlers[(int)dest_mode].insn_code;
12066 if (ior_code == CODE_FOR_nothing)
12067 abort ();
12068 emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
12069 if (dmode != dest_mode)
12070 {
12071 rtx temp = gen_reg_rtx (dest_mode);
12072 convert_move (temp, mask, 0);
12073 return temp;
12074 }
12075 return mask;
12076 }
12077 break;
12078 default:
12079 abort ();
12080 }
12081
12082 if (try_again)
12083 {
12084 vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
12085 if (vec_cmp_insn == INSN_NOT_AVAILABLE)
12086
12087 abort ();
12088 }
12089
12090 if (swap_operands)
12091 {
12092 rtx tmp;
12093 tmp = op0;
12094 op0 = op1;
12095 op1 = tmp;
12096 }
12097 }
12098
12099 emit_insn (gen_rtx_fmt_ee (SET,
12100 VOIDmode,
12101 mask,
12102 gen_rtx_fmt_Ei (UNSPEC, dest_mode,
12103 gen_rtvec (2, op0, op1),
12104 vec_cmp_insn)));
12105 if (dmode != dest_mode)
12106 {
12107 rtx temp = gen_reg_rtx (dest_mode);
12108 convert_move (temp, mask, 0);
12109 return temp;
12110 }
12111 return mask;
12112 }
12113
12114
12115
12116
12117 static int
12118 get_vsel_insn (enum machine_mode mode)
12119 {
12120 switch (mode)
12121 {
12122 case V4SImode:
12123 return UNSPEC_VSEL4SI;
12124 break;
12125 case V4SFmode:
12126 return UNSPEC_VSEL4SF;
12127 break;
12128 case V8HImode:
12129 return UNSPEC_VSEL8HI;
12130 break;
12131 case V16QImode:
12132 return UNSPEC_VSEL16QI;
12133 break;
12134 default:
12135 return INSN_NOT_AVAILABLE;
12136 break;
12137 }
12138 return INSN_NOT_AVAILABLE;
12139 }
12140
12141
12142
12143
12144 static void
12145 rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
12146 {
12147 rtx t, temp;
12148 enum machine_mode dest_mode = GET_MODE (dest);
12149 int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
12150
12151 temp = gen_reg_rtx (dest_mode);
12152
12153 t = gen_rtx_fmt_ee (SET, VOIDmode, temp,
12154 gen_rtx_fmt_Ei (UNSPEC, dest_mode,
12155 gen_rtvec (3, op1, op2, mask),
12156 vsel_insn_index));
12157 emit_insn (t);
12158 emit_move_insn (dest, temp);
12159 return;
12160 }
12161
12162
12163
12164
12165
12166 int
12167 rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
12168 rtx cond, rtx cc_op0, rtx cc_op1)
12169 {
12170 enum machine_mode dest_mode = GET_MODE (dest);
12171 enum rtx_code rcode = GET_CODE (cond);
12172 rtx mask;
12173
12174 if (!TARGET_ALTIVEC)
12175 return 0;
12176
12177
12178 mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
12179
12180 rs6000_emit_vector_select (dest, op1, op2, mask);
12181
12182 return 1;
12183 }
12184
12185
12186
12187
12188
12189 int
12190 rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
12191 {
12192 enum rtx_code code = GET_CODE (op);
12193 rtx op0 = rs6000_compare_op0;
12194 rtx op1 = rs6000_compare_op1;
12195 REAL_VALUE_TYPE c1;
12196 enum machine_mode compare_mode = GET_MODE (op0);
12197 enum machine_mode result_mode = GET_MODE (dest);
12198 rtx temp;
12199 bool is_against_zero;
12200
12201
12202 if (GET_MODE (op1) != compare_mode
12203
12204
12205 && (!TARGET_ISEL || !short_cint_operand (op1, VOIDmode)))
12206 return 0;
12207 if (GET_MODE (true_cond) != result_mode)
12208 return 0;
12209 if (GET_MODE (false_cond) != result_mode)
12210 return 0;
12211
12212
12213
12214 if (! rs6000_compare_fp_p)
12215 {
12216 if (TARGET_ISEL)
12217 return rs6000_emit_int_cmove (dest, op, true_cond, false_cond);
12218 return 0;
12219 }
12220 else if (TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS
12221 && GET_MODE_CLASS (compare_mode) == MODE_FLOAT)
12222 return 0;
12223
12224 is_against_zero = op1 == CONST0_RTX (compare_mode);
12225
12226
12227
12228
12229
12230
12231 if (GET_MODE_CLASS (compare_mode) == MODE_FLOAT
12232 && flag_trapping_math && ! is_against_zero)
12233 return 0;
12234
12235
12236
12237 if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
12238 || code == LTGT || code == LT || code == UNLE)
12239 {
12240 code = reverse_condition_maybe_unordered (code);
12241 temp = true_cond;
12242 true_cond = false_cond;
12243 false_cond = temp;
12244 }
12245
12246
12247
12248 if (code == UNEQ && HONOR_NANS (compare_mode))
12249 return 0;
12250
12251 if (GET_CODE (op1) == CONST_DOUBLE)
12252 REAL_VALUE_FROM_CONST_DOUBLE (c1, op1);
12253
12254
12255
12256
12257
12258
12259 if (HONOR_INFINITIES (compare_mode)
12260 && code != GT && code != UNGE
12261 && (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1))
12262
12263 && ((! rtx_equal_p (op0, false_cond) && ! rtx_equal_p (op1, false_cond))
12264 || (! rtx_equal_p (op0, true_cond)
12265 && ! rtx_equal_p (op1, true_cond))))
12266 return 0;
12267
12268
12269
12270
12271 if (! is_against_zero)
12272 {
12273 temp = gen_reg_rtx (compare_mode);
12274 emit_insn (gen_rtx_SET (VOIDmode, temp,
12275 gen_rtx_MINUS (compare_mode, op0, op1)));
12276 op0 = temp;
12277 op1 = CONST0_RTX (compare_mode);
12278 }
12279
12280
12281
12282 if (! HONOR_NANS (compare_mode))
12283 switch (code)
12284 {
12285 case GT:
12286 code = LE;
12287 temp = true_cond;
12288 true_cond = false_cond;
12289 false_cond = temp;
12290 break;
12291 case UNGE:
12292 code = GE;
12293 break;
12294 case UNEQ:
12295 code = EQ;
12296 break;
12297 default:
12298 break;
12299 }
12300
12301
12302 switch (code)
12303 {
12304 case GE:
12305 break;
12306
12307 case LE:
12308 temp = gen_reg_rtx (compare_mode);
12309 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12310 op0 = temp;
12311 break;
12312
12313 case ORDERED:
12314 temp = gen_reg_rtx (compare_mode);
12315 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (compare_mode, op0)));
12316 op0 = temp;
12317 break;
12318
12319 case EQ:
12320 temp = gen_reg_rtx (compare_mode);
12321 emit_insn (gen_rtx_SET (VOIDmode, temp,
12322 gen_rtx_NEG (compare_mode,
12323 gen_rtx_ABS (compare_mode, op0))));
12324 op0 = temp;
12325 break;
12326
12327 case UNGE:
12328
12329 temp = gen_reg_rtx (result_mode);
12330 emit_insn (gen_rtx_SET (VOIDmode, temp,
12331 gen_rtx_IF_THEN_ELSE (result_mode,
12332 gen_rtx_GE (VOIDmode,
12333 op0, op1),
12334 true_cond, false_cond)));
12335 false_cond = true_cond;
12336 true_cond = temp;
12337
12338 temp = gen_reg_rtx (compare_mode);
12339 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12340 op0 = temp;
12341 break;
12342
12343 case GT:
12344
12345 temp = gen_reg_rtx (result_mode);
12346 emit_insn (gen_rtx_SET (VOIDmode, temp,
12347 gen_rtx_IF_THEN_ELSE (result_mode,
12348 gen_rtx_GE (VOIDmode,
12349 op0, op1),
12350 true_cond, false_cond)));
12351 true_cond = false_cond;
12352 false_cond = temp;
12353
12354 temp = gen_reg_rtx (compare_mode);
12355 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
12356 op0 = temp;
12357 break;
12358
12359 default:
12360 abort ();
12361 }
12362
12363 emit_insn (gen_rtx_SET (VOIDmode, dest,
12364 gen_rtx_IF_THEN_ELSE (result_mode,
12365 gen_rtx_GE (VOIDmode,
12366 op0, op1),
12367 true_cond, false_cond)));
12368 return 1;
12369 }
12370
12371
12372
12373 static int
12374 rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
12375 {
12376 rtx condition_rtx, cr;
12377
12378
12379 if (GET_MODE (rs6000_compare_op0) != SImode)
12380 return 0;
12381
12382
12383
12384
12385 condition_rtx = rs6000_generate_compare (GET_CODE (op));
12386 cr = XEXP (condition_rtx, 0);
12387
12388 if (GET_MODE (cr) == CCmode)
12389 emit_insn (gen_isel_signed (dest, condition_rtx,
12390 true_cond, false_cond, cr));
12391 else
12392 emit_insn (gen_isel_unsigned (dest, condition_rtx,
12393 true_cond, false_cond, cr));
12394
12395 return 1;
12396 }
12397
12398 const char *
12399 output_isel (rtx *operands)
12400 {
12401 enum rtx_code code;
12402
12403 code = GET_CODE (operands[1]);
12404 if (code == GE || code == GEU || code == LE || code == LEU || code == NE)
12405 {
12406 PUT_CODE (operands[1], reverse_condition (code));
12407 return "isel %0,%3,%2,%j1";
12408 }
12409 else
12410 return "isel %0,%2,%3,%j1";
12411 }
12412
12413 void
12414 rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
12415 {
12416 enum machine_mode mode = GET_MODE (op0);
12417 enum rtx_code c;
12418 rtx target;
12419
12420 if (code == SMAX || code == SMIN)
12421 c = GE;
12422 else
12423 c = GEU;
12424
12425 if (code == SMAX || code == UMAX)
12426 target = emit_conditional_move (dest, c, op0, op1, mode,
12427 op0, op1, mode, 0);
12428 else
12429 target = emit_conditional_move (dest, c, op0, op1, mode,
12430 op1, op0, mode, 0);
12431 if (target == NULL_RTX)
12432 abort ();
12433 if (target != dest)
12434 emit_move_insn (dest, target);
12435 }
12436
12437
12438
12439
12440
12441
12442
12443 void
12444 rs6000_split_multireg_move (rtx dst, rtx src)
12445 {
12446
12447 int reg;
12448
12449 enum machine_mode mode;
12450
12451 enum machine_mode reg_mode;
12452 int reg_mode_size;
12453
12454 int nregs;
12455
12456 reg = REG_P (dst) ? REGNO (dst) : REGNO (src);
12457 mode = GET_MODE (dst);
12458 nregs = HARD_REGNO_NREGS (reg, mode);
12459 if (FP_REGNO_P (reg))
12460 reg_mode = DFmode;
12461 else if (ALTIVEC_REGNO_P (reg))
12462 reg_mode = V16QImode;
12463 else
12464 reg_mode = word_mode;
12465 reg_mode_size = GET_MODE_SIZE (reg_mode);
12466
12467 if (reg_mode_size * nregs != GET_MODE_SIZE (mode))
12468 abort ();
12469
12470 if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
12471 {
12472
12473
12474 int i;
12475 for (i = nregs - 1; i >= 0; i--)
12476 emit_insn (gen_rtx_SET (VOIDmode,
12477 simplify_gen_subreg (reg_mode, dst, mode,
12478 i * reg_mode_size),
12479 simplify_gen_subreg (reg_mode, src, mode,
12480 i * reg_mode_size)));
12481 }
12482 else
12483 {
12484 int i;
12485 int j = -1;
12486 bool used_update = false;
12487
12488 if (MEM_P (src) && INT_REGNO_P (reg))
12489 {
12490 rtx breg;
12491
12492 if (GET_CODE (XEXP (src, 0)) == PRE_INC
12493 || GET_CODE (XEXP (src, 0)) == PRE_DEC)
12494 {
12495 rtx delta_rtx;
12496 breg = XEXP (XEXP (src, 0), 0);
12497 delta_rtx = (GET_CODE (XEXP (src, 0)) == PRE_INC
12498 ? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
12499 : GEN_INT (-GET_MODE_SIZE (GET_MODE (src))));
12500 emit_insn (TARGET_32BIT
12501 ? gen_addsi3 (breg, breg, delta_rtx)
12502 : gen_adddi3 (breg, breg, delta_rtx));
12503 src = gen_rtx_MEM (mode, breg);
12504 }
12505 else if (! offsettable_memref_p (src))
12506 {
12507 rtx newsrc, basereg;
12508 basereg = gen_rtx_REG (Pmode, reg);
12509 emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
12510 newsrc = gen_rtx_MEM (GET_MODE (src), basereg);
12511 MEM_COPY_ATTRIBUTES (newsrc, src);
12512 src = newsrc;
12513 }
12514
12515 breg = XEXP (src, 0);
12516 if (GET_CODE (breg) == PLUS || GET_CODE (breg) == LO_SUM)
12517 breg = XEXP (breg, 0);
12518
12519
12520
12521 if (REG_P (breg)
12522 && REGNO (breg) >= REGNO (dst)
12523 && REGNO (breg) < REGNO (dst) + nregs)
12524 j = REGNO (breg) - REGNO (dst);
12525 }
12526
12527 if (GET_CODE (dst) == MEM && INT_REGNO_P (reg))
12528 {
12529 rtx breg;
12530
12531 if (GET_CODE (XEXP (dst, 0)) == PRE_INC
12532 || GET_CODE (XEXP (dst, 0)) == PRE_DEC)
12533 {
12534 rtx delta_rtx;
12535 breg = XEXP (XEXP (dst, 0), 0);
12536 delta_rtx = (GET_CODE (XEXP (dst, 0)) == PRE_INC
12537 ? GEN_INT (GET_MODE_SIZE (GET_MODE (dst)))
12538 : GEN_INT (-GET_MODE_SIZE (GET_MODE (dst))));
12539
12540
12541
12542
12543 if (TARGET_UPDATE)
12544 {
12545 rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
12546 emit_insn (TARGET_32BIT
12547 ? (TARGET_POWERPC64
12548 ? gen_movdi_si_update (breg, breg, delta_rtx, nsrc)
12549 : gen_movsi_update (breg, breg, delta_rtx, nsrc))
12550 : gen_movdi_di_update (breg, breg, delta_rtx, nsrc));
12551 used_update = true;
12552 }
12553 else
12554 emit_insn (TARGET_32BIT
12555 ? gen_addsi3 (breg, breg, delta_rtx)
12556 : gen_adddi3 (breg, breg, delta_rtx));
12557 dst = gen_rtx_MEM (mode, breg);
12558 }
12559 else if (! offsettable_memref_p (dst))
12560 abort ();
12561 }
12562
12563 for (i = 0; i < nregs; i++)
12564 {
12565
12566 ++j;
12567 if (j == nregs)
12568 j = 0;
12569
12570
12571
12572 if (j == 0 && used_update)
12573 continue;
12574
12575 emit_insn (gen_rtx_SET (VOIDmode,
12576 simplify_gen_subreg (reg_mode, dst, mode,
12577 j * reg_mode_size),
12578 simplify_gen_subreg (reg_mode, src, mode,
12579 j * reg_mode_size)));
12580 }
12581 }
12582 }
12583
12584
12585
12586
12587
12588
12589
12590
12591 int
12592 first_reg_to_save (void)
12593 {
12594 int first_reg;
12595
12596
12597 for (first_reg = 13; first_reg <= 31; first_reg++)
12598 if (regs_ever_live[first_reg]
12599 && (! call_used_regs[first_reg]
12600 || (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
12601 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
12602 || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
12603 || (TARGET_TOC && TARGET_MINIMAL_TOC)))))
12604 break;
12605
12606 #if TARGET_MACHO
12607 if (flag_pic
12608 && current_function_uses_pic_offset_table
12609 && first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM)
12610 return RS6000_PIC_OFFSET_TABLE_REGNUM;
12611 #endif
12612
12613 return first_reg;
12614 }
12615
12616
12617
12618 int
12619 first_fp_reg_to_save (void)
12620 {
12621 int first_reg;
12622
12623
12624 for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
12625 if (regs_ever_live[first_reg])
12626 break;
12627
12628 return first_reg;
12629 }
12630
12631
12632
12633 static int
12634 first_altivec_reg_to_save (void)
12635 {
12636 int i;
12637
12638
12639 if (! TARGET_ALTIVEC_ABI)
12640 return LAST_ALTIVEC_REGNO + 1;
12641
12642
12643 for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
12644 if (regs_ever_live[i])
12645 break;
12646
12647 return i;
12648 }
12649
12650
12651
12652
12653
12654 static unsigned int
12655 compute_vrsave_mask (void)
12656 {
12657 unsigned int i, mask = 0;
12658
12659
12660 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
12661 if (regs_ever_live[i])
12662 mask |= ALTIVEC_REG_BIT (i);
12663
12664 if (mask == 0)
12665 return mask;
12666
12667
12668
12669
12670
12671
12672 for (i = cfun->args_info.vregno - 1; i >= ALTIVEC_ARG_MIN_REG; --i)
12673 mask &= ~ALTIVEC_REG_BIT (i);
12674
12675
12676 {
12677 bool yes = false;
12678 diddle_return_value (is_altivec_return_reg, &yes);
12679 if (yes)
12680 mask &= ~ALTIVEC_REG_BIT (ALTIVEC_ARG_RETURN);
12681 }
12682
12683 return mask;
12684 }
12685
12686
12687
12688
12689
12690 static void
12691 compute_save_world_info (rs6000_stack_t *info_ptr)
12692 {
12693 info_ptr->world_save_p = 1;
12694 info_ptr->world_save_p
12695 = (WORLD_SAVE_P (info_ptr)
12696 && DEFAULT_ABI == ABI_DARWIN
12697 && ! (current_function_calls_setjmp && flag_exceptions)
12698 && info_ptr->first_fp_reg_save == FIRST_SAVED_FP_REGNO
12699 && info_ptr->first_gp_reg_save == FIRST_SAVED_GP_REGNO
12700 && info_ptr->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
12701 && info_ptr->cr_save_p);
12702
12703
12704
12705 if (WORLD_SAVE_P (info_ptr))
12706 {
12707 rtx insn;
12708 for ( insn = get_last_insn_anywhere (); insn; insn = PREV_INSN (insn))
12709 if ( GET_CODE (insn) == CALL_INSN
12710 && SIBLING_CALL_P (insn))
12711 {
12712 info_ptr->world_save_p = 0;
12713 break;
12714 }
12715 }
12716
12717 if (WORLD_SAVE_P (info_ptr))
12718 {
12719
12720
12721
12722 info_ptr->vrsave_size = 4;
12723
12724
12725 if (info_ptr->vrsave_mask == 0)
12726 info_ptr->vrsave_mask = compute_vrsave_mask ();
12727
12728
12729
12730
12731 if (info_ptr->first_fp_reg_save < FIRST_SAVED_FP_REGNO
12732 || info_ptr->first_altivec_reg_save < FIRST_SAVED_ALTIVEC_REGNO)
12733 abort ();
12734 }
12735 return;
12736 }
12737
12738
12739 static void
12740 is_altivec_return_reg (rtx reg, void *xyes)
12741 {
12742 bool *yes = (bool *) xyes;
12743 if (REGNO (reg) == ALTIVEC_ARG_RETURN)
12744 *yes = true;
12745 }
12746
12747
12748
12749
12750
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826
12827
12828
12829
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841 #ifndef ABI_STACK_BOUNDARY
12842 #define ABI_STACK_BOUNDARY STACK_BOUNDARY
12843 #endif
12844
12845 static rs6000_stack_t *
12846 rs6000_stack_info (void)
12847 {
12848 static rs6000_stack_t info, zero_info;
12849 rs6000_stack_t *info_ptr = &info;
12850 int reg_size = TARGET_32BIT ? 4 : 8;
12851 int ehrd_size;
12852 int save_align;
12853 HOST_WIDE_INT non_fixed_size;
12854
12855
12856 info = zero_info;
12857
12858 if (TARGET_SPE)
12859 {
12860
12861 if (cfun->machine->insn_chain_scanned_p == 0)
12862 cfun->machine->insn_chain_scanned_p
12863 = spe_func_has_64bit_regs_p () + 1;
12864 info_ptr->spe_64bit_regs_used = cfun->machine->insn_chain_scanned_p - 1;
12865 }
12866
12867
12868 info_ptr->abi = DEFAULT_ABI;
12869
12870
12871 info_ptr->first_gp_reg_save = first_reg_to_save ();
12872
12873
12874 if (((TARGET_TOC && TARGET_MINIMAL_TOC)
12875 || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
12876 || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
12877 && info_ptr->first_gp_reg_save > RS6000_PIC_OFFSET_TABLE_REGNUM)
12878 info_ptr->gp_size = reg_size * (32 - RS6000_PIC_OFFSET_TABLE_REGNUM);
12879 else
12880 info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save);
12881
12882
12883
12884
12885
12886
12887
12888
12889
12890
12891
12892
12893
12894 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
12895 info_ptr->gp_size = 0;
12896
12897 info_ptr->first_fp_reg_save = first_fp_reg_to_save ();
12898 info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);
12899
12900 info_ptr->first_altivec_reg_save = first_altivec_reg_to_save ();
12901 info_ptr->altivec_size = 16 * (LAST_ALTIVEC_REGNO + 1
12902 - info_ptr->first_altivec_reg_save);
12903
12904
12905 info_ptr->calls_p = (! current_function_is_leaf
12906 || cfun->machine->ra_needs_full_frame);
12907
12908
12909 if (rs6000_ra_ever_killed ()
12910 || (DEFAULT_ABI == ABI_AIX
12911 && current_function_profile
12912 && !TARGET_PROFILE_KERNEL)
12913 #ifdef TARGET_RELOCATABLE
12914 || (TARGET_RELOCATABLE && (get_pool_size () != 0))
12915 #endif
12916 || (info_ptr->first_fp_reg_save != 64
12917 && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
12918 || info_ptr->first_altivec_reg_save <= LAST_ALTIVEC_REGNO
12919 || (DEFAULT_ABI == ABI_V4 && current_function_calls_alloca)
12920 || (DEFAULT_ABI == ABI_DARWIN
12921 && flag_pic
12922 && current_function_uses_pic_offset_table)
12923 || info_ptr->calls_p)
12924 {
12925 info_ptr->lr_save_p = 1;
12926 regs_ever_live[LINK_REGISTER_REGNUM] = 1;
12927 }
12928
12929
12930 if (regs_ever_live[CR2_REGNO]
12931 || regs_ever_live[CR3_REGNO]
12932 || regs_ever_live[CR4_REGNO])
12933 {
12934 info_ptr->cr_save_p = 1;
12935 if (DEFAULT_ABI == ABI_V4)
12936 info_ptr->cr_size = reg_size;
12937 }
12938
12939
12940
12941
12942 if (current_function_calls_eh_return)
12943 {
12944 unsigned int i;
12945 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
12946 continue;
12947
12948
12949 ehrd_size = i * (TARGET_SPE_ABI
12950 && info_ptr->spe_64bit_regs_used != 0
12951 ? UNITS_PER_SPE_WORD : UNITS_PER_WORD);
12952 }
12953 else
12954 ehrd_size = 0;
12955
12956
12957 info_ptr->reg_size = reg_size;
12958 info_ptr->fixed_size = RS6000_SAVE_AREA;
12959 info_ptr->varargs_size = RS6000_VARARGS_AREA;
12960 info_ptr->vars_size = RS6000_ALIGN (get_frame_size (), 8);
12961 info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
12962 TARGET_ALTIVEC ? 16 : 8);
12963
12964 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
12965 info_ptr->spe_gp_size = 8 * (32 - info_ptr->first_gp_reg_save);
12966 else
12967 info_ptr->spe_gp_size = 0;
12968
12969 if (TARGET_ALTIVEC_ABI)
12970 info_ptr->vrsave_mask = compute_vrsave_mask ();
12971 else
12972 info_ptr->vrsave_mask = 0;
12973
12974 if (TARGET_ALTIVEC_VRSAVE && info_ptr->vrsave_mask)
12975 info_ptr->vrsave_size = 4;
12976 else
12977 info_ptr->vrsave_size = 0;
12978
12979 compute_save_world_info (info_ptr);
12980
12981
12982 switch (DEFAULT_ABI)
12983 {
12984 case ABI_NONE:
12985 default:
12986 abort ();
12987
12988 case ABI_AIX:
12989 case ABI_DARWIN:
12990 info_ptr->fp_save_offset = - info_ptr->fp_size;
12991 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
12992
12993 if (TARGET_ALTIVEC_ABI)
12994 {
12995 info_ptr->vrsave_save_offset
12996 = info_ptr->gp_save_offset - info_ptr->vrsave_size;
12997
12998
12999 if (info_ptr->altivec_size != 0)
13000 info_ptr->altivec_padding_size
13001 = 16 - (-info_ptr->vrsave_save_offset % 16);
13002 else
13003 info_ptr->altivec_padding_size = 0;
13004
13005 info_ptr->altivec_save_offset
13006 = info_ptr->vrsave_save_offset
13007 - info_ptr->altivec_padding_size
13008 - info_ptr->altivec_size;
13009
13010
13011 info_ptr->ehrd_offset = info_ptr->altivec_save_offset - ehrd_size;
13012 }
13013 else
13014 info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
13015 info_ptr->cr_save_offset = reg_size;
13016 info_ptr->lr_save_offset = 2*reg_size;
13017 break;
13018
13019 case ABI_V4:
13020 info_ptr->fp_save_offset = - info_ptr->fp_size;
13021 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
13022 info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
13023
13024 if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
13025 {
13026
13027
13028 if (info_ptr->spe_gp_size != 0)
13029 info_ptr->spe_padding_size
13030 = 8 - (-info_ptr->cr_save_offset % 8);
13031 else
13032 info_ptr->spe_padding_size = 0;
13033
13034 info_ptr->spe_gp_save_offset
13035 = info_ptr->cr_save_offset
13036 - info_ptr->spe_padding_size
13037 - info_ptr->spe_gp_size;
13038
13039
13040 info_ptr->toc_save_offset
13041 = info_ptr->spe_gp_save_offset - info_ptr->toc_size;
13042 }
13043 else if (TARGET_ALTIVEC_ABI)
13044 {
13045 info_ptr->vrsave_save_offset
13046 = info_ptr->cr_save_offset - info_ptr->vrsave_size;
13047
13048
13049 if (info_ptr->altivec_size != 0)
13050 info_ptr->altivec_padding_size
13051 = 16 - (-info_ptr->vrsave_save_offset % 16);
13052 else
13053 info_ptr->altivec_padding_size = 0;
13054
13055 info_ptr->altivec_save_offset
13056 = info_ptr->vrsave_save_offset
13057 - info_ptr->altivec_padding_size
13058 - info_ptr->altivec_size;
13059
13060
13061 info_ptr->toc_save_offset
13062 = info_ptr->altivec_save_offset - info_ptr->toc_size;
13063 }
13064 else
13065 info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->toc_size;
13066 info_ptr->ehrd_offset = info_ptr->toc_save_offset - ehrd_size;
13067 info_ptr->lr_save_offset = reg_size;
13068 break;
13069 }
13070
13071 save_align = (TARGET_ALTIVEC_ABI || DEFAULT_ABI == ABI_DARWIN) ? 16 : 8;
13072 info_ptr->save_size = RS6000_ALIGN (info_ptr->fp_size
13073 + info_ptr->gp_size
13074 + info_ptr->altivec_size
13075 + info_ptr->altivec_padding_size
13076 + info_ptr->spe_gp_size
13077 + info_ptr->spe_padding_size
13078 + ehrd_size
13079 + info_ptr->cr_size
13080 + info_ptr->lr_size
13081 + info_ptr->vrsave_size
13082 + info_ptr->toc_size,
13083 save_align);
13084
13085 non_fixed_size = (info_ptr->vars_size
13086 + info_ptr->parm_size
13087 + info_ptr->save_size
13088 + info_ptr->varargs_size);
13089
13090 info_ptr->total_size = RS6000_ALIGN (non_fixed_size + info_ptr->fixed_size,
13091 ABI_STACK_BOUNDARY / BITS_PER_UNIT);
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105 if (info_ptr->calls_p)
13106 info_ptr->push_p = 1;
13107
13108 else if (DEFAULT_ABI == ABI_V4)
13109 info_ptr->push_p = non_fixed_size != 0;
13110
13111 else if (frame_pointer_needed)
13112 info_ptr->push_p = 1;
13113
13114 else if (TARGET_XCOFF && write_symbols != NO_DEBUG)
13115 info_ptr->push_p = 1;
13116
13117 else
13118 info_ptr->push_p = non_fixed_size > (TARGET_32BIT ? 220 : 288);
13119
13120
13121 if (info_ptr->fp_size == 0)
13122 info_ptr->fp_save_offset = 0;
13123
13124 if (info_ptr->gp_size == 0)
13125 info_ptr->gp_save_offset = 0;
13126
13127 if (! TARGET_ALTIVEC_ABI || info_ptr->altivec_size == 0)
13128 info_ptr->altivec_save_offset = 0;
13129
13130 if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
13131 info_ptr->vrsave_save_offset = 0;
13132
13133 if (! TARGET_SPE_ABI
13134 || info_ptr->spe_64bit_regs_used == 0
13135 || info_ptr->spe_gp_size == 0)
13136 info_ptr->spe_gp_save_offset = 0;
13137
13138 if (! info_ptr->lr_save_p)
13139 info_ptr->lr_save_offset = 0;
13140
13141 if (! info_ptr->cr_save_p)
13142 info_ptr->cr_save_offset = 0;
13143
13144 if (! info_ptr->toc_save_p)
13145 info_ptr->toc_save_offset = 0;
13146
13147 return info_ptr;
13148 }
13149
13150
13151
13152
13153 static bool
13154 spe_func_has_64bit_regs_p (void)
13155 {
13156 rtx insns, insn;
13157
13158
13159
13160 if (current_function_calls_eh_return
13161 || current_function_calls_setjmp
13162 || current_function_has_nonlocal_goto)
13163 return true;
13164
13165 insns = get_insns ();
13166
13167 for (insn = NEXT_INSN (insns); insn != NULL_RTX; insn = NEXT_INSN (insn))
13168 {
13169 if (INSN_P (insn))
13170 {
13171 rtx i;
13172
13173
13174
13175
13176
13177
13178
13179
13180 i = PATTERN (insn);
13181 if (GET_CODE (i) == SET)
13182 {
13183 enum machine_mode mode = GET_MODE (SET_SRC (i));
13184
13185 if (SPE_VECTOR_MODE (mode))
13186 return true;
13187 if (TARGET_E500_DOUBLE && mode == DFmode)
13188 return true;
13189 }
13190 }
13191 }
13192
13193 return false;
13194 }
13195
13196 static void
13197 debug_stack_info (rs6000_stack_t *info)
13198 {
13199 const char *abi_string;
13200
13201 if (! info)
13202 info = rs6000_stack_info ();
13203
13204 fprintf (stderr, "\nStack information for function %s:\n",
13205 ((current_function_decl && DECL_NAME (current_function_decl))
13206 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
13207 : "<unknown>"));
13208
13209 switch (info->abi)
13210 {
13211 default: abi_string = "Unknown"; break;
13212 case ABI_NONE: abi_string = "NONE"; break;
13213 case ABI_AIX: abi_string = "AIX"; break;
13214 case ABI_DARWIN: abi_string = "Darwin"; break;
13215 case ABI_V4: abi_string = "V.4"; break;
13216 }
13217
13218 fprintf (stderr, "\tABI = %5s\n", abi_string);
13219
13220 if (TARGET_ALTIVEC_ABI)
13221 fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
13222
13223 if (TARGET_SPE_ABI)
13224 fprintf (stderr, "\tSPE ABI extensions enabled.\n");
13225
13226 if (info->first_gp_reg_save != 32)
13227 fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
13228
13229 if (info->first_fp_reg_save != 64)
13230 fprintf (stderr, "\tfirst_fp_reg_save = %5d\n", info->first_fp_reg_save);
13231
13232 if (info->first_altivec_reg_save <= LAST_ALTIVEC_REGNO)
13233 fprintf (stderr, "\tfirst_altivec_reg_save = %5d\n",
13234 info->first_altivec_reg_save);
13235
13236 if (info->lr_save_p)
13237 fprintf (stderr, "\tlr_save_p = %5d\n", info->lr_save_p);
13238
13239 if (info->cr_save_p)
13240 fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
13241
13242 if (info->toc_save_p)
13243 fprintf (stderr, "\ttoc_save_p = %5d\n", info->toc_save_p);
13244
13245 if (info->vrsave_mask)
13246 fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
13247
13248 if (info->push_p)
13249 fprintf (stderr, "\tpush_p = %5d\n", info->push_p);
13250
13251 if (info->calls_p)
13252 fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p);
13253
13254 if (info->gp_save_offset)
13255 fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
13256
13257 if (info->fp_save_offset)
13258 fprintf (stderr, "\tfp_save_offset = %5d\n", info->fp_save_offset);
13259
13260 if (info->altivec_save_offset)
13261 fprintf (stderr, "\taltivec_save_offset = %5d\n",
13262 info->altivec_save_offset);
13263
13264 if (info->spe_gp_save_offset)
13265 fprintf (stderr, "\tspe_gp_save_offset = %5d\n",
13266 info->spe_gp_save_offset);
13267
13268 if (info->vrsave_save_offset)
13269 fprintf (stderr, "\tvrsave_save_offset = %5d\n",
13270 info->vrsave_save_offset);
13271
13272 if (info->lr_save_offset)
13273 fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
13274
13275 if (info->cr_save_offset)
13276 fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
13277
13278 if (info->toc_save_offset)
13279 fprintf (stderr, "\ttoc_save_offset = %5d\n", info->toc_save_offset);
13280
13281 if (info->varargs_save_offset)
13282 fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
13283
13284 if (info->total_size)
13285 fprintf (stderr, "\ttotal_size = "HOST_WIDE_INT_PRINT_DEC"\n",
13286 info->total_size);
13287
13288 if (info->varargs_size)
13289 fprintf (stderr, "\tvarargs_size = %5d\n", info->varargs_size);
13290
13291 if (info->vars_size)
13292 fprintf (stderr, "\tvars_size = "HOST_WIDE_INT_PRINT_DEC"\n",
13293 info->vars_size);
13294
13295 if (info->parm_size)
13296 fprintf (stderr, "\tparm_size = %5d\n", info->parm_size);
13297
13298 if (info->fixed_size)
13299 fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
13300
13301 if (info->gp_size)
13302 fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
13303
13304 if (info->spe_gp_size)
13305 fprintf (stderr, "\tspe_gp_size = %5d\n", info->spe_gp_size);
13306
13307 if (info->fp_size)
13308 fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
13309
13310 if (info->altivec_size)
13311 fprintf (stderr, "\taltivec_size = %5d\n", info->altivec_size);
13312
13313 if (info->vrsave_size)
13314 fprintf (stderr, "\tvrsave_size = %5d\n", info->vrsave_size);
13315
13316 if (info->altivec_padding_size)
13317 fprintf (stderr, "\taltivec_padding_size= %5d\n",
13318 info->altivec_padding_size);
13319
13320 if (info->spe_padding_size)
13321 fprintf (stderr, "\tspe_padding_size = %5d\n",
13322 info->spe_padding_size);
13323
13324 if (info->lr_size)
13325 fprintf (stderr, "\tlr_size = %5d\n", info->lr_size);
13326
13327 if (info->cr_size)
13328 fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
13329
13330 if (info->toc_size)
13331 fprintf (stderr, "\ttoc_size = %5d\n", info->toc_size);
13332
13333 if (info->save_size)
13334 fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
13335
13336 if (info->reg_size != 4)
13337 fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
13338
13339 fprintf (stderr, "\n");
13340 }
13341
13342 rtx
13343 rs6000_return_addr (int count, rtx frame)
13344 {
13345
13346
13347
13348 if (count != 0 || (DEFAULT_ABI != ABI_AIX && flag_pic))
13349 {
13350 cfun->machine->ra_needs_full_frame = 1;
13351
13352 return
13353 gen_rtx_MEM
13354 (Pmode,
13355 memory_address
13356 (Pmode,
13357 plus_constant (copy_to_reg
13358 (gen_rtx_MEM (Pmode,
13359 memory_address (Pmode, frame))),
13360 RETURN_ADDRESS_OFFSET)));
13361 }
13362
13363 cfun->machine->ra_need_lr = 1;
13364 return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
13365 }
13366
13367
13368
13369
13370
13371
13372
13373
13374 static bool
13375 rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
13376 {
13377 tree type;
13378 if (decl)
13379 {
13380 if (TARGET_ALTIVEC_VRSAVE)
13381 {
13382 for (type = TYPE_ARG_TYPES (TREE_TYPE (decl));
13383 type; type = TREE_CHAIN (type))
13384 {
13385 if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE)
13386 return false;
13387 }
13388 }
13389 if (DEFAULT_ABI == ABI_DARWIN
13390 || (*targetm.binds_local_p) (decl))
13391 {
13392 tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl));
13393
13394 if (!lookup_attribute ("longcall", attr_list)
13395 || lookup_attribute ("shortcall", attr_list))
13396 return true;
13397 }
13398 }
13399 return false;
13400 }
13401
13402 static int
13403 rs6000_ra_ever_killed (void)
13404 {
13405 rtx top;
13406 rtx reg;
13407 rtx insn;
13408
13409 if (current_function_is_thunk)
13410 return 0;
13411
13412
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428 push_topmost_sequence ();
13429 top = get_insns ();
13430 pop_topmost_sequence ();
13431 reg = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
13432
13433 for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
13434 {
13435 if (INSN_P (insn))
13436 {
13437 if (FIND_REG_INC_NOTE (insn, reg))
13438 return 1;
13439 else if (GET_CODE (insn) == CALL_INSN
13440 && !SIBLING_CALL_P (insn))
13441 return 1;
13442 else if (set_of (reg, insn) != NULL_RTX
13443 && !prologue_epilogue_contains (insn))
13444 return 1;
13445 }
13446 }
13447 return 0;
13448 }
13449
13450
13451 static void
13452 rs6000_maybe_dead (rtx insn)
13453 {
13454 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
13455 const0_rtx,
13456 REG_NOTES (insn));
13457 }
13458
13459
13460
13461
13462
13463 void
13464 rs6000_emit_load_toc_table (int fromprolog)
13465 {
13466 rtx dest, insn;
13467 dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
13468
13469 if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
13470 {
13471 rtx temp = (fromprolog
13472 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
13473 : gen_reg_rtx (Pmode));
13474 insn = emit_insn (gen_load_toc_v4_pic_si (temp));
13475 if (fromprolog)
13476 rs6000_maybe_dead (insn);
13477 insn = emit_move_insn (dest, temp);
13478 if (fromprolog)
13479 rs6000_maybe_dead (insn);
13480 }
13481 else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
13482 {
13483 char buf[30];
13484 rtx tempLR = (fromprolog
13485 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
13486 : gen_reg_rtx (Pmode));
13487 rtx temp0 = (fromprolog
13488 ? gen_rtx_REG (Pmode, 0)
13489 : gen_reg_rtx (Pmode));
13490
13491 if (fromprolog)
13492 {
13493 rtx symF, symL;
13494
13495 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
13496 symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13497
13498 ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
13499 symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13500
13501 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1 (tempLR,
13502 symF)));
13503 rs6000_maybe_dead (emit_move_insn (dest, tempLR));
13504 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest,
13505 symL,
13506 symF)));
13507 }
13508 else
13509 {
13510 rtx tocsym;
13511
13512 tocsym = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
13513 emit_insn (gen_load_toc_v4_PIC_1b (tempLR, tocsym));
13514 emit_move_insn (dest, tempLR);
13515 emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
13516 }
13517 insn = emit_insn (gen_addsi3 (dest, temp0, dest));
13518 if (fromprolog)
13519 rs6000_maybe_dead (insn);
13520 }
13521 else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
13522 {
13523
13524 char buf[30];
13525 rtx realsym;
13526 ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
13527 realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
13528
13529 insn = emit_insn (gen_elf_high (dest, realsym));
13530 if (fromprolog)
13531 rs6000_maybe_dead (insn);
13532 insn = emit_insn (gen_elf_low (dest, dest, realsym));
13533 if (fromprolog)
13534 rs6000_maybe_dead (insn);
13535 }
13536 else if (DEFAULT_ABI == ABI_AIX)
13537 {
13538 if (TARGET_32BIT)
13539 insn = emit_insn (gen_load_toc_aix_si (dest));
13540 else
13541 insn = emit_insn (gen_load_toc_aix_di (dest));
13542 if (fromprolog)
13543 rs6000_maybe_dead (insn);
13544 }
13545 else
13546 abort ();
13547 }
13548
13549
13550
13551
13552 void
13553 rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
13554 {
13555 rs6000_stack_t *info = rs6000_stack_info ();
13556 rtx operands[2];
13557
13558 operands[0] = source;
13559 operands[1] = scratch;
13560
13561 if (info->lr_save_p)
13562 {
13563 rtx frame_rtx = stack_pointer_rtx;
13564 HOST_WIDE_INT sp_offset = 0;
13565 rtx tmp;
13566
13567 if (frame_pointer_needed
13568 || current_function_calls_alloca
13569 || info->total_size > 32767)
13570 {
13571 emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
13572 frame_rtx = operands[1];
13573 }
13574 else if (info->push_p)
13575 sp_offset = info->total_size;
13576
13577 tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
13578 tmp = gen_rtx_MEM (Pmode, tmp);
13579 emit_move_insn (tmp, operands[0]);
13580 }
13581 else
13582 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
13583 }
13584
13585 static GTY(()) int set = -1;
13586
13587 int
13588 get_TOC_alias_set (void)
13589 {
13590 if (set == -1)
13591 set = new_alias_set ();
13592 return set;
13593 }
13594
13595
13596
13597
13598 #if TARGET_ELF
13599 static int
13600 uses_TOC (void)
13601 {
13602 rtx insn;
13603
13604 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
13605 if (INSN_P (insn))
13606 {
13607 rtx pat = PATTERN (insn);
13608 int i;
13609
13610 if (GET_CODE (pat) == PARALLEL)
13611 for (i = 0; i < XVECLEN (pat, 0); i++)
13612 {
13613 rtx sub = XVECEXP (pat, 0, i);
13614 if (GET_CODE (sub) == USE)
13615 {
13616 sub = XEXP (sub, 0);
13617 if (GET_CODE (sub) == UNSPEC
13618 && XINT (sub, 1) == UNSPEC_TOC)
13619 return 1;
13620 }
13621 }
13622 }
13623 return 0;
13624 }
13625 #endif
13626
13627 rtx
13628 create_TOC_reference (rtx symbol)
13629 {
13630 return gen_rtx_PLUS (Pmode,
13631 gen_rtx_REG (Pmode, TOC_REGISTER),
13632 gen_rtx_CONST (Pmode,
13633 gen_rtx_MINUS (Pmode, symbol,
13634 gen_rtx_SYMBOL_REF (Pmode, toc_label_name))));
13635 }
13636
13637
13638
13639
13640
13641 void
13642 rs6000_aix_emit_builtin_unwind_init (void)
13643 {
13644 rtx mem;
13645 rtx stack_top = gen_reg_rtx (Pmode);
13646 rtx opcode_addr = gen_reg_rtx (Pmode);
13647 rtx opcode = gen_reg_rtx (SImode);
13648 rtx tocompare = gen_reg_rtx (SImode);
13649 rtx no_toc_save_needed = gen_label_rtx ();
13650
13651 mem = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
13652 emit_move_insn (stack_top, mem);
13653
13654 mem = gen_rtx_MEM (Pmode,
13655 gen_rtx_PLUS (Pmode, stack_top,
13656 GEN_INT (2 * GET_MODE_SIZE (Pmode))));
13657 emit_move_insn (opcode_addr, mem);
13658 emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
13659 emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
13660 : 0xE8410028, SImode));
13661
13662 do_compare_rtx_and_jump (opcode, tocompare, EQ, 1,
13663 SImode, NULL_RTX, NULL_RTX,
13664 no_toc_save_needed);
13665
13666 mem = gen_rtx_MEM (Pmode,
13667 gen_rtx_PLUS (Pmode, stack_top,
13668 GEN_INT (5 * GET_MODE_SIZE (Pmode))));
13669 emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
13670 emit_label (no_toc_save_needed);
13671 }
13672
13673
13674
13675
13676 static void
13677 rs6000_emit_stack_tie (void)
13678 {
13679 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
13680
13681 set_mem_alias_set (mem, rs6000_sr_alias_set);
13682 emit_insn (gen_stack_tie (mem));
13683 }
13684
13685
13686
13687
13688
13689 static void
13690 rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
13691 {
13692 rtx insn;
13693 rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
13694 rtx tmp_reg = gen_rtx_REG (Pmode, 0);
13695 rtx todec = gen_int_mode (-size, Pmode);
13696
13697 if (INTVAL (todec) != -size)
13698 {
13699 warning("stack frame too large");
13700 emit_insn (gen_trap ());
13701 return;
13702 }
13703
13704 if (current_function_limit_stack)
13705 {
13706 if (REG_P (stack_limit_rtx)
13707 && REGNO (stack_limit_rtx) > 1
13708 && REGNO (stack_limit_rtx) <= 31)
13709 {
13710 emit_insn (TARGET_32BIT
13711 ? gen_addsi3 (tmp_reg,
13712 stack_limit_rtx,
13713 GEN_INT (size))
13714 : gen_adddi3 (tmp_reg,
13715 stack_limit_rtx,
13716 GEN_INT (size)));
13717
13718 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
13719 const0_rtx));
13720 }
13721 else if (GET_CODE (stack_limit_rtx) == SYMBOL_REF
13722 && TARGET_32BIT
13723 && DEFAULT_ABI == ABI_V4)
13724 {
13725 rtx toload = gen_rtx_CONST (VOIDmode,
13726 gen_rtx_PLUS (Pmode,
13727 stack_limit_rtx,
13728 GEN_INT (size)));
13729
13730 emit_insn (gen_elf_high (tmp_reg, toload));
13731 emit_insn (gen_elf_low (tmp_reg, tmp_reg, toload));
13732 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
13733 const0_rtx));
13734 }
13735 else
13736 warning ("stack limit expression is not supported");
13737 }
13738
13739 if (copy_r12 || ! TARGET_UPDATE)
13740 emit_move_insn (gen_rtx_REG (Pmode, 12), stack_reg);
13741
13742 if (TARGET_UPDATE)
13743 {
13744 if (size > 32767)
13745 {
13746
13747 if (get_last_insn() == NULL_RTX)
13748 emit_note (NOTE_INSN_DELETED);
13749 insn = emit_move_insn (tmp_reg, todec);
13750 try_split (PATTERN (insn), insn, 0);
13751 todec = tmp_reg;
13752 }
13753
13754 insn = emit_insn (TARGET_32BIT
13755 ? gen_movsi_update (stack_reg, stack_reg,
13756 todec, stack_reg)
13757 : gen_movdi_di_update (stack_reg, stack_reg,
13758 todec, stack_reg));
13759 }
13760 else
13761 {
13762 insn = emit_insn (TARGET_32BIT
13763 ? gen_addsi3 (stack_reg, stack_reg, todec)
13764 : gen_adddi3 (stack_reg, stack_reg, todec));
13765 emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
13766 gen_rtx_REG (Pmode, 12));
13767 }
13768
13769 RTX_FRAME_RELATED_P (insn) = 1;
13770 REG_NOTES (insn) =
13771 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
13772 gen_rtx_SET (VOIDmode, stack_reg,
13773 gen_rtx_PLUS (Pmode, stack_reg,
13774 GEN_INT (-size))),
13775 REG_NOTES (insn));
13776 }
13777
13778
13779
13780
13781
13782
13783
13784 static void
13785 rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
13786 rtx reg2, rtx rreg)
13787 {
13788 rtx real, temp;
13789
13790
13791
13792 if (reg == reg2)
13793 reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
13794
13795 if (reg == rreg)
13796 reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
13797
13798 real = copy_rtx (PATTERN (insn));
13799
13800 if (reg2 != NULL_RTX)
13801 real = replace_rtx (real, reg2, rreg);
13802
13803 real = replace_rtx (real, reg,
13804 gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
13805 STACK_POINTER_REGNUM),
13806 GEN_INT (val)));
13807
13808
13809
13810
13811
13812 if (GET_CODE (real) == SET)
13813 {
13814 rtx set = real;
13815
13816 temp = simplify_rtx (SET_SRC (set));
13817 if (temp)
13818 SET_SRC (set) = temp;
13819 temp = simplify_rtx (SET_DEST (set));
13820 if (temp)
13821 SET_DEST (set) = temp;
13822 if (GET_CODE (SET_DEST (set)) == MEM)
13823 {
13824 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
13825 if (temp)
13826 XEXP (SET_DEST (set), 0) = temp;
13827 }
13828 }
13829 else if (GET_CODE (real) == PARALLEL)
13830 {
13831 int i;
13832 for (i = 0; i < XVECLEN (real, 0); i++)
13833 if (GET_CODE (XVECEXP (real, 0, i)) == SET)
13834 {
13835 rtx set = XVECEXP (real, 0, i);
13836
13837 temp = simplify_rtx (SET_SRC (set));
13838 if (temp)
13839 SET_SRC (set) = temp;
13840 temp = simplify_rtx (SET_DEST (set));
13841 if (temp)
13842 SET_DEST (set) = temp;
13843 if (GET_CODE (SET_DEST (set)) == MEM)
13844 {
13845 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
13846 if (temp)
13847 XEXP (SET_DEST (set), 0) = temp;
13848 }
13849 RTX_FRAME_RELATED_P (set) = 1;
13850 }
13851 }
13852 else
13853 abort ();
13854
13855 if (TARGET_SPE)
13856 real = spe_synthesize_frame_save (real);
13857
13858 RTX_FRAME_RELATED_P (insn) = 1;
13859 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
13860 real,
13861 REG_NOTES (insn));
13862 }
13863
13864
13865
13866
13867 static rtx
13868 spe_synthesize_frame_save (rtx real)
13869 {
13870 rtx synth, offset, reg, real2;
13871
13872 if (GET_CODE (real) != SET
13873 || GET_MODE (SET_SRC (real)) != V2SImode)
13874 return real;
13875
13876
13877
13878
13879
13880
13881
13882 if (GET_CODE (SET_DEST (real)) != MEM
13883 || GET_CODE (XEXP (SET_DEST (real), 0)) != PLUS
13884 || GET_CODE (SET_SRC (real)) != REG)
13885 abort ();
13886
13887
13888
13889
13890
13891
13892
13893
13894
13895 real2 = copy_rtx (real);
13896 PUT_MODE (SET_DEST (real2), SImode);
13897 reg = SET_SRC (real2);
13898 real2 = replace_rtx (real2, reg, gen_rtx_REG (SImode, REGNO (reg)));
13899 synth = copy_rtx (real2);
13900
13901 if (BYTES_BIG_ENDIAN)
13902 {
13903 offset = XEXP (XEXP (SET_DEST (real2), 0), 1);
13904 real2 = replace_rtx (real2, offset, GEN_INT (INTVAL (offset) + 4));
13905 }
13906
13907 reg = SET_SRC (synth);
13908
13909 synth = replace_rtx (synth, reg,
13910 gen_rtx_REG (SImode, REGNO (reg) + 1200));
13911
13912 offset = XEXP (XEXP (SET_DEST (synth), 0), 1);
13913 synth = replace_rtx (synth, offset,
13914 GEN_INT (INTVAL (offset)
13915 + (BYTES_BIG_ENDIAN ? 0 : 4)));
13916
13917 RTX_FRAME_RELATED_P (synth) = 1;
13918 RTX_FRAME_RELATED_P (real2) = 1;
13919 if (BYTES_BIG_ENDIAN)
13920 real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, synth, real2));
13921 else
13922 real = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, real2, synth));
13923
13924 return real;
13925 }
13926
13927
13928
13929
13930 static rtx
13931 generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
13932 {
13933 int nclobs, i;
13934 rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
13935 rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
13936
13937 clobs[0]
13938 = gen_rtx_SET (VOIDmode,
13939 vrsave,
13940 gen_rtx_UNSPEC_VOLATILE (SImode,
13941 gen_rtvec (2, reg, vrsave),
13942 30));
13943
13944 nclobs = 1;
13945
13946
13947
13948
13949
13950
13951
13952
13953
13954
13955
13956
13957
13958
13959
13960 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
13961 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
13962 {
13963 if (!epiloguep || call_used_regs [i])
13964 clobs[nclobs++] = gen_rtx_CLOBBER (VOIDmode,
13965 gen_rtx_REG (V4SImode, i));
13966 else
13967 {
13968 rtx reg = gen_rtx_REG (V4SImode, i);
13969
13970 clobs[nclobs++]
13971 = gen_rtx_SET (VOIDmode,
13972 reg,
13973 gen_rtx_UNSPEC (V4SImode,
13974 gen_rtvec (1, reg), 27));
13975 }
13976 }
13977
13978 insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
13979
13980 for (i = 0; i < nclobs; ++i)
13981 XVECEXP (insn, 0, i) = clobs[i];
13982
13983 return insn;
13984 }
13985
13986
13987
13988
13989 static void
13990 emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
13991 unsigned int regno, int offset, HOST_WIDE_INT total_size)
13992 {
13993 rtx reg, offset_rtx, insn, mem, addr, int_rtx;
13994 rtx replacea, replaceb;
13995
13996 int_rtx = GEN_INT (offset);
13997
13998
13999 if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
14000 || (TARGET_E500_DOUBLE && mode == DFmode)
14001 || (TARGET_SPE_ABI
14002 && SPE_VECTOR_MODE (mode)
14003 && !SPE_CONST_OFFSET_OK (offset)))
14004 {
14005
14006
14007 offset_rtx = gen_rtx_REG (Pmode, 11);
14008 emit_move_insn (offset_rtx, int_rtx);
14009
14010 replacea = offset_rtx;
14011 replaceb = int_rtx;
14012 }
14013 else
14014 {
14015 offset_rtx = int_rtx;
14016 replacea = NULL_RTX;
14017 replaceb = NULL_RTX;
14018 }
14019
14020 reg = gen_rtx_REG (mode, regno);
14021 addr = gen_rtx_PLUS (Pmode, frame_reg, offset_rtx);
14022 mem = gen_rtx_MEM (mode, addr);
14023 set_mem_alias_set (mem, rs6000_sr_alias_set);
14024
14025 insn = emit_move_insn (mem, reg);
14026
14027 rs6000_frame_related (insn, frame_ptr, total_size, replacea, replaceb);
14028 }
14029
14030
14031
14032
14033 static rtx
14034 gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
14035 {
14036 rtx int_rtx, offset_rtx;
14037
14038 int_rtx = GEN_INT (offset);
14039
14040 if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
14041 || (TARGET_E500_DOUBLE && mode == DFmode))
14042 {
14043 offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
14044 emit_move_insn (offset_rtx, int_rtx);
14045 }
14046 else
14047 offset_rtx = int_rtx;
14048
14049 return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, reg, offset_rtx));
14050 }
14051
14052 #ifndef TARGET_FIX_AND_CONTINUE
14053 #define TARGET_FIX_AND_CONTINUE 0
14054 #endif
14055
14056
14057
14058 void
14059 rs6000_emit_prologue (void)
14060 {
14061 rs6000_stack_t *info = rs6000_stack_info ();
14062 enum machine_mode reg_mode = Pmode;
14063 int reg_size = TARGET_32BIT ? 4 : 8;
14064 rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
14065 rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
14066 rtx frame_reg_rtx = sp_reg_rtx;
14067 rtx cr_save_rtx = NULL_RTX;
14068 rtx insn;
14069 int saving_FPRs_inline;
14070 int using_store_multiple;
14071 HOST_WIDE_INT sp_offset = 0;
14072
14073 if (TARGET_FIX_AND_CONTINUE)
14074 {
14075
14076
14077
14078
14079
14080 emit_insn (gen_nop ());
14081 emit_insn (gen_nop ());
14082 emit_insn (gen_nop ());
14083 emit_insn (gen_nop ());
14084 }
14085
14086 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14087 {
14088 reg_mode = V2SImode;
14089 reg_size = 8;
14090 }
14091
14092 using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
14093 && (!TARGET_SPE_ABI
14094 || info->spe_64bit_regs_used == 0)
14095 && info->first_gp_reg_save < 31);
14096 saving_FPRs_inline = (info->first_fp_reg_save == 64
14097 || FP_SAVE_INLINE (info->first_fp_reg_save)
14098 || current_function_calls_eh_return
14099 || cfun->machine->ra_need_lr);
14100
14101
14102 if (info->push_p
14103 && (DEFAULT_ABI == ABI_V4
14104 || current_function_calls_eh_return))
14105 {
14106 if (info->total_size < 32767)
14107 sp_offset = info->total_size;
14108 else
14109 frame_reg_rtx = frame_ptr_rtx;
14110 rs6000_emit_allocate_stack (info->total_size,
14111 (frame_reg_rtx != sp_reg_rtx
14112 && (info->cr_save_p
14113 || info->lr_save_p
14114 || info->first_fp_reg_save < 64
14115 || info->first_gp_reg_save < 32
14116 )));
14117 if (frame_reg_rtx != sp_reg_rtx)
14118 rs6000_emit_stack_tie ();
14119 }
14120
14121
14122 if (WORLD_SAVE_P (info))
14123 {
14124 int i, j, sz;
14125 rtx treg;
14126 rtvec p;
14127
14128
14129 if (info->lr_save_p)
14130 {
14131 insn = emit_move_insn (gen_rtx_REG (Pmode, 0),
14132 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
14133 RTX_FRAME_RELATED_P (insn) = 1;
14134 }
14135
14136
14137
14138
14139 if (info->gp_save_offset != -220
14140 || info->fp_save_offset != -144
14141 || info->lr_save_offset != 8
14142 || info->cr_save_offset != 4
14143 || !info->push_p
14144 || !info->lr_save_p
14145 || (current_function_calls_eh_return && info->ehrd_offset != -432)
14146 || (info->vrsave_save_offset != -224
14147 || info->altivec_save_offset != (-224 -16 -192)))
14148 abort ();
14149
14150 treg = gen_rtx_REG (SImode, 11);
14151 emit_move_insn (treg, GEN_INT (-info->total_size));
14152
14153
14154
14155
14156
14157 sz = 6;
14158 sz += 32 - info->first_gp_reg_save;
14159 sz += 64 - info->first_fp_reg_save;
14160 sz += LAST_ALTIVEC_REGNO - info->first_altivec_reg_save + 1;
14161 p = rtvec_alloc (sz);
14162 j = 0;
14163 RTVEC_ELT (p, j++) = gen_rtx_CLOBBER (VOIDmode,
14164 gen_rtx_REG (Pmode,
14165 LINK_REGISTER_REGNUM));
14166 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
14167 gen_rtx_SYMBOL_REF (Pmode,
14168 "*save_world"));
14169
14170
14171 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14172 {
14173 rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14174 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14175 GEN_INT (info->fp_save_offset
14176 + sp_offset + 8 * i));
14177 rtx mem = gen_rtx_MEM (DFmode, addr);
14178 set_mem_alias_set (mem, rs6000_sr_alias_set);
14179
14180 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14181 }
14182 for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
14183 {
14184 rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
14185 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14186 GEN_INT (info->altivec_save_offset
14187 + sp_offset + 16 * i));
14188 rtx mem = gen_rtx_MEM (V4SImode, addr);
14189 set_mem_alias_set (mem, rs6000_sr_alias_set);
14190
14191 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14192 }
14193 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14194 {
14195 rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14196 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14197 GEN_INT (info->gp_save_offset
14198 + sp_offset + reg_size * i));
14199 rtx mem = gen_rtx_MEM (reg_mode, addr);
14200 set_mem_alias_set (mem, rs6000_sr_alias_set);
14201
14202 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14203 }
14204
14205 {
14206
14207 rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
14208 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14209 GEN_INT (info->cr_save_offset
14210 + sp_offset));
14211 rtx mem = gen_rtx_MEM (reg_mode, addr);
14212 set_mem_alias_set (mem, rs6000_sr_alias_set);
14213
14214 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
14215 }
14216
14217 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 0));
14218 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode, treg);
14219 RTVEC_ELT (p, j++) = gen_rtx_CLOBBER (VOIDmode, sp_reg_rtx);
14220
14221 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14222 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14223 NULL_RTX, NULL_RTX);
14224
14225 if (current_function_calls_eh_return)
14226 {
14227 unsigned int i;
14228 for (i = 0; ; ++i)
14229 {
14230 unsigned int regno = EH_RETURN_DATA_REGNO (i);
14231 if (regno == INVALID_REGNUM)
14232 break;
14233 emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, regno,
14234 info->ehrd_offset + sp_offset
14235 + reg_size * (int) i,
14236 info->total_size);
14237 }
14238 }
14239 }
14240
14241
14242 if (!WORLD_SAVE_P (info) && TARGET_ALTIVEC_ABI && info->altivec_size != 0)
14243 {
14244 int i;
14245
14246
14247
14248 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
14249 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
14250 {
14251 rtx areg, savereg, mem;
14252 int offset;
14253
14254 offset = info->altivec_save_offset + sp_offset
14255 + 16 * (i - info->first_altivec_reg_save);
14256
14257 savereg = gen_rtx_REG (V4SImode, i);
14258
14259 areg = gen_rtx_REG (Pmode, 0);
14260 emit_move_insn (areg, GEN_INT (offset));
14261
14262
14263 mem = gen_rtx_MEM (V4SImode,
14264 gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
14265
14266 set_mem_alias_set (mem, rs6000_sr_alias_set);
14267
14268 insn = emit_move_insn (mem, savereg);
14269
14270 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14271 areg, GEN_INT (offset));
14272 }
14273 }
14274
14275
14276
14277
14278
14279
14280
14281
14282 if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
14283 && !WORLD_SAVE_P (info) && info->vrsave_mask != 0)
14284 {
14285 rtx reg, mem, vrsave;
14286 int offset;
14287
14288
14289
14290
14291 reg = gen_rtx_REG (SImode, 0);
14292 vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
14293 if (TARGET_MACHO)
14294 emit_insn (gen_get_vrsave_internal (reg));
14295 else
14296 emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
14297
14298
14299 offset = info->vrsave_save_offset + sp_offset;
14300 mem
14301 = gen_rtx_MEM (SImode,
14302 gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (offset)));
14303 set_mem_alias_set (mem, rs6000_sr_alias_set);
14304 insn = emit_move_insn (mem, reg);
14305
14306
14307 emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
14308
14309 insn = emit_insn (generate_set_vrsave (reg, info, 0));
14310 }
14311
14312
14313 if (!WORLD_SAVE_P (info) && info->lr_save_p)
14314 {
14315 insn = emit_move_insn (gen_rtx_REG (Pmode, 0),
14316 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
14317 RTX_FRAME_RELATED_P (insn) = 1;
14318 }
14319
14320
14321 if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
14322 {
14323 rtx set;
14324
14325 cr_save_rtx = gen_rtx_REG (SImode, 12);
14326 insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
14327 RTX_FRAME_RELATED_P (insn) = 1;
14328
14329
14330
14331
14332
14333
14334 set = gen_rtx_SET (VOIDmode, cr_save_rtx,
14335 gen_rtx_REG (SImode, CR2_REGNO));
14336 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
14337 set,
14338 REG_NOTES (insn));
14339 }
14340
14341
14342
14343 if (!WORLD_SAVE_P (info) && saving_FPRs_inline)
14344 {
14345 int i;
14346 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14347 if ((regs_ever_live[info->first_fp_reg_save+i]
14348 && ! call_used_regs[info->first_fp_reg_save+i]))
14349 emit_frame_save (frame_reg_rtx, frame_ptr_rtx, DFmode,
14350 info->first_fp_reg_save + i,
14351 info->fp_save_offset + sp_offset + 8 * i,
14352 info->total_size);
14353 }
14354 else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
14355 {
14356 int i;
14357 char rname[30];
14358 const char *alloc_rname;
14359 rtvec p;
14360 p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
14361
14362 RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
14363 gen_rtx_REG (Pmode,
14364 LINK_REGISTER_REGNUM));
14365 sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
14366 info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
14367 alloc_rname = ggc_strdup (rname);
14368 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
14369 gen_rtx_SYMBOL_REF (Pmode,
14370 alloc_rname));
14371 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
14372 {
14373 rtx addr, reg, mem;
14374 reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14375 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14376 GEN_INT (info->fp_save_offset
14377 + sp_offset + 8*i));
14378 mem = gen_rtx_MEM (DFmode, addr);
14379 set_mem_alias_set (mem, rs6000_sr_alias_set);
14380
14381 RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
14382 }
14383 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14384 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14385 NULL_RTX, NULL_RTX);
14386 }
14387
14388
14389
14390 if (!WORLD_SAVE_P (info) && using_store_multiple)
14391 {
14392 rtvec p;
14393 int i;
14394 p = rtvec_alloc (32 - info->first_gp_reg_save);
14395 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14396 {
14397 rtx addr, reg, mem;
14398 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14399 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14400 GEN_INT (info->gp_save_offset
14401 + sp_offset
14402 + reg_size * i));
14403 mem = gen_rtx_MEM (reg_mode, addr);
14404 set_mem_alias_set (mem, rs6000_sr_alias_set);
14405
14406 RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, mem, reg);
14407 }
14408 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14409 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14410 NULL_RTX, NULL_RTX);
14411 }
14412 else if (!WORLD_SAVE_P (info))
14413 {
14414 int i;
14415 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14416 if ((regs_ever_live[info->first_gp_reg_save+i]
14417 && (! call_used_regs[info->first_gp_reg_save+i]
14418 || (i+info->first_gp_reg_save
14419 == RS6000_PIC_OFFSET_TABLE_REGNUM
14420 && TARGET_TOC && TARGET_MINIMAL_TOC)))
14421 || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
14422 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
14423 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
14424 {
14425 rtx addr, reg, mem;
14426 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14427
14428 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14429 {
14430 int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
14431 rtx b;
14432
14433 if (!SPE_CONST_OFFSET_OK (offset))
14434 {
14435 b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
14436 emit_move_insn (b, GEN_INT (offset));
14437 }
14438 else
14439 b = GEN_INT (offset);
14440
14441 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
14442 mem = gen_rtx_MEM (V2SImode, addr);
14443 set_mem_alias_set (mem, rs6000_sr_alias_set);
14444 insn = emit_move_insn (mem, reg);
14445
14446 if (GET_CODE (b) == CONST_INT)
14447 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14448 NULL_RTX, NULL_RTX);
14449 else
14450 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14451 b, GEN_INT (offset));
14452 }
14453 else
14454 {
14455 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14456 GEN_INT (info->gp_save_offset
14457 + sp_offset
14458 + reg_size * i));
14459 mem = gen_rtx_MEM (reg_mode, addr);
14460 set_mem_alias_set (mem, rs6000_sr_alias_set);
14461
14462 insn = emit_move_insn (mem, reg);
14463 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14464 NULL_RTX, NULL_RTX);
14465 }
14466 }
14467 }
14468
14469
14470
14471 if (!WORLD_SAVE_P (info) && current_function_calls_eh_return)
14472 {
14473 unsigned int i, regno;
14474
14475
14476 if (TARGET_AIX)
14477 {
14478 rtx addr, reg, mem;
14479
14480 reg = gen_rtx_REG (reg_mode, 2);
14481 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14482 GEN_INT (sp_offset + 5 * reg_size));
14483 mem = gen_rtx_MEM (reg_mode, addr);
14484 set_mem_alias_set (mem, rs6000_sr_alias_set);
14485
14486 insn = emit_move_insn (mem, reg);
14487 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14488 NULL_RTX, NULL_RTX);
14489 PATTERN (insn) = gen_blockage ();
14490 }
14491
14492 for (i = 0; ; ++i)
14493 {
14494 regno = EH_RETURN_DATA_REGNO (i);
14495 if (regno == INVALID_REGNUM)
14496 break;
14497
14498 emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, regno,
14499 info->ehrd_offset + sp_offset
14500 + reg_size * (int) i,
14501 info->total_size);
14502 }
14503 }
14504
14505
14506 if (!WORLD_SAVE_P (info) && info->lr_save_p)
14507 {
14508 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14509 GEN_INT (info->lr_save_offset + sp_offset));
14510 rtx reg = gen_rtx_REG (Pmode, 0);
14511 rtx mem = gen_rtx_MEM (Pmode, addr);
14512
14513
14514
14515 insn = emit_move_insn (mem, reg);
14516 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14517 NULL_RTX, NULL_RTX);
14518 }
14519
14520
14521 if (!WORLD_SAVE_P (info) && info->cr_save_p)
14522 {
14523 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14524 GEN_INT (info->cr_save_offset + sp_offset));
14525 rtx mem = gen_rtx_MEM (SImode, addr);
14526
14527 rtx magic_eh_cr_reg = gen_rtx_REG (SImode, CR2_REGNO);
14528
14529 set_mem_alias_set (mem, rs6000_sr_alias_set);
14530
14531
14532
14533 if (REGNO (frame_reg_rtx) == 12)
14534 {
14535 rtx set;
14536
14537 cr_save_rtx = gen_rtx_REG (SImode, 0);
14538 insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
14539 RTX_FRAME_RELATED_P (insn) = 1;
14540 set = gen_rtx_SET (VOIDmode, cr_save_rtx, magic_eh_cr_reg);
14541 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
14542 set,
14543 REG_NOTES (insn));
14544
14545 }
14546 insn = emit_move_insn (mem, cr_save_rtx);
14547
14548 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
14549 NULL_RTX, NULL_RTX);
14550 }
14551
14552
14553
14554 if (!WORLD_SAVE_P (info) && info->push_p
14555 && !(DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return))
14556 rs6000_emit_allocate_stack (info->total_size, FALSE);
14557
14558
14559 if (frame_pointer_needed)
14560 {
14561 insn = emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
14562 sp_reg_rtx);
14563 RTX_FRAME_RELATED_P (insn) = 1;
14564 }
14565
14566
14567 if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
14568 || (DEFAULT_ABI == ABI_V4 && flag_pic == 1
14569 && regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]))
14570 {
14571
14572
14573
14574
14575 int save_LR_around_toc_setup = (TARGET_ELF
14576 && DEFAULT_ABI != ABI_AIX
14577 && flag_pic
14578 && ! info->lr_save_p
14579 && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0);
14580 if (save_LR_around_toc_setup)
14581 {
14582 rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
14583
14584 insn = emit_move_insn (frame_ptr_rtx, lr);
14585 rs6000_maybe_dead (insn);
14586 RTX_FRAME_RELATED_P (insn) = 1;
14587
14588 rs6000_emit_load_toc_table (TRUE);
14589
14590 insn = emit_move_insn (lr, frame_ptr_rtx);
14591 rs6000_maybe_dead (insn);
14592 RTX_FRAME_RELATED_P (insn) = 1;
14593 }
14594 else
14595 rs6000_emit_load_toc_table (TRUE);
14596 }
14597
14598 #if TARGET_MACHO
14599 if (DEFAULT_ABI == ABI_DARWIN
14600 && flag_pic && current_function_uses_pic_offset_table)
14601 {
14602 rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
14603 rtx src = machopic_function_base_sym ();
14604
14605 rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (lr, src)));
14606
14607 insn = emit_move_insn (gen_rtx_REG (Pmode,
14608 RS6000_PIC_OFFSET_TABLE_REGNUM),
14609 lr);
14610 rs6000_maybe_dead (insn);
14611 }
14612 #endif
14613 }
14614
14615
14616
14617 static void
14618 rs6000_output_function_prologue (FILE *file,
14619 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
14620 {
14621 rs6000_stack_t *info = rs6000_stack_info ();
14622
14623 if (TARGET_DEBUG_STACK)
14624 debug_stack_info (info);
14625
14626
14627
14628 if (info->first_fp_reg_save < 64
14629 && !FP_SAVE_INLINE (info->first_fp_reg_save))
14630 fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
14631 SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
14632 RESTORE_FP_PREFIX, info->first_fp_reg_save - 32,
14633 RESTORE_FP_SUFFIX);
14634
14635
14636 if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined)
14637 {
14638 fputs ("\t.extern __mulh\n", file);
14639 fputs ("\t.extern __mull\n", file);
14640 fputs ("\t.extern __divss\n", file);
14641 fputs ("\t.extern __divus\n", file);
14642 fputs ("\t.extern __quoss\n", file);
14643 fputs ("\t.extern __quous\n", file);
14644 common_mode_defined = 1;
14645 }
14646
14647 if (! HAVE_prologue)
14648 {
14649 start_sequence ();
14650
14651
14652
14653 emit_note (NOTE_INSN_DELETED);
14654 rs6000_emit_prologue ();
14655 emit_note (NOTE_INSN_DELETED);
14656
14657
14658 {
14659 rtx insn;
14660 unsigned addr = 0;
14661 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
14662 {
14663 INSN_ADDRESSES_NEW (insn, addr);
14664 addr += 4;
14665 }
14666 }
14667
14668 if (TARGET_DEBUG_STACK)
14669 debug_rtx_list (get_insns (), 100);
14670 final (get_insns (), file, FALSE, FALSE);
14671 end_sequence ();
14672 }
14673
14674 rs6000_pic_labelno++;
14675 }
14676
14677
14678
14679
14680
14681
14682
14683
14684 void
14685 rs6000_emit_epilogue (int sibcall)
14686 {
14687 rs6000_stack_t *info;
14688 int restoring_FPRs_inline;
14689 int using_load_multiple;
14690 int using_mfcr_multiple;
14691 int use_backchain_to_restore_sp;
14692 int sp_offset = 0;
14693 rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
14694 rtx frame_reg_rtx = sp_reg_rtx;
14695 enum machine_mode reg_mode = Pmode;
14696 int reg_size = TARGET_32BIT ? 4 : 8;
14697 int i;
14698
14699 info = rs6000_stack_info ();
14700
14701 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14702 {
14703 reg_mode = V2SImode;
14704 reg_size = 8;
14705 }
14706
14707 using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
14708 && (!TARGET_SPE_ABI
14709 || info->spe_64bit_regs_used == 0)
14710 && info->first_gp_reg_save < 31);
14711 restoring_FPRs_inline = (sibcall
14712 || current_function_calls_eh_return
14713 || info->first_fp_reg_save == 64
14714 || FP_SAVE_INLINE (info->first_fp_reg_save));
14715 use_backchain_to_restore_sp = (frame_pointer_needed
14716 || current_function_calls_alloca
14717 || info->total_size > 32767);
14718 using_mfcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
14719 || rs6000_cpu == PROCESSOR_PPC603
14720 || rs6000_cpu == PROCESSOR_PPC750
14721 || optimize_size);
14722
14723 if (WORLD_SAVE_P (info))
14724 {
14725 int i, j;
14726 char rname[30];
14727 const char *alloc_rname;
14728 rtvec p;
14729
14730
14731
14732
14733
14734
14735
14736
14737 p = rtvec_alloc (9
14738 + 1
14739 + 32 - info->first_gp_reg_save
14740 + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
14741 + 63 + 1 - info->first_fp_reg_save);
14742
14743 strcpy (rname, ((current_function_calls_eh_return) ?
14744 "*eh_rest_world_r10" : "*rest_world"));
14745 alloc_rname = ggc_strdup (rname);
14746
14747 j = 0;
14748 RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
14749 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
14750 gen_rtx_REG (Pmode,
14751 LINK_REGISTER_REGNUM));
14752 RTVEC_ELT (p, j++)
14753 = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
14754
14755
14756 RTVEC_ELT (p, j++)
14757 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
14758
14759 {
14760
14761 rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
14762 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14763 GEN_INT (info->cr_save_offset));
14764 rtx mem = gen_rtx_MEM (reg_mode, addr);
14765 set_mem_alias_set (mem, rs6000_sr_alias_set);
14766
14767 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14768 }
14769
14770 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14771 {
14772 rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
14773 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14774 GEN_INT (info->gp_save_offset
14775 + reg_size * i));
14776 rtx mem = gen_rtx_MEM (reg_mode, addr);
14777 set_mem_alias_set (mem, rs6000_sr_alias_set);
14778
14779 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14780 }
14781 for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
14782 {
14783 rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
14784 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14785 GEN_INT (info->altivec_save_offset
14786 + 16 * i));
14787 rtx mem = gen_rtx_MEM (V4SImode, addr);
14788 set_mem_alias_set (mem, rs6000_sr_alias_set);
14789
14790 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14791 }
14792 for (i = 0; info->first_fp_reg_save + i <= 63; i++)
14793 {
14794 rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
14795 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14796 GEN_INT (info->fp_save_offset
14797 + 8 * i));
14798 rtx mem = gen_rtx_MEM (DFmode, addr);
14799 set_mem_alias_set (mem, rs6000_sr_alias_set);
14800
14801 RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
14802 }
14803 RTVEC_ELT (p, j++)
14804 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
14805 RTVEC_ELT (p, j++)
14806 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 12));
14807 RTVEC_ELT (p, j++)
14808 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 7));
14809 RTVEC_ELT (p, j++)
14810 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
14811 RTVEC_ELT (p, j++)
14812 = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
14813 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
14814
14815 return;
14816 }
14817
14818
14819
14820
14821 if (use_backchain_to_restore_sp)
14822 {
14823
14824
14825 if (DEFAULT_ABI == ABI_V4)
14826 frame_reg_rtx = gen_rtx_REG (Pmode, 11);
14827
14828 emit_move_insn (frame_reg_rtx,
14829 gen_rtx_MEM (Pmode, sp_reg_rtx));
14830
14831 }
14832 else if (info->push_p)
14833 {
14834 if (DEFAULT_ABI == ABI_V4
14835 || current_function_calls_eh_return)
14836 sp_offset = info->total_size;
14837 else
14838 {
14839 emit_insn (TARGET_32BIT
14840 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
14841 GEN_INT (info->total_size))
14842 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
14843 GEN_INT (info->total_size)));
14844 }
14845 }
14846
14847
14848 if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
14849 {
14850 int i;
14851
14852 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
14853 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
14854 {
14855 rtx addr, areg, mem;
14856
14857 areg = gen_rtx_REG (Pmode, 0);
14858 emit_move_insn
14859 (areg, GEN_INT (info->altivec_save_offset
14860 + sp_offset
14861 + 16 * (i - info->first_altivec_reg_save)));
14862
14863
14864 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
14865 mem = gen_rtx_MEM (V4SImode, addr);
14866 set_mem_alias_set (mem, rs6000_sr_alias_set);
14867
14868 emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
14869 }
14870 }
14871
14872
14873 if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
14874 && info->vrsave_mask != 0)
14875 {
14876 rtx addr, mem, reg;
14877
14878 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14879 GEN_INT (info->vrsave_save_offset + sp_offset));
14880 mem = gen_rtx_MEM (SImode, addr);
14881 set_mem_alias_set (mem, rs6000_sr_alias_set);
14882 reg = gen_rtx_REG (SImode, 12);
14883 emit_move_insn (reg, mem);
14884
14885 emit_insn (generate_set_vrsave (reg, info, 1));
14886 }
14887
14888
14889 if (info->lr_save_p)
14890 {
14891 rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
14892 info->lr_save_offset + sp_offset);
14893
14894 set_mem_alias_set (mem, rs6000_sr_alias_set);
14895
14896 emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
14897 }
14898
14899
14900 if (info->cr_save_p)
14901 {
14902 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14903 GEN_INT (info->cr_save_offset + sp_offset));
14904 rtx mem = gen_rtx_MEM (SImode, addr);
14905
14906 set_mem_alias_set (mem, rs6000_sr_alias_set);
14907
14908 emit_move_insn (gen_rtx_REG (SImode, 12), mem);
14909 }
14910
14911
14912 if (info->lr_save_p)
14913 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
14914 gen_rtx_REG (Pmode, 0));
14915
14916
14917 if (current_function_calls_eh_return)
14918 {
14919 unsigned int i, regno;
14920
14921 if (TARGET_AIX)
14922 {
14923 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14924 GEN_INT (sp_offset + 5 * reg_size));
14925 rtx mem = gen_rtx_MEM (reg_mode, addr);
14926
14927 set_mem_alias_set (mem, rs6000_sr_alias_set);
14928
14929 emit_move_insn (gen_rtx_REG (reg_mode, 2), mem);
14930 }
14931
14932 for (i = 0; ; ++i)
14933 {
14934 rtx mem;
14935
14936 regno = EH_RETURN_DATA_REGNO (i);
14937 if (regno == INVALID_REGNUM)
14938 break;
14939
14940 mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
14941 info->ehrd_offset + sp_offset
14942 + reg_size * (int) i);
14943 set_mem_alias_set (mem, rs6000_sr_alias_set);
14944
14945 emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
14946 }
14947 }
14948
14949
14950
14951 if (using_load_multiple)
14952 {
14953 rtvec p;
14954 p = rtvec_alloc (32 - info->first_gp_reg_save);
14955 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14956 {
14957 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14958 GEN_INT (info->gp_save_offset
14959 + sp_offset
14960 + reg_size * i));
14961 rtx mem = gen_rtx_MEM (reg_mode, addr);
14962
14963 set_mem_alias_set (mem, rs6000_sr_alias_set);
14964
14965 RTVEC_ELT (p, i) =
14966 gen_rtx_SET (VOIDmode,
14967 gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
14968 mem);
14969 }
14970 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
14971 }
14972 else
14973 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
14974 if ((regs_ever_live[info->first_gp_reg_save+i]
14975 && (! call_used_regs[info->first_gp_reg_save+i]
14976 || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
14977 && TARGET_TOC && TARGET_MINIMAL_TOC)))
14978 || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
14979 && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
14980 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
14981 {
14982 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
14983 GEN_INT (info->gp_save_offset
14984 + sp_offset
14985 + reg_size * i));
14986 rtx mem = gen_rtx_MEM (reg_mode, addr);
14987
14988
14989 if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
14990 {
14991 int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
14992 rtx b;
14993
14994 if (!SPE_CONST_OFFSET_OK (offset))
14995 {
14996 b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
14997 emit_move_insn (b, GEN_INT (offset));
14998 }
14999 else
15000 b = GEN_INT (offset);
15001
15002 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
15003 mem = gen_rtx_MEM (V2SImode, addr);
15004 }
15005
15006 set_mem_alias_set (mem, rs6000_sr_alias_set);
15007
15008 emit_move_insn (gen_rtx_REG (reg_mode,
15009 info->first_gp_reg_save + i), mem);
15010 }
15011
15012
15013 if (restoring_FPRs_inline)
15014 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
15015 if ((regs_ever_live[info->first_fp_reg_save+i]
15016 && ! call_used_regs[info->first_fp_reg_save+i]))
15017 {
15018 rtx addr, mem;
15019 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
15020 GEN_INT (info->fp_save_offset
15021 + sp_offset
15022 + 8 * i));
15023 mem = gen_rtx_MEM (DFmode, addr);
15024 set_mem_alias_set (mem, rs6000_sr_alias_set);
15025
15026 emit_move_insn (gen_rtx_REG (DFmode,
15027 info->first_fp_reg_save + i),
15028 mem);
15029 }
15030
15031
15032 if (info->cr_save_p)
15033 {
15034 rtx r12_rtx = gen_rtx_REG (SImode, 12);
15035 int count = 0;
15036
15037 if (using_mfcr_multiple)
15038 {
15039 for (i = 0; i < 8; i++)
15040 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15041 count++;
15042 if (count == 0)
15043 abort ();
15044 }
15045
15046 if (using_mfcr_multiple && count > 1)
15047 {
15048 rtvec p;
15049 int ndx;
15050
15051 p = rtvec_alloc (count);
15052
15053 ndx = 0;
15054 for (i = 0; i < 8; i++)
15055 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15056 {
15057 rtvec r = rtvec_alloc (2);
15058 RTVEC_ELT (r, 0) = r12_rtx;
15059 RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
15060 RTVEC_ELT (p, ndx) =
15061 gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
15062 gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
15063 ndx++;
15064 }
15065 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
15066 if (ndx != count)
15067 abort ();
15068 }
15069 else
15070 for (i = 0; i < 8; i++)
15071 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
15072 {
15073 emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode,
15074 CR0_REGNO+i),
15075 r12_rtx));
15076 }
15077 }
15078
15079
15080
15081
15082
15083
15084
15085 if (DEFAULT_ABI == ABI_V4
15086 || current_function_calls_eh_return)
15087 {
15088 if (frame_reg_rtx != sp_reg_rtx)
15089 rs6000_emit_stack_tie ();
15090
15091 if (use_backchain_to_restore_sp)
15092 {
15093 emit_move_insn (sp_reg_rtx, frame_reg_rtx);
15094 }
15095 else if (sp_offset != 0)
15096 {
15097 emit_insn (TARGET_32BIT
15098 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
15099 GEN_INT (sp_offset))
15100 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
15101 GEN_INT (sp_offset)));
15102 }
15103 }
15104
15105 if (current_function_calls_eh_return)
15106 {
15107 rtx sa = EH_RETURN_STACKADJ_RTX;
15108 emit_insn (TARGET_32BIT
15109 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
15110 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
15111 }
15112
15113 if (!sibcall)
15114 {
15115 rtvec p;
15116 if (! restoring_FPRs_inline)
15117 p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
15118 else
15119 p = rtvec_alloc (2);
15120
15121 RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
15122 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
15123 gen_rtx_REG (Pmode,
15124 LINK_REGISTER_REGNUM));
15125
15126
15127
15128 if (! restoring_FPRs_inline)
15129 {
15130 int i;
15131 char rname[30];
15132 const char *alloc_rname;
15133
15134 sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
15135 info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
15136 alloc_rname = ggc_strdup (rname);
15137 RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
15138 gen_rtx_SYMBOL_REF (Pmode,
15139 alloc_rname));
15140
15141 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
15142 {
15143 rtx addr, mem;
15144 addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
15145 GEN_INT (info->fp_save_offset + 8*i));
15146 mem = gen_rtx_MEM (DFmode, addr);
15147 set_mem_alias_set (mem, rs6000_sr_alias_set);
15148
15149 RTVEC_ELT (p, i+3) =
15150 gen_rtx_SET (VOIDmode,
15151 gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
15152 mem);
15153 }
15154 }
15155
15156 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
15157 }
15158 }
15159
15160
15161
15162 static void
15163 rs6000_output_function_epilogue (FILE *file,
15164 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
15165 {
15166 rs6000_stack_t *info = rs6000_stack_info ();
15167
15168 if (! HAVE_epilogue)
15169 {
15170 rtx insn = get_last_insn ();
15171
15172
15173 if (GET_CODE (insn) == NOTE)
15174 insn = prev_nonnote_insn (insn);
15175 if (insn == 0 || GET_CODE (insn) != BARRIER)
15176 {
15177
15178
15179 start_sequence ();
15180
15181
15182
15183 emit_note (NOTE_INSN_DELETED);
15184 rs6000_emit_epilogue (FALSE);
15185 emit_note (NOTE_INSN_DELETED);
15186
15187
15188 {
15189 rtx insn;
15190 unsigned addr = 0;
15191 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
15192 {
15193 INSN_ADDRESSES_NEW (insn, addr);
15194 addr += 4;
15195 }
15196 }
15197
15198 if (TARGET_DEBUG_STACK)
15199 debug_rtx_list (get_insns (), 100);
15200 final (get_insns (), file, FALSE, FALSE);
15201 end_sequence ();
15202 }
15203 }
15204
15205 #if TARGET_MACHO
15206 macho_branch_islands ();
15207
15208
15209 {
15210 rtx insn = get_last_insn ();
15211 while (insn
15212 && NOTE_P (insn)
15213 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL)
15214 insn = PREV_INSN (insn);
15215 if (insn
15216 && (LABEL_P (insn)
15217 || (NOTE_P (insn)
15218 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
15219 fputs ("\tnop\n", file);
15220 }
15221 #endif
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237 if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
15238 && rs6000_traceback != traceback_none)
15239 {
15240 const char *fname = NULL;
15241 const char *language_string = lang_hooks.name;
15242 int fixed_parms = 0, float_parms = 0, parm_info = 0;
15243 int i;
15244 int optional_tbtab;
15245
15246 if (rs6000_traceback == traceback_full)
15247 optional_tbtab = 1;
15248 else if (rs6000_traceback == traceback_part)
15249 optional_tbtab = 0;
15250 else
15251 optional_tbtab = !optimize_size && !TARGET_ELF;
15252
15253 if (optional_tbtab)
15254 {
15255 fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
15256 while (*fname == '.')
15257 fname++;
15258
15259
15260
15261 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
15262 ASM_OUTPUT_LABEL (file, fname);
15263 }
15264
15265
15266
15267
15268
15269
15270
15271
15272
15273
15274
15275
15276 fputs ("\t.long 0\n", file);
15277
15278
15279 fputs ("\t.byte 0,", file);
15280
15281
15282
15283
15284
15285
15286 if (! strcmp (language_string, "GNU C"))
15287 i = 0;
15288 else if (! strcmp (language_string, "GNU F77")
15289 || ! strcmp (language_string, "GNU F95"))
15290 i = 1;
15291 else if (! strcmp (language_string, "GNU Pascal"))
15292 i = 2;
15293 else if (! strcmp (language_string, "GNU Ada"))
15294 i = 3;
15295 else if (! strcmp (language_string, "GNU C++"))
15296 i = 9;
15297 else if (! strcmp (language_string, "GNU Java"))
15298 i = 13;
15299 else if (! strcmp (language_string, "GNU Objective-C"))
15300 i = 14;
15301 else
15302 abort ();
15303 fprintf (file, "%d,", i);
15304
15305
15306
15307
15308
15309
15310
15311 fprintf (file, "%d,",
15312 (optional_tbtab << 5) | ((info->first_fp_reg_save != 64) << 1));
15313
15314
15315
15316
15317
15318
15319
15320 fprintf (file, "%d,",
15321 ((optional_tbtab << 6)
15322 | ((optional_tbtab & frame_pointer_needed) << 5)
15323 | (info->cr_save_p << 1)
15324 | (info->lr_save_p)));
15325
15326
15327
15328 fprintf (file, "%d,",
15329 (info->push_p << 7) | (64 - info->first_fp_reg_save));
15330
15331
15332 fprintf (file, "%d,", (32 - first_reg_to_save ()));
15333
15334 if (optional_tbtab)
15335 {
15336
15337
15338 tree decl;
15339 int next_parm_info_bit = 31;
15340
15341 for (decl = DECL_ARGUMENTS (current_function_decl);
15342 decl; decl = TREE_CHAIN (decl))
15343 {
15344 rtx parameter = DECL_INCOMING_RTL (decl);
15345 enum machine_mode mode = GET_MODE (parameter);
15346
15347 if (GET_CODE (parameter) == REG)
15348 {
15349 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
15350 {
15351 int bits;
15352
15353 float_parms++;
15354
15355 if (mode == SFmode)
15356 bits = 0x2;
15357 else if (mode == DFmode || mode == TFmode)
15358 bits = 0x3;
15359 else
15360 abort ();
15361
15362
15363 if (next_parm_info_bit > 0)
15364 parm_info |= (bits << (next_parm_info_bit - 1));
15365 next_parm_info_bit -= 2;
15366 }
15367 else
15368 {
15369 fixed_parms += ((GET_MODE_SIZE (mode)
15370 + (UNITS_PER_WORD - 1))
15371 / UNITS_PER_WORD);
15372 next_parm_info_bit -= 1;
15373 }
15374 }
15375 }
15376 }
15377
15378
15379
15380
15381 fprintf (file, "%d,", fixed_parms);
15382
15383
15384
15385
15386
15387
15388
15389
15390 fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));
15391
15392 if (! optional_tbtab)
15393 return;
15394
15395
15396
15397
15398
15399
15400
15401
15402
15403
15404 if (fixed_parms || float_parms)
15405 fprintf (file, "\t.long %d\n", parm_info);
15406
15407
15408 fputs ("\t.long ", file);
15409 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
15410 if (TARGET_AIX)
15411 RS6000_OUTPUT_BASENAME (file, fname);
15412 else
15413 assemble_name (file, fname);
15414 putc ('-', file);
15415 rs6000_output_function_entry (file, fname);
15416 putc ('\n', file);
15417
15418
15419
15420
15421
15422
15423
15424
15425
15426
15427
15428
15429 if (*fname == '*')
15430 ++fname;
15431 fprintf (file, "\t.short %d\n", (int) strlen (fname));
15432
15433
15434 assemble_string (fname, strlen (fname));
15435
15436
15437
15438 if (frame_pointer_needed)
15439 fputs ("\t.byte 31\n", file);
15440
15441 fputs ("\t.align 2\n", file);
15442 }
15443 }
15444
15445
15446
15447
15448
15449
15450
15451
15452
15453
15454
15455
15456
15457
15458
15459
15460
15461
15462
15463
15464
15465
15466
15467
15468
15469
15470
15471
15472
15473
15474
15475
15476
15477 static void
15478 rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
15479 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
15480 tree function)
15481 {
15482 rtx this, insn, funexp;
15483
15484 reload_completed = 1;
15485 epilogue_completed = 1;
15486 no_new_pseudos = 1;
15487 reset_block_changes ();
15488
15489
15490 emit_note (NOTE_INSN_PROLOGUE_END);
15491
15492
15493
15494 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
15495 this = gen_rtx_REG (Pmode, 4);
15496 else
15497 this = gen_rtx_REG (Pmode, 3);
15498
15499
15500 if (delta)
15501 {
15502 rtx delta_rtx = GEN_INT (delta);
15503 emit_insn (TARGET_32BIT
15504 ? gen_addsi3 (this, this, delta_rtx)
15505 : gen_adddi3 (this, this, delta_rtx));
15506 }
15507
15508
15509 if (vcall_offset)
15510 {
15511 rtx vcall_offset_rtx = GEN_INT (vcall_offset);
15512 rtx tmp = gen_rtx_REG (Pmode, 12);
15513
15514 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
15515 if (((unsigned HOST_WIDE_INT) vcall_offset) + 0x8000 >= 0x10000)
15516 {
15517 emit_insn (TARGET_32BIT
15518 ? gen_addsi3 (tmp, tmp, vcall_offset_rtx)
15519 : gen_adddi3 (tmp, tmp, vcall_offset_rtx));
15520 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
15521 }
15522 else
15523 {
15524 rtx loc = gen_rtx_PLUS (Pmode, tmp, vcall_offset_rtx);
15525
15526 emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc));
15527 }
15528 emit_insn (TARGET_32BIT
15529 ? gen_addsi3 (this, this, tmp)
15530 : gen_adddi3 (this, this, tmp));
15531 }
15532
15533
15534 if (!TREE_USED (function))
15535 {
15536 assemble_external (function);
15537 TREE_USED (function) = 1;
15538 }
15539 funexp = XEXP (DECL_RTL (function), 0);
15540 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
15541
15542 #if TARGET_MACHO
15543 if (MACHOPIC_INDIRECT)
15544 funexp = machopic_indirect_call_target (funexp);
15545 #endif
15546
15547
15548
15549 insn = emit_call_insn (
15550 gen_rtx_PARALLEL (VOIDmode,
15551 gen_rtvec (4,
15552 gen_rtx_CALL (VOIDmode,
15553 funexp, const0_rtx),
15554 gen_rtx_USE (VOIDmode, const0_rtx),
15555 gen_rtx_USE (VOIDmode,
15556 gen_rtx_REG (SImode,
15557 LINK_REGISTER_REGNUM)),
15558 gen_rtx_RETURN (VOIDmode))));
15559 SIBLING_CALL_P (insn) = 1;
15560 emit_barrier ();
15561
15562
15563
15564
15565
15566 insn = get_insns ();
15567 insn_locators_initialize ();
15568 shorten_branches (insn);
15569 final_start_function (insn, file, 1);
15570 final (insn, file, 1, 0);
15571 final_end_function ();
15572
15573 reload_completed = 0;
15574 epilogue_completed = 0;
15575 no_new_pseudos = 0;
15576 }
15577
15578
15579
15580
15581
15582
15583
15584
15585
15586
15587
15588
15589
15590
15591
15592
15593
15594
15595
15596
15597
15598
15599
15600
15601
15602
15603
15604
15605
15606
15607 static unsigned
15608 rs6000_hash_constant (rtx k)
15609 {
15610 enum rtx_code code = GET_CODE (k);
15611 enum machine_mode mode = GET_MODE (k);
15612 unsigned result = (code << 3) ^ mode;
15613 const char *format;
15614 int flen, fidx;
15615
15616 format = GET_RTX_FORMAT (code);
15617 flen = strlen (format);
15618 fidx = 0;
15619
15620 switch (code)
15621 {
15622 case LABEL_REF:
15623 return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
15624
15625 case CONST_DOUBLE:
15626 if (mode != VOIDmode)
15627 return real_hash (CONST_DOUBLE_REAL_VALUE (k)) * result;
15628 flen = 2;
15629 break;
15630
15631 case CODE_LABEL:
15632 fidx = 3;
15633 break;
15634
15635 default:
15636 break;
15637 }
15638
15639 for (; fidx < flen; fidx++)
15640 switch (format[fidx])
15641 {
15642 case 's':
15643 {
15644 unsigned i, len;
15645 const char *str = XSTR (k, fidx);
15646 len = strlen (str);
15647 result = result * 613 + len;
15648 for (i = 0; i < len; i++)
15649 result = result * 613 + (unsigned) str[i];
15650 break;
15651 }
15652 case 'u':
15653 case 'e':
15654 result = result * 1231 + rs6000_hash_constant (XEXP (k, fidx));
15655 break;
15656 case 'i':
15657 case 'n':
15658 result = result * 613 + (unsigned) XINT (k, fidx);
15659 break;
15660 case 'w':
15661 if (sizeof (unsigned) >= sizeof (HOST_WIDE_INT))
15662 result = result * 613 + (unsigned) XWINT (k, fidx);
15663 else
15664 {
15665 size_t i;
15666 for (i = 0; i < sizeof(HOST_WIDE_INT)/sizeof(unsigned); i++)
15667 result = result * 613 + (unsigned) (XWINT (k, fidx)
15668 >> CHAR_BIT * i);
15669 }
15670 break;
15671 case '0':
15672 break;
15673 default:
15674 abort ();
15675 }
15676
15677 return result;
15678 }
15679
15680 static unsigned
15681 toc_hash_function (const void *hash_entry)
15682 {
15683 const struct toc_hash_struct *thc =
15684 (const struct toc_hash_struct *) hash_entry;
15685 return rs6000_hash_constant (thc->key) ^ thc->key_mode;
15686 }
15687
15688
15689
15690 static int
15691 toc_hash_eq (const void *h1, const void *h2)
15692 {
15693 rtx r1 = ((const struct toc_hash_struct *) h1)->key;
15694 rtx r2 = ((const struct toc_hash_struct *) h2)->key;
15695
15696 if (((const struct toc_hash_struct *) h1)->key_mode
15697 != ((const struct toc_hash_struct *) h2)->key_mode)
15698 return 0;
15699
15700 return rtx_equal_p (r1, r2);
15701 }
15702
15703
15704
15705
15706
15707
15708 #define VTABLE_NAME_P(NAME) \
15709 (strncmp ("_vt.", name, strlen("_vt.")) == 0 \
15710 || strncmp ("_ZTV", name, strlen ("_ZTV")) == 0 \
15711 || strncmp ("_ZTT", name, strlen ("_ZTT")) == 0 \
15712 || strncmp ("_ZTI", name, strlen ("_ZTI")) == 0 \
15713 || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
15714
15715 void
15716 rs6000_output_symbol_ref (FILE *file, rtx x)
15717 {
15718
15719
15720
15721
15722
15723
15724 const char *name = XSTR (x, 0);
15725
15726 if (VTABLE_NAME_P (name))
15727 {
15728 RS6000_OUTPUT_BASENAME (file, name);
15729 }
15730 else
15731 assemble_name (file, name);
15732 }
15733
15734
15735
15736
15737 void
15738 output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
15739 {
15740 char buf[256];
15741 const char *name = buf;
15742 const char *real_name;
15743 rtx base = x;
15744 int offset = 0;
15745
15746 if (TARGET_NO_TOC)
15747 abort ();
15748
15749
15750
15751
15752
15753 if (TARGET_TOC && GET_CODE (x) != LABEL_REF)
15754 {
15755 struct toc_hash_struct *h;
15756 void * * found;
15757
15758
15759
15760 if (toc_hash_table == NULL)
15761 toc_hash_table = htab_create_ggc (1021, toc_hash_function,
15762 toc_hash_eq, NULL);
15763
15764 h = ggc_alloc (sizeof (*h));
15765 h->key = x;
15766 h->key_mode = mode;
15767 h->labelno = labelno;
15768
15769 found = htab_find_slot (toc_hash_table, h, 1);
15770 if (*found == NULL)
15771 *found = h;
15772 else
15773
15774 {
15775 fputs ("\t.set ", file);
15776 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
15777 fprintf (file, "%d,", labelno);
15778 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
15779 fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
15780 found)->labelno));
15781 return;
15782 }
15783 }
15784
15785
15786
15787 if (GET_CODE (x) == CONST_DOUBLE
15788 && STRICT_ALIGNMENT
15789 && GET_MODE_BITSIZE (mode) >= 64
15790 && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
15791 ASM_OUTPUT_ALIGN (file, 3);
15792 }
15793
15794 (*targetm.asm_out.internal_label) (file, "LC", labelno);
15795
15796
15797
15798
15799 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == TFmode)
15800 {
15801 REAL_VALUE_TYPE rv;
15802 long k[4];
15803
15804 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
15805 REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
15806
15807 if (TARGET_64BIT)
15808 {
15809 if (TARGET_MINIMAL_TOC)
15810 fputs (DOUBLE_INT_ASM_OP, file);
15811 else
15812 fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
15813 k[0] & 0xffffffff, k[1] & 0xffffffff,
15814 k[2] & 0xffffffff, k[3] & 0xffffffff);
15815 fprintf (file, "0x%lx%08lx,0x%lx%08lx\n",
15816 k[0] & 0xffffffff, k[1] & 0xffffffff,
15817 k[2] & 0xffffffff, k[3] & 0xffffffff);
15818 return;
15819 }
15820 else
15821 {
15822 if (TARGET_MINIMAL_TOC)
15823 fputs ("\t.long ", file);
15824 else
15825 fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
15826 k[0] & 0xffffffff, k[1] & 0xffffffff,
15827 k[2] & 0xffffffff, k[3] & 0xffffffff);
15828 fprintf (file, "0x%lx,0x%lx,0x%lx,0x%lx\n",
15829 k[0] & 0xffffffff, k[1] & 0xffffffff,
15830 k[2] & 0xffffffff, k[3] & 0xffffffff);
15831 return;
15832 }
15833 }
15834 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
15835 {
15836 REAL_VALUE_TYPE rv;
15837 long k[2];
15838
15839 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
15840 REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
15841
15842 if (TARGET_64BIT)
15843 {
15844 if (TARGET_MINIMAL_TOC)
15845 fputs (DOUBLE_INT_ASM_OP, file);
15846 else
15847 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
15848 k[0] & 0xffffffff, k[1] & 0xffffffff);
15849 fprintf (file, "0x%lx%08lx\n",
15850 k[0] & 0xffffffff, k[1] & 0xffffffff);
15851 return;
15852 }
15853 else
15854 {
15855 if (TARGET_MINIMAL_TOC)
15856 fputs ("\t.long ", file);
15857 else
15858 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
15859 k[0] & 0xffffffff, k[1] & 0xffffffff);
15860 fprintf (file, "0x%lx,0x%lx\n",
15861 k[0] & 0xffffffff, k[1] & 0xffffffff);
15862 return;
15863 }
15864 }
15865 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
15866 {
15867 REAL_VALUE_TYPE rv;
15868 long l;
15869
15870 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
15871 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
15872
15873 if (TARGET_64BIT)
15874 {
15875 if (TARGET_MINIMAL_TOC)
15876 fputs (DOUBLE_INT_ASM_OP, file);
15877 else
15878 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
15879 fprintf (file, "0x%lx00000000\n", l & 0xffffffff);
15880 return;
15881 }
15882 else
15883 {
15884 if (TARGET_MINIMAL_TOC)
15885 fputs ("\t.long ", file);
15886 else
15887 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
15888 fprintf (file, "0x%lx\n", l & 0xffffffff);
15889 return;
15890 }
15891 }
15892 else if (GET_MODE (x) == VOIDmode
15893 && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
15894 {
15895 unsigned HOST_WIDE_INT low;
15896 HOST_WIDE_INT high;
15897
15898 if (GET_CODE (x) == CONST_DOUBLE)
15899 {
15900 low = CONST_DOUBLE_LOW (x);
15901 high = CONST_DOUBLE_HIGH (x);
15902 }
15903 else
15904 #if HOST_BITS_PER_WIDE_INT == 32
15905 {
15906 low = INTVAL (x);
15907 high = (low & 0x80000000) ? ~0 : 0;
15908 }
15909 #else
15910 {
15911 low = INTVAL (x) & 0xffffffff;
15912 high = (HOST_WIDE_INT) INTVAL (x) >> 32;
15913 }
15914 #endif
15915
15916
15917
15918
15919
15920
15921
15922
15923
15924
15925
15926 if (TARGET_64BIT && POINTER_SIZE < GET_MODE_BITSIZE (mode))
15927 abort ();
15928
15929 if (POINTER_SIZE > GET_MODE_BITSIZE (mode))
15930 {
15931 #if HOST_BITS_PER_WIDE_INT == 32
15932 lshift_double (low, high, POINTER_SIZE - GET_MODE_BITSIZE (mode),
15933 POINTER_SIZE, &low, &high, 0);
15934 #else
15935 low |= high << 32;
15936 low <<= POINTER_SIZE - GET_MODE_BITSIZE (mode);
15937 high = (HOST_WIDE_INT) low >> 32;
15938 low &= 0xffffffff;
15939 #endif
15940 }
15941
15942 if (TARGET_64BIT)
15943 {
15944 if (TARGET_MINIMAL_TOC)
15945 fputs (DOUBLE_INT_ASM_OP, file);
15946 else
15947 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
15948 (long) high & 0xffffffff, (long) low & 0xffffffff);
15949 fprintf (file, "0x%lx%08lx\n",
15950 (long) high & 0xffffffff, (long) low & 0xffffffff);
15951 return;
15952 }
15953 else
15954 {
15955 if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
15956 {
15957 if (TARGET_MINIMAL_TOC)
15958 fputs ("\t.long ", file);
15959 else
15960 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
15961 (long) high & 0xffffffff, (long) low & 0xffffffff);
15962 fprintf (file, "0x%lx,0x%lx\n",
15963 (long) high & 0xffffffff, (long) low & 0xffffffff);
15964 }
15965 else
15966 {
15967 if (TARGET_MINIMAL_TOC)
15968 fputs ("\t.long ", file);
15969 else
15970 fprintf (file, "\t.tc IS_%lx[TC],", (long) low & 0xffffffff);
15971 fprintf (file, "0x%lx\n", (long) low & 0xffffffff);
15972 }
15973 return;
15974 }
15975 }
15976
15977 if (GET_CODE (x) == CONST)
15978 {
15979 if (GET_CODE (XEXP (x, 0)) != PLUS)
15980 abort ();
15981
15982 base = XEXP (XEXP (x, 0), 0);
15983 offset = INTVAL (XEXP (XEXP (x, 0), 1));
15984 }
15985
15986 if (GET_CODE (base) == SYMBOL_REF)
15987 name = XSTR (base, 0);
15988 else if (GET_CODE (base) == LABEL_REF)
15989 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (base, 0)));
15990 else if (GET_CODE (base) == CODE_LABEL)
15991 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));
15992 else
15993 abort ();
15994
15995 real_name = (*targetm.strip_name_encoding) (name);
15996 if (TARGET_MINIMAL_TOC)
15997 fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
15998 else
15999 {
16000 fprintf (file, "\t.tc %s", real_name);
16001
16002 if (offset < 0)
16003 fprintf (file, ".N%d", - offset);
16004 else if (offset)
16005 fprintf (file, ".P%d", offset);
16006
16007 fputs ("[TC],", file);
16008 }
16009
16010
16011
16012
16013
16014
16015
16016 if (VTABLE_NAME_P (name))
16017 {
16018 RS6000_OUTPUT_BASENAME (file, name);
16019 if (offset < 0)
16020 fprintf (file, "%d", offset);
16021 else if (offset > 0)
16022 fprintf (file, "+%d", offset);
16023 }
16024 else
16025 output_addr_const (file, x);
16026 putc ('\n', file);
16027 }
16028
16029
16030
16031
16032
16033
16034
16035
16036
16037 void
16038 output_ascii (FILE *file, const char *p, int n)
16039 {
16040 char c;
16041 int i, count_string;
16042 const char *for_string = "\t.byte \"";
16043 const char *for_decimal = "\t.byte ";
16044 const char *to_close = NULL;
16045
16046 count_string = 0;
16047 for (i = 0; i < n; i++)
16048 {
16049 c = *p++;
16050 if (c >= ' ' && c < 0177)
16051 {
16052 if (for_string)
16053 fputs (for_string, file);
16054 putc (c, file);
16055
16056
16057 if (c == '"')
16058 {
16059 putc (c, file);
16060 ++count_string;
16061 }
16062
16063 for_string = NULL;
16064 for_decimal = "\"\n\t.byte ";
16065 to_close = "\"\n";
16066 ++count_string;
16067
16068 if (count_string >= 512)
16069 {
16070 fputs (to_close, file);
16071
16072 for_string = "\t.byte \"";
16073 for_decimal = "\t.byte ";
16074 to_close = NULL;
16075 count_string = 0;
16076 }
16077 }
16078 else
16079 {
16080 if (for_decimal)
16081 fputs (for_decimal, file);
16082 fprintf (file, "%d", c);
16083
16084 for_string = "\n\t.byte \"";
16085 for_decimal = ", ";
16086 to_close = "\n";
16087 count_string = 0;
16088 }
16089 }
16090
16091
16092 if (to_close)
16093 fputs (to_close, file);
16094 }
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106
16107
16108 void
16109 rs6000_gen_section_name (char **buf, const char *filename,
16110 const char *section_desc)
16111 {
16112 const char *q, *after_last_slash, *last_period = 0;
16113 char *p;
16114 int len;
16115
16116 after_last_slash = filename;
16117 for (q = filename; *q; q++)
16118 {
16119 if (*q == '/')
16120 after_last_slash = q + 1;
16121 else if (*q == '.')
16122 last_period = q;
16123 }
16124
16125 len = strlen (after_last_slash) + strlen (section_desc) + 2;
16126 *buf = (char *) xmalloc (len);
16127
16128 p = *buf;
16129 *p++ = '_';
16130
16131 for (q = after_last_slash; *q; q++)
16132 {
16133 if (q == last_period)
16134 {
16135 strcpy (p, section_desc);
16136 p += strlen (section_desc);
16137 break;
16138 }
16139
16140 else if (ISALNUM (*q))
16141 *p++ = *q;
16142 }
16143
16144 if (last_period == 0)
16145 strcpy (p, section_desc);
16146 else
16147 *p = '\0';
16148 }
16149
16150
16151
16152 void
16153 output_profile_hook (int labelno ATTRIBUTE_UNUSED)
16154 {
16155 if (TARGET_PROFILE_KERNEL)
16156 return;
16157
16158 if (DEFAULT_ABI == ABI_AIX)
16159 {
16160 #ifndef NO_PROFILE_COUNTERS
16161 # define NO_PROFILE_COUNTERS 0
16162 #endif
16163 if (NO_PROFILE_COUNTERS)
16164 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 0);
16165 else
16166 {
16167 char buf[30];
16168 const char *label_name;
16169 rtx fun;
16170
16171 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
16172 label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
16173 fun = gen_rtx_SYMBOL_REF (Pmode, label_name);
16174
16175 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
16176 fun, Pmode);
16177 }
16178 }
16179 else if (DEFAULT_ABI == ABI_DARWIN)
16180 {
16181 const char *mcount_name = RS6000_MCOUNT;
16182 int caller_addr_regno = LINK_REGISTER_REGNUM;
16183
16184
16185 current_function_uses_pic_offset_table = 1;
16186
16187 #if TARGET_MACHO
16188
16189
16190 if (MACHOPIC_INDIRECT
16191 && current_function_uses_pic_offset_table)
16192 caller_addr_regno = 0;
16193 #endif
16194 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name),
16195 0, VOIDmode, 1,
16196 gen_rtx_REG (Pmode, caller_addr_regno), Pmode);
16197 }
16198 }
16199
16200
16201
16202 void
16203 output_function_profiler (FILE *file, int labelno)
16204 {
16205 char buf[100];
16206 int save_lr = 8;
16207
16208 switch (DEFAULT_ABI)
16209 {
16210 default:
16211 abort ();
16212
16213 case ABI_V4:
16214 save_lr = 4;
16215 if (!TARGET_32BIT)
16216 {
16217 warning ("no profiling of 64-bit code for this ABI");
16218 return;
16219 }
16220 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
16221 fprintf (file, "\tmflr %s\n", reg_names[0]);
16222 if (flag_pic == 1)
16223 {
16224 fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
16225 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
16226 reg_names[0], save_lr, reg_names[1]);
16227 asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
16228 asm_fprintf (file, "\t{l|lwz} %s,", reg_names[0]);
16229 assemble_name (file, buf);
16230 asm_fprintf (file, "@got(%s)\n", reg_names[12]);
16231 }
16232 else if (flag_pic > 1)
16233 {
16234 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
16235 reg_names[0], save_lr, reg_names[1]);
16236
16237 fputs ("\tbl 1f\n\t.long ", file);
16238 assemble_name (file, buf);
16239 fputs ("-.\n1:", file);
16240 asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
16241 asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
16242 reg_names[0], reg_names[11]);
16243 asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
16244 reg_names[0], reg_names[0], reg_names[11]);
16245 }
16246 else
16247 {
16248 asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
16249 assemble_name (file, buf);
16250 fputs ("@ha\n", file);
16251 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
16252 reg_names[0], save_lr, reg_names[1]);
16253 asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
16254 assemble_name (file, buf);
16255 asm_fprintf (file, "@l(%s)\n", reg_names[12]);
16256 }
16257
16258
16259 fprintf (file, "\tbl %s%s\n",
16260 RS6000_MCOUNT, flag_pic ? "@plt" : "");
16261 break;
16262
16263 case ABI_AIX:
16264 case ABI_DARWIN:
16265 if (!TARGET_PROFILE_KERNEL)
16266 {
16267
16268 }
16269 else
16270 {
16271 if (TARGET_32BIT)
16272 abort ();
16273
16274 asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
16275 asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
16276
16277 if (cfun->static_chain_decl != NULL)
16278 {
16279 asm_fprintf (file, "\tstd %s,24(%s)\n",
16280 reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
16281 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
16282 asm_fprintf (file, "\tld %s,24(%s)\n",
16283 reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
16284 }
16285 else
16286 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
16287 }
16288 break;
16289 }
16290 }
16291
16292
16293
16294
16295
16296
16297
16298
16299 static int
16300 rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
16301 int verbose ATTRIBUTE_UNUSED,
16302 rtx insn, int more)
16303 {
16304 if (GET_CODE (PATTERN (insn)) == USE
16305 || GET_CODE (PATTERN (insn)) == CLOBBER)
16306 return more;
16307
16308 if (rs6000_sched_groups)
16309 {
16310 if (is_microcoded_insn (insn))
16311 return 0;
16312 else if (is_cracked_insn (insn))
16313 return more > 2 ? more - 2 : 0;
16314 }
16315
16316 return more - 1;
16317 }
16318
16319
16320
16321
16322 static int
16323 rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
16324 {
16325 if (! recog_memoized (insn))
16326 return 0;
16327
16328 if (REG_NOTE_KIND (link) != 0)
16329 return 0;
16330
16331 if (REG_NOTE_KIND (link) == 0)
16332 {
16333
16334
16335
16336
16337 if (rs6000_sched_groups
16338 && GET_CODE (PATTERN (insn)) == SET
16339 && GET_CODE (PATTERN (dep_insn)) == SET
16340 && GET_CODE (XEXP (PATTERN (insn), 1)) == MEM
16341 && GET_CODE (XEXP (PATTERN (dep_insn), 0)) == MEM
16342 && (GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (insn), 1)))
16343 > GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (dep_insn), 0)))))
16344 return cost + 14;
16345
16346 switch (get_attr_type (insn))
16347 {
16348 case TYPE_JMPREG:
16349
16350
16351
16352
16353
16354 return TARGET_POWER ? 5 : 4;
16355 case TYPE_BRANCH:
16356
16357
16358 if ((rs6000_cpu_attr == CPU_PPC603
16359 || rs6000_cpu_attr == CPU_PPC604
16360 || rs6000_cpu_attr == CPU_PPC604E
16361 || rs6000_cpu_attr == CPU_PPC620
16362 || rs6000_cpu_attr == CPU_PPC630
16363 || rs6000_cpu_attr == CPU_PPC750
16364 || rs6000_cpu_attr == CPU_PPC7400
16365 || rs6000_cpu_attr == CPU_PPC7450
16366 || rs6000_cpu_attr == CPU_POWER4
16367 || rs6000_cpu_attr == CPU_POWER5)
16368 && recog_memoized (dep_insn)
16369 && (INSN_CODE (dep_insn) >= 0)
16370 && (get_attr_type (dep_insn) == TYPE_CMP
16371 || get_attr_type (dep_insn) == TYPE_COMPARE
16372 || get_attr_type (dep_insn) == TYPE_DELAYED_COMPARE
16373 || get_attr_type (dep_insn) == TYPE_IMUL_COMPARE
16374 || get_attr_type (dep_insn) == TYPE_LMUL_COMPARE
16375 || get_attr_type (dep_insn) == TYPE_FPCOMPARE
16376 || get_attr_type (dep_insn) == TYPE_CR_LOGICAL
16377 || get_attr_type (dep_insn) == TYPE_DELAYED_CR))
16378 return cost + 2;
16379 default:
16380 break;
16381 }
16382
16383 }
16384
16385 return cost;
16386 }
16387
16388
16389
16390
16391 static bool
16392 is_microcoded_insn (rtx insn)
16393 {
16394 if (!insn || !INSN_P (insn)
16395 || GET_CODE (PATTERN (insn)) == USE
16396 || GET_CODE (PATTERN (insn)) == CLOBBER)
16397 return false;
16398
16399 if (rs6000_sched_groups)
16400 {
16401 enum attr_type type = get_attr_type (insn);
16402 if (type == TYPE_LOAD_EXT_U
16403 || type == TYPE_LOAD_EXT_UX
16404 || type == TYPE_LOAD_UX
16405 || type == TYPE_STORE_UX
16406 || type == TYPE_MFCR)
16407 return true;
16408 }
16409
16410 return false;
16411 }
16412
16413
16414
16415
16416
16417
16418
16419 static int
16420 is_dispatch_slot_restricted (rtx insn)
16421 {
16422 enum attr_type type;
16423
16424 if (!rs6000_sched_groups)
16425 return 0;
16426
16427 if (!insn
16428 || insn == NULL_RTX
16429 || GET_CODE (insn) == NOTE
16430 || GET_CODE (PATTERN (insn)) == USE
16431 || GET_CODE (PATTERN (insn)) == CLOBBER)
16432 return 0;
16433
16434 type = get_attr_type (insn);
16435
16436 switch (type)
16437 {
16438 case TYPE_MFCR:
16439 case TYPE_MFCRF:
16440 case TYPE_MTCR:
16441 case TYPE_DELAYED_CR:
16442 case TYPE_CR_LOGICAL:
16443 case TYPE_MTJMPR:
16444 case TYPE_MFJMPR:
16445 return 1;
16446 case TYPE_IDIV:
16447 case TYPE_LDIV:
16448 return 2;
16449 default:
16450 if (rs6000_cpu == PROCESSOR_POWER5
16451 && is_cracked_insn (insn))
16452 return 2;
16453 return 0;
16454 }
16455 }
16456
16457
16458
16459
16460 static bool
16461 is_cracked_insn (rtx insn)
16462 {
16463 if (!insn || !INSN_P (insn)
16464 || GET_CODE (PATTERN (insn)) == USE
16465 || GET_CODE (PATTERN (insn)) == CLOBBER)
16466 return false;
16467
16468 if (rs6000_sched_groups)
16469 {
16470 enum attr_type type = get_attr_type (insn);
16471 if (type == TYPE_LOAD_U || type == TYPE_STORE_U
16472 || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
16473 || type == TYPE_FPLOAD_UX || type == TYPE_FPSTORE_UX
16474 || type == TYPE_LOAD_EXT || type == TYPE_DELAYED_CR
16475 || type == TYPE_COMPARE || type == TYPE_DELAYED_COMPARE
16476 || type == TYPE_IMUL_COMPARE || type == TYPE_LMUL_COMPARE
16477 || type == TYPE_IDIV || type == TYPE_LDIV
16478 || type == TYPE_INSERT_WORD)
16479 return true;
16480 }
16481
16482 return false;
16483 }
16484
16485
16486
16487
16488 static bool
16489 is_branch_slot_insn (rtx insn)
16490 {
16491 if (!insn || !INSN_P (insn)
16492 || GET_CODE (PATTERN (insn)) == USE
16493 || GET_CODE (PATTERN (insn)) == CLOBBER)
16494 return false;
16495
16496 if (rs6000_sched_groups)
16497 {
16498 enum attr_type type = get_attr_type (insn);
16499 if (type == TYPE_BRANCH || type == TYPE_JMPREG)
16500 return true;
16501 return false;
16502 }
16503
16504 return false;
16505 }
16506
16507
16508
16509
16510
16511
16512
16513 static int
16514 rs6000_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
16515 {
16516
16517
16518
16519
16520
16521 #if 0
16522 if (! INSN_P (insn))
16523 return priority;
16524
16525 if (GET_CODE (PATTERN (insn)) == USE)
16526 return priority;
16527
16528 switch (rs6000_cpu_attr) {
16529 case CPU_PPC750:
16530 switch (get_attr_type (insn))
16531 {
16532 default:
16533 break;
16534
16535 case TYPE_IMUL:
16536 case TYPE_IDIV:
16537 fprintf (stderr, "priority was %#x (%d) before adjustment\n",
16538 priority, priority);
16539 if (priority >= 0 && priority < 0x01000000)
16540 priority >>= 3;
16541 break;
16542 }
16543 }
16544 #endif
16545
16546 if (is_dispatch_slot_restricted (insn)
16547 && reload_completed
16548 && current_sched_info->sched_max_insns_priority
16549 && rs6000_sched_restricted_insns_priority)
16550 {
16551
16552
16553
16554 if (rs6000_sched_restricted_insns_priority == 1)
16555
16556
16557
16558 return current_sched_info->sched_max_insns_priority;
16559 else if (rs6000_sched_restricted_insns_priority == 2)
16560
16561
16562
16563 return (priority + 1);
16564 }
16565
16566 return priority;
16567 }
16568
16569
16570
16571 static int
16572 rs6000_issue_rate (void)
16573 {
16574
16575 if (!reload_completed)
16576 return 1;
16577
16578 switch (rs6000_cpu_attr) {
16579 case CPU_RIOS1:
16580 case CPU_RS64A:
16581 case CPU_PPC601:
16582 case CPU_PPC7450:
16583 return 3;
16584 case CPU_PPC440:
16585 case CPU_PPC603:
16586 case CPU_PPC750:
16587 case CPU_PPC7400:
16588 case CPU_PPC8540:
16589 return 2;
16590 case CPU_RIOS2:
16591 case CPU_PPC604:
16592 case CPU_PPC604E:
16593 case CPU_PPC620:
16594 case CPU_PPC630:
16595 return 4;
16596 case CPU_POWER4:
16597 case CPU_POWER5:
16598 return 5;
16599 default:
16600 return 1;
16601 }
16602 }
16603
16604
16605
16606
16607 static int
16608 rs6000_use_sched_lookahead (void)
16609 {
16610 if (rs6000_cpu_attr == CPU_PPC8540)
16611 return 4;
16612 return 0;
16613 }
16614
16615
16616
16617 static bool
16618 is_mem_ref (rtx pat)
16619 {
16620 const char * fmt;
16621 int i, j;
16622 bool ret = false;
16623
16624 if (GET_CODE (pat) == MEM)
16625 return true;
16626
16627
16628 fmt = GET_RTX_FORMAT (GET_CODE (pat));
16629
16630 for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0 && !ret; i--)
16631 {
16632 if (fmt[i] == 'e')
16633 ret |= is_mem_ref (XEXP (pat, i));
16634 else if (fmt[i] == 'E')
16635 for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
16636 ret |= is_mem_ref (XVECEXP (pat, i, j));
16637 }
16638
16639 return ret;
16640 }
16641
16642
16643
16644 static bool
16645 is_load_insn1 (rtx pat)
16646 {
16647 if (!pat || pat == NULL_RTX)
16648 return false;
16649
16650 if (GET_CODE (pat) == SET)
16651 return is_mem_ref (SET_SRC (pat));
16652
16653 if (GET_CODE (pat) == PARALLEL)
16654 {
16655 int i;
16656
16657 for (i = 0; i < XVECLEN (pat, 0); i++)
16658 if (is_load_insn1 (XVECEXP (pat, 0, i)))
16659 return true;
16660 }
16661
16662 return false;
16663 }
16664
16665
16666
16667 static bool
16668 is_load_insn (rtx insn)
16669 {
16670 if (!insn || !INSN_P (insn))
16671 return false;
16672
16673 if (GET_CODE (insn) == CALL_INSN)
16674 return false;
16675
16676 return is_load_insn1 (PATTERN (insn));
16677 }
16678
16679
16680
16681 static bool
16682 is_store_insn1 (rtx pat)
16683 {
16684 if (!pat || pat == NULL_RTX)
16685 return false;
16686
16687 if (GET_CODE (pat) == SET)
16688 return is_mem_ref (SET_DEST (pat));
16689
16690 if (GET_CODE (pat) == PARALLEL)
16691 {
16692 int i;
16693
16694 for (i = 0; i < XVECLEN (pat, 0); i++)
16695 if (is_store_insn1 (XVECEXP (pat, 0, i)))
16696 return true;
16697 }
16698
16699 return false;
16700 }
16701
16702
16703
16704 static bool
16705 is_store_insn (rtx insn)
16706 {
16707 if (!insn || !INSN_P (insn))
16708 return false;
16709
16710 return is_store_insn1 (PATTERN (insn));
16711 }
16712
16713
16714
16715
16716 static bool
16717 rs6000_is_costly_dependence (rtx insn, rtx next, rtx link, int cost,
16718 int distance)
16719 {
16720
16721
16722
16723 if (rs6000_sched_costly_dep == no_dep_costly)
16724 return false;
16725
16726
16727
16728
16729 if (rs6000_sched_costly_dep == all_deps_costly)
16730 return true;
16731
16732 if (rs6000_sched_costly_dep == store_to_load_dep_costly
16733 && is_load_insn (next)
16734 && is_store_insn (insn))
16735
16736 return true;
16737
16738 if (rs6000_sched_costly_dep == true_store_to_load_dep_costly
16739 && is_load_insn (next)
16740 && is_store_insn (insn)
16741 && (!link || (int) REG_NOTE_KIND (link) == 0))
16742
16743
16744 return true;
16745
16746
16747
16748 if (rs6000_sched_costly_dep <= max_dep_latency
16749 && ((cost - distance) >= (int)rs6000_sched_costly_dep))
16750 return true;
16751
16752 return false;
16753 }
16754
16755
16756
16757
16758
16759 static rtx
16760 get_next_active_insn (rtx insn, rtx tail)
16761 {
16762 if (insn == NULL_RTX || insn == tail)
16763 return NULL_RTX;
16764
16765 while (1)
16766 {
16767 insn = NEXT_INSN (insn);
16768 if (insn == NULL_RTX || insn == tail)
16769 return NULL_RTX;
16770
16771 if (CALL_P (insn)
16772 || JUMP_P (insn)
16773 || (NONJUMP_INSN_P (insn)
16774 && GET_CODE (PATTERN (insn)) != USE
16775 && GET_CODE (PATTERN (insn)) != CLOBBER
16776 && INSN_CODE (insn) != CODE_FOR_stack_tie))
16777 break;
16778 }
16779 return insn;
16780 }
16781
16782
16783
16784
16785
16786
16787
16788
16789
16790
16791
16792
16793
16794
16795 static bool
16796 insn_terminates_group_p (rtx insn, enum group_termination which_group)
16797 {
16798 enum attr_type type;
16799
16800 if (! insn)
16801 return false;
16802
16803 type = get_attr_type (insn);
16804
16805 if (is_microcoded_insn (insn))
16806 return true;
16807
16808 if (which_group == current_group)
16809 {
16810 if (is_branch_slot_insn (insn))
16811 return true;
16812 return false;
16813 }
16814 else if (which_group == previous_group)
16815 {
16816 if (is_dispatch_slot_restricted (insn))
16817 return true;
16818 return false;
16819 }
16820
16821 return false;
16822 }
16823
16824
16825
16826
16827 static bool
16828 is_costly_group (rtx *group_insns, rtx next_insn)
16829 {
16830 int i;
16831 rtx link;
16832 int cost;
16833 int issue_rate = rs6000_issue_rate ();
16834
16835 for (i = 0; i < issue_rate; i++)
16836 {
16837 rtx insn = group_insns[i];
16838 if (!insn)
16839 continue;
16840 for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
16841 {
16842 rtx next = XEXP (link, 0);
16843 if (next == next_insn)
16844 {
16845 cost = insn_cost (insn, link, next_insn);
16846 if (rs6000_is_costly_dependence (insn, next_insn, link, cost, 0))
16847 return true;
16848 }
16849 }
16850 }
16851
16852 return false;
16853 }
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
16864
16865
16866
16867
16868 static int
16869 force_new_group (int sched_verbose, FILE *dump, rtx *group_insns,
16870 rtx next_insn, bool *group_end, int can_issue_more,
16871 int *group_count)
16872 {
16873 rtx nop;
16874 bool force;
16875 int issue_rate = rs6000_issue_rate ();
16876 bool end = *group_end;
16877 int i;
16878
16879 if (next_insn == NULL_RTX)
16880 return can_issue_more;
16881
16882 if (rs6000_sched_insert_nops > sched_finish_regroup_exact)
16883 return can_issue_more;
16884
16885 force = is_costly_group (group_insns, next_insn);
16886 if (!force)
16887 return can_issue_more;
16888
16889 if (sched_verbose > 6)
16890 fprintf (dump,"force: group count = %d, can_issue_more = %d\n",
16891 *group_count ,can_issue_more);
16892
16893 if (rs6000_sched_insert_nops == sched_finish_regroup_exact)
16894 {
16895 if (*group_end)
16896 can_issue_more = 0;
16897
16898
16899
16900
16901
16902
16903 if (can_issue_more && !is_branch_slot_insn (next_insn))
16904 can_issue_more--;
16905
16906 while (can_issue_more > 0)
16907 {
16908 nop = gen_nop();
16909 emit_insn_before (nop, next_insn);
16910 can_issue_more--;
16911 }
16912
16913 *group_end = true;
16914 return 0;
16915 }
16916
16917 if (rs6000_sched_insert_nops < sched_finish_regroup_exact)
16918 {
16919 int n_nops = rs6000_sched_insert_nops;
16920
16921
16922
16923 if (can_issue_more == 0)
16924 can_issue_more = issue_rate;
16925 can_issue_more--;
16926 if (can_issue_more == 0)
16927 {
16928 can_issue_more = issue_rate - 1;
16929 (*group_count)++;
16930 end = true;
16931 for (i = 0; i < issue_rate; i++)
16932 {
16933 group_insns[i] = 0;
16934 }
16935 }
16936
16937 while (n_nops > 0)
16938 {
16939 nop = gen_nop ();
16940 emit_insn_before (nop, next_insn);
16941 if (can_issue_more == issue_rate - 1)
16942 end = false;
16943 can_issue_more--;
16944 if (can_issue_more == 0)
16945 {
16946 can_issue_more = issue_rate - 1;
16947 (*group_count)++;
16948 end = true;
16949 for (i = 0; i < issue_rate; i++)
16950 {
16951 group_insns[i] = 0;
16952 }
16953 }
16954 n_nops--;
16955 }
16956
16957
16958 can_issue_more++;
16959
16960
16961 *group_end
16962 = (end
16963 || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
16964 || (can_issue_more <= 2 && is_cracked_insn (next_insn))
16965 || (can_issue_more < issue_rate &&
16966 insn_terminates_group_p (next_insn, previous_group)));
16967 if (*group_end && end)
16968 (*group_count)--;
16969
16970 if (sched_verbose > 6)
16971 fprintf (dump, "done force: group count = %d, can_issue_more = %d\n",
16972 *group_count, can_issue_more);
16973 return can_issue_more;
16974 }
16975
16976 return can_issue_more;
16977 }
16978
16979
16980
16981
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993
16994
16995
16996
16997
16998
16999
17000
17001
17002
17003
17004
17005
17006
17007 static int
17008 redefine_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
17009 {
17010 rtx insn, next_insn;
17011 int issue_rate;
17012 int can_issue_more;
17013 int slot, i;
17014 bool group_end;
17015 int group_count = 0;
17016 rtx *group_insns;
17017
17018
17019 issue_rate = rs6000_issue_rate ();
17020 group_insns = alloca (issue_rate * sizeof (rtx));
17021 for (i = 0; i < issue_rate; i++)
17022 {
17023 group_insns[i] = 0;
17024 }
17025 can_issue_more = issue_rate;
17026 slot = 0;
17027 insn = get_next_active_insn (prev_head_insn, tail);
17028 group_end = false;
17029
17030 while (insn != NULL_RTX)
17031 {
17032 slot = (issue_rate - can_issue_more);
17033 group_insns[slot] = insn;
17034 can_issue_more =
17035 rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
17036 if (insn_terminates_group_p (insn, current_group))
17037 can_issue_more = 0;
17038
17039 next_insn = get_next_active_insn (insn, tail);
17040 if (next_insn == NULL_RTX)
17041 return group_count + 1;
17042
17043
17044 group_end
17045 = (can_issue_more == 0
17046 || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
17047 || (can_issue_more <= 2 && is_cracked_insn (next_insn))
17048 || (can_issue_more < issue_rate &&
17049 insn_terminates_group_p (next_insn, previous_group)));
17050
17051 can_issue_more = force_new_group (sched_verbose, dump, group_insns,
17052 next_insn, &group_end, can_issue_more,
17053 &group_count);
17054
17055 if (group_end)
17056 {
17057 group_count++;
17058 can_issue_more = 0;
17059 for (i = 0; i < issue_rate; i++)
17060 {
17061 group_insns[i] = 0;
17062 }
17063 }
17064
17065 if (GET_MODE (next_insn) == TImode && can_issue_more)
17066 PUT_MODE(next_insn, VOIDmode);
17067 else if (!can_issue_more && GET_MODE (next_insn) != TImode)
17068 PUT_MODE (next_insn, TImode);
17069
17070 insn = next_insn;
17071 if (can_issue_more == 0)
17072 can_issue_more = issue_rate;
17073 }
17074
17075 return group_count;
17076 }
17077
17078
17079
17080
17081
17082
17083
17084 static int
17085 pad_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
17086 {
17087 rtx insn, next_insn;
17088 rtx nop;
17089 int issue_rate;
17090 int can_issue_more;
17091 int group_end;
17092 int group_count = 0;
17093
17094
17095 issue_rate = rs6000_issue_rate ();
17096 can_issue_more = issue_rate;
17097
17098 insn = get_next_active_insn (prev_head_insn, tail);
17099 next_insn = get_next_active_insn (insn, tail);
17100
17101 while (insn != NULL_RTX)
17102 {
17103 can_issue_more =
17104 rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
17105
17106 group_end = (next_insn == NULL_RTX || GET_MODE (next_insn) == TImode);
17107
17108 if (next_insn == NULL_RTX)
17109 break;
17110
17111 if (group_end)
17112 {
17113
17114
17115
17116
17117 if (can_issue_more
17118 && (rs6000_sched_insert_nops == sched_finish_pad_groups)
17119 && !insn_terminates_group_p (insn, current_group)
17120 && !insn_terminates_group_p (next_insn, previous_group))
17121 {
17122 if (!is_branch_slot_insn(next_insn))
17123 can_issue_more--;
17124
17125 while (can_issue_more)
17126 {
17127 nop = gen_nop ();
17128 emit_insn_before (nop, next_insn);
17129 can_issue_more--;
17130 }
17131 }
17132
17133 can_issue_more = issue_rate;
17134 group_count++;
17135 }
17136
17137 insn = next_insn;
17138 next_insn = get_next_active_insn (insn, tail);
17139 }
17140
17141 return group_count;
17142 }
17143
17144
17145
17146
17147 static void
17148 rs6000_sched_finish (FILE *dump, int sched_verbose)
17149 {
17150 int n_groups;
17151
17152 if (sched_verbose)
17153 fprintf (dump, "=== Finishing schedule.\n");
17154
17155 if (reload_completed && rs6000_sched_groups)
17156 {
17157 if (rs6000_sched_insert_nops == sched_finish_none)
17158 return;
17159
17160 if (rs6000_sched_insert_nops == sched_finish_pad_groups)
17161 n_groups = pad_groups (dump, sched_verbose,
17162 current_sched_info->prev_head,
17163 current_sched_info->next_tail);
17164 else
17165 n_groups = redefine_groups (dump, sched_verbose,
17166 current_sched_info->prev_head,
17167 current_sched_info->next_tail);
17168
17169 if (sched_verbose >= 6)
17170 {
17171 fprintf (dump, "ngroups = %d\n", n_groups);
17172 print_rtl (dump, current_sched_info->prev_head);
17173 fprintf (dump, "Done finish_sched\n");
17174 }
17175 }
17176 }
17177
17178
17179
17180 int
17181 rs6000_trampoline_size (void)
17182 {
17183 int ret = 0;
17184
17185 switch (DEFAULT_ABI)
17186 {
17187 default:
17188 abort ();
17189
17190 case ABI_AIX:
17191 ret = (TARGET_32BIT) ? 12 : 24;
17192 break;
17193
17194 case ABI_DARWIN:
17195 case ABI_V4:
17196 ret = (TARGET_32BIT) ? 40 : 48;
17197 break;
17198 }
17199
17200 return ret;
17201 }
17202
17203
17204
17205
17206
17207 void
17208 rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
17209 {
17210 enum machine_mode pmode = Pmode;
17211 int regsize = (TARGET_32BIT) ? 4 : 8;
17212 rtx ctx_reg = force_reg (pmode, cxt);
17213
17214 switch (DEFAULT_ABI)
17215 {
17216 default:
17217 abort ();
17218
17219
17220 #define MEM_DEREF(addr) gen_rtx_MEM (pmode, memory_address (pmode, addr))
17221 #define MEM_PLUS(addr,offset) \
17222 gen_rtx_MEM (pmode, memory_address (pmode, plus_constant (addr, offset)))
17223
17224
17225 case ABI_AIX:
17226 {
17227 rtx fn_reg = gen_reg_rtx (pmode);
17228 rtx toc_reg = gen_reg_rtx (pmode);
17229 emit_move_insn (fn_reg, MEM_DEREF (fnaddr));
17230 emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize));
17231 emit_move_insn (MEM_DEREF (addr), fn_reg);
17232 emit_move_insn (MEM_PLUS (addr, regsize), toc_reg);
17233 emit_move_insn (MEM_PLUS (addr, 2*regsize), ctx_reg);
17234 }
17235 break;
17236
17237
17238 case ABI_DARWIN:
17239 case ABI_V4:
17240 emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
17241 FALSE, VOIDmode, 4,
17242 addr, pmode,
17243 GEN_INT (rs6000_trampoline_size ()), SImode,
17244 fnaddr, pmode,
17245 ctx_reg, pmode);
17246 break;
17247 }
17248
17249 return;
17250 }
17251
17252
17253
17254
17255 const struct attribute_spec rs6000_attribute_table[] =
17256 {
17257
17258 { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute },
17259 { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
17260 { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
17261 #ifdef SUBTARGET_ATTRIBUTE_TABLE
17262 SUBTARGET_ATTRIBUTE_TABLE,
17263 #endif
17264 { NULL, 0, 0, false, false, false, NULL }
17265 };
17266
17267
17268
17269
17270
17271
17272
17273
17274
17275
17276
17277 static tree
17278 rs6000_handle_altivec_attribute (tree *node,
17279 tree name ATTRIBUTE_UNUSED,
17280 tree args,
17281 int flags ATTRIBUTE_UNUSED,
17282 bool *no_add_attrs)
17283 {
17284 tree type = *node, result = NULL_TREE;
17285 enum machine_mode mode;
17286 int unsigned_p;
17287 char altivec_type
17288 = ((args && TREE_CODE (args) == TREE_LIST && TREE_VALUE (args)
17289 && TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
17290 ? *IDENTIFIER_POINTER (TREE_VALUE (args))
17291 : '?');
17292
17293 while (POINTER_TYPE_P (type)
17294 || TREE_CODE (type) == FUNCTION_TYPE
17295 || TREE_CODE (type) == METHOD_TYPE
17296 || TREE_CODE (type) == ARRAY_TYPE)
17297 type = TREE_TYPE (type);
17298
17299 mode = TYPE_MODE (type);
17300
17301
17302 if (type == long_unsigned_type_node || type == long_integer_type_node)
17303 {
17304 if (TARGET_64BIT)
17305 error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
17306 else if (rs6000_warn_altivec_long)
17307 warning ("use of %<long%> in AltiVec types is deprecated; use %<int%>");
17308 }
17309 else if (type == long_long_unsigned_type_node
17310 || type == long_long_integer_type_node)
17311 error ("use of %<long long%> in AltiVec types is invalid");
17312 else if (type == double_type_node)
17313 error ("use of %<double%> in AltiVec types is invalid");
17314 else if (type == long_double_type_node)
17315 error ("use of %<long double%> in AltiVec types is invalid");
17316 else if (type == boolean_type_node)
17317 error ("use of boolean types in AltiVec types is invalid");
17318 else if (TREE_CODE (type) == COMPLEX_TYPE)
17319 error ("use of %<complex%> in AltiVec types is invalid");
17320
17321 switch (altivec_type)
17322 {
17323 case 'v':
17324 unsigned_p = TYPE_UNSIGNED (type);
17325 switch (mode)
17326 {
17327 case SImode:
17328 result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
17329 break;
17330 case HImode:
17331 result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
17332 break;
17333 case QImode:
17334 result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
17335 break;
17336 case SFmode: result = V4SF_type_node; break;
17337
17338
17339
17340 case V4SImode: case V8HImode: case V16QImode: case V4SFmode:
17341 result = type;
17342 default: break;
17343 }
17344 break;
17345 case 'b':
17346 switch (mode)
17347 {
17348 case SImode: case V4SImode: result = bool_V4SI_type_node; break;
17349 case HImode: case V8HImode: result = bool_V8HI_type_node; break;
17350 case QImode: case V16QImode: result = bool_V16QI_type_node;
17351 default: break;
17352 }
17353 break;
17354 case 'p':
17355 switch (mode)
17356 {
17357 case V8HImode: result = pixel_V8HI_type_node;
17358 default: break;
17359 }
17360 default: break;
17361 }
17362
17363 if (result && result != type && TYPE_READONLY (type))
17364 result = build_qualified_type (result, TYPE_QUAL_CONST);
17365
17366 *no_add_attrs = true;
17367
17368 if (result)
17369 *node = reconstruct_complex_type (*node, result);
17370
17371 return NULL_TREE;
17372 }
17373
17374
17375
17376
17377 static const char *
17378 rs6000_mangle_fundamental_type (tree type)
17379 {
17380 if (type == bool_char_type_node) return "U6__boolc";
17381 if (type == bool_short_type_node) return "U6__bools";
17382 if (type == pixel_type_node) return "u7__pixel";
17383 if (type == bool_int_type_node) return "U6__booli";
17384
17385
17386 return NULL;
17387 }
17388
17389
17390
17391
17392 static tree
17393 rs6000_handle_longcall_attribute (tree *node, tree name,
17394 tree args ATTRIBUTE_UNUSED,
17395 int flags ATTRIBUTE_UNUSED,
17396 bool *no_add_attrs)
17397 {
17398 if (TREE_CODE (*node) != FUNCTION_TYPE
17399 && TREE_CODE (*node) != FIELD_DECL
17400 && TREE_CODE (*node) != TYPE_DECL)
17401 {
17402 warning ("%qs attribute only applies to functions",
17403 IDENTIFIER_POINTER (name));
17404 *no_add_attrs = true;
17405 }
17406
17407 return NULL_TREE;
17408 }
17409
17410
17411
17412 static void
17413 rs6000_set_default_type_attributes (tree type)
17414 {
17415 if (rs6000_default_long_calls
17416 && (TREE_CODE (type) == FUNCTION_TYPE
17417 || TREE_CODE (type) == METHOD_TYPE))
17418 TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
17419 NULL_TREE,
17420 TYPE_ATTRIBUTES (type));
17421 }
17422
17423
17424
17425
17426 struct rtx_def *
17427 rs6000_longcall_ref (rtx call_ref)
17428 {
17429 const char *call_name;
17430 tree node;
17431
17432 if (GET_CODE (call_ref) != SYMBOL_REF)
17433 return call_ref;
17434
17435
17436 call_name = XSTR (call_ref, 0);
17437 if (*call_name == '.')
17438 {
17439 while (*call_name == '.')
17440 call_name++;
17441
17442 node = get_identifier (call_name);
17443 call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node));
17444 }
17445
17446 return force_reg (Pmode, call_ref);
17447 }
17448
17449 #ifdef USING_ELFOS_H
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460 static void
17461 rs6000_elf_select_rtx_section (enum machine_mode mode, rtx x,
17462 unsigned HOST_WIDE_INT align)
17463 {
17464 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
17465 toc_section ();
17466 else
17467 default_elf_select_rtx_section (mode, x, align);
17468 }
17469
17470
17471
17472
17473
17474
17475 static void
17476 rs6000_elf_select_section (tree decl, int reloc,
17477 unsigned HOST_WIDE_INT align)
17478 {
17479
17480
17481
17482
17483 default_elf_select_section_1 (decl, reloc, align,
17484 flag_pic || DEFAULT_ABI == ABI_AIX);
17485 }
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495 static void
17496 rs6000_elf_unique_section (tree decl, int reloc)
17497 {
17498
17499
17500 default_unique_section_1 (decl, reloc,
17501 flag_pic || DEFAULT_ABI == ABI_AIX);
17502 }
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512 static void
17513 rs6000_elf_encode_section_info (tree decl, rtx rtl, int first)
17514 {
17515 default_encode_section_info (decl, rtl, first);
17516
17517 if (first
17518 && TREE_CODE (decl) == FUNCTION_DECL
17519 && !TARGET_AIX
17520 && DEFAULT_ABI == ABI_AIX)
17521 {
17522 rtx sym_ref = XEXP (rtl, 0);
17523 size_t len = strlen (XSTR (sym_ref, 0));
17524 char *str = alloca (len + 2);
17525 str[0] = '.';
17526 memcpy (str + 1, XSTR (sym_ref, 0), len + 1);
17527 XSTR (sym_ref, 0) = ggc_alloc_string (str, len + 1);
17528 }
17529 }
17530
17531 static bool
17532 rs6000_elf_in_small_data_p (tree decl)
17533 {
17534 if (rs6000_sdata == SDATA_NONE)
17535 return false;
17536
17537
17538 if (TREE_CODE (decl) == STRING_CST)
17539 return false;
17540
17541
17542 if (TREE_CODE (decl) == FUNCTION_DECL)
17543 return false;
17544
17545 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
17546 {
17547 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
17548 if (strcmp (section, ".sdata") == 0
17549 || strcmp (section, ".sdata2") == 0
17550 || strcmp (section, ".sbss") == 0
17551 || strcmp (section, ".sbss2") == 0
17552 || strcmp (section, ".PPC.EMB.sdata0") == 0
17553 || strcmp (section, ".PPC.EMB.sbss0") == 0)
17554 return true;
17555 }
17556 else
17557 {
17558 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
17559
17560 if (size > 0
17561 && (unsigned HOST_WIDE_INT) size <= g_switch_value
17562
17563
17564 && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)))
17565 return true;
17566 }
17567
17568 return false;
17569 }
17570
17571 #endif
17572
17573
17574
17575
17576
17577
17578
17579
17580
17581 struct rtx_def *
17582 find_addr_reg (rtx addr)
17583 {
17584 while (GET_CODE (addr) == PLUS)
17585 {
17586 if (GET_CODE (XEXP (addr, 0)) == REG
17587 && REGNO (XEXP (addr, 0)) != 0)
17588 addr = XEXP (addr, 0);
17589 else if (GET_CODE (XEXP (addr, 1)) == REG
17590 && REGNO (XEXP (addr, 1)) != 0)
17591 addr = XEXP (addr, 1);
17592 else if (CONSTANT_P (XEXP (addr, 0)))
17593 addr = XEXP (addr, 1);
17594 else if (CONSTANT_P (XEXP (addr, 1)))
17595 addr = XEXP (addr, 0);
17596 else
17597 abort ();
17598 }
17599 if (GET_CODE (addr) == REG && REGNO (addr) != 0)
17600 return addr;
17601 abort ();
17602 }
17603
17604 void
17605 rs6000_fatal_bad_address (rtx op)
17606 {
17607 fatal_insn ("bad address", op);
17608 }
17609
17610 #if TARGET_MACHO
17611
17612 static tree branch_island_list = 0;
17613
17614
17615
17616
17617 static void
17618 add_compiler_branch_island (tree label_name, tree function_name,
17619 int line_number)
17620 {
17621 tree branch_island = build_tree_list (function_name, label_name);
17622 TREE_TYPE (branch_island) = build_int_cst (NULL_TREE, line_number);
17623 TREE_CHAIN (branch_island) = branch_island_list;
17624 branch_island_list = branch_island;
17625 }
17626
17627 #define BRANCH_ISLAND_LABEL_NAME(BRANCH_ISLAND) TREE_VALUE (BRANCH_ISLAND)
17628 #define BRANCH_ISLAND_FUNCTION_NAME(BRANCH_ISLAND) TREE_PURPOSE (BRANCH_ISLAND)
17629 #define BRANCH_ISLAND_LINE_NUMBER(BRANCH_ISLAND) \
17630 TREE_INT_CST_LOW (TREE_TYPE (BRANCH_ISLAND))
17631
17632
17633
17634
17635
17636
17637
17638 static void
17639 macho_branch_islands (void)
17640 {
17641 char tmp_buf[512];
17642 tree branch_island;
17643
17644 for (branch_island = branch_island_list;
17645 branch_island;
17646 branch_island = TREE_CHAIN (branch_island))
17647 {
17648 const char *label =
17649 IDENTIFIER_POINTER (BRANCH_ISLAND_LABEL_NAME (branch_island));
17650 const char *name =
17651 IDENTIFIER_POINTER (BRANCH_ISLAND_FUNCTION_NAME (branch_island));
17652 char name_buf[512];
17653
17654 if (name[0] == '*' || name[0] == '&')
17655 strcpy (name_buf, name+1);
17656 else
17657 {
17658 name_buf[0] = '_';
17659 strcpy (name_buf+1, name);
17660 }
17661 strcpy (tmp_buf, "\n");
17662 strcat (tmp_buf, label);
17663 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
17664 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
17665 dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
17666 #endif
17667 if (flag_pic)
17668 {
17669 strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
17670 strcat (tmp_buf, label);
17671 strcat (tmp_buf, "_pic\n");
17672 strcat (tmp_buf, label);
17673 strcat (tmp_buf, "_pic:\n\tmflr r11\n");
17674
17675 strcat (tmp_buf, "\taddis r11,r11,ha16(");
17676 strcat (tmp_buf, name_buf);
17677 strcat (tmp_buf, " - ");
17678 strcat (tmp_buf, label);
17679 strcat (tmp_buf, "_pic)\n");
17680
17681 strcat (tmp_buf, "\tmtlr r0\n");
17682
17683 strcat (tmp_buf, "\taddi r12,r11,lo16(");
17684 strcat (tmp_buf, name_buf);
17685 strcat (tmp_buf, " - ");
17686 strcat (tmp_buf, label);
17687 strcat (tmp_buf, "_pic)\n");
17688
17689 strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
17690 }
17691 else
17692 {
17693 strcat (tmp_buf, ":\nlis r12,hi16(");
17694 strcat (tmp_buf, name_buf);
17695 strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
17696 strcat (tmp_buf, name_buf);
17697 strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
17698 }
17699 output_asm_insn (tmp_buf, 0);
17700 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
17701 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
17702 dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
17703 #endif
17704 }
17705
17706 branch_island_list = 0;
17707 }
17708
17709
17710
17711
17712 static int
17713 no_previous_def (tree function_name)
17714 {
17715 tree branch_island;
17716 for (branch_island = branch_island_list;
17717 branch_island;
17718 branch_island = TREE_CHAIN (branch_island))
17719 if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
17720 return 0;
17721 return 1;
17722 }
17723
17724
17725
17726
17727 static tree
17728 get_prev_label (tree function_name)
17729 {
17730 tree branch_island;
17731 for (branch_island = branch_island_list;
17732 branch_island;
17733 branch_island = TREE_CHAIN (branch_island))
17734 if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
17735 return BRANCH_ISLAND_LABEL_NAME (branch_island);
17736 return 0;
17737 }
17738
17739
17740
17741
17742
17743
17744 char *
17745 output_call (rtx insn, rtx *operands, int dest_operand_number,
17746 int cookie_operand_number)
17747 {
17748 static char buf[256];
17749 if (GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
17750 && (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
17751 {
17752 tree labelname;
17753 tree funname = get_identifier (XSTR (operands[dest_operand_number], 0));
17754
17755 if (no_previous_def (funname))
17756 {
17757 int line_number = 0;
17758 rtx label_rtx = gen_label_rtx ();
17759 char *label_buf, temp_buf[256];
17760 ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
17761 CODE_LABEL_NUMBER (label_rtx));
17762 label_buf = temp_buf[0] == '*' ? temp_buf + 1 : temp_buf;
17763 labelname = get_identifier (label_buf);
17764 for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
17765 if (insn)
17766 line_number = NOTE_LINE_NUMBER (insn);
17767 add_compiler_branch_island (labelname, funname, line_number);
17768 }
17769 else
17770 labelname = get_prev_label (funname);
17771
17772
17773
17774
17775
17776
17777 sprintf (buf, "jbsr %%z%d,%.246s",
17778 dest_operand_number, IDENTIFIER_POINTER (labelname));
17779 }
17780 else
17781 sprintf (buf, "bl %%z%d", dest_operand_number);
17782 return buf;
17783 }
17784
17785
17786
17787 void
17788 machopic_output_stub (FILE *file, const char *symb, const char *stub)
17789 {
17790 unsigned int length;
17791 char *symbol_name, *lazy_ptr_name;
17792 char *local_label_0;
17793 static int label = 0;
17794
17795
17796 symb = (*targetm.strip_name_encoding) (symb);
17797
17798
17799 length = strlen (symb);
17800 symbol_name = alloca (length + 32);
17801 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
17802
17803 lazy_ptr_name = alloca (length + 32);
17804 GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name, symb, length);
17805
17806 if (flag_pic == 2)
17807 machopic_picsymbol_stub1_section ();
17808 else
17809 machopic_symbol_stub1_section ();
17810
17811 if (flag_pic == 2)
17812 {
17813 fprintf (file, "\t.align 5\n");
17814
17815 fprintf (file, "%s:\n", stub);
17816 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
17817
17818 label++;
17819 local_label_0 = alloca (sizeof("\"L0000000000$spb\""));
17820 sprintf (local_label_0, "\"L%011d$spb\"", label);
17821
17822 fprintf (file, "\tmflr r0\n");
17823 fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
17824 fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
17825 fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
17826 lazy_ptr_name, local_label_0);
17827 fprintf (file, "\tmtlr r0\n");
17828 fprintf (file, "\t%s r12,lo16(%s-%s)(r11)\n",
17829 (TARGET_64BIT ? "ldu" : "lwzu"),
17830 lazy_ptr_name, local_label_0);
17831 fprintf (file, "\tmtctr r12\n");
17832 fprintf (file, "\tbctr\n");
17833 }
17834 else
17835 {
17836 fprintf (file, "\t.align 4\n");
17837
17838 fprintf (file, "%s:\n", stub);
17839 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
17840
17841 fprintf (file, "\tlis r11,ha16(%s)\n", lazy_ptr_name);
17842 fprintf (file, "\t%s r12,lo16(%s)(r11)\n",
17843 (TARGET_64BIT ? "ldu" : "lwzu"),
17844 lazy_ptr_name);
17845 fprintf (file, "\tmtctr r12\n");
17846 fprintf (file, "\tbctr\n");
17847 }
17848
17849 machopic_lazy_symbol_ptr_section ();
17850 fprintf (file, "%s:\n", lazy_ptr_name);
17851 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
17852 fprintf (file, "%sdyld_stub_binding_helper\n",
17853 (TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t"));
17854 }
17855
17856
17857
17858
17859
17860
17861 #define SMALL_INT(X) ((unsigned) (INTVAL(X) + 0x8000) < 0x10000)
17862
17863 rtx
17864 rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
17865 rtx reg)
17866 {
17867 rtx base, offset;
17868
17869 if (reg == NULL && ! reload_in_progress && ! reload_completed)
17870 reg = gen_reg_rtx (Pmode);
17871
17872 if (GET_CODE (orig) == CONST)
17873 {
17874 if (GET_CODE (XEXP (orig, 0)) == PLUS
17875 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
17876 return orig;
17877
17878 if (GET_CODE (XEXP (orig, 0)) == PLUS)
17879 {
17880
17881
17882 rtx reg_temp = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
17883
17884 base =
17885 rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
17886 Pmode, reg_temp);
17887 offset =
17888 rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
17889 Pmode, reg);
17890 }
17891 else
17892 abort ();
17893
17894 if (GET_CODE (offset) == CONST_INT)
17895 {
17896 if (SMALL_INT (offset))
17897 return plus_constant (base, INTVAL (offset));
17898 else if (! reload_in_progress && ! reload_completed)
17899 offset = force_reg (Pmode, offset);
17900 else
17901 {
17902 rtx mem = force_const_mem (Pmode, orig);
17903 return machopic_legitimize_pic_address (mem, Pmode, reg);
17904 }
17905 }
17906 return gen_rtx_PLUS (Pmode, base, offset);
17907 }
17908
17909
17910 return machopic_legitimize_pic_address (orig, mode, reg);
17911 }
17912
17913
17914
17915
17916
17917
17918 void
17919 toc_section (void)
17920 {
17921 }
17922
17923
17924
17925
17926 static void
17927 rs6000_darwin_file_start (void)
17928 {
17929 static const struct
17930 {
17931 const char *arg;
17932 const char *name;
17933 int if_set;
17934 } mapping[] = {
17935 { "ppc64", "ppc64", MASK_64BIT },
17936 { "970", "ppc970", MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64 },
17937 { "power4", "ppc970", 0 },
17938 { "G5", "ppc970", 0 },
17939 { "7450", "ppc7450", 0 },
17940 { "7400", "ppc7400", MASK_ALTIVEC },
17941 { "G4", "ppc7400", 0 },
17942 { "750", "ppc750", 0 },
17943 { "740", "ppc750", 0 },
17944 { "G3", "ppc750", 0 },
17945 { "604e", "ppc604e", 0 },
17946 { "604", "ppc604", 0 },
17947 { "603e", "ppc603", 0 },
17948 { "603", "ppc603", 0 },
17949 { "601", "ppc601", 0 },
17950 { NULL, "ppc", 0 } };
17951 const char *cpu_id = "";
17952 size_t i;
17953
17954 rs6000_file_start();
17955
17956
17957 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
17958 if (rs6000_select[i].set_arch_p && rs6000_select[i].string
17959 && rs6000_select[i].string[0] != '\0')
17960 cpu_id = rs6000_select[i].string;
17961
17962
17963
17964
17965
17966 i = 0;
17967 while (mapping[i].arg != NULL
17968 && strcmp (mapping[i].arg, cpu_id) != 0
17969 && (mapping[i].if_set & target_flags) == 0)
17970 i++;
17971
17972 fprintf (asm_out_file, "\t.machine %s\n", mapping[i].name);
17973 }
17974
17975 #endif
17976
17977 #if TARGET_ELF
17978 static unsigned int
17979 rs6000_elf_section_type_flags (tree decl, const char *name, int reloc)
17980 {
17981 return default_section_type_flags_1 (decl, name, reloc,
17982 flag_pic || DEFAULT_ABI == ABI_AIX);
17983 }
17984
17985
17986
17987
17988
17989
17990
17991
17992 static void
17993 rs6000_elf_asm_out_constructor (rtx symbol, int priority)
17994 {
17995 const char *section = ".ctors";
17996 char buf[16];
17997
17998 if (priority != DEFAULT_INIT_PRIORITY)
17999 {
18000 sprintf (buf, ".ctors.%.5u",
18001
18002
18003
18004 MAX_INIT_PRIORITY - priority);
18005 section = buf;
18006 }
18007
18008 named_section_flags (section, SECTION_WRITE);
18009 assemble_align (POINTER_SIZE);
18010
18011 if (TARGET_RELOCATABLE)
18012 {
18013 fputs ("\t.long (", asm_out_file);
18014 output_addr_const (asm_out_file, symbol);
18015 fputs (")@fixup\n", asm_out_file);
18016 }
18017 else
18018 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
18019 }
18020
18021 static void
18022 rs6000_elf_asm_out_destructor (rtx symbol, int priority)
18023 {
18024 const char *section = ".dtors";
18025 char buf[16];
18026
18027 if (priority != DEFAULT_INIT_PRIORITY)
18028 {
18029 sprintf (buf, ".dtors.%.5u",
18030
18031
18032
18033 MAX_INIT_PRIORITY - priority);
18034 section = buf;
18035 }
18036
18037 named_section_flags (section, SECTION_WRITE);
18038 assemble_align (POINTER_SIZE);
18039
18040 if (TARGET_RELOCATABLE)
18041 {
18042 fputs ("\t.long (", asm_out_file);
18043 output_addr_const (asm_out_file, symbol);
18044 fputs (")@fixup\n", asm_out_file);
18045 }
18046 else
18047 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
18048 }
18049
18050 void
18051 rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
18052 {
18053 if (TARGET_64BIT)
18054 {
18055 fputs ("\t.section\t\".opd\",\"aw\"\n\t.align 3\n", file);
18056 ASM_OUTPUT_LABEL (file, name);
18057 fputs (DOUBLE_INT_ASM_OP, file);
18058 rs6000_output_function_entry (file, name);
18059 fputs (",.TOC.@tocbase,0\n\t.previous\n", file);
18060 if (DOT_SYMBOLS)
18061 {
18062 fputs ("\t.size\t", file);
18063 assemble_name (file, name);
18064 fputs (",24\n\t.type\t.", file);
18065 assemble_name (file, name);
18066 fputs (",@function\n", file);
18067 if (TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
18068 {
18069 fputs ("\t.globl\t.", file);
18070 assemble_name (file, name);
18071 putc ('\n', file);
18072 }
18073 }
18074 else
18075 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
18076 ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
18077 rs6000_output_function_entry (file, name);
18078 fputs (":\n", file);
18079 return;
18080 }
18081
18082 if (TARGET_RELOCATABLE
18083 && (get_pool_size () != 0 || current_function_profile)
18084 && uses_TOC ())
18085 {
18086 char buf[256];
18087
18088 (*targetm.asm_out.internal_label) (file, "LCL", rs6000_pic_labelno);
18089
18090 ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
18091 fprintf (file, "\t.long ");
18092 assemble_name (file, buf);
18093 putc ('-', file);
18094 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
18095 assemble_name (file, buf);
18096 putc ('\n', file);
18097 }
18098
18099 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
18100 ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
18101
18102 if (DEFAULT_ABI == ABI_AIX)
18103 {
18104 const char *desc_name, *orig_name;
18105
18106 orig_name = (*targetm.strip_name_encoding) (name);
18107 desc_name = orig_name;
18108 while (*desc_name == '.')
18109 desc_name++;
18110
18111 if (TREE_PUBLIC (decl))
18112 fprintf (file, "\t.globl %s\n", desc_name);
18113
18114 fprintf (file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
18115 fprintf (file, "%s:\n", desc_name);
18116 fprintf (file, "\t.long %s\n", orig_name);
18117 fputs ("\t.long _GLOBAL_OFFSET_TABLE_\n", file);
18118 if (DEFAULT_ABI == ABI_AIX)
18119 fputs ("\t.long 0\n", file);
18120 fprintf (file, "\t.previous\n");
18121 }
18122 ASM_OUTPUT_LABEL (file, name);
18123 }
18124
18125 static void
18126 rs6000_elf_end_indicate_exec_stack (void)
18127 {
18128 if (TARGET_32BIT)
18129 file_end_indicate_exec_stack ();
18130 }
18131 #endif
18132
18133 #if TARGET_XCOFF
18134 static void
18135 rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
18136 {
18137 fputs (GLOBAL_ASM_OP, stream);
18138 RS6000_OUTPUT_BASENAME (stream, name);
18139 putc ('\n', stream);
18140 }
18141
18142 static void
18143 rs6000_xcoff_asm_named_section (const char *name, unsigned int flags,
18144 tree decl ATTRIBUTE_UNUSED)
18145 {
18146 int smclass;
18147 static const char * const suffix[3] = { "PR", "RO", "RW" };
18148
18149 if (flags & SECTION_CODE)
18150 smclass = 0;
18151 else if (flags & SECTION_WRITE)
18152 smclass = 2;
18153 else
18154 smclass = 1;
18155
18156 fprintf (asm_out_file, "\t.csect %s%s[%s],%u\n",
18157 (flags & SECTION_CODE) ? "." : "",
18158 name, suffix[smclass], flags & SECTION_ENTSIZE);
18159 }
18160
18161 static void
18162 rs6000_xcoff_select_section (tree decl, int reloc,
18163 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
18164 {
18165 if (decl_readonly_section_1 (decl, reloc, 1))
18166 {
18167 if (TREE_PUBLIC (decl))
18168 read_only_data_section ();
18169 else
18170 read_only_private_data_section ();
18171 }
18172 else
18173 {
18174 if (TREE_PUBLIC (decl))
18175 data_section ();
18176 else
18177 private_data_section ();
18178 }
18179 }
18180
18181 static void
18182 rs6000_xcoff_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
18183 {
18184 const char *name;
18185
18186
18187 if (!TREE_PUBLIC (decl)
18188 || DECL_COMMON (decl)
18189 || DECL_INITIAL (decl) == NULL_TREE
18190 || DECL_INITIAL (decl) == error_mark_node
18191 || (flag_zero_initialized_in_bss
18192 && initializer_zerop (DECL_INITIAL (decl))))
18193 return;
18194
18195 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
18196 name = (*targetm.strip_name_encoding) (name);
18197 DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
18198 }
18199
18200
18201
18202
18203
18204
18205
18206 static void
18207 rs6000_xcoff_select_rtx_section (enum machine_mode mode, rtx x,
18208 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
18209 {
18210 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
18211 toc_section ();
18212 else
18213 read_only_private_data_section ();
18214 }
18215
18216
18217
18218 static const char *
18219 rs6000_xcoff_strip_name_encoding (const char *name)
18220 {
18221 size_t len;
18222 if (*name == '*')
18223 name++;
18224 len = strlen (name);
18225 if (name[len - 1] == ']')
18226 return ggc_alloc_string (name, len - 4);
18227 else
18228 return name;
18229 }
18230
18231
18232
18233 static unsigned int
18234 rs6000_xcoff_section_type_flags (tree decl, const char *name, int reloc)
18235 {
18236 unsigned int align;
18237 unsigned int flags = default_section_type_flags_1 (decl, name, reloc, 1);
18238
18239
18240 if (flags & SECTION_CODE)
18241 align = MIN_UNITS_PER_WORD;
18242 else
18243
18244 align = MAX ((DECL_ALIGN (decl) / BITS_PER_UNIT),
18245 int_size_in_bytes (TREE_TYPE (decl)) > MIN_UNITS_PER_WORD
18246 ? UNITS_PER_FP_WORD : MIN_UNITS_PER_WORD);
18247
18248 return flags | (exact_log2 (align) & SECTION_ENTSIZE);
18249 }
18250
18251
18252
18253
18254
18255
18256
18257
18258
18259
18260
18261
18262
18263 static void
18264 rs6000_xcoff_file_start (void)
18265 {
18266 rs6000_gen_section_name (&xcoff_bss_section_name,
18267 main_input_filename, ".bss_");
18268 rs6000_gen_section_name (&xcoff_private_data_section_name,
18269 main_input_filename, ".rw_");
18270 rs6000_gen_section_name (&xcoff_read_only_section_name,
18271 main_input_filename, ".ro_");
18272
18273 fputs ("\t.file\t", asm_out_file);
18274 output_quoted_string (asm_out_file, main_input_filename);
18275 fputc ('\n', asm_out_file);
18276 if (write_symbols != NO_DEBUG)
18277 private_data_section ();
18278 text_section ();
18279 if (profile_flag)
18280 fprintf (asm_out_file, "\t.extern %s\n", RS6000_MCOUNT);
18281 rs6000_file_start ();
18282 }
18283
18284
18285
18286
18287 static void
18288 rs6000_xcoff_file_end (void)
18289 {
18290 text_section ();
18291 fputs ("_section_.text:\n", asm_out_file);
18292 data_section ();
18293 fputs (TARGET_32BIT
18294 ? "\t.long _section_.text\n" : "\t.llong _section_.text\n",
18295 asm_out_file);
18296 }
18297 #endif
18298
18299 #if TARGET_MACHO
18300
18301
18302
18303 static bool
18304 rs6000_binds_local_p (tree decl)
18305 {
18306 return default_binds_local_p_1 (decl, 0);
18307 }
18308 #endif
18309
18310
18311
18312
18313
18314 static bool
18315 rs6000_rtx_costs (rtx x, int code, int outer_code, int *total)
18316 {
18317 enum machine_mode mode = GET_MODE (x);
18318
18319 switch (code)
18320 {
18321
18322 case CONST_INT:
18323 if (((outer_code == SET
18324 || outer_code == PLUS
18325 || outer_code == MINUS)
18326 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
18327 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')))
18328 || (outer_code == AND
18329 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
18330 || (CONST_OK_FOR_LETTER_P (INTVAL (x),
18331 mode == SImode ? 'L' : 'J'))
18332 || mask_operand (x, VOIDmode)))
18333 || ((outer_code == IOR || outer_code == XOR)
18334 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
18335 || (CONST_OK_FOR_LETTER_P (INTVAL (x),
18336 mode == SImode ? 'L' : 'J'))))
18337 || outer_code == ASHIFT
18338 || outer_code == ASHIFTRT
18339 || outer_code == LSHIFTRT
18340 || outer_code == ROTATE
18341 || outer_code == ROTATERT
18342 || outer_code == ZERO_EXTRACT
18343 || (outer_code == MULT
18344 && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I'))
18345 || ((outer_code == DIV || outer_code == UDIV
18346 || outer_code == MOD || outer_code == UMOD)
18347 && exact_log2 (INTVAL (x)) >= 0)
18348 || (outer_code == COMPARE
18349 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
18350 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')))
18351 || (outer_code == EQ
18352 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
18353 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
18354 || (CONST_OK_FOR_LETTER_P (INTVAL (x),
18355 mode == SImode ? 'L' : 'J'))))
18356 || (outer_code == GTU
18357 && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I'))
18358 || (outer_code == LTU
18359 && CONST_OK_FOR_LETTER_P (INTVAL (x), 'P')))
18360 {
18361 *total = 0;
18362 return true;
18363 }
18364 else if ((outer_code == PLUS
18365 && reg_or_add_cint64_operand (x, VOIDmode))
18366 || (outer_code == MINUS
18367 && reg_or_sub_cint64_operand (x, VOIDmode))
18368 || ((outer_code == SET
18369 || outer_code == IOR
18370 || outer_code == XOR)
18371 && (INTVAL (x)
18372 & ~ (unsigned HOST_WIDE_INT) 0xffffffff) == 0))
18373 {
18374 *total = COSTS_N_INSNS (1);
18375 return true;
18376 }
18377
18378
18379 case CONST_DOUBLE:
18380 if (mode == DImode
18381 && ((outer_code == AND
18382 && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
18383 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
18384 || mask64_operand (x, DImode)))
18385 || ((outer_code == IOR || outer_code == XOR)
18386 && CONST_DOUBLE_HIGH (x) == 0
18387 && (CONST_DOUBLE_LOW (x)
18388 & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)))
18389 {
18390 *total = 0;
18391 return true;
18392 }
18393 else if (mode == DImode
18394 && (outer_code == SET
18395 || outer_code == IOR
18396 || outer_code == XOR)
18397 && CONST_DOUBLE_HIGH (x) == 0)
18398 {
18399 *total = COSTS_N_INSNS (1);
18400 return true;
18401 }
18402
18403
18404 case CONST:
18405 case HIGH:
18406 case SYMBOL_REF:
18407 case MEM:
18408
18409
18410
18411 *total = optimize_size ? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (2);
18412 return true;
18413
18414 case LABEL_REF:
18415 *total = 0;
18416 return true;
18417
18418 case PLUS:
18419 if (mode == DFmode)
18420 {
18421 if (GET_CODE (XEXP (x, 0)) == MULT)
18422 {
18423
18424 if (outer_code == NEG)
18425 *total = rs6000_cost->dmul - rs6000_cost->fp;
18426 else
18427 *total = rs6000_cost->dmul;
18428 }
18429 else
18430 *total = rs6000_cost->fp;
18431 }
18432 else if (mode == SFmode)
18433 {
18434
18435 if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
18436 *total = 0;
18437 else
18438 *total = rs6000_cost->fp;
18439 }
18440 else if (GET_CODE (XEXP (x, 0)) == MULT)
18441 {
18442
18443 rs6000_rtx_costs (XEXP (x, 0), MULT, PLUS, total);
18444 *total += COSTS_N_INSNS (1);
18445 }
18446 else
18447 *total = COSTS_N_INSNS (1);
18448 return false;
18449
18450 case MINUS:
18451 if (mode == DFmode)
18452 {
18453 if (GET_CODE (XEXP (x, 0)) == MULT)
18454 {
18455
18456 if (outer_code == NEG)
18457 *total = 0;
18458 else
18459 *total = rs6000_cost->dmul;
18460 }
18461 else
18462 *total = rs6000_cost->fp;
18463 }
18464 else if (mode == SFmode)
18465 {
18466
18467 if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
18468 *total = 0;
18469 else
18470 *total = rs6000_cost->fp;
18471 }
18472 else if (GET_CODE (XEXP (x, 0)) == MULT)
18473 {
18474
18475 rs6000_rtx_costs (XEXP (x, 0), MULT, MINUS, total);
18476 *total += COSTS_N_INSNS (1);
18477 }
18478 else
18479 *total = COSTS_N_INSNS (1);
18480 return false;
18481
18482 case MULT:
18483 if (GET_CODE (XEXP (x, 1)) == CONST_INT
18484 && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'I'))
18485 {
18486 if (INTVAL (XEXP (x, 1)) >= -256
18487 && INTVAL (XEXP (x, 1)) <= 255)
18488 *total = rs6000_cost->mulsi_const9;
18489 else
18490 *total = rs6000_cost->mulsi_const;
18491 }
18492
18493 else if ((mode == DFmode || mode == SFmode)
18494 && (outer_code == PLUS || outer_code == MINUS))
18495 *total = 0;
18496 else if (mode == DFmode)
18497 *total = rs6000_cost->dmul;
18498 else if (mode == SFmode)
18499 *total = rs6000_cost->fp;
18500 else if (mode == DImode)
18501 *total = rs6000_cost->muldi;
18502 else
18503 *total = rs6000_cost->mulsi;
18504 return false;
18505
18506 case DIV:
18507 case MOD:
18508 if (FLOAT_MODE_P (mode))
18509 {
18510 *total = mode == DFmode ? rs6000_cost->ddiv
18511 : rs6000_cost->sdiv;
18512 return false;
18513 }
18514
18515
18516 case UDIV:
18517 case UMOD:
18518 if (GET_CODE (XEXP (x, 1)) == CONST_INT
18519 && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
18520 {
18521 if (code == DIV || code == MOD)
18522
18523 *total = COSTS_N_INSNS (2);
18524 else
18525
18526 *total = COSTS_N_INSNS (1);
18527 }
18528 else
18529 {
18530 if (GET_MODE (XEXP (x, 1)) == DImode)
18531 *total = rs6000_cost->divdi;
18532 else
18533 *total = rs6000_cost->divsi;
18534 }
18535
18536 if (code == MOD || code == UMOD)
18537 *total += COSTS_N_INSNS (2);
18538 return false;
18539
18540 case FFS:
18541 *total = COSTS_N_INSNS (4);
18542 return false;
18543
18544 case NOT:
18545 if (outer_code == AND || outer_code == IOR || outer_code == XOR)
18546 {
18547 *total = 0;
18548 return false;
18549 }
18550
18551
18552 case AND:
18553 case IOR:
18554 case XOR:
18555 case ZERO_EXTRACT:
18556 *total = COSTS_N_INSNS (1);
18557 return false;
18558
18559 case ASHIFT:
18560 case ASHIFTRT:
18561 case LSHIFTRT:
18562 case ROTATE:
18563 case ROTATERT:
18564
18565 if (outer_code == TRUNCATE
18566 && GET_CODE (XEXP (x, 0)) == MULT)
18567 {
18568 if (mode == DImode)
18569 *total = rs6000_cost->muldi;
18570 else
18571 *total = rs6000_cost->mulsi;
18572 return true;
18573 }
18574 else if (outer_code == AND)
18575 *total = 0;
18576 else
18577 *total = COSTS_N_INSNS (1);
18578 return false;
18579
18580 case SIGN_EXTEND:
18581 case ZERO_EXTEND:
18582 if (GET_CODE (XEXP (x, 0)) == MEM)
18583 *total = 0;
18584 else
18585 *total = COSTS_N_INSNS (1);
18586 return false;
18587
18588 case COMPARE:
18589 case NEG:
18590 case ABS:
18591 if (!FLOAT_MODE_P (mode))
18592 {
18593 *total = COSTS_N_INSNS (1);
18594 return false;
18595 }
18596
18597
18598 case FLOAT:
18599 case UNSIGNED_FLOAT:
18600 case FIX:
18601 case UNSIGNED_FIX:
18602 case FLOAT_EXTEND:
18603 case FLOAT_TRUNCATE:
18604 *total = rs6000_cost->fp;
18605 return false;
18606
18607 case UNSPEC:
18608 switch (XINT (x, 1))
18609 {
18610 case UNSPEC_FRSP:
18611 *total = rs6000_cost->fp;
18612 return true;
18613
18614 default:
18615 break;
18616 }
18617 break;
18618
18619 case CALL:
18620 case IF_THEN_ELSE:
18621 if (optimize_size)
18622 {
18623 *total = COSTS_N_INSNS (1);
18624 return true;
18625 }
18626 else if (FLOAT_MODE_P (mode)
18627 && TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS)
18628 {
18629 *total = rs6000_cost->fp;
18630 return false;
18631 }
18632 break;
18633
18634 case EQ:
18635 case GTU:
18636 case LTU:
18637
18638
18639 if (mode == Pmode
18640 && (outer_code == NEG || outer_code == PLUS))
18641 {
18642 *total = COSTS_N_INSNS (1);
18643 return true;
18644 }
18645 if (outer_code == SET)
18646 {
18647 if (XEXP (x, 1) == const0_rtx)
18648 {
18649 *total = COSTS_N_INSNS (2);
18650 return true;
18651 }
18652 else if (mode == Pmode)
18653 {
18654 *total = COSTS_N_INSNS (3);
18655 return false;
18656 }
18657 }
18658
18659
18660 case GT:
18661 case LT:
18662 case UNORDERED:
18663 if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
18664 {
18665 *total = COSTS_N_INSNS (2);
18666 return true;
18667 }
18668
18669 if (outer_code == COMPARE)
18670 {
18671 *total = 0;
18672 return true;
18673 }
18674 break;
18675
18676 default:
18677 break;
18678 }
18679
18680 return false;
18681 }
18682
18683
18684
18685
18686 int
18687 rs6000_register_move_cost (enum machine_mode mode,
18688 enum reg_class from, enum reg_class to)
18689 {
18690
18691 if (reg_classes_intersect_p (to, GENERAL_REGS)
18692 || reg_classes_intersect_p (from, GENERAL_REGS))
18693 {
18694 if (! reg_classes_intersect_p (to, GENERAL_REGS))
18695 from = to;
18696
18697 if (from == FLOAT_REGS || from == ALTIVEC_REGS)
18698 return (rs6000_memory_move_cost (mode, from, 0)
18699 + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
18700
18701
18702
18703 else if (from == CR_REGS)
18704 return 4;
18705
18706 else
18707
18708 return 2 * HARD_REGNO_NREGS (0, mode);
18709 }
18710
18711
18712 else if (reg_classes_intersect_p (to, from))
18713 return mode == TFmode ? 4 : 2;
18714
18715
18716 else
18717 return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
18718 + rs6000_register_move_cost (mode, from, GENERAL_REGS));
18719 }
18720
18721
18722
18723
18724 int
18725 rs6000_memory_move_cost (enum machine_mode mode, enum reg_class class,
18726 int in ATTRIBUTE_UNUSED)
18727 {
18728 if (reg_classes_intersect_p (class, GENERAL_REGS))
18729 return 4 * HARD_REGNO_NREGS (0, mode);
18730 else if (reg_classes_intersect_p (class, FLOAT_REGS))
18731 return 4 * HARD_REGNO_NREGS (32, mode);
18732 else if (reg_classes_intersect_p (class, ALTIVEC_REGS))
18733 return 4 * HARD_REGNO_NREGS (FIRST_ALTIVEC_REGNO, mode);
18734 else
18735 return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
18736 }
18737
18738
18739
18740 static rtx
18741 rs6000_complex_function_value (enum machine_mode mode)
18742 {
18743 unsigned int regno;
18744 rtx r1, r2;
18745 enum machine_mode inner = GET_MODE_INNER (mode);
18746 unsigned int inner_bytes = GET_MODE_SIZE (inner);
18747
18748 if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
18749 regno = FP_ARG_RETURN;
18750 else
18751 {
18752 regno = GP_ARG_RETURN;
18753
18754
18755 if (TARGET_32BIT && inner_bytes >= 4)
18756 return gen_rtx_REG (mode, regno);
18757 }
18758
18759 if (inner_bytes >= 8)
18760 return gen_rtx_REG (mode, regno);
18761
18762 r1 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno),
18763 const0_rtx);
18764 r2 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno + 1),
18765 GEN_INT (inner_bytes));
18766 return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
18767 }
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779 rtx
18780 rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
18781 {
18782 enum machine_mode mode;
18783 unsigned int regno;
18784
18785
18786 if (rs6000_darwin64_abi
18787 && TYPE_MODE (valtype) == BLKmode
18788 && TREE_CODE (valtype) == RECORD_TYPE
18789 && int_size_in_bytes (valtype) > 0)
18790 {
18791 CUMULATIVE_ARGS valcum;
18792 rtx valret;
18793
18794 valcum.words = 0;
18795 valcum.fregno = FP_ARG_MIN_REG;
18796 valcum.vregno = ALTIVEC_ARG_MIN_REG;
18797
18798
18799 valret = rs6000_darwin64_record_arg (&valcum, valtype, 1, true);
18800 if (valret)
18801 return valret;
18802
18803 }
18804
18805 if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
18806 {
18807
18808 return gen_rtx_PARALLEL (DImode,
18809 gen_rtvec (2,
18810 gen_rtx_EXPR_LIST (VOIDmode,
18811 gen_rtx_REG (SImode, GP_ARG_RETURN),
18812 const0_rtx),
18813 gen_rtx_EXPR_LIST (VOIDmode,
18814 gen_rtx_REG (SImode,
18815 GP_ARG_RETURN + 1),
18816 GEN_INT (4))));
18817 }
18818
18819 if ((INTEGRAL_TYPE_P (valtype)
18820 && TYPE_PRECISION (valtype) < BITS_PER_WORD)
18821 || POINTER_TYPE_P (valtype))
18822 mode = TARGET_32BIT ? SImode : DImode;
18823 else
18824 mode = TYPE_MODE (valtype);
18825
18826 if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
18827 regno = FP_ARG_RETURN;
18828 else if (TREE_CODE (valtype) == COMPLEX_TYPE
18829 && targetm.calls.split_complex_arg)
18830 return rs6000_complex_function_value (mode);
18831 else if (TREE_CODE (valtype) == VECTOR_TYPE
18832 && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
18833 && ALTIVEC_VECTOR_MODE (mode))
18834 regno = ALTIVEC_ARG_RETURN;
18835 else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
18836 && (mode == DFmode || mode == DCmode))
18837 return spe_build_register_parallel (mode, GP_ARG_RETURN);
18838 else
18839 regno = GP_ARG_RETURN;
18840
18841 return gen_rtx_REG (mode, regno);
18842 }
18843
18844
18845
18846 rtx
18847 rs6000_libcall_value (enum machine_mode mode)
18848 {
18849 unsigned int regno;
18850
18851 if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
18852 {
18853
18854 return gen_rtx_PARALLEL (DImode,
18855 gen_rtvec (2,
18856 gen_rtx_EXPR_LIST (VOIDmode,
18857 gen_rtx_REG (SImode, GP_ARG_RETURN),
18858 const0_rtx),
18859 gen_rtx_EXPR_LIST (VOIDmode,
18860 gen_rtx_REG (SImode,
18861 GP_ARG_RETURN + 1),
18862 GEN_INT (4))));
18863 }
18864
18865 if (GET_MODE_CLASS (mode) == MODE_FLOAT
18866 && TARGET_HARD_FLOAT && TARGET_FPRS)
18867 regno = FP_ARG_RETURN;
18868 else if (ALTIVEC_VECTOR_MODE (mode)
18869 && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI)
18870 regno = ALTIVEC_ARG_RETURN;
18871 else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
18872 return rs6000_complex_function_value (mode);
18873 else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
18874 && (mode == DFmode || mode == DCmode))
18875 return spe_build_register_parallel (mode, GP_ARG_RETURN);
18876 else
18877 regno = GP_ARG_RETURN;
18878
18879 return gen_rtx_REG (mode, regno);
18880 }
18881
18882
18883
18884 HOST_WIDE_INT
18885 rs6000_initial_elimination_offset (int from, int to)
18886 {
18887 rs6000_stack_t *info = rs6000_stack_info ();
18888 HOST_WIDE_INT offset;
18889
18890 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
18891 offset = info->push_p ? 0 : -info->total_size;
18892 else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
18893 offset = info->total_size;
18894 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
18895 offset = info->push_p ? info->total_size : 0;
18896 else if (from == RS6000_PIC_OFFSET_TABLE_REGNUM)
18897 offset = 0;
18898 else
18899 abort ();
18900
18901 return offset;
18902 }
18903
18904
18905
18906 static bool
18907 is_ev64_opaque_type (tree type)
18908 {
18909 return (TARGET_SPE
18910 && (type == opaque_V2SI_type_node
18911 || type == opaque_V2SF_type_node
18912 || type == opaque_p_V2SI_type_node));
18913 }
18914
18915 static rtx
18916 rs6000_dwarf_register_span (rtx reg)
18917 {
18918 unsigned regno;
18919
18920 if (TARGET_SPE
18921 && (SPE_VECTOR_MODE (GET_MODE (reg))
18922 || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
18923 ;
18924 else
18925 return NULL_RTX;
18926
18927 regno = REGNO (reg);
18928
18929
18930
18931
18932 return
18933 gen_rtx_PARALLEL (VOIDmode,
18934 BYTES_BIG_ENDIAN
18935 ? gen_rtvec (2,
18936 gen_rtx_REG (SImode, regno + 1200),
18937 gen_rtx_REG (SImode, regno))
18938 : gen_rtvec (2,
18939 gen_rtx_REG (SImode, regno),
18940 gen_rtx_REG (SImode, regno + 1200)));
18941 }
18942
18943
18944
18945 unsigned int
18946 rs6000_dbx_register_number (unsigned int regno)
18947 {
18948 if (regno <= 63 || write_symbols != DWARF2_DEBUG)
18949 return regno;
18950 if (regno == MQ_REGNO)
18951 return 100;
18952 if (regno == LINK_REGISTER_REGNUM)
18953 return 108;
18954 if (regno == COUNT_REGISTER_REGNUM)
18955 return 109;
18956 if (CR_REGNO_P (regno))
18957 return regno - CR0_REGNO + 86;
18958 if (regno == XER_REGNO)
18959 return 101;
18960 if (ALTIVEC_REGNO_P (regno))
18961 return regno - FIRST_ALTIVEC_REGNO + 1124;
18962 if (regno == VRSAVE_REGNO)
18963 return 356;
18964 if (regno == VSCR_REGNO)
18965 return 67;
18966 if (regno == SPE_ACC_REGNO)
18967 return 99;
18968 if (regno == SPEFSCR_REGNO)
18969 return 612;
18970
18971
18972 if (regno >= 1200 && regno < 1232)
18973 return regno;
18974
18975 abort ();
18976 }
18977
18978
18979 static enum machine_mode
18980 rs6000_eh_return_filter_mode (void)
18981 {
18982 return TARGET_32BIT ? SImode : word_mode;
18983 }
18984
18985
18986 static bool
18987 rs6000_vector_mode_supported_p (enum machine_mode mode)
18988 {
18989
18990 if (TARGET_SPE && SPE_VECTOR_MODE (mode))
18991 return true;
18992
18993 else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
18994 return true;
18995
18996 else
18997 return false;
18998 }
18999
19000 #include "gt-rs6000.h"